├── .gitignore ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ellen │ │ └── basequickandroid │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── ellen │ │ │ ├── basequickandroid │ │ │ ├── Adapter1.java │ │ │ ├── Adapter2.java │ │ │ ├── MainActivity.java │ │ │ ├── base │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseApplication.java │ │ │ │ ├── BaseDialog.java │ │ │ │ ├── BaseDialogFragment.java │ │ │ │ ├── BaseFloatingView.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseNotification.java │ │ │ │ ├── BasePopWindow.java │ │ │ │ ├── BaseToast.java │ │ │ │ ├── adapter │ │ │ │ │ ├── listview │ │ │ │ │ │ └── BaseListViewAdapter.java │ │ │ │ │ ├── recyclerview │ │ │ │ │ │ ├── BaseMultipleRecyclerViewAdapter.java │ │ │ │ │ │ ├── BaseRecyclerViewAdapter.java │ │ │ │ │ │ ├── BaseSingleRecyclerViewAdapter.java │ │ │ │ │ │ └── BaseViewHolder.java │ │ │ │ │ └── viewpager │ │ │ │ │ │ ├── BaseFragmentPagerAdapter.java │ │ │ │ │ │ ├── BaseFragmentStateAdapter.java │ │ │ │ │ │ └── BaseViewPagerAdapter.java │ │ │ │ └── exception │ │ │ │ │ ├── BaseNoRuntimeException.java │ │ │ │ │ └── BaseRunntimException.java │ │ │ ├── dialog │ │ │ │ ├── AutoToast.java │ │ │ │ └── SystemWaitDialog.java │ │ │ ├── net │ │ │ │ ├── NetHelper.java │ │ │ │ ├── NetInterface.java │ │ │ │ ├── NetManager.java │ │ │ │ ├── ReturnCode.java │ │ │ │ └── ReturnCodeHandler.java │ │ │ ├── save │ │ │ │ └── key_value │ │ │ │ │ ├── BaseKeyValueHelper.java │ │ │ │ │ ├── MMKVHelper.java │ │ │ │ │ └── SharePreferenceHelper.java │ │ │ ├── structure │ │ │ │ └── mvp │ │ │ │ │ ├── BaseMvpActivity.java │ │ │ │ │ ├── basemvp │ │ │ │ │ ├── BaseModel.java │ │ │ │ │ ├── BasePresenter.java │ │ │ │ │ └── BaseView.java │ │ │ │ │ └── demo │ │ │ │ │ └── login │ │ │ │ │ ├── LoginActivity.java │ │ │ │ │ ├── LoginAgreement.java │ │ │ │ │ ├── LoginModel.java │ │ │ │ │ └── LoginPresenter.java │ │ │ └── util │ │ │ │ ├── BaseLog.java │ │ │ │ ├── BitmapUtils.java │ │ │ │ ├── ContentProviderUtils.java │ │ │ │ ├── ImageChooseUtils.java │ │ │ │ ├── PermissionUtils.java │ │ │ │ ├── ToastUtils.java │ │ │ │ ├── UriUtils.java │ │ │ │ ├── WebViewSetttingUtils.java │ │ │ │ ├── collectionutil │ │ │ │ ├── ArrangeInterface.java │ │ │ │ ├── CollectionUtils.java │ │ │ │ ├── CompareableException.java │ │ │ │ └── CompareableInterface.java │ │ │ │ └── statusutil │ │ │ │ ├── OSUtils.java │ │ │ │ ├── StatusUtils.java │ │ │ │ └── SystemBarTintManager.java │ │ │ └── example │ │ │ ├── FragmentReplace │ │ │ └── FragmentPlace.java │ │ │ ├── Java23_Design_Patterns │ │ │ ├── Builder │ │ │ │ ├── Builder.java │ │ │ │ ├── Computer.java │ │ │ │ └── MacBuilder.java │ │ │ └── SingleInstace │ │ │ │ ├── DCLModeSingleInstance.java │ │ │ │ ├── HungryModeSingleInstance.java │ │ │ │ ├── LazybonesModeSingleInstace.java │ │ │ │ ├── StaticCodePieceSingleInstace.java │ │ │ │ └── StaticInnerClassSingleInstace.java │ │ │ ├── LibraryUseDemo │ │ │ └── RxJava │ │ │ │ └── RxJavaDemo.java │ │ │ ├── Serach │ │ │ └── Serach.java │ │ │ └── Sort │ │ │ └── Sort.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ └── ripple_effect.xml │ │ ├── layout │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── dialog_wait.xml │ │ ├── item_recycler_view.xml │ │ ├── item_recycler_view1.xml │ │ └── toast_layout.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── file_paths.xml │ └── test │ └── java │ └── com │ └── ellen │ └── basequickandroid │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.ellen.basequickandroid" 7 | minSdkVersion 21 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:28.0.0' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 28 | implementation 'com.jakewharton:butterknife:8.8.1' 29 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 30 | implementation "com.android.support:recyclerview-v7:28.0.0" 31 | implementation 'com.tencent:mmkv:1.0.19' 32 | // replace "1.0.19" with any available version 33 | 34 | implementation 'io.reactivex.rxjava2:rxjava:2.0.1' 35 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' 36 | } 37 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | # okhttp -------------------------------------------------------------------------------- /app/src/androidTest/java/com/ellen/basequickandroid/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.ellen.basequickandroid", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 31 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/Adapter1.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.ellen.basequickandroid.base.adapter.recyclerview.BaseSingleRecyclerViewAdapter; 9 | import com.ellen.basequickandroid.base.adapter.recyclerview.BaseViewHolder; 10 | 11 | import java.util.List; 12 | 13 | public class Adapter1 extends BaseSingleRecyclerViewAdapter { 14 | 15 | 16 | public Adapter1(Context context, List dataList) { 17 | super(context, dataList); 18 | } 19 | 20 | @Override 21 | protected int getItemLayoutId() { 22 | return R.layout.item_recycler_view; 23 | } 24 | 25 | @Override 26 | protected Adapter1ViewHolder getNewViewHolder(View view) { 27 | return new Adapter1ViewHolder(view); 28 | } 29 | 30 | @Override 31 | protected void showData(Adapter1ViewHolder adapter1ViewHolder, int position) { 32 | adapter1ViewHolder.tv.setText(getDataList().get(position)); 33 | } 34 | 35 | public static class Adapter1ViewHolder extends BaseViewHolder{ 36 | 37 | TextView tv; 38 | 39 | public Adapter1ViewHolder(@NonNull View itemView) { 40 | super(itemView); 41 | tv = itemView.findViewById(R.id.tv); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/Adapter2.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.ellen.basequickandroid.base.adapter.recyclerview.BaseMultipleRecyclerViewAdapter; 11 | import com.ellen.basequickandroid.base.adapter.recyclerview.BaseViewHolder; 12 | 13 | public class Adapter2 extends BaseMultipleRecyclerViewAdapter { 14 | 15 | 16 | private final static int TYPE_TOP = 1; 17 | private final static int TYPE_CENTER = 2; 18 | 19 | public Adapter2(Context context) { 20 | super(context); 21 | } 22 | 23 | @Override 24 | protected int getMultipleItemViewType(int position) { 25 | if(position % 5 == 0){ 26 | return TYPE_TOP; 27 | }else { 28 | return TYPE_CENTER; 29 | } 30 | } 31 | 32 | @Override 33 | protected int getItemSize() { 34 | return 18; 35 | } 36 | 37 | @Override 38 | protected BaseViewHolder getNewBaseViewHolder(@NonNull ViewGroup viewGroup, int itemType) { 39 | if(itemType == TYPE_TOP){ 40 | View view = LayoutInflater.from(getContext()).inflate(R.layout.item_recycler_view,null); 41 | return new TopViewHolder(view); 42 | }else if(itemType == TYPE_CENTER){ 43 | View view = LayoutInflater.from(getContext()).inflate(R.layout.item_recycler_view1,null); 44 | return new CenterViewHolder(view); 45 | } 46 | return null; 47 | } 48 | 49 | @Override 50 | protected void showData(BaseViewHolder baseViewHolder, int position) { 51 | if(baseViewHolder instanceof TopViewHolder){ 52 | //加载顶部item的数据 53 | TopViewHolder topViewHolder = (TopViewHolder) baseViewHolder; 54 | topViewHolder.textView.setText("广告"); 55 | }else if(baseViewHolder instanceof CenterViewHolder){ 56 | //加载中间item的数据 57 | CenterViewHolder centerViewHolder = (CenterViewHolder) baseViewHolder; 58 | centerViewHolder.textView.setText("新闻"); 59 | } 60 | } 61 | 62 | static class TopViewHolder extends BaseViewHolder{ 63 | 64 | TextView textView; 65 | 66 | public TopViewHolder(@NonNull View itemView) { 67 | super(itemView); 68 | textView = itemView.findViewById(R.id.tv); 69 | } 70 | } 71 | 72 | static class CenterViewHolder extends BaseViewHolder{ 73 | TextView textView; 74 | public CenterViewHolder(@NonNull View itemView) { 75 | super(itemView); 76 | textView = itemView.findViewById(R.id.tv); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.widget.GridLayoutManager; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.util.Log; 11 | import android.view.View; 12 | import android.webkit.WebView; 13 | 14 | import com.ellen.basequickandroid.base.BaseActivity; 15 | import com.ellen.basequickandroid.base.BaseDialog; 16 | import com.ellen.basequickandroid.base.adapter.recyclerview.BaseRecyclerViewAdapter; 17 | import com.ellen.basequickandroid.dialog.SystemWaitDialog; 18 | import com.ellen.basequickandroid.util.BaseLog; 19 | import com.ellen.basequickandroid.util.ContentProviderUtils; 20 | import com.ellen.basequickandroid.util.ImageChooseUtils; 21 | import com.ellen.basequickandroid.util.PermissionUtils; 22 | import com.ellen.basequickandroid.util.ToastUtils; 23 | import com.ellen.basequickandroid.util.WebViewSetttingUtils; 24 | import com.ellen.basequickandroid.util.collectionutil.CollectionUtils; 25 | 26 | import java.security.acl.Permission; 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | import butterknife.BindView; 31 | import butterknife.ButterKnife; 32 | import butterknife.OnClick; 33 | 34 | public class MainActivity extends BaseActivity implements BaseActivity.ButterKnifeInterface { 35 | 36 | @BindView(R.id.web_view) 37 | WebView webView; 38 | @BindView(R.id.recycler_view) 39 | RecyclerView recyclerView; 40 | 41 | private ImageChooseUtils imageChooseUtils; 42 | 43 | @OnClick(R.id.bt1) 44 | void onClick(View view) { 45 | imageChooseUtils = new ImageChooseUtils(this, this, new ImageChooseUtils.ChooseImageCallback() { 46 | @Override 47 | public void successs(String path) { 48 | Log.e("选择的图片地址是", path); 49 | } 50 | 51 | @Override 52 | public void failure() { 53 | 54 | } 55 | }); 56 | imageChooseUtils.toSystemAlbum(1); 57 | } 58 | 59 | @Override 60 | protected void setStatus() { 61 | 62 | } 63 | 64 | @Override 65 | protected int setLayoutId() { 66 | return R.layout.activity_main; 67 | } 68 | 69 | private PermissionUtils permissionUtils; 70 | 71 | @Override 72 | protected void initView() { 73 | List stringList = new ArrayList<>(); 74 | stringList.add("1"); 75 | Adapter1 adapter1 = new Adapter1(this,stringList); 76 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); 77 | recyclerView.setLayoutManager(linearLayoutManager); 78 | adapter1.setOnItemClickListener(new BaseRecyclerViewAdapter.OnItemClickListener() { 79 | @Override 80 | public void onItemClick(RecyclerView.ViewHolder viewHolder, int position) { 81 | ToastUtils.toast(MainActivity.this,position+""); 82 | } 83 | }); 84 | recyclerView.setAdapter(adapter1); 85 | } 86 | 87 | @Override 88 | protected void initData() { 89 | //加载百度首页 90 | WebViewSetttingUtils.loadUrl(webView, "https://www.baidu.com/"); 91 | BaseLog.d("ss", "dsadasd"); 92 | } 93 | 94 | @Override 95 | protected void destory() { 96 | 97 | } 98 | 99 | @Override 100 | protected Boolean isSetVerticalScreen() { 101 | return null; 102 | } 103 | 104 | @Override 105 | public void initButterKnife() { 106 | ButterKnife.bind(this); 107 | } 108 | 109 | @Override 110 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 111 | super.onActivityResult(requestCode, resultCode, data); 112 | imageChooseUtils.onActivityResult(requestCode, resultCode, data); 113 | } 114 | 115 | @Override 116 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 117 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 118 | permissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.content.pm.ActivityInfo; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v7.app.AppCompatActivity; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public abstract class BaseActivity extends AppCompatActivity { 14 | 15 | //管理Activity的 16 | private static List activityList = new ArrayList<>(); 17 | 18 | @Override 19 | protected void onCreate(@Nullable Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setStatus(); 22 | setContentView(setLayoutId()); 23 | //是否支持ButterKnife接口 24 | if(this instanceof ButterKnifeInterface){ 25 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 26 | butterKnifeInterface.initButterKnife(); 27 | } 28 | initView(); 29 | initData(); 30 | //横竖屏设置 31 | if(isSetVerticalScreen() != null){ 32 | if(isSetVerticalScreen()){ 33 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 34 | }else { 35 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 36 | } 37 | } 38 | activityList.add(this); 39 | } 40 | 41 | @Override 42 | public void finish() { 43 | super.finish(); 44 | } 45 | 46 | //设置状态栏 47 | protected abstract void setStatus(); 48 | //设置布局id 49 | protected abstract int setLayoutId(); 50 | protected abstract void initView(); 51 | protected abstract void initData(); 52 | //Activity销毁时回调 53 | protected abstract void destory(); 54 | //设置横竖屏,null->跟随系统,true->横屏,false->竖屏 55 | protected abstract Boolean isSetVerticalScreen(); 56 | 57 | protected String getTag(){ 58 | return getClass().getSimpleName(); 59 | } 60 | 61 | @Override 62 | protected void onDestroy() { 63 | super.onDestroy(); 64 | activityList.remove(this); 65 | destory(); 66 | } 67 | 68 | public void quitApp(){ 69 | for(Activity activity:activityList){ 70 | activity.finish(); 71 | } 72 | } 73 | 74 | //支持ButterKnife的接口 75 | public interface ButterKnifeInterface { 76 | void initButterKnife(); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | import java.lang.ref.WeakReference; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * 为什么要基化此类?因为需要进行一些应用全局配置 16 | * 例如:统计应用的Activity工作时间,Activity的启动次数等等 17 | */ 18 | public abstract class BaseApplication extends Application { 19 | 20 | private AppManager appManager; 21 | 22 | private AppActivityLifecycleCallbacks appActivityLifecycleCallbacks; 23 | public static WeakReference baseApplicationWeakReference; 24 | 25 | @Override 26 | public void onCreate() { 27 | super.onCreate(); 28 | //初始化库 & SDK 29 | baseApplicationWeakReference = new WeakReference<>(this); 30 | initLibraySetting(); 31 | if (isListenerActivity()) { 32 | appManager = new AppManager(); 33 | super.registerActivityLifecycleCallbacks(activityLifecycleCallbacks); 34 | }else { 35 | if(appActivityLifecycleCallbacks != null){ 36 | super.registerActivityLifecycleCallbacks(appActivityLifecycleCallbacks); 37 | } 38 | } 39 | } 40 | 41 | public AppManager getAppManager(){ 42 | return baseApplicationWeakReference.get().appManager; 43 | } 44 | 45 | public ActivityManger getActivityManager(Activity activity){ 46 | if(isListenerActivity()) { 47 | return getAppManager().appManagerMap.get(activity.getPackageName() + activity.getClass().getName()); 48 | }else { 49 | Log.e("您没有开启Activity监控","ok"); 50 | return null; 51 | } 52 | } 53 | 54 | //获取某个Activity的工作记录 55 | public Map> getActivityWorkRecord(Activity activity){ 56 | if(isListenerActivity()){ 57 | ActivityManger activityManger = getActivityManager(activity); 58 | if(activityManger != null) { 59 | return activityManger.timeMap; 60 | }else { 61 | return null; 62 | } 63 | } else { 64 | Log.e("您没有开启Activity监控","ok"); 65 | return null; 66 | } 67 | } 68 | 69 | //是否监听用户Activity相关行为 70 | protected abstract Boolean isListenerActivity(); 71 | protected abstract void initLibraySetting(); 72 | 73 | public void registerAppActivityLifecycleCallbacks(AppActivityLifecycleCallbacks appActivityLifecycleCallbacks) { 74 | this.appActivityLifecycleCallbacks = appActivityLifecycleCallbacks; 75 | } 76 | 77 | private ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() { 78 | @Override 79 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 80 | statistics(activity.getPackageName(),activity.getClass().getName(),ActivityManger.ACTIVITY_ON_CREATE,System.currentTimeMillis()); 81 | if(appActivityLifecycleCallbacks != null) { 82 | appActivityLifecycleCallbacks.onActivityCreated(activity,savedInstanceState); 83 | } 84 | } 85 | 86 | @Override 87 | public void onActivityStarted(Activity activity) { 88 | statistics(activity.getPackageName(),activity.getClass().getName(),ActivityManger.ACTIVITY_ON_START,System.currentTimeMillis()); 89 | if(appActivityLifecycleCallbacks != null) { 90 | appActivityLifecycleCallbacks.onActivityStarted(activity); 91 | } 92 | } 93 | 94 | @Override 95 | public void onActivityResumed(Activity activity) { 96 | statistics(activity.getPackageName(),activity.getClass().getName(),ActivityManger.ACTIVITY_ON_RESUME,System.currentTimeMillis()); 97 | if(appActivityLifecycleCallbacks != null) { 98 | appActivityLifecycleCallbacks.onActivityResumed(activity); 99 | } 100 | } 101 | 102 | @Override 103 | public void onActivityPaused(Activity activity) { 104 | statistics(activity.getPackageName(),activity.getClass().getName(),ActivityManger.ACTIVITY_ON_PAUSE,System.currentTimeMillis()); 105 | if(appActivityLifecycleCallbacks != null) { 106 | appActivityLifecycleCallbacks.onActivityPaused(activity); 107 | } 108 | } 109 | 110 | @Override 111 | public void onActivityStopped(Activity activity) { 112 | statistics(activity.getPackageName(),activity.getClass().getName(),ActivityManger.ACTIVITY_ON_STOP,System.currentTimeMillis()); 113 | if(appActivityLifecycleCallbacks != null) { 114 | appActivityLifecycleCallbacks.onActivityStopped(activity); 115 | } 116 | } 117 | 118 | @Override 119 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 120 | 121 | } 122 | 123 | @Override 124 | public void onActivityDestroyed(Activity activity) { 125 | statistics(activity.getPackageName(),activity.getClass().getName(),ActivityManger.ACTIVITY_ON_DESTORY,System.currentTimeMillis()); 126 | if(appActivityLifecycleCallbacks != null) { 127 | appActivityLifecycleCallbacks.onActivityDestroyed(activity); 128 | } 129 | } 130 | 131 | private void statistics(String packageName,String className,String lifeName,long time){ 132 | boolean isHaveThisActivity = appManager.appManagerMap.containsKey(packageName+className); 133 | if(isHaveThisActivity){ 134 | ActivityManger activityManger = appManager.appManagerMap.get(packageName+className); 135 | activityManger.statistics(lifeName,time); 136 | }else { 137 | ActivityManger activityManger = new ActivityManger(packageName,className); 138 | activityManger.statistics(lifeName,time); 139 | appManager.appManagerMap.put(packageName+className,activityManger); 140 | } 141 | } 142 | }; 143 | 144 | public static class AppManager { 145 | 146 | private Map appManagerMap; 147 | 148 | public Map getAppManagerMap() { 149 | return appManagerMap; 150 | } 151 | 152 | public void setAppManagerMap(Map appManagerMap) { 153 | this.appManagerMap = appManagerMap; 154 | } 155 | 156 | public AppManager(){ 157 | appManagerMap = new HashMap<>(); 158 | } 159 | 160 | } 161 | 162 | public static class ActivityManger { 163 | 164 | public static final String ACTIVITY_ON_CREATE = "activity_on_create"; 165 | public static final String ACTIVITY_ON_START = "activity_on_start"; 166 | public static final String ACTIVITY_ON_RESUME = "activity_on_resume"; 167 | public static final String ACTIVITY_ON_PAUSE = "activity_on_pause"; 168 | public static final String ACTIVITY_ON_STOP = "activity_on_stop"; 169 | public static final String ACTIVITY_ON_RESTART = "activity_on_restart"; 170 | public static final String ACTIVITY_ON_DESTORY = "activity_on_destory"; 171 | 172 | public ActivityManger(String packageName,String name) { 173 | this.name = name; 174 | this.packageName = packageName; 175 | } 176 | 177 | //名字 178 | private String name; 179 | //包名 180 | private String packageName; 181 | //执行onCreate的次数 182 | private int createTimes; 183 | //执行onStart的次数 184 | private int startTimes; 185 | //执行onResume的次数 186 | private int resumeTimes; 187 | //执行onPause的次数 188 | private int pauseTimes; 189 | //执行onStop的次数 190 | private int stopTimes; 191 | //执行onRestart的次数 192 | private int restartTimes; 193 | //执行onDestory的次数 194 | private int destoryTimes; 195 | //统计函数调用的时间轴 196 | private Map> timeMap; 197 | //记录工作时间 198 | private long workTime = 0; 199 | 200 | public String getName() { 201 | return name; 202 | } 203 | 204 | public void setName(String name) { 205 | this.name = name; 206 | } 207 | 208 | public String getPackageName() { 209 | return packageName; 210 | } 211 | 212 | public void setPackageName(String packageName) { 213 | this.packageName = packageName; 214 | } 215 | 216 | public int getCreateTimes() { 217 | return createTimes; 218 | } 219 | 220 | public void setCreateTimes(int createTimes) { 221 | this.createTimes = createTimes; 222 | } 223 | 224 | public int getStartTimes() { 225 | return startTimes; 226 | } 227 | 228 | public void setStartTimes(int startTimes) { 229 | this.startTimes = startTimes; 230 | } 231 | 232 | public int getResumeTimes() { 233 | return resumeTimes; 234 | } 235 | 236 | public void setResumeTimes(int resumeTimes) { 237 | this.resumeTimes = resumeTimes; 238 | } 239 | 240 | public int getPauseTimes() { 241 | return pauseTimes; 242 | } 243 | 244 | public void setPauseTimes(int pauseTimes) { 245 | this.pauseTimes = pauseTimes; 246 | } 247 | 248 | public int getStopTimes() { 249 | return stopTimes; 250 | } 251 | 252 | public void setStopTimes(int stopTimes) { 253 | this.stopTimes = stopTimes; 254 | } 255 | 256 | public int getRestartTimes() { 257 | return restartTimes; 258 | } 259 | 260 | public void setRestartTimes(int restartTimes) { 261 | this.restartTimes = restartTimes; 262 | } 263 | 264 | public int getDestoryTimes() { 265 | return destoryTimes; 266 | } 267 | 268 | public void setDestoryTimes(int destoryTimes) { 269 | this.destoryTimes = destoryTimes; 270 | } 271 | 272 | public Map> getTimeMap() { 273 | return timeMap; 274 | } 275 | 276 | public void setTimeMap(Map> timeMap) { 277 | this.timeMap = timeMap; 278 | } 279 | 280 | public void statistics(String lifeName, long time){ 281 | if(timeMap == null){ 282 | timeMap = new HashMap<>(); 283 | } 284 | switch (lifeName){ 285 | case ACTIVITY_ON_CREATE: 286 | createTimes++; 287 | break; 288 | case ACTIVITY_ON_START: 289 | startTimes++; 290 | break; 291 | case ACTIVITY_ON_RESUME: 292 | resumeTimes++; 293 | break; 294 | case ACTIVITY_ON_PAUSE: 295 | pauseTimes++; 296 | break; 297 | case ACTIVITY_ON_STOP: 298 | stopTimes++; 299 | break; 300 | case ACTIVITY_ON_RESTART: 301 | restartTimes++; 302 | break; 303 | case ACTIVITY_ON_DESTORY: 304 | destoryTimes++; 305 | break; 306 | } 307 | if(timeMap.get(lifeName) == null){ 308 | ArrayList timeArrayList = new ArrayList<>(); 309 | timeArrayList.add(time); 310 | timeMap.put(lifeName,timeArrayList); 311 | }else { 312 | List timeArrayList = timeMap.get(lifeName); 313 | timeArrayList.add(time); 314 | } 315 | Log.e("用户操作",packageName+"_"+name+"-->"+lifeName+":"+time); 316 | } 317 | 318 | } 319 | 320 | public interface AppActivityLifecycleCallbacks extends ActivityLifecycleCallbacks{}; 321 | } 322 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseDialog.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.Context; 6 | import android.content.DialogInterface; 7 | import android.view.View; 8 | 9 | import java.lang.ref.WeakReference; 10 | 11 | public abstract class BaseDialog { 12 | 13 | private AlertDialog dialog; 14 | private WeakReference contextWeakReference; 15 | private WeakReference activityWeakReference; 16 | private OnDismissListener onDismissListener; 17 | 18 | public BaseDialog(Context context){ 19 | contextWeakReference = new WeakReference<>(context); 20 | init(); 21 | } 22 | 23 | public BaseDialog(Context context, Activity activity){ 24 | contextWeakReference = new WeakReference<>(context); 25 | activityWeakReference = new WeakReference<>(activity); 26 | init(); 27 | } 28 | 29 | protected String getTag(){ 30 | return getClass().getSimpleName(); 31 | } 32 | 33 | private void init(){ 34 | dialog = new AlertDialog.Builder(contextWeakReference.get()).create(); 35 | View view = onCreateView(); 36 | //设置布局 37 | dialog.setView(view); 38 | if(this instanceof ButterKnifeInterface){ 39 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 40 | butterKnifeInterface.initButterKnife(view); 41 | } 42 | if(setCancelable() != null){ 43 | dialog.setCancelable(setCancelable()); 44 | } 45 | if(setCanceledOnTouchOutside() != null) { 46 | dialog.setCanceledOnTouchOutside(setCanceledOnTouchOutside()); 47 | } 48 | dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 49 | @Override 50 | public void onDismiss(DialogInterface dialog) { 51 | if(onDismissListener != null){ 52 | onDismissListener.dismiss(); 53 | } 54 | } 55 | }); 56 | } 57 | 58 | public void show(){ 59 | showBefore(); 60 | dialog.show(); 61 | onResume(); 62 | } 63 | 64 | public void dismiss(){ 65 | dissmissBefore(); 66 | if(this instanceof ButterKnifeInterface){ 67 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 68 | butterKnifeInterface.unBindButterKnife(); 69 | } 70 | dialog.dismiss(); 71 | destory(); 72 | } 73 | 74 | public Activity getActivity(){ 75 | return activityWeakReference.get(); 76 | } 77 | 78 | public Context getContext(){ 79 | return contextWeakReference.get(); 80 | } 81 | 82 | public OnDismissListener getOnDismissListener() { 83 | return onDismissListener; 84 | } 85 | 86 | public void setOnDismissListener(OnDismissListener onDismissListener) { 87 | this.onDismissListener = onDismissListener; 88 | } 89 | 90 | protected abstract View onCreateView(); 91 | protected abstract void showBefore(); 92 | protected abstract void onResume(); 93 | protected abstract void dissmissBefore(); 94 | protected abstract void destory(); 95 | protected abstract Boolean setCancelable(); 96 | protected abstract Boolean setCanceledOnTouchOutside(); 97 | 98 | public interface ButterKnifeInterface{ 99 | void initButterKnife(View view); 100 | void unBindButterKnife(); 101 | } 102 | 103 | public interface OnDismissListener{ 104 | void dismiss(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.graphics.Color; 4 | import android.graphics.drawable.ColorDrawable; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.DialogFragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | public abstract class BaseDialogFragment extends DialogFragment { 14 | 15 | @Nullable 16 | @Override 17 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 18 | View view = inflater.inflate(setLayout(), container, false); 19 | if(this instanceof ButterKnifeInterface){ 20 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 21 | butterKnifeInterface.initButterKnife(view); 22 | } 23 | if(setCancelable() != null) { 24 | this.setCancelable(setCancelable()); 25 | } 26 | if(setCanceledOnTouchOutside() != null) { 27 | getDialog().setCanceledOnTouchOutside(setCanceledOnTouchOutside()); 28 | } 29 | if(setWinowTransparent() != null && setWinowTransparent()) { 30 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 31 | } 32 | initView(); 33 | initData(); 34 | return view; 35 | } 36 | 37 | protected String getTAG(){ 38 | return getClass().getSimpleName(); 39 | } 40 | 41 | @Override 42 | public void onDestroy() { 43 | super.onDestroy(); 44 | if(this instanceof ButterKnifeInterface){ 45 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 46 | butterKnifeInterface.unBindButterKnife(); 47 | } 48 | } 49 | 50 | protected abstract void initData(); 51 | protected abstract void initView(); 52 | protected abstract int setLayout(); 53 | protected abstract Boolean setCancelable(); 54 | protected abstract Boolean setCanceledOnTouchOutside(); 55 | protected abstract Boolean setWinowTransparent(); 56 | 57 | //支持ButterKnife的接口 58 | public interface ButterKnifeInterface { 59 | void initButterKnife(View view); 60 | void unBindButterKnife(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseFloatingView.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.WindowManager; 8 | 9 | import java.lang.ref.WeakReference; 10 | 11 | /** 12 | * 13 | * 悬浮View封装 14 | * 15 | */ 16 | public abstract class BaseFloatingView { 17 | private WindowManager windowManager; 18 | private View view; 19 | private WeakReference activityWeakReference; 20 | private WindowManager.LayoutParams layoutParams; 21 | private boolean isFirestAdd = false; 22 | private View.OnTouchListener onTouchListener; 23 | 24 | public BaseFloatingView(Activity activity){ 25 | activityWeakReference = new WeakReference<>(activity); 26 | windowManager = (WindowManager) activity.getApplication().getSystemService(Context.WINDOW_SERVICE); 27 | //1.创建一个Layoutparams出来 28 | layoutParams = new WindowManager.LayoutParams(); 29 | setLayoutParams(layoutParams); 30 | //2.布局映射一个View对象出来 31 | LayoutInflater inflater; 32 | inflater = LayoutInflater.from(activity.getApplication()); 33 | view = getFloatingView(inflater); 34 | //初始化view对象,可以绑定控件 35 | initView(view); 36 | } 37 | 38 | public View.OnTouchListener getOnTouchListener() { 39 | return onTouchListener; 40 | } 41 | 42 | public void setOnTouchListener(View.OnTouchListener onTouchListener) { 43 | this.onTouchListener = onTouchListener; 44 | } 45 | 46 | public boolean isFirestAdd() { 47 | return isFirestAdd; 48 | } 49 | 50 | public boolean isShow(){ 51 | return view.getVisibility() == View.VISIBLE; 52 | } 53 | 54 | public void careatAndShow(){ 55 | if(onTouchListener != null){ 56 | view.setOnTouchListener(onTouchListener); 57 | } 58 | windowManager.addView(view,layoutParams); 59 | isFirestAdd = true; 60 | } 61 | 62 | public void hide(){ 63 | view.setVisibility(View.GONE); 64 | } 65 | 66 | public void show(){ 67 | view.setVisibility(View.VISIBLE); 68 | } 69 | 70 | public void cancel(){ 71 | windowManager.removeView(view); 72 | } 73 | 74 | public Activity getActivity(){ 75 | return activityWeakReference.get(); 76 | } 77 | 78 | public Context getContext(){ 79 | return activityWeakReference.get(); 80 | } 81 | 82 | protected abstract void initView(View view); 83 | protected abstract void setLayoutParams(WindowManager.LayoutParams layoutParams); 84 | protected abstract View getFloatingView(LayoutInflater inflater); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | public abstract class BaseFragment extends Fragment { 12 | 13 | @Nullable 14 | @Override 15 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 16 | View view = inflater.inflate(setLayout(), container, false); 17 | if(this instanceof ButterKnifeInterface){ 18 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 19 | butterKnifeInterface.initButterKnife(view); 20 | } 21 | initView(); 22 | initData(); 23 | return view; 24 | } 25 | 26 | protected String getTAG(){ 27 | return getClass().getSimpleName(); 28 | } 29 | 30 | @Override 31 | public void onDestroy() { 32 | super.onDestroy(); 33 | if(this instanceof ButterKnifeInterface){ 34 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 35 | butterKnifeInterface.unBindButterKnife(); 36 | } 37 | } 38 | 39 | @Override 40 | public void setUserVisibleHint(boolean isVisibleToUser) { 41 | if(isVisibleToUser){ 42 | if(this instanceof LazyLoadInterface){ 43 | LazyLoadInterface lazyLoadInterface = (LazyLoadInterface) this; 44 | lazyLoadInterface.lazyLoad(); 45 | } 46 | } 47 | super.setUserVisibleHint(isVisibleToUser); 48 | } 49 | 50 | protected abstract void initData(); 51 | protected abstract void initView(); 52 | protected abstract int setLayout(); 53 | 54 | //支持ButterKnife的接口 55 | public interface ButterKnifeInterface { 56 | void initButterKnife(View view); 57 | void unBindButterKnife(); 58 | } 59 | 60 | public interface LazyLoadInterface{ 61 | void lazyLoad(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseNotification.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.widget.RemoteViews; 10 | 11 | import java.lang.ref.WeakReference; 12 | 13 | /** 14 | * 适配8.0 & 自定义通知 & 适配各种型号手机 15 | */ 16 | public abstract class BaseNotification { 17 | 18 | private NotificationManager notificationManager; 19 | private WeakReference contextWeakReference; 20 | private Notification notification; 21 | 22 | //通知id 23 | private int notificationId; 24 | //点击通知栏的意图 25 | private Intent notificationIntent; 26 | //通知cancel事件 27 | private OnNotificationCancelListener onNotificationCancelListener; 28 | //是否通知显示了 29 | private boolean isShowNotificaiton = false; 30 | 31 | public boolean isShowNotificaiton(){ 32 | return isShowNotificaiton; 33 | } 34 | 35 | public OnNotificationCancelListener getOnNotificationCancelListener() { 36 | return onNotificationCancelListener; 37 | } 38 | 39 | public void setOnNotificationCancelListener(OnNotificationCancelListener onNotificationCancelListener) { 40 | this.onNotificationCancelListener = onNotificationCancelListener; 41 | } 42 | 43 | public Context getContext(){ 44 | return contextWeakReference.get(); 45 | } 46 | 47 | public Intent getNotificationIntent() { 48 | return notificationIntent; 49 | } 50 | 51 | public void setNotificationIntent(Intent notificationIntent) { 52 | this.notificationIntent = notificationIntent; 53 | } 54 | 55 | public int getNotificationId() { 56 | return notificationId; 57 | } 58 | 59 | public void setNotificationId(int notificationId) { 60 | this.notificationId = notificationId; 61 | } 62 | 63 | public BaseNotification(Context context) { 64 | contextWeakReference = new WeakReference<>(context); 65 | notificationManager = (NotificationManager) contextWeakReference.get().getSystemService(Context.NOTIFICATION_SERVICE); 66 | notificationId = setNotificationId(); 67 | notificationIntent = setNotificationIntent(); 68 | } 69 | 70 | protected String getTag(){ 71 | return getClass().getSimpleName(); 72 | } 73 | 74 | public void showNotification() { 75 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { 76 | //适配8.0以上的通知 77 | NotificationChannel channel = new NotificationChannel(String.valueOf(notificationId), setChannelName(), NotificationManager.IMPORTANCE_HIGH); 78 | notificationManager.createNotificationChannel(channel); 79 | Notification.Builder build = new Notification.Builder(contextWeakReference.get(), String.valueOf(notificationId)); 80 | build.setSmallIcon(setIconResourecId()) 81 | .setTicker(setTicker()) 82 | .setContentTitle(setTitle()) 83 | .setContentText(titleContent()); 84 | if (isAutoCancel() != null) { 85 | if(isAutoCancel()) { 86 | build.setAutoCancel(true); 87 | } 88 | } 89 | notification = build.build(); 90 | } else { 91 | //8.0以下执行这里 92 | notification = new Notification(); 93 | notification.tickerText = setTicker(); 94 | if (isAutoCancel() != null) { 95 | if (isAutoCancel()) { 96 | notification.flags = Notification.FLAG_AUTO_CANCEL; 97 | } 98 | } 99 | notification.icon = setIconResourecId(); 100 | isShowNotificaiton = true; 101 | } 102 | RemoteViews remoteViews = new RemoteViews(contextWeakReference.get().getPackageName(), setNotificationLayoutId()); 103 | initView(remoteViews); 104 | notification.contentView = remoteViews; 105 | //封装一个Intent 106 | PendingIntent resultPendingIntent = PendingIntent.getActivity(contextWeakReference.get(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); 107 | // 设置通知主题的意图 108 | notification.contentIntent = resultPendingIntent; 109 | notificationManager.notify(notificationId, notification); 110 | } 111 | 112 | public void cancelNotification(){ 113 | cancelBefore(); 114 | notificationManager.cancel(notificationId); 115 | if(onNotificationCancelListener != null){ 116 | onNotificationCancelListener.cancel(); 117 | } 118 | isShowNotificaiton = false; 119 | } 120 | 121 | protected abstract int setNotificationLayoutId(); 122 | protected abstract String setTicker(); 123 | protected abstract void initView(RemoteViews remoteViews); 124 | protected abstract int setIconResourecId(); 125 | protected abstract Boolean isAutoCancel(); 126 | protected abstract String setChannelName(); 127 | protected abstract String setTitle(); 128 | protected abstract String titleContent(); 129 | protected abstract int setNotificationId(); 130 | protected abstract Intent setNotificationIntent(); 131 | protected abstract void cancelBefore(); 132 | 133 | public interface OnNotificationCancelListener{ 134 | void cancel(); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BasePopWindow.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.graphics.drawable.Drawable; 7 | import android.os.Build; 8 | import android.view.View; 9 | import android.view.WindowManager; 10 | import android.widget.PopupWindow; 11 | 12 | import java.lang.ref.WeakReference; 13 | 14 | public abstract class BasePopwindow { 15 | 16 | private PopupWindow popupWindow; 17 | private WeakReference activityWeakReference; 18 | //dismiss事件触发 19 | private OnDismissListener onDismissListener; 20 | 21 | public BasePopwindow(Activity activity, Context context){ 22 | activityWeakReference = new WeakReference<>(activity); 23 | View view = onCreateView(); 24 | if(this instanceof ButterKnifeInterface){ 25 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 26 | butterKnifeInterface.initButterKnife(view); 27 | } 28 | popupWindow = new PopupWindow(view,setWidth(),setHeight(),isGetFocus()); 29 | 30 | // 设置PopupWindow的背景 31 | if(isSetBackgroundDrawable()!= null && isSetBackgroundDrawable()) { 32 | popupWindow.setBackgroundDrawable(setBackgroundDrawable()); 33 | } 34 | // 设置PopupWindow是否能响应外部点击事件 35 | popupWindow.setOutsideTouchable(isResponseOutsideTouchable()); 36 | // 设置PopupWindow是否能响应点击事件 37 | popupWindow.setTouchable(isResponseTouchable()); 38 | //设置其它,例如:可以通过这个方法完成虚拟键盘适配等 39 | setOtherSetting(popupWindow); 40 | 41 | popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { 42 | @Override 43 | public void onDismiss() { 44 | if(onDismissListener != null){ 45 | onDismissListener.dissmiss(); 46 | } 47 | } 48 | }); 49 | } 50 | 51 | protected String getTag(){ 52 | return getClass().getSimpleName(); 53 | } 54 | 55 | protected void onResume(){} 56 | 57 | protected void onstart(){} 58 | 59 | private void showBefore(){ 60 | if(isSetShowBackgroundBlack()){ 61 | WindowManager.LayoutParams lp = activityWeakReference.get().getWindow().getAttributes(); 62 | lp.alpha = 0.3f; 63 | activityWeakReference.get().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 64 | activityWeakReference.get().getWindow().setAttributes(lp); 65 | } 66 | onstart(); 67 | } 68 | 69 | //显示在目标View的下方 70 | protected void showAsDropDown(View parentView){ 71 | showBefore(); 72 | popupWindow.showAsDropDown(parentView); 73 | onResume(); 74 | } 75 | 76 | //显示在目标View的下方,并且加上偏移量 77 | public void showAsDropDown(View parentView,int xoff,int yoff){ 78 | showBefore(); 79 | popupWindow.showAsDropDown(parentView,xoff,yoff); 80 | onResume(); 81 | } 82 | 83 | @TargetApi(Build.VERSION_CODES.KITKAT) 84 | public void showAsDropDown(View parentView, int xoff, int yoff, int gravity){ 85 | showBefore(); 86 | popupWindow.showAsDropDown(parentView,xoff,yoff,gravity); 87 | onResume(); 88 | } 89 | 90 | public void showAtLocation(View parentView,int gravity,int xoff,int yoff){ 91 | showBefore(); 92 | popupWindow.showAtLocation(parentView,gravity,xoff,yoff); 93 | onResume(); 94 | } 95 | 96 | public void dismiss(){ 97 | dismissBefore(); 98 | //解除绑定 99 | if(this instanceof ButterKnifeInterface){ 100 | ButterKnifeInterface butterKnifeInterface = (ButterKnifeInterface) this; 101 | butterKnifeInterface.unBindButterKnife(); 102 | } 103 | //如果设置了背景暗化,那么这里去除背景暗化 104 | if(isSetShowBackgroundBlack()){ 105 | //去掉暗色背景 106 | WindowManager.LayoutParams lp = activityWeakReference.get().getWindow().getAttributes(); 107 | lp.alpha = 1.0f; 108 | activityWeakReference.get().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 109 | activityWeakReference.get().getWindow().setAttributes(lp); 110 | } 111 | popupWindow.dismiss(); 112 | } 113 | 114 | //创建Popwindow的View 115 | protected abstract View onCreateView(); 116 | //设置宽度 117 | protected abstract int setWidth(); 118 | //设置高度 119 | protected abstract int setHeight(); 120 | //是否获取焦点 121 | protected abstract boolean isGetFocus(); 122 | //是否设置背景Drawable 123 | protected abstract Boolean isSetBackgroundDrawable(); 124 | //设置背景Drawable 125 | protected abstract Drawable setBackgroundDrawable(); 126 | //是否相应外部点击事件 127 | protected abstract boolean isResponseOutsideTouchable(); 128 | //是否相应内部点击事件 129 | protected abstract boolean isResponseTouchable(); 130 | //设置其它 131 | protected abstract void setOtherSetting(PopupWindow popupWindow); 132 | //设置背景暗化 133 | protected abstract Boolean isSetShowBackgroundBlack(); 134 | //dismiss之前调用 135 | protected abstract void dismissBefore(); 136 | 137 | public Activity getActivity(){ 138 | return activityWeakReference.get(); 139 | } 140 | 141 | public Context getContext(){ 142 | return activityWeakReference.get(); 143 | } 144 | 145 | public OnDismissListener getOnDismissListener() { 146 | return onDismissListener; 147 | } 148 | 149 | public void setOnDismissListener(OnDismissListener onDismissListener) { 150 | this.onDismissListener = onDismissListener; 151 | } 152 | 153 | public interface ButterKnifeInterface{ 154 | void initButterKnife(View view); 155 | void unBindButterKnife(); 156 | } 157 | 158 | public interface OnDismissListener{ 159 | void dissmiss(); 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/BaseToast.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.content.Context; 6 | import android.view.View; 7 | import android.widget.Toast; 8 | 9 | import java.lang.ref.WeakReference; 10 | 11 | /** 12 | * 自定义Toast基类,可支持任意的布局 13 | */ 14 | public abstract class BaseToast { 15 | 16 | private WeakReference activityWeakReference; 17 | private Toast toast; 18 | private View toastView; 19 | 20 | public BaseToast(Activity activity){ 21 | activityWeakReference = new WeakReference<>(activity); 22 | init(); 23 | } 24 | 25 | private void init() { 26 | toastView = onCreateView(); 27 | toast = new Toast(activityWeakReference.get()); 28 | setToastGravity(toast); 29 | toast.setDuration(getDuration()); 30 | toast.setView(toastView); 31 | } 32 | 33 | protected abstract View onCreateView(); 34 | 35 | public void show(){ 36 | toast.show(); 37 | } 38 | 39 | public Context getContext(){ 40 | return activityWeakReference.get(); 41 | } 42 | 43 | protected abstract int getDuration(); 44 | protected abstract void setToastGravity(Toast toast); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/listview/BaseListViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.listview; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | 9 | import java.lang.ref.WeakReference; 10 | import java.util.List; 11 | 12 | public abstract class BaseListViewAdapter extends BaseAdapter { 13 | 14 | private WeakReference contextWeakReference; 15 | private List dataList; 16 | 17 | public Context getContext() { 18 | return contextWeakReference.get(); 19 | } 20 | 21 | public List getDataList() { 22 | return dataList; 23 | } 24 | 25 | public void setDataList(List dataList) { 26 | this.dataList = dataList; 27 | } 28 | 29 | public BaseListViewAdapter(Context context, List dataList){ 30 | this.contextWeakReference = new WeakReference<>(context); 31 | this.dataList = dataList; 32 | } 33 | 34 | @Override 35 | public int getCount() { 36 | return dataList.size(); 37 | } 38 | 39 | @Override 40 | public Object getItem(int position) { 41 | return dataList.get(position); 42 | } 43 | 44 | @Override 45 | public long getItemId(int position) { 46 | return position; 47 | } 48 | 49 | @Override 50 | public View getView(int position, View convertView, ViewGroup parent) { 51 | ViewHolder viewHolder = null; 52 | if(convertView == null){ 53 | convertView = LayoutInflater.from(getContext()).inflate(getItemLayoutId(),null); 54 | viewHolder = getNewViewHolder(); 55 | initViewHolder((E)viewHolder,convertView); 56 | convertView.setTag(viewHolder); 57 | }else { 58 | viewHolder = (ViewHolder) convertView.getTag(); 59 | } 60 | showData((E)viewHolder,position); 61 | return convertView; 62 | } 63 | 64 | //显示数据的时候回调 65 | protected abstract void showData(E viewHolder,int position); 66 | //绑定iewHolder里控件时回调 67 | protected abstract void initViewHolder(E viewHolder,View view); 68 | //获取item布局id时回调 69 | protected abstract int getItemLayoutId(); 70 | //绑定一个新的ViewHolder时回调 71 | protected abstract ViewHolder getNewViewHolder(); 72 | 73 | public static class ViewHolder{} 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/recyclerview/BaseMultipleRecyclerViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.recyclerview; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import java.lang.ref.WeakReference; 9 | 10 | public abstract class BaseMultipleRecyclerViewAdapter extends BaseRecyclerViewAdapter { 11 | 12 | private WeakReference contextWeakReference; 13 | 14 | public BaseMultipleRecyclerViewAdapter(Context context){ 15 | contextWeakReference = new WeakReference<>(context); 16 | } 17 | 18 | public Context getContext(){ 19 | return contextWeakReference.get(); 20 | } 21 | 22 | @NonNull 23 | @Override 24 | public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int itemType) { 25 | return getNewBaseViewHolder(viewGroup,itemType); 26 | } 27 | 28 | @Override 29 | public void onBindViewHolder(@NonNull final BaseViewHolder baseViewHolder, final int position) { 30 | showData(baseViewHolder,position); 31 | if(onItemClickListener != null){ 32 | baseViewHolder.itemView.setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View v) { 35 | onItemClickListener.onItemClick(baseViewHolder,position); 36 | } 37 | }); 38 | } 39 | } 40 | 41 | @Override 42 | public int getItemCount() { 43 | return getItemSize(); 44 | } 45 | 46 | @Override 47 | public int getItemViewType(int position) { 48 | return getMultipleItemViewType(position); 49 | } 50 | 51 | protected abstract int getMultipleItemViewType(int position); 52 | protected abstract int getItemSize(); 53 | protected abstract BaseViewHolder getNewBaseViewHolder(@NonNull ViewGroup viewGroup, int itemType); 54 | protected abstract void showData(BaseViewHolder baseViewHolder, int position); 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/recyclerview/BaseRecyclerViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.recyclerview; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | 5 | public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter { 6 | 7 | public OnItemClickListener onItemClickListener; 8 | 9 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 10 | this.onItemClickListener = onItemClickListener; 11 | } 12 | 13 | public interface OnItemClickListener{ 14 | void onItemClick(T t,int position); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/recyclerview/BaseSingleRecyclerViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.recyclerview; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import java.lang.ref.WeakReference; 11 | import java.util.List; 12 | 13 | public abstract class BaseSingleRecyclerViewAdapter extends BaseRecyclerViewAdapter { 14 | 15 | private WeakReference contextWeakReference; 16 | private List dataList; 17 | 18 | public BaseSingleRecyclerViewAdapter(Context context,List dataList){ 19 | contextWeakReference = new WeakReference<>(context); 20 | this.dataList = dataList; 21 | } 22 | 23 | public Context getContext(){ 24 | return contextWeakReference.get(); 25 | } 26 | 27 | @NonNull 28 | @Override 29 | public VH onCreateViewHolder(@NonNull ViewGroup viewGroup, int itemType) { 30 | View view = LayoutInflater.from(getContext()).inflate(getItemLayoutId(),null); 31 | return getNewViewHolder(view); 32 | } 33 | 34 | @Override 35 | public void onBindViewHolder(@NonNull final VH vh, final int position) { 36 | showData(vh,position); 37 | if(onItemClickListener != null){ 38 | vh.itemView.setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | onItemClickListener.onItemClick(vh,position); 42 | } 43 | }); 44 | } 45 | } 46 | 47 | @Override 48 | public int getItemCount() { 49 | return dataList.size(); 50 | } 51 | 52 | public List getDataList() { 53 | return dataList; 54 | } 55 | 56 | protected abstract int getItemLayoutId(); 57 | protected abstract VH getNewViewHolder(View view); 58 | protected abstract void showData(VH vh, int position); 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/recyclerview/BaseViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.recyclerview; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | public class BaseViewHolder extends RecyclerView.ViewHolder { 8 | 9 | public BaseViewHolder(@NonNull View itemView) { 10 | super(itemView); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/viewpager/BaseFragmentPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.viewpager; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | public abstract class BaseFragmentPagerAdapter extends FragmentPagerAdapter { 8 | 9 | public BaseFragmentPagerAdapter(FragmentManager fm) { 10 | super(fm); 11 | } 12 | 13 | @Override 14 | public Fragment getItem(int position) { 15 | return getFragment(position); 16 | } 17 | 18 | @Override 19 | public int getCount() { 20 | return getFragmentPagerSize(); 21 | } 22 | 23 | protected abstract int getFragmentPagerSize(); 24 | protected abstract Fragment getFragment(int position); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/viewpager/BaseFragmentStateAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.viewpager; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentStatePagerAdapter; 6 | 7 | public abstract class BaseFragmentStateAdapter extends FragmentStatePagerAdapter { 8 | 9 | public BaseFragmentStateAdapter(FragmentManager fm) { 10 | super(fm); 11 | } 12 | 13 | @Override 14 | public Fragment getItem(int position) { 15 | return getFragment(position); 16 | } 17 | 18 | @Override 19 | public int getCount() { 20 | return getFragmentPagerSize(); 21 | } 22 | 23 | protected abstract int getFragmentPagerSize(); 24 | protected abstract Fragment getFragment(int position); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/adapter/viewpager/BaseViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.adapter.viewpager; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | public abstract class BaseViewPagerAdapter extends PagerAdapter { 9 | @Override 10 | public int getCount() { 11 | return getPagerItemSize(); 12 | } 13 | 14 | @Override 15 | public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { 16 | return view == object; 17 | } 18 | 19 | //设置viewpage内部东西的方法,如果viewpage内没有子空间滑动产生不了动画效果 20 | @Override 21 | public Object instantiateItem(ViewGroup container, int position) { 22 | View view = getView(position); 23 | container.addView(view); 24 | return view; 25 | } 26 | 27 | @Override 28 | public void destroyItem(ViewGroup container, int position, Object object) { 29 | container.removeView((View) object); 30 | } 31 | 32 | //目的是展示title上的文字, 33 | @Override 34 | public CharSequence getPageTitle(int position) { 35 | return getPagetTitle(position); 36 | } 37 | 38 | protected abstract View getView(int position); 39 | protected abstract String getPagetTitle(int position); 40 | protected abstract int getPagerItemSize(); 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/exception/BaseNoRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.exception; 2 | 3 | /** 4 | * 非运行时异常的基类 5 | */ 6 | public class BaseNoRuntimeException extends Exception{ 7 | 8 | private String errorCode; 9 | private String errorMessage; 10 | 11 | public BaseNoRuntimeException(String errorCode,String errorMessage){ 12 | this.errorCode = errorCode; 13 | this.errorMessage = errorMessage; 14 | } 15 | 16 | @Override 17 | public String getMessage() { 18 | return errorCode+""+errorMessage; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/base/exception/BaseRunntimException.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.base.exception; 2 | 3 | /** 4 | * 运行时异常的基类 5 | */ 6 | public class BaseRunntimException extends RuntimeException { 7 | 8 | private String errorCode; 9 | private String errorMessage; 10 | 11 | public BaseRunntimException(String errorCode,String errorMessage){ 12 | this.errorCode = errorCode; 13 | this.errorMessage = errorMessage; 14 | } 15 | 16 | @Override 17 | public String getMessage() { 18 | return errorCode+""+errorMessage; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/dialog/AutoToast.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.dialog; 2 | 3 | import android.app.Activity; 4 | import android.view.Gravity; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.widget.Toast; 8 | 9 | import com.ellen.basequickandroid.R; 10 | import com.ellen.basequickandroid.base.BaseToast; 11 | 12 | public class AutoToast extends BaseToast { 13 | 14 | public AutoToast(Activity activity) { 15 | super(activity); 16 | } 17 | 18 | @Override 19 | protected View onCreateView() { 20 | View view = LayoutInflater.from(getContext()).inflate(R.layout.toast_layout,null); 21 | return view; 22 | } 23 | 24 | @Override 25 | protected int getDuration() { 26 | return Toast.LENGTH_LONG; 27 | } 28 | 29 | @Override 30 | protected void setToastGravity(Toast toast) { 31 | toast.setGravity(Gravity.BOTTOM,0,0); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/dialog/SystemWaitDialog.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.dialog; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | 7 | import com.ellen.basequickandroid.R; 8 | import com.ellen.basequickandroid.base.BaseDialog; 9 | 10 | public class SystemWaitDialog extends BaseDialog implements BaseDialog.ButterKnifeInterface { 11 | 12 | public SystemWaitDialog(Context context) { 13 | super(context); 14 | } 15 | 16 | @Override 17 | protected View onCreateView() { 18 | View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_wait,null); 19 | return view; 20 | } 21 | 22 | @Override 23 | protected void showBefore() { 24 | 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | 30 | } 31 | 32 | @Override 33 | protected void dissmissBefore() { 34 | 35 | } 36 | 37 | @Override 38 | protected void destory() { 39 | 40 | } 41 | 42 | @Override 43 | protected Boolean setCancelable() { 44 | return null; 45 | } 46 | 47 | @Override 48 | protected Boolean setCanceledOnTouchOutside() { 49 | return null; 50 | } 51 | 52 | @Override 53 | public void initButterKnife(View view) { 54 | 55 | } 56 | 57 | @Override 58 | public void unBindButterKnife() { 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/net/NetHelper.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.net; 2 | 3 | /** 4 | * 网络请求三步骤抽象封装 5 | * 6 | * 1.请求前: 7 | * 1.1 检测url是否规范 & 是否存在 8 | * 1.2 检测网络状态 9 | * 1.2.1 无网状态 ->提升用户,显示无网View,提供Retry机制 10 | * 1.2.2 流量状态 ->如果是视频音频,会提示用户,否则不会 11 | * 1.2.3 WiFi状态 ->不提示用户 12 | * 13 | * 2.请求中: 14 | * 2.1 如何抽象使用的库(OkHttp,Retrofit,Volley)? 15 | * 2.2 超时设置与处理(Callback接口) 16 | * 2.3 外码处理(分为细化模式&粗糙模式&自定义模式) 17 | * 18 | * 3.请求后: 19 | * 3.1 规定内码含义 20 | * 3.2 内码处理回调(便于修改 & 维护) 21 | * 22 | */ 23 | public abstract class NetHelper { 24 | 25 | //请求的网络地址 26 | private String url; 27 | private long connectTimeout = 0; 28 | private long readTimeout = 0; 29 | 30 | public NetHelper(String url,long connectTimeout,long readTimeout){ 31 | this.url = url; 32 | this.connectTimeout = connectTimeout; 33 | this.readTimeout = readTimeout; 34 | } 35 | 36 | //完成访问网络,并请求Json / XML数据 37 | public abstract String startRequest(String url,long connectTimeout,long readTimeout); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/net/NetInterface.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.net; 2 | 3 | public interface NetInterface { 4 | 5 | //网络切换至WiFi模式 6 | void switchWifi(); 7 | //网络切换至流量模式 8 | void switchFlow(); 9 | //网络切换至无网状态 10 | void switchNoNet(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/net/NetManager.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.net; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.IntentFilter; 7 | import android.net.ConnectivityManager; 8 | import android.net.NetworkInfo; 9 | 10 | import java.lang.ref.WeakReference; 11 | 12 | import static android.content.Context.CONNECTIVITY_SERVICE; 13 | import static android.net.ConnectivityManager.TYPE_WIFI; 14 | import static android.net.ConnectivityManager.TYPE_MOBILE; 15 | 16 | /** 17 | * 此类仅仅是提供网络监听的一种状态变化:WiFi状态 & 流量状态 & 无网状态 18 | */ 19 | public class NetManager { 20 | 21 | private WeakReference contextWeakReference; 22 | private NetworkChangeReceiver networkChangeReceiver; 23 | private final String NET_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; 24 | 25 | private NetInterface netInterface; 26 | 27 | public NetManager(Context context){ 28 | contextWeakReference = new WeakReference<>(context); 29 | } 30 | 31 | public void registerNetChangeReceiver(NetInterface netInterface){ 32 | this.netInterface = netInterface; 33 | //开启广播的监听 34 | IntentFilter intentFilter = new IntentFilter(); 35 | intentFilter.addAction(NET_ACTION); 36 | networkChangeReceiver = new NetworkChangeReceiver(this); 37 | contextWeakReference.get().registerReceiver(networkChangeReceiver, intentFilter); 38 | } 39 | 40 | public void unregisterNetChangerReceiver(){ 41 | contextWeakReference.get().unregisterReceiver(networkChangeReceiver); 42 | } 43 | 44 | private static class NetworkChangeReceiver extends BroadcastReceiver { 45 | 46 | private WeakReference netManagerWeakReference; 47 | 48 | public NetworkChangeReceiver(NetManager netManager){ 49 | netManagerWeakReference = new WeakReference<>(netManager); 50 | } 51 | 52 | @Override 53 | public void onReceive(Context context, Intent intent) { 54 | ConnectivityManager connectionManager = (ConnectivityManager) netManagerWeakReference.get() 55 | .contextWeakReference.get().getSystemService(CONNECTIVITY_SERVICE); 56 | NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo(); 57 | if (networkInfo != null && networkInfo.isAvailable()) { 58 | switch (networkInfo.getType()) { 59 | case TYPE_MOBILE: 60 | netManagerWeakReference.get().netInterface.switchFlow(); 61 | break; 62 | case TYPE_WIFI: 63 | netManagerWeakReference.get().netInterface.switchWifi(); 64 | break; 65 | default: 66 | break; 67 | } 68 | } else { 69 | netManagerWeakReference.get().netInterface.switchNoNet(); 70 | } 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/net/ReturnCode.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.net; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * 服务器外码内码状态定义 & 内码设置和状态对应定义 7 | * @param 服务器外码对应的状态封装类型 8 | * @param 服务器内码对应的类型 9 | * @param 服务器内码对应的状态封装类型 10 | */ 11 | public class ReturnCode { 12 | 13 | //定义外码 & 外码对应的状态 14 | private Map actionOuterCodeMap; 15 | //定义内码 & 内码对应的状态 16 | private Map actionInternalCodeMap; 17 | 18 | public ReturnCode(Map actionOuterCodeMap,Map actionInternalCodeMap){ 19 | this.actionOuterCodeMap = actionOuterCodeMap; 20 | this.actionInternalCodeMap = actionInternalCodeMap; 21 | } 22 | 23 | public ServerOuterCodeMessage startCheckOuterCode(String url,int outerCode){ 24 | return new ServerOuterCodeMessage(url,System.currentTimeMillis(),outerCode,actionOuterCodeMap.get(outerCode)); 25 | } 26 | 27 | public ServerInternalCodeMessage startCheckInternalCode(String url,E e){ 28 | return new ServerInternalCodeMessage(url,System.currentTimeMillis(),e,actionInternalCodeMap.get(e)); 29 | } 30 | 31 | /** 32 | * 服务器外码封装类 33 | */ 34 | public class ServerOuterCodeMessage { 35 | 36 | //记录url地址 37 | private String url; 38 | //记录处理的时间 39 | private long handlerTime; 40 | //记录外码 41 | private int outerCode; 42 | //记录外对应的状态 43 | private T handlerResult; 44 | 45 | public ServerOuterCodeMessage(String url, long handlerTime, int outerCode, T handlerResult) { 46 | this.url = url; 47 | this.handlerTime = handlerTime; 48 | this.outerCode = outerCode; 49 | this.handlerResult = handlerResult; 50 | } 51 | 52 | public String getUrl() { 53 | return url; 54 | } 55 | 56 | public void setUrl(String url) { 57 | this.url = url; 58 | } 59 | 60 | public long getHandlerTime() { 61 | return handlerTime; 62 | } 63 | 64 | public void setHandlerTime(long handlerTime) { 65 | this.handlerTime = handlerTime; 66 | } 67 | 68 | public int getOuterCode() { 69 | return outerCode; 70 | } 71 | 72 | public void setOuterCode(int outerCode) { 73 | this.outerCode = outerCode; 74 | } 75 | 76 | public T getHandlerResult() { 77 | return handlerResult; 78 | } 79 | 80 | public void setHandlerResult(T handlerResult) { 81 | this.handlerResult = handlerResult; 82 | } 83 | } 84 | 85 | /** 86 | * 服务器内码封装类 87 | */ 88 | public class ServerInternalCodeMessage{ 89 | 90 | //记录url地址 91 | private String url; 92 | //记录处理的时间 93 | private long handlerTime; 94 | //记录内码 95 | private E internalCode; 96 | //记录内码的状态 97 | private F handlerResult; 98 | 99 | public ServerInternalCodeMessage(String url, long handlerTime, E internalCode, F handlerResult) { 100 | this.url = url; 101 | this.handlerTime = handlerTime; 102 | this.internalCode = internalCode; 103 | this.handlerResult = handlerResult; 104 | } 105 | 106 | public String getUrl() { 107 | return url; 108 | } 109 | 110 | public void setUrl(String url) { 111 | this.url = url; 112 | } 113 | 114 | public long getHandlerTime() { 115 | return handlerTime; 116 | } 117 | 118 | public void setHandlerTime(long handlerTime) { 119 | this.handlerTime = handlerTime; 120 | } 121 | 122 | public E getInternalCode() { 123 | return internalCode; 124 | } 125 | 126 | public void setInternalCode(E internalCode) { 127 | this.internalCode = internalCode; 128 | } 129 | 130 | public F getHandlerResult() { 131 | return handlerResult; 132 | } 133 | 134 | public void setHandlerResult(F handlerResult) { 135 | this.handlerResult = handlerResult; 136 | } 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/net/ReturnCodeHandler.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.net; 2 | 3 | public class ReturnCodeHandler{ 4 | private ReturnCode returnCode; 5 | 6 | public ReturnCodeHandler(ReturnCode returnCode){ 7 | this.returnCode = returnCode; 8 | } 9 | 10 | public void checkOuterCode(String url,int outerCode,OuterCodeHandlerCallback outerCodeHandlerCallback){ 11 | outerCodeHandlerCallback.outerCodeHandlerCallback(returnCode.startCheckOuterCode(url,outerCode)); 12 | } 13 | 14 | public void checkInternalCode(String url,Object internalCode,InternalCodeHandlerCallback internalCodeHandlerCallback){ 15 | internalCodeHandlerCallback.internalCodeHandlerCallback(returnCode.startCheckInternalCode(url,internalCode)); 16 | } 17 | 18 | public interface OuterCodeHandlerCallback{ 19 | void outerCodeHandlerCallback(ReturnCode.ServerOuterCodeMessage serverOuterCodeMessage); 20 | } 21 | 22 | public interface InternalCodeHandlerCallback{ 23 | void internalCodeHandlerCallback(ReturnCode.ServerInternalCodeMessage serverInternalCodeMessage); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/save/key_value/BaseKeyValueHelper.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.save.key_value; 2 | 3 | /** 4 | * SharedPreference或者MMKV的抽象层 5 | */ 6 | public abstract class BaseKeyValueHelper { 7 | 8 | private String name; 9 | 10 | public BaseKeyValueHelper(String name){ 11 | this.name = name; 12 | } 13 | 14 | //存储获取非加密数据 15 | public abstract void save(String key,Object value); 16 | public abstract Object getValue(String key,Object defaultValue); 17 | 18 | //存储获取加密数据 19 | public abstract void safeSave(String encryptionString,String key,Object value); 20 | public abstract Object safeGetValue(String encryptionString,String key,Object defaultValue); 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/save/key_value/MMKVHelper.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.save.key_value; 2 | 3 | import com.tencent.mmkv.MMKV; 4 | 5 | public class MMKVHelper extends BaseKeyValueHelper { 6 | 7 | private MMKV mmkv; 8 | 9 | public MMKVHelper(String name) { 10 | super(name); 11 | mmkv = MMKV.mmkvWithID(name); 12 | } 13 | 14 | @Override 15 | public void save(String key, Object value) { 16 | if (value instanceof String) { 17 | mmkv.encode(key,(String)value); 18 | } else if (value instanceof Integer) { 19 | mmkv.encode(key,(Integer) value); 20 | } else if (value instanceof Boolean) { 21 | mmkv.encode(key,(Boolean) value); 22 | } else if (value instanceof Float) { 23 | mmkv.encode(key,(Float) value); 24 | } else if (value instanceof Long) { 25 | mmkv.encode(key,(Long) value); 26 | } else { 27 | mmkv.encode(key,(String)value); 28 | } 29 | } 30 | 31 | @Override 32 | public Object getValue(String key, Object defaultValue) { 33 | Object value; 34 | if (defaultValue instanceof String) { 35 | value = mmkv.decodeString(key); 36 | if(value == null) value = defaultValue; 37 | } else if (defaultValue instanceof Integer) { 38 | value = mmkv.getInt(key, (Integer) defaultValue); 39 | } else if (defaultValue instanceof Boolean) { 40 | value = mmkv.getBoolean(key, (Boolean) defaultValue); 41 | } else if (defaultValue instanceof Float) { 42 | value = mmkv.getFloat(key, (Float) defaultValue ); 43 | } else if (defaultValue instanceof Long) { 44 | value = mmkv.getLong(key, (Long) defaultValue); 45 | } else { 46 | value = mmkv.getString(key, (String) defaultValue); 47 | } 48 | return value; 49 | } 50 | 51 | @Override 52 | public void safeSave(String encryptionString, String key, Object value) { 53 | save(encryptionString + key,value); 54 | } 55 | 56 | @Override 57 | public Object safeGetValue(String encryptionString, String key, Object defaultValue) { 58 | return getValue(encryptionString + key,defaultValue); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/save/key_value/SharePreferenceHelper.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.save.key_value; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | public class SharePreferenceHelper extends BaseKeyValueHelper { 7 | 8 | private SharedPreferences sharedPreferences; 9 | /* 10 | * 保存手机里面的名字 11 | */private SharedPreferences.Editor editor; 12 | 13 | 14 | public SharePreferenceHelper(Context context, String fileName) { 15 | super(fileName); 16 | sharedPreferences = context.getSharedPreferences(fileName, 17 | Context.MODE_PRIVATE); 18 | editor = sharedPreferences.edit(); 19 | } 20 | 21 | @Override 22 | public void save(String key, Object value) { 23 | if (value instanceof String) { 24 | editor.putString(key, (String) value); 25 | } else if (value instanceof Integer) { 26 | editor.putInt(key, (Integer) value); 27 | } else if (value instanceof Boolean) { 28 | editor.putBoolean(key, (Boolean) value); 29 | } else if (value instanceof Float) { 30 | editor.putFloat(key, (Float) value); 31 | } else if (value instanceof Long) { 32 | editor.putLong(key, (Long) value); 33 | } else { 34 | editor.putString(key, value.toString()); 35 | } 36 | editor.commit(); 37 | } 38 | 39 | @Override 40 | public Object getValue(String key, Object defaultObject) { 41 | if (defaultObject instanceof String) { 42 | return sharedPreferences.getString(key, (String) defaultObject); 43 | } else if (defaultObject instanceof Integer) { 44 | return sharedPreferences.getInt(key, (Integer) defaultObject); 45 | } else if (defaultObject instanceof Boolean) { 46 | return sharedPreferences.getBoolean(key, (Boolean) defaultObject); 47 | } else if (defaultObject instanceof Float) { 48 | return sharedPreferences.getFloat(key, (Float) defaultObject); 49 | } else if (defaultObject instanceof Long) { 50 | return sharedPreferences.getLong(key, (Long) defaultObject); 51 | } else { 52 | return sharedPreferences.getString(key, null); 53 | } 54 | } 55 | 56 | @Override 57 | public void safeSave(String encryptionString, String key, Object value) { 58 | save(encryptionString + key, value); 59 | } 60 | 61 | @Override 62 | public Object safeGetValue(String encryptionString, String key, Object defaultObject) { 63 | String newKey = encryptionString + key; 64 | return getValue(newKey, defaultObject); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/BaseMvpActivity.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.ellen.basequickandroid.base.BaseActivity; 7 | import com.ellen.basequickandroid.structure.mvp.basemvp.BasePresenter; 8 | 9 | public abstract class BaseMvpActivity

extends BaseActivity { 10 | protected P mPresenter; 11 | 12 | @Override 13 | protected void onCreate(@Nullable Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | initMVP(); 16 | } 17 | 18 | protected abstract void initMVP(); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/basemvp/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.basemvp; 2 | 3 | public interface BaseModel { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/basemvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.basemvp; 2 | 3 | public class BasePresenter { 4 | 5 | //Model层 6 | public M mModel; 7 | //View层 8 | public V mView; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/basemvp/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.basemvp; 2 | 3 | //View层 4 | public interface BaseView{ 5 | 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/demo/login/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.demo.login; 2 | 3 | import android.util.Log; 4 | import android.view.View; 5 | import android.widget.Button; 6 | 7 | import com.ellen.basequickandroid.R; 8 | import com.ellen.basequickandroid.base.BaseActivity; 9 | import com.ellen.basequickandroid.base.BaseToast; 10 | import com.ellen.basequickandroid.dialog.AutoToast; 11 | import com.ellen.basequickandroid.structure.mvp.BaseMvpActivity; 12 | 13 | import butterknife.BindView; 14 | import butterknife.ButterKnife; 15 | import butterknife.OnClick; 16 | 17 | public class LoginActivity extends BaseMvpActivity implements LoginAgreement.LoginAgreementView, BaseActivity.ButterKnifeInterface { 18 | 19 | @BindView(R.id.bt) 20 | Button btLogin; 21 | 22 | @OnClick(R.id.bt) 23 | void onClick(View view){ 24 | login("ellen","1234"); 25 | AutoToast autoToast = new AutoToast(this); 26 | autoToast.show(); 27 | } 28 | 29 | @Override 30 | protected void setStatus() { 31 | 32 | } 33 | 34 | @Override 35 | protected int setLayoutId() { 36 | return R.layout.activity_login; 37 | } 38 | 39 | @Override 40 | protected void initView() { 41 | 42 | } 43 | 44 | @Override 45 | protected void initData() { 46 | 47 | } 48 | 49 | @Override 50 | protected void destory() { 51 | 52 | } 53 | 54 | @Override 55 | protected Boolean isSetVerticalScreen() { 56 | return null; 57 | } 58 | 59 | @Override 60 | public void login(String account, String password) { 61 | if(checkAccountPassword(account,password)){ 62 | mPresenter.login(account,password); 63 | } 64 | } 65 | 66 | @Override 67 | public boolean checkAccountPassword(String account, String password) { 68 | return true; 69 | } 70 | 71 | @Override 72 | public void loginSuccess(String json) { 73 | btLogin.setText("登陆成功"); 74 | } 75 | 76 | @Override 77 | public void loginFailure(String errMessage) { 78 | btLogin.setText("登陆失败"); 79 | } 80 | 81 | @Override 82 | public void initButterKnife() { 83 | ButterKnife.bind(this); 84 | } 85 | 86 | @Override 87 | protected void initMVP() { 88 | mPresenter = new LoginPresenter(); 89 | mPresenter.mModel = new LoginModel(); 90 | mPresenter.mView = this; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/demo/login/LoginAgreement.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.demo.login; 2 | 3 | import com.ellen.basequickandroid.structure.mvp.basemvp.BaseModel; 4 | import com.ellen.basequickandroid.structure.mvp.basemvp.BasePresenter; 5 | import com.ellen.basequickandroid.structure.mvp.basemvp.BaseView; 6 | 7 | public interface LoginAgreement { 8 | 9 | //协议化M层 10 | interface LoginAgreementModel extends BaseModel{ 11 | boolean login(String account,String password); 12 | } 13 | 14 | //协议化View层 15 | interface LoginAgreementView extends BaseView{ 16 | //登陆的时候回调 17 | void login(String account,String password); 18 | //验证账号密码的规范 19 | boolean checkAccountPassword(String account,String password); 20 | //登陆成功回调,json为服务器返回的Json 21 | void loginSuccess(String json); 22 | //登陆失败回调,errMessage为错误信息 23 | void loginFailure(String errMessage); 24 | } 25 | 26 | abstract class LoginAgreementPresenter extends BasePresenter{ 27 | protected abstract void login(String account,String password); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/demo/login/LoginModel.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.demo.login; 2 | 3 | public class LoginModel implements LoginAgreement.LoginAgreementModel { 4 | 5 | @Override 6 | public boolean login(String account, String password) { 7 | return true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/structure/mvp/demo/login/LoginPresenter.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.structure.mvp.demo.login; 2 | 3 | import io.reactivex.Observable; 4 | import io.reactivex.ObservableEmitter; 5 | import io.reactivex.ObservableOnSubscribe; 6 | import io.reactivex.Observer; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | import io.reactivex.disposables.Disposable; 9 | import io.reactivex.schedulers.Schedulers; 10 | 11 | public class LoginPresenter extends LoginAgreement.LoginAgreementPresenter { 12 | 13 | @Override 14 | protected void login(final String account, final String password) { 15 | 16 | Observable.create(new ObservableOnSubscribe() { 17 | @Override 18 | public void subscribe(ObservableEmitter emitter) throws Exception { 19 | emitter.onNext(mModel.login(account,password)); 20 | emitter.onComplete(); 21 | } 22 | }).subscribeOn(Schedulers.io()) 23 | .observeOn(AndroidSchedulers.mainThread()) 24 | .subscribe(new Observer() { 25 | @Override 26 | public void onSubscribe(Disposable d) { 27 | 28 | } 29 | 30 | @Override 31 | public void onNext(Boolean value) { 32 | if(value){ 33 | //完成登陆 34 | mView.loginSuccess(""); 35 | }else { 36 | //失败登陆 37 | mView.loginFailure("sdsd"); 38 | } 39 | } 40 | 41 | @Override 42 | public void onError(Throwable e) { 43 | 44 | } 45 | 46 | @Override 47 | public void onComplete() { 48 | 49 | } 50 | }); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/BaseLog.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.util.Log; 4 | 5 | public class BaseLog { 6 | 7 | private static boolean isLog = false; 8 | 9 | public static boolean isIsLog() { 10 | return isLog; 11 | } 12 | 13 | public static void setIsLog(boolean isLog) { 14 | BaseLog.isLog = isLog; 15 | } 16 | 17 | public static void e(String tag,String cotent){ 18 | if(isIsLog()){ 19 | Log.e(tag,cotent); 20 | } 21 | } 22 | 23 | public static void d(String tag,String content){ 24 | if(isIsLog()){ 25 | Log.d(tag,content); 26 | } 27 | } 28 | 29 | public static void i(String tag,String content){ 30 | if(isIsLog()){ 31 | Log.i(tag,content); 32 | } 33 | } 34 | 35 | public static void v(String tag,String content){ 36 | if(isIsLog()){ 37 | Log.v(tag,content); 38 | } 39 | } 40 | 41 | public static void w(String tag,String content){ 42 | if(isIsLog()){ 43 | Log.w(tag,content); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/BitmapUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Color; 8 | import android.graphics.PixelFormat; 9 | import android.graphics.drawable.Drawable; 10 | import android.net.Uri; 11 | 12 | import java.io.File; 13 | import java.io.FileNotFoundException; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | 18 | /** 19 | * 20 | * 1.将Drawable转化为Bitmap 21 | * 2.获取到纯色Bitmap 22 | * 23 | */ 24 | public class BitmapUtils { 25 | 26 | //Drawable -> Bitmap 27 | public static Bitmap drawableToBitmap(Drawable drawable) { 28 | // 取 drawable 的长宽 29 | int w = drawable.getIntrinsicWidth(); 30 | int h = drawable.getIntrinsicHeight(); 31 | // 取 drawable 的颜色格式 32 | Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 33 | : Bitmap.Config.RGB_565; 34 | // 建立对应 bitmap 35 | Bitmap bitmap = Bitmap.createBitmap(w, h, config); 36 | // 建立对应 bitmap 的画布 37 | Canvas canvas = new Canvas(bitmap); 38 | drawable.setBounds(0, 0, w, h); 39 | // 把 drawable 内容画到画布中 40 | drawable.draw(canvas); 41 | return bitmap; 42 | } 43 | 44 | //获取到纯色Bitmap 45 | public static Bitmap getColorBitmap(int width,int height,String colorString){ 46 | Bitmap bitmap = Bitmap.createBitmap(width, height, 47 | Bitmap.Config.ARGB_8888); 48 | bitmap.eraseColor(Color.parseColor(colorString));//填充颜色 49 | return bitmap; 50 | } 51 | 52 | //通过本地地址获取到Bitmap 53 | public static Bitmap getSampledBitmap(String filePath, int reqWidth, int reqHeight) { 54 | BitmapFactory.Options options = new BitmapFactory.Options(); 55 | options.inJustDecodeBounds = true; 56 | options.inPreferredConfig = Bitmap.Config.ARGB_8888; 57 | BitmapFactory.decodeFile(filePath, options); 58 | int inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 59 | options.inSampleSize = inSampleSize; 60 | options.inJustDecodeBounds = false; 61 | return BitmapFactory.decodeFile(filePath, options); 62 | } 63 | 64 | public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 65 | // Raw height and width of image 66 | final int height = options.outHeight; 67 | final int width = options.outWidth; 68 | int inSampleSize = 1; 69 | 70 | if (height > reqHeight || width > reqWidth) { 71 | 72 | final int halfHeight = height / 2; 73 | final int halfWidth = width / 2; 74 | 75 | // Calculate the largest inSampleSize value that is a power of 2 and keeps both 76 | // height and width larger than the requested height and width. 77 | while ((halfHeight / inSampleSize) >= reqHeight 78 | && (halfWidth / inSampleSize) >= reqWidth) { 79 | inSampleSize *= 2; 80 | } 81 | } 82 | 83 | return inSampleSize; 84 | } 85 | 86 | //保存Bitmap到本地 87 | public static String saveBitmap(Bitmap bm, String filePath) { 88 | File f = new File(filePath); 89 | if (f.exists()) { 90 | f.delete(); 91 | } 92 | try { 93 | FileOutputStream out = new FileOutputStream(f); 94 | bm.compress(Bitmap.CompressFormat.PNG, 90, out); 95 | out.flush(); 96 | out.close(); 97 | return f.getPath(); 98 | } catch (FileNotFoundException e) { 99 | e.printStackTrace(); 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | } 103 | // System.out.println("保存文件--->" + f.getAbsolutePath()); 104 | return filePath; 105 | } 106 | 107 | public static Bitmap getThumbnailByPath(String path, int size, Context context) throws IOException { 108 | Uri userPickedUri = Uri.fromFile(new File(path)); 109 | return getThumbnailByUri(userPickedUri,size,context); 110 | } 111 | 112 | //得到本地图片对应的缩图 113 | public static Bitmap getThumbnailByUri(Uri uri, int size, Context context) throws IOException { 114 | InputStream input = context.getContentResolver().openInputStream(uri); 115 | //配置BitmapFactory.Options,inJustDecodeBounds设为true,以获取图片的宽高 116 | BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options(); 117 | onlyBoundsOptions.inJustDecodeBounds = true; 118 | onlyBoundsOptions.inDither=true;//optional 119 | onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional 120 | 121 | //计算inSampleSize缩放比例 122 | BitmapFactory.decodeStream(input, null, onlyBoundsOptions); 123 | input.close(); 124 | if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) 125 | return null; 126 | int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth; 127 | double ratio = (originalSize > size) ? (originalSize / size) : 1.0; 128 | //获取到缩放比例后,再次设置BitmapFactory.Options,获取图片缩略图 129 | BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); 130 | bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio); 131 | bitmapOptions.inDither=true;//optional 132 | bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional 133 | input = context.getContentResolver().openInputStream(uri); 134 | Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions); 135 | input.close(); 136 | return bitmap; 137 | } 138 | 139 | /** 140 | * 将double的比例采用近似值的方式转为int 141 | * @param ratio 142 | * @return 143 | */ 144 | private static int getPowerOfTwoForSampleRatio(double ratio){ 145 | int k = Integer.highestOneBit((int)Math.floor(ratio)); 146 | if(k==0) return 1; 147 | else return k; 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/ContentProviderUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.provider.MediaStore; 6 | 7 | import com.ellen.basequickandroid.util.collectionutil.ArrangeInterface; 8 | 9 | import java.io.File; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * 内容提供者工具类 15 | * 1.获取本地所有的图片 16 | * 2.获取本地所有的视频 17 | * 3.获取本地所有的音频 18 | * 19 | * 使用之前请申请文件读写权限 20 | */ 21 | public class ContentProviderUtils { 22 | 23 | //通过内容提供者获取本地所有图片的地址集合 24 | public static List getIamgePathList(Context context) { 25 | Cursor cur = context.getContentResolver() 26 | .query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 27 | new String[]{MediaStore.Images.Media.DATA}, 28 | "", 29 | new String[]{}, 30 | MediaStore.Images.Media.DATE_MODIFIED + " DESC"); 31 | List imagePathList = new ArrayList<>(cur.getCount()); 32 | if (cur.moveToFirst()) { 33 | while (!cur.isAfterLast()) { 34 | //过滤掉空的图片 35 | if (new File(cur.getString(0)).exists()) { 36 | imagePathList.add(cur.getString(0)); 37 | } 38 | cur.moveToNext(); 39 | } 40 | } 41 | cur.close(); 42 | return imagePathList; 43 | } 44 | 45 | //通过内容提供者获取本地所有的图片地址集合 46 | public static List getVideoPathList(Context context) { 47 | String[] projection = new String[]{ 48 | MediaStore.Video.Media.DATA, 49 | MediaStore.Video.Media.DURATION 50 | }; 51 | Cursor cursor = context.getContentResolver().query( 52 | MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, 53 | null, null); 54 | List videoPathList = new ArrayList<>(cursor.getCount()); 55 | while (cursor.moveToNext()) { 56 | String path = cursor 57 | .getString(cursor 58 | .getColumnIndexOrThrow(MediaStore.Video.Media.DATA)); 59 | long duration = cursor 60 | .getInt(cursor 61 | .getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)); 62 | if (duration > 0) { 63 | //过滤掉时长为0的视频 64 | videoPathList.add(path); 65 | } 66 | } 67 | cursor.close(); 68 | return videoPathList; 69 | } 70 | 71 | public static List getMusicPathList(Context context) { 72 | List musicList = new ArrayList<>(); 73 | Cursor c = null; 74 | c = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, 75 | MediaStore.Audio.Media.DEFAULT_SORT_ORDER); 76 | 77 | while (c.moveToNext()) { 78 | String path = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));// 路径 79 | String name = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)); // 歌曲名 80 | String album = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)); // 专辑 81 | String artist = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)); // 作者 82 | long size = c.getLong(c.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));// 大小 83 | int duration = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));// 时长 84 | int musicId = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));// 歌曲的id 85 | int albumId = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID)); 86 | if (duration != 0) { 87 | Music music = new Music(); 88 | music.setPath(path); 89 | music.setName(name); 90 | music.setAlbum(album); 91 | music.setArtist(artist); 92 | music.setSize(size); 93 | music.setDuration(duration); 94 | music.setMusicId(musicId); 95 | music.setAlbumId(albumId); 96 | musicList.add(music); 97 | } 98 | } 99 | return musicList; 100 | } 101 | 102 | 103 | public static class Music implements ArrangeInterface { 104 | 105 | private String name; 106 | private String path; 107 | private String album; 108 | private long size; 109 | private int musicId; 110 | private String artist; 111 | 112 | public String getArtist() { 113 | return artist; 114 | } 115 | 116 | public void setArtist(String artist) { 117 | this.artist = artist; 118 | } 119 | 120 | public long getDuration() { 121 | return duration; 122 | } 123 | 124 | public void setDuration(long duration) { 125 | this.duration = duration; 126 | } 127 | 128 | private long duration; 129 | 130 | public String getAlbum() { 131 | return album; 132 | } 133 | 134 | public void setAlbum(String album) { 135 | this.album = album; 136 | } 137 | 138 | public long getSize() { 139 | return size; 140 | } 141 | 142 | public void setSize(long size) { 143 | this.size = size; 144 | } 145 | 146 | public int getMusicId() { 147 | return musicId; 148 | } 149 | 150 | public void setMusicId(int musicId) { 151 | this.musicId = musicId; 152 | } 153 | 154 | public int getAlbumId() { 155 | return albumId; 156 | } 157 | 158 | public void setAlbumId(int albumId) { 159 | this.albumId = albumId; 160 | } 161 | 162 | private int albumId; 163 | 164 | public String getPath() { 165 | return path; 166 | } 167 | 168 | public void setPath(String path) { 169 | this.path = path; 170 | } 171 | 172 | public String getName() { 173 | return name; 174 | } 175 | 176 | public void setName(String name) { 177 | this.name = name; 178 | } 179 | 180 | @Override 181 | public boolean identical(Music music) { 182 | return this.getArtist().equals(music.getArtist()); 183 | } 184 | } 185 | 186 | 187 | } 188 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/ImageChooseUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.provider.MediaStore; 9 | import android.support.annotation.Nullable; 10 | import android.support.v4.content.FileProvider; 11 | 12 | import java.io.File; 13 | import java.lang.ref.WeakReference; 14 | 15 | /** 16 | * 17 | * 提示,在使用之前一定要获取文件读写权限。 18 | * 19 | * 手机图片选择工具类 20 | * 1.选择相册图片 21 | * 2.选择使用相机进行拍摄(适配Android N) 22 | * 23 | * 使用前请配置: 24 | * 【1】在AndroidManifest.xml中配置 25 | * 30 | * 33 | * 34 | * 35 | * 【2】在res下新建一个xml文件夹,并且配置一个file_paths.xml文件 36 | * 37 | * 38 | * 39 | * 40 | * 41 | */ 42 | public class ImageChooseUtils { 43 | 44 | private WeakReference activityWeakReference; 45 | private WeakReference contextWeakReference; 46 | private ChooseImageCallback chooseImageCallback; 47 | private int requestCode; 48 | private String chooseImagePath; 49 | private boolean isChooseSystemAlbum = false; 50 | 51 | public ImageChooseUtils(Context context,Activity activity,ChooseImageCallback chooseImageCallback){ 52 | activityWeakReference = new WeakReference<>(activity); 53 | contextWeakReference = new WeakReference<>(context); 54 | this.chooseImageCallback = chooseImageCallback; 55 | } 56 | 57 | //调用系统相机 58 | public void toCameraActivity(String imageName,String authority,int requestCode) { 59 | this.requestCode = requestCode; 60 | Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 61 | File file = new File(contextWeakReference.get().getExternalCacheDir(), imageName + ".png"); 62 | chooseImagePath = file.getAbsolutePath(); 63 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 64 | openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, 65 | FileProvider.getUriForFile(contextWeakReference.get(), authority, file)); 66 | } else { 67 | openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); 68 | } 69 | activityWeakReference.get().startActivityForResult(openCameraIntent, requestCode); 70 | } 71 | 72 | //调用系统相册 73 | public void toSystemAlbum(int requestCode){ 74 | this.requestCode = requestCode; 75 | isChooseSystemAlbum = true; 76 | Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI); 77 | photoPickerIntent.setType("image/*"); 78 | activityWeakReference.get().startActivityForResult(photoPickerIntent, requestCode); 79 | } 80 | 81 | public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data){ 82 | if(this.requestCode == requestCode){ 83 | if(resultCode == Activity.RESULT_OK){ 84 | if(isChooseSystemAlbum){ 85 | //这里是选择了系统相册的逻辑 86 | Uri uri = data.getData(); 87 | chooseImagePath = UriUtils.getRealFilePath(contextWeakReference.get(),uri); 88 | chooseImageCallback.successs(chooseImagePath); 89 | }else { 90 | //这里是选择了相机的逻辑 91 | chooseImageCallback.successs(chooseImagePath); 92 | } 93 | }else { 94 | chooseImageCallback.failure(); 95 | } 96 | } 97 | } 98 | 99 | public interface ChooseImageCallback{ 100 | void successs(String path); 101 | void failure(); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/PermissionUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.os.Build; 8 | import android.support.annotation.NonNull; 9 | import android.support.v4.app.ActivityCompat; 10 | 11 | import java.lang.ref.WeakReference; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | //权限申请工具类 17 | public class PermissionUtils { 18 | 19 | private int requestCode; 20 | private List permissionList; 21 | private WeakReference weakReferenceActivity; 22 | private WeakReference weakReferenceContext; 23 | private PermissionCallback permissionCallback; 24 | 25 | public PermissionUtils(Activity activity, Context context){ 26 | weakReferenceActivity = new WeakReference<>(activity); 27 | weakReferenceContext = new WeakReference<>(context); 28 | } 29 | 30 | /** 31 | * 32 | * @param permissionString 33 | * @return false:具有该权限 34 | */ 35 | private boolean checkPermission(String permissionString){ 36 | boolean falg = false; 37 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { 38 | if (ActivityCompat.checkSelfPermission(weakReferenceContext.get(), permissionString) != PackageManager.PERMISSION_GRANTED) { 39 | falg = true; 40 | } 41 | }else { 42 | falg = false; 43 | } 44 | return falg; 45 | } 46 | 47 | public void checkPermissions(String[] permissionArray,int requestCode,PermissionCallback permissionCallback){ 48 | this.permissionList = Arrays.asList(permissionArray); 49 | this.requestCode = requestCode; 50 | this.permissionCallback = permissionCallback; 51 | boolean falg = false; 52 | for(String permissionString:permissionList){ 53 | falg = checkPermission(permissionString); 54 | if(falg){ 55 | break; 56 | } 57 | } 58 | 59 | //申请权限 60 | if(falg) { 61 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 62 | weakReferenceActivity.get().requestPermissions(permissionArray,requestCode); 63 | } 64 | }else { 65 | this.permissionCallback.success(); 66 | } 67 | } 68 | 69 | public void checkPermissions(List permissionList,int requestCode,PermissionCallback permissionCallback){ 70 | this.permissionList = permissionList; 71 | this.requestCode = requestCode; 72 | this.permissionCallback = permissionCallback; 73 | boolean falg = false; 74 | for(String permissionString:permissionList){ 75 | falg = checkPermission(permissionString); 76 | if(falg){ 77 | break; 78 | } 79 | } 80 | 81 | //申请权限 82 | if(falg) { 83 | String[] permissionArray = new String[permissionList.size()]; 84 | permissionList.toArray(permissionArray); 85 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 86 | weakReferenceActivity.get().requestPermissions(permissionArray,requestCode); 87 | } 88 | }else { 89 | this.permissionCallback.success(); 90 | } 91 | } 92 | 93 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 94 | if(this.requestCode == requestCode){ 95 | int sum = 0; 96 | for (int i = 0; i < permissions.length; i++) { 97 | if(grantResults[i] == 0){ 98 | sum++; 99 | } 100 | } 101 | if(sum == this.permissionList.size()){ 102 | //成功 103 | permissionCallback.success(); 104 | }else { 105 | //失败 106 | permissionCallback.failure(); 107 | } 108 | } 109 | } 110 | 111 | //检测文件读写权限 112 | public void startCheckFileReadWritePermission(int requestCode,PermissionCallback permissionCallback){ 113 | List permissionList = new ArrayList<>(); 114 | permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); 115 | permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE); 116 | checkPermissions(permissionList,requestCode,permissionCallback); 117 | } 118 | 119 | 120 | public interface PermissionCallback{ 121 | void success(); 122 | void failure(); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | public class ToastUtils { 7 | 8 | public static void toast(Context context,String contetnt){ 9 | Toast.makeText(context,contetnt,Toast.LENGTH_SHORT).show(); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/UriUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | import android.provider.MediaStore; 8 | 9 | public class UriUtils { 10 | 11 | public static String getRealFilePath(final Context context, final Uri uri ) { 12 | if ( null == uri ) return null; 13 | final String scheme = uri.getScheme(); 14 | String data = null; 15 | if ( scheme == null ) 16 | data = uri.getPath(); 17 | else if ( ContentResolver.SCHEME_FILE.equals( scheme ) ) { 18 | data = uri.getPath(); 19 | } else if ( ContentResolver.SCHEME_CONTENT.equals( scheme ) ) { 20 | Cursor cursor = context.getContentResolver().query( uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null ); 21 | if ( null != cursor ) { 22 | if ( cursor.moveToFirst() ) { 23 | int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA ); 24 | if ( index > -1 ) { 25 | data = cursor.getString( index ); 26 | } 27 | } 28 | cursor.close(); 29 | } 30 | } 31 | return data; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/WebViewSetttingUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util; 2 | 3 | import android.webkit.WebView; 4 | 5 | public class WebViewSetttingUtils { 6 | 7 | public static void loadUrl(WebView webView,String url){ 8 | //通过WebView的WebSetting类设置能够执行JavaScript的脚本 9 | webView.getSettings().setJavaScriptEnabled(true); 10 | webView.loadUrl(url); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/collectionutil/ArrangeInterface.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.collectionutil; 2 | 3 | public interface ArrangeInterface { 4 | boolean identical(T t); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/collectionutil/CollectionUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.collectionutil; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class CollectionUtils { 7 | 8 | //对某个集合进行排序 9 | public static List sort(List eList) { 10 | List copyList = new ArrayList<>(); 11 | for(E e:eList){ 12 | copyList.add(e); 13 | } 14 | E e = eList.get(0); 15 | if (!(e instanceof CompareableInterface)) { 16 | //抛出异常 -> 说明它没有实现比较器接口 17 | throw new CompareableException("", "your class Not Implemented CompareableInterface"); 18 | } 19 | //使用冒泡排序进行排序 20 | for (int i = 0; i < copyList.size(); i++) { 21 | for (int j = i + 1; j < copyList.size(); j++) { 22 | CompareableInterface iCompareable = (CompareableInterface) copyList.get(i); 23 | if (iCompareable.compareTo(copyList.get(j)) >= 0) { 24 | E e1 = copyList.get(i); 25 | copyList.set(i, copyList.get(j)); 26 | copyList.set(j, e1); 27 | } 28 | } 29 | } 30 | return copyList; 31 | } 32 | 33 | //对某个集合进行整理算法 34 | public static List> arrange(List eList){ 35 | E e = eList.get(0); 36 | if (!(e instanceof ArrangeInterface)) { 37 | //抛出异常 -> 说明它没有实现归类整理器接口 38 | throw new CompareableException("", "your class Not Implemented ArrangeInterface"); 39 | } 40 | if(eList == null || eList.size() == 0){ 41 | //执行这里说明无法进行整理归类 42 | return null; 43 | } 44 | List copyList = new ArrayList<>(); 45 | List> listList = new ArrayList<>(); 46 | for(E e1:eList){ 47 | copyList.add(e1); 48 | } 49 | for(int i = 0;i < eList.size();i++){ 50 | boolean isAddList = true; 51 | for(List list:listList){ 52 | E eCompare = list.get(0); 53 | ArrangeInterface arrangeInterface = (ArrangeInterface) eList.get(i); 54 | boolean falg = arrangeInterface.identical(eCompare); 55 | if(falg){ 56 | //是相同的 57 | list.add(eList.get(i)); 58 | isAddList = false; 59 | break; 60 | } 61 | } 62 | if(isAddList){ 63 | List eList1 = new ArrayList<>(); 64 | eList1.add(eList.get(i)); 65 | listList.add(eList1); 66 | } 67 | } 68 | return listList; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/collectionutil/CompareableException.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.collectionutil; 2 | 3 | public class CompareableException extends RuntimeException{ 4 | 5 | private String errorCode; 6 | private String errorMessage; 7 | 8 | public CompareableException(String errorCode,String errorMessage){ 9 | this.errorCode = errorCode; 10 | this.errorMessage = errorMessage; 11 | } 12 | 13 | @Override 14 | public String getMessage() { 15 | return errorCode+""+errorMessage; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/collectionutil/CompareableInterface.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.collectionutil; 2 | 3 | //用于比较器 4 | public interface CompareableInterface { 5 | //比较二者的大小 0 相同,正值代表外面大于里面,负值代表里面大于外面 6 | int compareTo(T t); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/statusutil/OSUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.statusutil; 2 | 3 | import android.os.Build; 4 | import android.text.TextUtils; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | 10 | public class OSUtils { 11 | 12 | public static final String ROM_MIUI = "MIUI"; 13 | public static final String ROM_EMUI = "EMUI"; 14 | public static final String ROM_FLYME = "FLYME"; 15 | public static final String ROM_OPPO = "OPPO"; 16 | public static final String ROM_SMARTISAN = "SMARTISAN"; 17 | public static final String ROM_VIVO = "VIVO"; 18 | public static final String ROM_QIKU = "QIKU"; 19 | 20 | private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name"; 21 | private static final String KEY_VERSION_EMUI = "ro.build.version.emui"; 22 | private static final String KEY_VERSION_OPPO = "ro.build.version.opporom"; 23 | private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version"; 24 | private static final String KEY_VERSION_VIVO = "ro.vivo.os.version"; 25 | 26 | private static String sName; 27 | private static String sVersion; 28 | 29 | public static boolean isEmui() { 30 | return check(ROM_EMUI); 31 | } 32 | 33 | public static boolean isMiui() { 34 | return check(ROM_MIUI); 35 | } 36 | 37 | public static boolean isVivo() { 38 | return check(ROM_VIVO); 39 | } 40 | 41 | public static boolean isOppo() { 42 | return check(ROM_OPPO); 43 | } 44 | 45 | public static boolean isFlyme() { 46 | return check(ROM_FLYME); 47 | } 48 | 49 | public static boolean is360() { 50 | return check(ROM_QIKU) || check("360"); 51 | } 52 | 53 | public static boolean isSmartisan() { 54 | return check(ROM_SMARTISAN); 55 | } 56 | 57 | public static String getName() { 58 | if (sName == null) { 59 | check(""); 60 | } 61 | return sName; 62 | } 63 | 64 | public static String getVersion() { 65 | if (sVersion == null) { 66 | check(""); 67 | } 68 | return sVersion; 69 | } 70 | 71 | public static boolean check(String rom) { 72 | if (sName != null) { 73 | return sName.equals(rom); 74 | } 75 | 76 | if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) { 77 | sName = ROM_MIUI; 78 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) { 79 | sName = ROM_EMUI; 80 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) { 81 | sName = ROM_OPPO; 82 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) { 83 | sName = ROM_VIVO; 84 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) { 85 | sName = ROM_SMARTISAN; 86 | } else { 87 | sVersion = Build.DISPLAY; 88 | if (sVersion.toUpperCase().contains(ROM_FLYME)) { 89 | sName = ROM_FLYME; 90 | } else { 91 | sVersion = Build.UNKNOWN; 92 | sName = Build.MANUFACTURER.toUpperCase(); 93 | } 94 | } 95 | return sName.equals(rom); 96 | } 97 | 98 | public static String getProp(String name) { 99 | String line = null; 100 | BufferedReader input = null; 101 | try { 102 | Process p = Runtime.getRuntime().exec("getprop " + name); 103 | input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); 104 | line = input.readLine(); 105 | input.close(); 106 | } catch (IOException ex) { 107 | return null; 108 | } finally { 109 | if (input != null) { 110 | try { 111 | input.close(); 112 | } catch (IOException e) { 113 | e.printStackTrace(); 114 | } 115 | } 116 | } 117 | return line; 118 | } 119 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/statusutil/StatusUtils.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.statusutil; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.app.Activity; 6 | import android.content.Context; 7 | import android.graphics.Color; 8 | import android.os.Build; 9 | import android.support.annotation.IntDef; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.view.Window; 13 | import android.view.WindowManager; 14 | 15 | import java.lang.annotation.Retention; 16 | import java.lang.annotation.RetentionPolicy; 17 | import java.lang.reflect.Field; 18 | import java.lang.reflect.Method; 19 | 20 | /** 21 | * 负责修改状态栏的工具类 22 | */ 23 | public class StatusUtils { 24 | public final static int TYPE_MIUI = 0; 25 | public final static int TYPE_FLYME = 1; 26 | public final static int TYPE_M = 3;//6.0 27 | 28 | @IntDef({TYPE_MIUI, 29 | TYPE_FLYME, 30 | TYPE_M}) 31 | @Retention(RetentionPolicy.SOURCE) 32 | @interface ViewType { 33 | } 34 | 35 | //设置全屏 36 | public static void setFullScreen(Activity activity){ 37 | activity.requestWindowFeature(Window.FEATURE_NO_TITLE); 38 | activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 39 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 40 | } 41 | 42 | /** 43 | * 修改状态栏颜色,支持4.4以上版本 44 | * 45 | * @param colorId 颜色 46 | */ 47 | public static void setStatusBarColor(Activity activity, int colorId) { 48 | 49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 50 | Window window = activity.getWindow(); 51 | window.setStatusBarColor(colorId); 52 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 53 | //使用SystemBarTintManager,需要先将状态栏设置为透明 54 | setTranslucentStatus(activity); 55 | SystemBarTintManager systemBarTintManager = new SystemBarTintManager(activity); 56 | systemBarTintManager.setStatusBarTintEnabled(true);//显示状态栏 57 | systemBarTintManager.setStatusBarTintColor(colorId);//设置状态栏颜色 58 | } 59 | } 60 | 61 | /** 62 | * 设置状态栏透明 63 | */ 64 | @TargetApi(19) 65 | public static void setTranslucentStatus(Activity activity) { 66 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 67 | //5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色 68 | Window window = activity.getWindow(); 69 | View decorView = window.getDecorView(); 70 | //两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间 71 | int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 72 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 73 | decorView.setSystemUiVisibility(option); 74 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 75 | window.setStatusBarColor(Color.TRANSPARENT); 76 | //导航栏颜色也可以正常设置 77 | //window.setNavigationBarColor(Color.TRANSPARENT); 78 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 79 | Window window = activity.getWindow(); 80 | WindowManager.LayoutParams attributes = window.getAttributes(); 81 | int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 82 | attributes.flags |= flagTranslucentStatus; 83 | //int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; 84 | //attributes.flags |= flagTranslucentNavigation; 85 | window.setAttributes(attributes); 86 | } 87 | } 88 | 89 | 90 | /** 91 | * 代码实现android:fitsSystemWindows 92 | * 93 | * @param activity 94 | */ 95 | public static void setRootViewFitsSystemWindows(Activity activity, boolean fitSystemWindows) { 96 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 97 | ViewGroup winContent = (ViewGroup) activity.findViewById(android.R.id.content); 98 | if (winContent.getChildCount() > 0) { 99 | ViewGroup rootView = (ViewGroup) winContent.getChildAt(0); 100 | if (rootView != null) { 101 | rootView.setFitsSystemWindows(fitSystemWindows); 102 | } 103 | } 104 | } 105 | 106 | } 107 | 108 | 109 | /** 110 | * 设置状态栏深色浅色切换 111 | */ 112 | public static boolean setStatusBarDarkTheme(Activity activity, boolean dark) { 113 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 114 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 115 | setStatusBarFontIconDark(activity, TYPE_M, dark); 116 | } else if (OSUtils.isMiui()) { 117 | setStatusBarFontIconDark(activity, TYPE_MIUI, dark); 118 | } else if (OSUtils.isFlyme()) { 119 | setStatusBarFontIconDark(activity, TYPE_FLYME, dark); 120 | } else {//其他情况 121 | return false; 122 | } 123 | 124 | return true; 125 | } 126 | return false; 127 | } 128 | 129 | /** 130 | * 设置 状态栏深色浅色切换 131 | */ 132 | public static boolean setStatusBarFontIconDark(Activity activity, @ViewType int type, boolean dark) { 133 | switch (type) { 134 | case TYPE_MIUI: 135 | return setMiuiUI(activity, dark); 136 | case TYPE_FLYME: 137 | return setFlymeUI(activity, dark); 138 | case TYPE_M: 139 | default: 140 | return setCommonUI(activity,dark); 141 | } 142 | } 143 | 144 | //设置6.0 状态栏深色浅色切换 145 | public static boolean setCommonUI(Activity activity, boolean dark) { 146 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 147 | View decorView = activity.getWindow().getDecorView(); 148 | if (decorView != null) { 149 | int vis = decorView.getSystemUiVisibility(); 150 | if (dark) { 151 | vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 152 | } else { 153 | vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 154 | } 155 | if (decorView.getSystemUiVisibility() != vis) { 156 | decorView.setSystemUiVisibility(vis); 157 | } 158 | return true; 159 | } 160 | } 161 | return false; 162 | 163 | } 164 | 165 | //设置Flyme 状态栏深色浅色切换 166 | public static boolean setFlymeUI(Activity activity, boolean dark) { 167 | try { 168 | Window window = activity.getWindow(); 169 | WindowManager.LayoutParams lp = window.getAttributes(); 170 | Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); 171 | Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags"); 172 | darkFlag.setAccessible(true); 173 | meizuFlags.setAccessible(true); 174 | int bit = darkFlag.getInt(null); 175 | int value = meizuFlags.getInt(lp); 176 | if (dark) { 177 | value |= bit; 178 | } else { 179 | value &= ~bit; 180 | } 181 | meizuFlags.setInt(lp, value); 182 | window.setAttributes(lp); 183 | return true; 184 | } catch (Exception e) { 185 | e.printStackTrace(); 186 | return false; 187 | } 188 | } 189 | 190 | //设置MIUI 状态栏深色浅色切换 191 | public static boolean setMiuiUI(Activity activity, boolean dark) { 192 | try { 193 | Window window = activity.getWindow(); 194 | Class clazz = activity.getWindow().getClass(); 195 | @SuppressLint("PrivateApi") Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); 196 | Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); 197 | int darkModeFlag = field.getInt(layoutParams); 198 | Method extraFlagField = clazz.getDeclaredMethod("setExtraFlags", int.class, int.class); 199 | extraFlagField.setAccessible(true); 200 | if (dark) { //状态栏亮色且黑色字体 201 | extraFlagField.invoke(window, darkModeFlag, darkModeFlag); 202 | } else { 203 | extraFlagField.invoke(window, 0, darkModeFlag); 204 | } 205 | return true; 206 | } catch (Exception e) { 207 | e.printStackTrace(); 208 | return false; 209 | } 210 | } 211 | //获取状态栏高度 212 | public static int getStatusBarHeight(Context context) { 213 | int result = 0; 214 | int resourceId = context.getResources().getIdentifier( 215 | "status_bar_height", "dimen", "android"); 216 | if (resourceId > 0) { 217 | result = context.getResources().getDimensionPixelSize(resourceId); 218 | } 219 | return result; 220 | } 221 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/basequickandroid/util/statusutil/SystemBarTintManager.java: -------------------------------------------------------------------------------- 1 | package com.ellen.basequickandroid.util.statusutil; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.app.Activity; 6 | import android.content.Context; 7 | import android.content.res.Configuration; 8 | import android.content.res.Resources; 9 | import android.content.res.TypedArray; 10 | import android.graphics.drawable.Drawable; 11 | import android.os.Build; 12 | import android.util.DisplayMetrics; 13 | import android.util.TypedValue; 14 | import android.view.Gravity; 15 | import android.view.View; 16 | import android.view.ViewConfiguration; 17 | import android.view.ViewGroup; 18 | import android.view.Window; 19 | import android.view.WindowManager; 20 | import android.widget.FrameLayout.LayoutParams; 21 | 22 | import java.lang.reflect.Method; 23 | 24 | /** 25 | * Class to manage status and navigation bar tint effects when using KitKat 26 | * translucent system UI modes. 27 | * 28 | */ 29 | public class SystemBarTintManager { 30 | 31 | static { 32 | // Android allows a system property to override the presence of the navigation bar. 33 | // Used by the emulator. 34 | // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076 35 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 36 | try { 37 | Class c = Class.forName("android.os.SystemProperties"); 38 | Method m = c.getDeclaredMethod("get", String.class); 39 | m.setAccessible(true); 40 | sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); 41 | } catch (Throwable e) { 42 | sNavBarOverride = null; 43 | } 44 | } 45 | } 46 | 47 | 48 | /** 49 | * The default system bar tint color value. 50 | */ 51 | public static final int DEFAULT_TINT_COLOR = 0x99000000; 52 | 53 | private static String sNavBarOverride; 54 | 55 | private final SystemBarConfig mConfig; 56 | private boolean mStatusBarAvailable; 57 | private boolean mNavBarAvailable; 58 | private boolean mStatusBarTintEnabled; 59 | private boolean mNavBarTintEnabled; 60 | private View mStatusBarTintView; 61 | private View mNavBarTintView; 62 | 63 | /** 64 | * Constructor. Call this in the host activity onCreate method after its 65 | * content view has been set. You should always create new instances when 66 | * the host activity is recreated. 67 | * 68 | * @param activity The host activity. 69 | */ 70 | @SuppressLint("ResourceType") 71 | @TargetApi(19) 72 | public SystemBarTintManager(Activity activity) { 73 | 74 | Window win = activity.getWindow(); 75 | ViewGroup decorViewGroup = (ViewGroup) win.getDecorView(); 76 | 77 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 78 | // check theme attrs 79 | int[] attrs = {android.R.attr.windowTranslucentStatus, 80 | android.R.attr.windowTranslucentNavigation}; 81 | TypedArray a = activity.obtainStyledAttributes(attrs); 82 | try { 83 | mStatusBarAvailable = a.getBoolean(0, false); 84 | mNavBarAvailable = a.getBoolean(1, false); 85 | } finally { 86 | a.recycle(); 87 | } 88 | 89 | // check window flags 90 | WindowManager.LayoutParams winParams = win.getAttributes(); 91 | int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 92 | if ((winParams.flags & bits) != 0) { 93 | mStatusBarAvailable = true; 94 | } 95 | bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; 96 | if ((winParams.flags & bits) != 0) { 97 | mNavBarAvailable = true; 98 | } 99 | } 100 | 101 | mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable); 102 | // device might not have virtual navigation keys 103 | if (!mConfig.hasNavigtionBar()) { 104 | mNavBarAvailable = false; 105 | } 106 | 107 | if (mStatusBarAvailable) { 108 | setupStatusBarView(activity, decorViewGroup); 109 | } 110 | if (mNavBarAvailable) { 111 | setupNavBarView(activity, decorViewGroup); 112 | } 113 | 114 | } 115 | 116 | /** 117 | * Enable tinting of the system status bar. 118 | * 119 | * If the platform is running Jelly Bean or earlier, or translucent system 120 | * UI modes have not been enabled in either the theme or via window flags, 121 | * then this method does nothing. 122 | * 123 | * @param enabled True to enable tinting, false to disable it (default). 124 | */ 125 | public void setStatusBarTintEnabled(boolean enabled) { 126 | mStatusBarTintEnabled = enabled; 127 | if (mStatusBarAvailable) { 128 | mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); 129 | } 130 | } 131 | 132 | /** 133 | * Enable tinting of the system navigation bar. 134 | * 135 | * If the platform does not have soft navigation keys, is running Jelly Bean 136 | * or earlier, or translucent system UI modes have not been enabled in either 137 | * the theme or via window flags, then this method does nothing. 138 | * 139 | * @param enabled True to enable tinting, false to disable it (default). 140 | */ 141 | public void setNavigationBarTintEnabled(boolean enabled) { 142 | mNavBarTintEnabled = enabled; 143 | if (mNavBarAvailable) { 144 | mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); 145 | } 146 | } 147 | 148 | /** 149 | * Apply the specified color tint to all system UI bars. 150 | * 151 | * @param color The color of the background tint. 152 | */ 153 | public void setTintColor(int color) { 154 | setStatusBarTintColor(color); 155 | setNavigationBarTintColor(color); 156 | } 157 | 158 | /** 159 | * Apply the specified drawable or color resource to all system UI bars. 160 | * 161 | * @param res The identifier of the resource. 162 | */ 163 | public void setTintResource(int res) { 164 | setStatusBarTintResource(res); 165 | setNavigationBarTintResource(res); 166 | } 167 | 168 | /** 169 | * Apply the specified drawable to all system UI bars. 170 | * 171 | * @param drawable The drawable to use as the background, or null to remove it. 172 | */ 173 | public void setTintDrawable(Drawable drawable) { 174 | setStatusBarTintDrawable(drawable); 175 | setNavigationBarTintDrawable(drawable); 176 | } 177 | 178 | /** 179 | * Apply the specified alpha to all system UI bars. 180 | * 181 | * @param alpha The alpha to use 182 | */ 183 | public void setTintAlpha(float alpha) { 184 | setStatusBarAlpha(alpha); 185 | setNavigationBarAlpha(alpha); 186 | } 187 | 188 | /** 189 | * Apply the specified color tint to the system status bar. 190 | * 191 | * @param color The color of the background tint. 192 | */ 193 | public void setStatusBarTintColor(int color) { 194 | if (mStatusBarAvailable) { 195 | mStatusBarTintView.setBackgroundColor(color); 196 | } 197 | } 198 | 199 | /** 200 | * Apply the specified drawable or color resource to the system status bar. 201 | * 202 | * @param res The identifier of the resource. 203 | */ 204 | public void setStatusBarTintResource(int res) { 205 | if (mStatusBarAvailable) { 206 | mStatusBarTintView.setBackgroundResource(res); 207 | } 208 | } 209 | 210 | /** 211 | * Apply the specified drawable to the system status bar. 212 | * 213 | * @param drawable The drawable to use as the background, or null to remove it. 214 | */ 215 | @SuppressWarnings("deprecation") 216 | public void setStatusBarTintDrawable(Drawable drawable) { 217 | if (mStatusBarAvailable) { 218 | mStatusBarTintView.setBackgroundDrawable(drawable); 219 | } 220 | } 221 | 222 | /** 223 | * Apply the specified alpha to the system status bar. 224 | * 225 | * @param alpha The alpha to use 226 | */ 227 | @TargetApi(11) 228 | public void setStatusBarAlpha(float alpha) { 229 | if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 230 | mStatusBarTintView.setAlpha(alpha); 231 | } 232 | } 233 | 234 | /** 235 | * Apply the specified color tint to the system navigation bar. 236 | * 237 | * @param color The color of the background tint. 238 | */ 239 | public void setNavigationBarTintColor(int color) { 240 | if (mNavBarAvailable) { 241 | mNavBarTintView.setBackgroundColor(color); 242 | } 243 | } 244 | 245 | /** 246 | * Apply the specified drawable or color resource to the system navigation bar. 247 | * 248 | * @param res The identifier of the resource. 249 | */ 250 | public void setNavigationBarTintResource(int res) { 251 | if (mNavBarAvailable) { 252 | mNavBarTintView.setBackgroundResource(res); 253 | } 254 | } 255 | 256 | /** 257 | * Apply the specified drawable to the system navigation bar. 258 | * 259 | * @param drawable The drawable to use as the background, or null to remove it. 260 | */ 261 | @SuppressWarnings("deprecation") 262 | public void setNavigationBarTintDrawable(Drawable drawable) { 263 | if (mNavBarAvailable) { 264 | mNavBarTintView.setBackgroundDrawable(drawable); 265 | } 266 | } 267 | 268 | /** 269 | * Apply the specified alpha to the system navigation bar. 270 | * 271 | * @param alpha The alpha to use 272 | */ 273 | @TargetApi(11) 274 | public void setNavigationBarAlpha(float alpha) { 275 | if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 276 | mNavBarTintView.setAlpha(alpha); 277 | } 278 | } 279 | 280 | /** 281 | * Get the system bar configuration. 282 | * 283 | * @return The system bar configuration for the current device configuration. 284 | */ 285 | public SystemBarConfig getConfig() { 286 | return mConfig; 287 | } 288 | 289 | /** 290 | * Is tinting enabled for the system status bar? 291 | * 292 | * @return True if enabled, False otherwise. 293 | */ 294 | public boolean isStatusBarTintEnabled() { 295 | return mStatusBarTintEnabled; 296 | } 297 | 298 | /** 299 | * Is tinting enabled for the system navigation bar? 300 | * 301 | * @return True if enabled, False otherwise. 302 | */ 303 | public boolean isNavBarTintEnabled() { 304 | return mNavBarTintEnabled; 305 | } 306 | 307 | private void setupStatusBarView(Context context, ViewGroup decorViewGroup) { 308 | mStatusBarTintView = new View(context); 309 | LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight()); 310 | params.gravity = Gravity.TOP; 311 | if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) { 312 | params.rightMargin = mConfig.getNavigationBarWidth(); 313 | } 314 | mStatusBarTintView.setLayoutParams(params); 315 | mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); 316 | mStatusBarTintView.setVisibility(View.GONE); 317 | decorViewGroup.addView(mStatusBarTintView); 318 | } 319 | 320 | private void setupNavBarView(Context context, ViewGroup decorViewGroup) { 321 | mNavBarTintView = new View(context); 322 | LayoutParams params; 323 | if (mConfig.isNavigationAtBottom()) { 324 | params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight()); 325 | params.gravity = Gravity.BOTTOM; 326 | } else { 327 | params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT); 328 | params.gravity = Gravity.RIGHT; 329 | } 330 | mNavBarTintView.setLayoutParams(params); 331 | mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); 332 | mNavBarTintView.setVisibility(View.GONE); 333 | decorViewGroup.addView(mNavBarTintView); 334 | } 335 | 336 | /** 337 | * Class which describes system bar sizing and other characteristics for the current 338 | * device configuration. 339 | * 340 | */ 341 | public static class SystemBarConfig { 342 | 343 | private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; 344 | private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height"; 345 | private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape"; 346 | private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; 347 | private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; 348 | 349 | private final boolean mTranslucentStatusBar; 350 | private final boolean mTranslucentNavBar; 351 | private final int mStatusBarHeight; 352 | private final int mActionBarHeight; 353 | private final boolean mHasNavigationBar; 354 | private final int mNavigationBarHeight; 355 | private final int mNavigationBarWidth; 356 | private final boolean mInPortrait; 357 | private final float mSmallestWidthDp; 358 | 359 | private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) { 360 | Resources res = activity.getResources(); 361 | mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT); 362 | mSmallestWidthDp = getSmallestWidthDp(activity); 363 | mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME); 364 | mActionBarHeight = getActionBarHeight(activity); 365 | mNavigationBarHeight = getNavigationBarHeight(activity); 366 | mNavigationBarWidth = getNavigationBarWidth(activity); 367 | mHasNavigationBar = (mNavigationBarHeight > 0); 368 | mTranslucentStatusBar = translucentStatusBar; 369 | mTranslucentNavBar = traslucentNavBar; 370 | } 371 | 372 | @TargetApi(14) 373 | private int getActionBarHeight(Context context) { 374 | int result = 0; 375 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 376 | TypedValue tv = new TypedValue(); 377 | context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true); 378 | result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); 379 | } 380 | return result; 381 | } 382 | 383 | @TargetApi(14) 384 | private int getNavigationBarHeight(Context context) { 385 | Resources res = context.getResources(); 386 | int result = 0; 387 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 388 | if (hasNavBar(context)) { 389 | String key; 390 | if (mInPortrait) { 391 | key = NAV_BAR_HEIGHT_RES_NAME; 392 | } else { 393 | key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME; 394 | } 395 | return getInternalDimensionSize(res, key); 396 | } 397 | } 398 | return result; 399 | } 400 | 401 | @TargetApi(14) 402 | private int getNavigationBarWidth(Context context) { 403 | Resources res = context.getResources(); 404 | int result = 0; 405 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 406 | if (hasNavBar(context)) { 407 | return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME); 408 | } 409 | } 410 | return result; 411 | } 412 | 413 | @TargetApi(14) 414 | private boolean hasNavBar(Context context) { 415 | Resources res = context.getResources(); 416 | int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android"); 417 | if (resourceId != 0) { 418 | boolean hasNav = res.getBoolean(resourceId); 419 | // check override flag (see static block) 420 | if ("1".equals(sNavBarOverride)) { 421 | hasNav = false; 422 | } else if ("0".equals(sNavBarOverride)) { 423 | hasNav = true; 424 | } 425 | return hasNav; 426 | } else { // fallback 427 | return !ViewConfiguration.get(context).hasPermanentMenuKey(); 428 | } 429 | } 430 | 431 | private int getInternalDimensionSize(Resources res, String key) { 432 | int result = 0; 433 | int resourceId = res.getIdentifier(key, "dimen", "android"); 434 | if (resourceId > 0) { 435 | result = res.getDimensionPixelSize(resourceId); 436 | } 437 | return result; 438 | } 439 | 440 | @SuppressLint("NewApi") 441 | private float getSmallestWidthDp(Activity activity) { 442 | DisplayMetrics metrics = new DisplayMetrics(); 443 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 444 | activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); 445 | } else { 446 | // TODO this is not correct, but we don't really care pre-kitkat 447 | activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 448 | } 449 | float widthDp = metrics.widthPixels / metrics.density; 450 | float heightDp = metrics.heightPixels / metrics.density; 451 | return Math.min(widthDp, heightDp); 452 | } 453 | 454 | /** 455 | * Should a navigation bar appear at the bottom of the screen in the current 456 | * device configuration? A navigation bar may appear on the right side of 457 | * the screen in certain configurations. 458 | * 459 | * @return True if navigation should appear at the bottom of the screen, False otherwise. 460 | */ 461 | public boolean isNavigationAtBottom() { 462 | return (mSmallestWidthDp >= 600 || mInPortrait); 463 | } 464 | 465 | /** 466 | * Get the height of the system status bar. 467 | * 468 | * @return The height of the status bar (in pixels). 469 | */ 470 | public int getStatusBarHeight() { 471 | return mStatusBarHeight; 472 | } 473 | 474 | /** 475 | * Get the height of the action bar. 476 | * 477 | * @return The height of the action bar (in pixels). 478 | */ 479 | public int getActionBarHeight() { 480 | return mActionBarHeight; 481 | } 482 | 483 | /** 484 | * Does this device have a system navigation bar? 485 | * 486 | * @return True if this device uses soft key navigation, False otherwise. 487 | */ 488 | public boolean hasNavigtionBar() { 489 | return mHasNavigationBar; 490 | } 491 | 492 | /** 493 | * Get the height of the system navigation bar. 494 | * 495 | * @return The height of the navigation bar (in pixels). If the device does not have 496 | * soft navigation keys, this will always return 0. 497 | */ 498 | public int getNavigationBarHeight() { 499 | return mNavigationBarHeight; 500 | } 501 | 502 | /** 503 | * Get the width of the system navigation bar when it is placed vertically on the screen. 504 | * 505 | * @return The width of the navigation bar (in pixels). If the device does not have 506 | * soft navigation keys, this will always return 0. 507 | */ 508 | public int getNavigationBarWidth() { 509 | return mNavigationBarWidth; 510 | } 511 | 512 | /** 513 | * Get the layout inset for any system UI that appears at the top of the screen. 514 | * 515 | * @param withActionBar True to include the height of the action bar, False otherwise. 516 | * @return The layout inset (in pixels). 517 | */ 518 | public int getPixelInsetTop(boolean withActionBar) { 519 | return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0); 520 | } 521 | 522 | /** 523 | * Get the layout inset for any system UI that appears at the bottom of the screen. 524 | * 525 | * @return The layout inset (in pixels). 526 | */ 527 | public int getPixelInsetBottom() { 528 | if (mTranslucentNavBar && isNavigationAtBottom()) { 529 | return mNavigationBarHeight; 530 | } else { 531 | return 0; 532 | } 533 | } 534 | 535 | /** 536 | * Get the layout inset for any system UI that appears at the right of the screen. 537 | * 538 | * @return The layout inset (in pixels). 539 | */ 540 | public int getPixelInsetRight() { 541 | if (mTranslucentNavBar && !isNavigationAtBottom()) { 542 | return mNavigationBarWidth; 543 | } else { 544 | return 0; 545 | } 546 | } 547 | 548 | } 549 | 550 | } 551 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/FragmentReplace/FragmentPlace.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.FragmentReplace; 2 | 3 | public class FragmentPlace { 4 | 5 | // 复制以下代码到你的Activity即可 6 | // private void replaceFragment(String tag) { 7 | // tvTitle.setText(tag); 8 | // if (currentFragment != null) { 9 | // getSupportFragmentManager().beginTransaction().hide(currentFragment).commit(); 10 | // } 11 | // currentFragment = (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag); 12 | // if (currentFragment == null) { 13 | // switch (tag) { 14 | // case "首页": 15 | // currentFragment = new HomeFragment(); 16 | // break; 17 | // case "新闻": 18 | // currentFragment = new NewsFragment(); 19 | // break; 20 | // case "更多": 21 | // currentFragment = new MoreFragment(); 22 | // break; 23 | // } 24 | // getSupportFragmentManager().beginTransaction().add(R.id.fl_main, currentFragment, tag).commit(); 25 | // }else { 26 | // getSupportFragmentManager().beginTransaction().show(currentFragment).commit(); 27 | // } 28 | // } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/Builder/Builder.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.Builder; 2 | 3 | public interface Builder { 4 | 5 | Builder builderBoard(String mBoard); 6 | Builder builderDisplay(String mDisplay); 7 | Builder builderOS(String mOS); 8 | Computer build(); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/Builder/Computer.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.Builder; 2 | 3 | public class Computer { 4 | 5 | protected String mBoard; 6 | protected String mDisplay; 7 | protected String mOS; 8 | 9 | public void setmBoard(String mBoard) { 10 | this.mBoard = mBoard; 11 | } 12 | 13 | public void setmDisplay(String mDisplay) { 14 | this.mDisplay = mDisplay; 15 | } 16 | 17 | public void setmOS(String mOS) { 18 | this.mOS = mOS; 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | return "Computer{" + 24 | "mBoard='" + mBoard + '\'' + 25 | ", mDisplay='" + mDisplay + '\'' + 26 | ", mOS='" + mOS + '\'' + 27 | '}'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/Builder/MacBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.Builder; 2 | 3 | public class MacBuilder implements Builder{ 4 | 5 | private Computer macComputer = new Computer(); 6 | 7 | @Override 8 | public Builder builderBoard(String mBoard) { 9 | macComputer.setmBoard(mBoard); 10 | return this; 11 | } 12 | 13 | @Override 14 | public Builder builderDisplay(String mDisplay) { 15 | macComputer.setmDisplay(mDisplay); 16 | return this; 17 | } 18 | 19 | @Override 20 | public Builder builderOS(String mOS) { 21 | macComputer.setmOS(mOS); 22 | return this; 23 | } 24 | 25 | @Override 26 | public Computer build() { 27 | return macComputer; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/SingleInstace/DCLModeSingleInstance.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.SingleInstace; 2 | 3 | /** 4 | * 双重检测锁机制,线程安全的 5 | */ 6 | public class DCLModeSingleInstance { 7 | 8 | private static volatile DCLModeSingleInstance singleInstance = null; 9 | 10 | private DCLModeSingleInstance(){ 11 | 12 | } 13 | 14 | public static DCLModeSingleInstance getInstance(){ 15 | if(singleInstance == null){ 16 | synchronized (DCLModeSingleInstance.class){ 17 | if(singleInstance == null){ 18 | singleInstance = new DCLModeSingleInstance(); 19 | } 20 | } 21 | } 22 | return singleInstance; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/SingleInstace/HungryModeSingleInstance.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.SingleInstace; 2 | 3 | /** 4 | * 饿汉式单例模式,线程安全的 5 | */ 6 | public class HungryModeSingleInstance { 7 | 8 | //在项目运行是就存在单例对象 9 | private static HungryModeSingleInstance singleInstance = new HungryModeSingleInstance(); 10 | 11 | private HungryModeSingleInstance(){ 12 | 13 | } 14 | 15 | public static HungryModeSingleInstance getInstance(){ 16 | return singleInstance; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/SingleInstace/LazybonesModeSingleInstace.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.SingleInstace; 2 | 3 | /** 4 | * 懒汉单例模式,容易出现线程安全问题 5 | */ 6 | public class LazybonesModeSingleInstace { 7 | 8 | private static LazybonesModeSingleInstace singleInstace = null; 9 | 10 | private LazybonesModeSingleInstace(){} 11 | 12 | 13 | public static LazybonesModeSingleInstace getInstace(){ 14 | if(singleInstace == null) { 15 | //当获取单例的时候才进行创建 16 | singleInstace = new LazybonesModeSingleInstace(); 17 | } 18 | return singleInstace; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/SingleInstace/StaticCodePieceSingleInstace.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.SingleInstace; 2 | 3 | /** 4 | * 静态代码块单例模式,线程安全的,还有个枚举的,就不写了 5 | */ 6 | public class StaticCodePieceSingleInstace { 7 | 8 | private static StaticCodePieceSingleInstace singleInstace = null; 9 | 10 | static { 11 | singleInstace = new StaticCodePieceSingleInstace(); 12 | } 13 | 14 | private StaticCodePieceSingleInstace(){ 15 | 16 | } 17 | 18 | public static StaticCodePieceSingleInstace getInstance(){ 19 | return singleInstace; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Java23_Design_Patterns/SingleInstace/StaticInnerClassSingleInstace.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Java23_Design_Patterns.SingleInstace; 2 | 3 | /** 4 | * 静态内部类的方式,线程安全的 5 | */ 6 | public class StaticInnerClassSingleInstace { 7 | 8 | 9 | // 私有构造 10 | private StaticInnerClassSingleInstace() {} 11 | 12 | // 静态内部类 13 | private static class InnerObject{ 14 | private static StaticInnerClassSingleInstace single = new StaticInnerClassSingleInstace(); 15 | } 16 | 17 | public static StaticInnerClassSingleInstace getInstance() { 18 | return InnerObject.single; 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/LibraryUseDemo/RxJava/RxJavaDemo.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.LibraryUseDemo.RxJava; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.drawable.BitmapDrawable; 5 | import android.graphics.drawable.Drawable; 6 | import android.util.Log; 7 | 8 | import java.util.function.Consumer; 9 | 10 | import io.reactivex.Observable; 11 | import io.reactivex.ObservableEmitter; 12 | import io.reactivex.ObservableOnSubscribe; 13 | import io.reactivex.Observer; 14 | import io.reactivex.android.schedulers.AndroidSchedulers; 15 | import io.reactivex.disposables.Disposable; 16 | import io.reactivex.schedulers.Schedulers; 17 | 18 | import static android.content.ContentValues.TAG; 19 | import static java.lang.Thread.sleep; 20 | 21 | public class RxJavaDemo { 22 | 23 | 24 | 25 | // Observable.create(new ObservableOnSubscribe() { 26 | // @Override 27 | // public void subscribe(ObservableEmitter emitter) throws Exception { 28 | // for (int i=0;i() { 49 | // @Override 50 | // public void accept(Drawable drawable) throws Exception { 51 | // //回调后在UI界面上展示出来 52 | // } 53 | // }); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Serach/Serach.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Serach; 2 | 3 | //查找算法归类 4 | public class Serach { 5 | 6 | /* 7 | * 循环实现二分查找算法arr 已排好序的数组x 需要查找的数-1 无法查到数据 8 | */ 9 | public static int binarySearch(int[] arr, int x) { 10 | int low = 0; 11 | int high = arr.length-1; 12 | while(low <= high) { 13 | int middle = (low + high)/2; 14 | if(x == arr[middle]) { 15 | return middle; 16 | }else if(x dataset[endIndex]||beginIndex>endIndex){ 29 | return -1; 30 | } 31 | if(data dataset[midIndex]){ 34 | return binarySearch(dataset,data,midIndex+1,endIndex); 35 | }else { 36 | return midIndex; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/ellen/example/Sort/Sort.java: -------------------------------------------------------------------------------- 1 | package com.ellen.example.Sort; 2 | 3 | //排序算法归类 4 | public class Sort { 5 | 6 | //冒泡排序范例 7 | public static void maoPaoSort(int[] array){ 8 | for(int i=0;iarray[j]) { 11 | int temp = array[i]; 12 | array[i] = array[j]; 13 | array[j] = temp; 14 | } 15 | } 16 | } 17 | } 18 | 19 | //选择排序范例 20 | public static void chooseSort(int[] array){ 21 | for(int i=0;i 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_effect.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |