├── .gitignore ├── README.md ├── apk ├── Java_release_v1.0.0(002).apk └── Kotlin_release_v1.0.0(001).apk ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── java ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── proguardMapping.txt └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── android │ │ └── java │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── android │ │ │ ├── base │ │ │ ├── BaseApplication.java │ │ │ ├── DontSwipeBack.java │ │ │ ├── FrameFragment.java │ │ │ ├── MainActivity.java │ │ │ ├── UtilFragment.java │ │ │ └── WidgetFragment.java │ │ │ ├── frame │ │ │ ├── TestLeakActivity.java │ │ │ ├── guide │ │ │ │ ├── GuideActivity.java │ │ │ │ └── SimpleViewAdapter.java │ │ │ ├── http │ │ │ │ ├── AATest │ │ │ │ │ ├── ApiService.java │ │ │ │ │ ├── TestRetrofitActivity.java │ │ │ │ │ ├── UrlConstant.java │ │ │ │ │ ├── WangYiNewsWebviewActivity.java │ │ │ │ │ └── bean │ │ │ │ │ │ ├── NewsListBean.java │ │ │ │ │ │ └── WeatherBean.java │ │ │ │ ├── CookieJarManage.java │ │ │ │ ├── ExceptionUtil.java │ │ │ │ ├── RetrofitFactory.java │ │ │ │ ├── SSLSocketFactoryUtil.java │ │ │ │ ├── SchedulerUtil.java │ │ │ │ ├── converter │ │ │ │ │ ├── CustomGsonConverterFactory.java │ │ │ │ │ ├── CustomGsonRequestBodyConverter.java │ │ │ │ │ ├── CustomGsonResponseBodyConverter.java │ │ │ │ │ └── 说明.md │ │ │ │ ├── function │ │ │ │ │ └── RetryWithDelay.java │ │ │ │ ├── interceptor │ │ │ │ │ ├── HttpCacheInterceptor.java │ │ │ │ │ ├── HttpLogInterceptor.java │ │ │ │ │ └── MaxRetryInterceptor.java │ │ │ │ └── model │ │ │ │ │ ├── BaseListResponse.java │ │ │ │ │ └── BaseResponse.java │ │ │ ├── mvc │ │ │ │ ├── AATest │ │ │ │ │ ├── TestActivityMvc.java │ │ │ │ │ ├── TestFragmentMvc.java │ │ │ │ │ ├── TestMvcActivity.java │ │ │ │ │ ├── TestMvcFragment.java │ │ │ │ │ ├── TestMvcListActivity.java │ │ │ │ │ ├── TestMvcListFragment.java │ │ │ │ │ ├── TestWebviewActivity.java │ │ │ │ │ ├── adapter │ │ │ │ │ │ └── NewsListAdapter.java │ │ │ │ │ ├── convert │ │ │ │ │ │ ├── NewsFunction.java │ │ │ │ │ │ └── WeatherFunction.java │ │ │ │ │ ├── entity │ │ │ │ │ │ ├── NewsListBean.java │ │ │ │ │ │ └── WeatherBean.java │ │ │ │ │ └── server │ │ │ │ │ │ ├── ApiHelper.java │ │ │ │ │ │ ├── ApiService.java │ │ │ │ │ │ └── Config.java │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseListActivity.java │ │ │ │ ├── BaseListFragment.java │ │ │ │ ├── IBaseListView.java │ │ │ │ ├── IBaseView.java │ │ │ │ ├── ImageInterface.java │ │ │ │ ├── WebviewActivity.java │ │ │ │ ├── WebviewFragment.java │ │ │ │ └── extra │ │ │ │ │ ├── RecyclerView │ │ │ │ │ ├── CustomLoadMoreView.java │ │ │ │ │ └── LoadMoreAdapter.java │ │ │ │ │ └── http │ │ │ │ │ └── CustomObserver.java │ │ │ ├── mvp │ │ │ │ ├── AATest │ │ │ │ │ ├── TestActivityMvp.java │ │ │ │ │ ├── TestFragmentMvp.java │ │ │ │ │ ├── listType │ │ │ │ │ │ ├── TestMvpListActivity.java │ │ │ │ │ │ ├── TestMvpListFragment.java │ │ │ │ │ │ ├── TestMvpListModel.java │ │ │ │ │ │ ├── TestMvpListPresenter.java │ │ │ │ │ │ └── TestMvpListView.java │ │ │ │ │ └── notListType │ │ │ │ │ │ ├── TestMvpActivity.java │ │ │ │ │ │ ├── TestMvpFragment.java │ │ │ │ │ │ ├── TestMvpModel.java │ │ │ │ │ │ ├── TestMvpPresenter.java │ │ │ │ │ │ └── TestMvpView.java │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseListActivity.java │ │ │ │ ├── BaseListFragment.java │ │ │ │ ├── BaseListPresenter.java │ │ │ │ ├── BasePresenter.java │ │ │ │ ├── CommonBaseActivity.java │ │ │ │ ├── CommonBaseFragment.java │ │ │ │ ├── IBaseListView.java │ │ │ │ ├── IBaseView.java │ │ │ │ ├── extra │ │ │ │ │ └── http │ │ │ │ │ │ └── CustomObserver.java │ │ │ │ └── 注意点.md │ │ │ └── mvvm │ │ │ │ ├── AATest │ │ │ │ ├── TestActivityMvvm.java │ │ │ │ ├── TestFragmentMvvm.java │ │ │ │ ├── convert │ │ │ │ │ ├── CustomRequestBodyConverter.java │ │ │ │ │ ├── NewsConverterFactory.java │ │ │ │ │ ├── NewsResponseBodyConverter.java │ │ │ │ │ ├── WeatherConverterFactory.java │ │ │ │ │ └── WeatherResponseBodyConverter.java │ │ │ │ ├── listType │ │ │ │ │ ├── TestMvvmListActivity.java │ │ │ │ │ ├── TestMvvmListActivityViewModel.java │ │ │ │ │ ├── TestMvvmListFragment.java │ │ │ │ │ └── TestMvvmListFragmentViewModel.java │ │ │ │ ├── notListType │ │ │ │ │ ├── TestMvvmActivity.java │ │ │ │ │ ├── TestMvvmActivityViewModel.java │ │ │ │ │ ├── TestMvvmFragment.java │ │ │ │ │ └── TestMvvmFragmentViewModel.java │ │ │ │ └── server │ │ │ │ │ ├── ApiHelper.java │ │ │ │ │ ├── ApiService.java │ │ │ │ │ └── Config.java │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseListActivity.java │ │ │ │ ├── BaseListFragment.java │ │ │ │ ├── BaseListViewModel.java │ │ │ │ ├── BaseViewModel.java │ │ │ │ ├── BaseViewModelWithData.java │ │ │ │ ├── CommonBaseActivity.java │ │ │ │ ├── CommonBaseFragment.java │ │ │ │ ├── IBaseListView.java │ │ │ │ ├── IBaseView.java │ │ │ │ └── extra │ │ │ │ └── LiveDataEntity │ │ │ │ ├── DialogConfig.java │ │ │ │ └── ErrorResponse.java │ │ │ ├── util │ │ │ ├── AlertDialogUtil.java │ │ │ ├── AndroidBug5497Workaround.java │ │ │ ├── ApkDownloadUtil.java │ │ │ ├── AudioUtil.java │ │ │ ├── BrightnessUtil.java │ │ │ ├── ByteUnit.java │ │ │ ├── CPUUtil.java │ │ │ ├── CacheUtil.java │ │ │ ├── CapturePicture │ │ │ │ ├── CapturePictureUtil.java │ │ │ │ ├── TestCaptureGridViewActivity.java │ │ │ │ ├── TestCaptureListViewActivity.java │ │ │ │ ├── TestCaptureRecyclerViewActivity.java │ │ │ │ └── TestCaptureWebViewActivity.java │ │ │ ├── CheckFastClickUtil.java │ │ │ ├── CleanUtil.java │ │ │ ├── CommonLayoutUtil.java │ │ │ ├── CrashHandler.java │ │ │ ├── DataDueUtil.java │ │ │ ├── DateUtil.java │ │ │ ├── DeviceUtil.java │ │ │ ├── DigitalUtil.java │ │ │ ├── DrawableUtil.java │ │ │ ├── EmptyUtil.java │ │ │ ├── EncodeUtil.java │ │ │ ├── ExtraUtil.java │ │ │ ├── FileUtil.java │ │ │ ├── HandlerUtil.java │ │ │ ├── IOUtil.java │ │ │ ├── IntentUtil.java │ │ │ ├── JsonUtil.java │ │ │ ├── KeyboardUtil.java │ │ │ ├── LayoutParamsUtil.java │ │ │ ├── LogUtil.java │ │ │ ├── NetReceiver.java │ │ │ ├── NetworkUtil.java │ │ │ ├── NotificationUtil.java │ │ │ ├── OnAppBarStateChangeListener.java │ │ │ ├── OnMultiClickListener.java │ │ │ ├── PhoneUtil.java │ │ │ ├── PickerViewUtil.java │ │ │ ├── PinyinUtil.java │ │ │ ├── SDCardUtil.java │ │ │ ├── ScreenUtil.java │ │ │ ├── ShellUtil.java │ │ │ ├── SizeUtil.java │ │ │ ├── SpannableStringUtil.java │ │ │ ├── StatusBar │ │ │ │ ├── StatusBarUtil.java │ │ │ │ └── TestStatusBarUtilActivity.java │ │ │ ├── StringUtil.java │ │ │ ├── SystemUtil.java │ │ │ ├── TestUtilActivity.java │ │ │ ├── ToastUtil.java │ │ │ ├── TransformUtil.java │ │ │ ├── VibrationUtil.java │ │ │ ├── ZipUtil.java │ │ │ ├── activity │ │ │ │ ├── ActivityUtil.java │ │ │ │ └── TestJumpActivity.java │ │ │ ├── app │ │ │ │ ├── AATest │ │ │ │ │ ├── AppAdapter.java │ │ │ │ │ └── TestAppListActivity.java │ │ │ │ ├── AppInfo.java │ │ │ │ └── AppUtil.java │ │ │ ├── bitmap │ │ │ │ ├── BitmapUtil.java │ │ │ │ └── TestBitmapActivity.java │ │ │ ├── code │ │ │ │ ├── BarCodeUtil.java │ │ │ │ ├── QRCodeUtil.java │ │ │ │ └── TestCodeUtilActivity.java │ │ │ ├── encrypt │ │ │ │ ├── AESCBCUtil.java │ │ │ │ ├── AESUtil.java │ │ │ │ ├── Base64.java │ │ │ │ ├── DESCBCUtil.java │ │ │ │ ├── DESUtil.java │ │ │ │ ├── MessageDigestUtil.java │ │ │ │ ├── RSAUtil.java │ │ │ │ └── SingtureUtil.java │ │ │ ├── glide │ │ │ │ ├── GlideUtil.java │ │ │ │ ├── SectionRoundedCorners.java │ │ │ │ └── TestGlideActivity.java │ │ │ ├── location │ │ │ │ ├── LocationService.java │ │ │ │ └── LocationUtil.java │ │ │ ├── permission │ │ │ │ ├── PermissionUtil.java │ │ │ │ └── TestPermissionActivity.java │ │ │ ├── regex │ │ │ │ ├── RegexConstant.java │ │ │ │ └── RegexUtil.java │ │ │ ├── service │ │ │ │ ├── ServiceUtil.java │ │ │ │ └── TestService.java │ │ │ ├── sharedPreferences │ │ │ │ ├── withContext │ │ │ │ │ └── SPUtil.java │ │ │ │ └── withoutContext │ │ │ │ │ ├── SPUtil.java │ │ │ │ │ └── SPUtils.java │ │ │ ├── threadPool │ │ │ │ ├── AATest │ │ │ │ │ ├── CalculateTask.java │ │ │ │ │ └── TestThreadPoolUtilActivity.java │ │ │ │ ├── StepThread.java │ │ │ │ ├── ThreadPoolManager.java │ │ │ │ └── ThreadPoolUtil.java │ │ │ └── traffic │ │ │ │ ├── NetworkStatsHelper.java │ │ │ │ ├── TrafficInfo.java │ │ │ │ └── TrafficStatsUtil.java │ │ │ └── widget │ │ │ ├── ArcView.java │ │ │ ├── CustomViewPager.java │ │ │ ├── Dialog │ │ │ ├── BaseDialog.java │ │ │ ├── CommonDialog.java │ │ │ ├── ConfirmDialog.java │ │ │ └── TestDialogActivity.java │ │ │ ├── FloatWindow │ │ │ ├── NeedPermission │ │ │ │ ├── AATest │ │ │ │ │ ├── TestFloatPageOneActivity.java │ │ │ │ │ ├── TestFloatPageThreeActivity.java │ │ │ │ │ └── TestFloatPageTwoActivity.java │ │ │ │ ├── FloatActivity.java │ │ │ │ ├── FloatLifecycle.java │ │ │ │ ├── FloatPermissionUtil.java │ │ │ │ ├── FloatWindow.java │ │ │ │ ├── IFloatWindow.java │ │ │ │ ├── IFloatWindowImpl.java │ │ │ │ ├── MoveType.java │ │ │ │ ├── OnPermissionListener.java │ │ │ │ ├── OnViewListener.java │ │ │ │ ├── OnViewStateListener.java │ │ │ │ ├── ScreenType.java │ │ │ │ └── compat │ │ │ │ │ └── MIUI.java │ │ │ ├── NoPermission │ │ │ │ ├── AATest │ │ │ │ │ └── TestFloatPageActivity.java │ │ │ │ ├── FloatWindow.java │ │ │ │ ├── IFloatWindow.java │ │ │ │ ├── MoveType.java │ │ │ │ ├── OnViewListener.java │ │ │ │ └── ScreenType.java │ │ │ └── TestFloatActivity.java │ │ │ ├── InputLayout.java │ │ │ ├── LoadingDialog │ │ │ ├── LoadingDialog.java │ │ │ └── LoadingView.java │ │ │ ├── LoadingLayout │ │ │ ├── LoadingLayout.java │ │ │ └── TestLoadingLayoutActivity.java │ │ │ ├── MaxHeightRecyclerView.java │ │ │ ├── PasswordEditText.java │ │ │ ├── PhotoViewer │ │ │ ├── PhotoViewActivity.java │ │ │ ├── PhotoViewAdapter.java │ │ │ ├── helper │ │ │ │ └── CustomGestureDetector.java │ │ │ ├── listener │ │ │ │ ├── OnGestureListener.java │ │ │ │ ├── OnMatrixChangedListener.java │ │ │ │ ├── OnOutsidePhotoTapListener.java │ │ │ │ ├── OnPhotoTapListener.java │ │ │ │ ├── OnScaleChangedListener.java │ │ │ │ ├── OnSingleFlingListener.java │ │ │ │ ├── OnViewDragListener.java │ │ │ │ └── OnViewTapListener.java │ │ │ └── widget │ │ │ │ ├── PhotoView.java │ │ │ │ ├── PhotoViewAttacher.java │ │ │ │ └── PhotoViewPager.java │ │ │ ├── PicGetterDialog │ │ │ ├── AATest │ │ │ │ ├── CustomPicGetterDialog.java │ │ │ │ └── TestPicGetterDialogActivity.java │ │ │ ├── BasePicGetterDialog.java │ │ │ ├── OnPicGetterListener.java │ │ │ ├── PicGetterDialog.java │ │ │ └── 说明.md │ │ │ ├── PopupWindow │ │ │ ├── AATest │ │ │ │ ├── PopupWindowAdapter.java │ │ │ │ └── TestPopupWindowActivity.java │ │ │ ├── CommonPopupWindow.java │ │ │ └── WindowHelper.java │ │ │ ├── ProgressBar │ │ │ └── TestProgressBarActivity.java │ │ │ ├── RecyclerView │ │ │ ├── AATest │ │ │ │ ├── TestFooterAdapter.java │ │ │ │ ├── TestFooterAdapterActivity.java │ │ │ │ ├── TestHeaderAdapter.java │ │ │ │ ├── TestHeaderAdapterActivity.java │ │ │ │ ├── TestLoadMoreWrapper.java │ │ │ │ ├── TestLoadMoreWrapperActivity.java │ │ │ │ ├── TestMultiAdapter.java │ │ │ │ ├── TestMultiAdapterActivity.java │ │ │ │ ├── TestMultiLoadMoreAdapter.java │ │ │ │ ├── TestMultiLoadMoreAdapterActivity.java │ │ │ │ ├── TestRecyclerViewActivity.java │ │ │ │ ├── TestSingleAdapter.java │ │ │ │ ├── TestSingleAdapterActivity.java │ │ │ │ ├── TestSingleLoadMoreAdapter.java │ │ │ │ ├── TestSingleLoadMoreAdapterActivity.java │ │ │ │ └── entity │ │ │ │ │ ├── DateBean.java │ │ │ │ │ ├── DetailBean.java │ │ │ │ │ └── MonthBean.java │ │ │ ├── BaseAdapter.java │ │ │ ├── LoadMoreAdapter.java │ │ │ ├── LoadMoreListener.java │ │ │ ├── LoadMoreWrapper.java │ │ │ ├── MultiViewType.java │ │ │ └── ViewHolder.java │ │ │ ├── ScrollTextView.java │ │ │ ├── ShadowLayout.java │ │ │ ├── TestSingleWidgetActivity.java │ │ │ ├── TitleBar.java │ │ │ ├── VerifyCodeView.java │ │ │ ├── ViewHolder.java │ │ │ └── justtext │ │ │ ├── AATest │ │ │ ├── SpanConfigAdapter.java │ │ │ └── TestJusttextActivity.java │ │ │ ├── ArrayUtils.java │ │ │ ├── EmptyArray.java │ │ │ ├── JustTextView.java │ │ │ ├── JustUtils.java │ │ │ ├── SpanConfig.java │ │ │ ├── SpanSet.java │ │ │ └── TextLine.java │ └── res │ │ ├── layout │ │ ├── activity_common_layout.xml │ │ ├── activity_guide.xml │ │ ├── activity_list_layout.xml │ │ ├── activity_main.xml │ │ ├── activity_photo_view.xml │ │ ├── activity_test_adapter.xml │ │ ├── activity_test_bitmap.xml │ │ ├── activity_test_capture_gridview.xml │ │ ├── activity_test_capture_listview.xml │ │ ├── activity_test_capture_recyclerview.xml │ │ ├── activity_test_capture_webview.xml │ │ ├── activity_test_code_util.xml │ │ ├── activity_test_fragment.xml │ │ ├── activity_test_glide.xml │ │ ├── activity_test_justtext.xml │ │ ├── activity_test_loading_layout.xml │ │ ├── activity_test_mvc.xml │ │ ├── activity_test_mvc_list.xml │ │ ├── activity_test_pic_getter_dialog.xml │ │ ├── activity_test_popup_window.xml │ │ ├── activity_test_progress_bar.xml │ │ ├── activity_test_single_widget.xml │ │ ├── activity_weather.xml │ │ ├── activity_webview.xml │ │ ├── fragment_frame.xml │ │ ├── fragment_test_mvc.xml │ │ ├── fragment_test_mvc_list.xml │ │ ├── fragment_util.xml │ │ ├── fragment_webview.xml │ │ ├── fragment_widget.xml │ │ ├── item_span_config.xml │ │ └── view_load_more.xml │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── android │ └── java │ └── ExampleUnitTest.java ├── kotlin ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── proguardMapping.txt └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── android │ │ └── basicproject │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── android │ │ │ ├── base │ │ │ ├── BaseApplication.kt │ │ │ ├── DontSwipeBack.kt │ │ │ ├── FrameFragment.kt │ │ │ ├── MainActivity.kt │ │ │ ├── UtilFragment.kt │ │ │ └── WidgetFragment.kt │ │ │ ├── frame │ │ │ ├── TestLeakActivity.kt │ │ │ ├── camera │ │ │ │ └── zxing │ │ │ │ │ ├── AATest │ │ │ │ │ ├── ScanActivity.kt │ │ │ │ │ └── TestZXingActivity.kt │ │ │ │ │ ├── camera │ │ │ │ │ ├── AutoFocusCallback.java │ │ │ │ │ ├── CameraConfigurationManager.java │ │ │ │ │ ├── CameraManager.java │ │ │ │ │ ├── PlanarYUVLuminanceSource.java │ │ │ │ │ └── PreviewCallback.java │ │ │ │ │ ├── decode │ │ │ │ │ ├── CaptureActivityHandler.java │ │ │ │ │ ├── DecodeFormatManager.java │ │ │ │ │ ├── DecodeHandler.java │ │ │ │ │ ├── DecodeThread.java │ │ │ │ │ ├── FinishListener.java │ │ │ │ │ ├── InactivityTimer.java │ │ │ │ │ ├── Intents.java │ │ │ │ │ └── RGBLuminanceSource.java │ │ │ │ │ ├── encode │ │ │ │ │ └── EncodingHandler.java │ │ │ │ │ ├── sound │ │ │ │ │ └── BeepManager.kt │ │ │ │ │ ├── ui │ │ │ │ │ └── CaptureActivity.kt │ │ │ │ │ ├── util │ │ │ │ │ ├── QRCodeUtil.java │ │ │ │ │ └── QRConstant.java │ │ │ │ │ └── view │ │ │ │ │ ├── ViewfinderResultPointCallback.java │ │ │ │ │ └── ViewfinderView.java │ │ │ ├── guide │ │ │ │ ├── GuideActivity.kt │ │ │ │ └── SimpleViewAdapter.kt │ │ │ ├── http │ │ │ │ ├── AATest │ │ │ │ │ ├── ApiService.kt │ │ │ │ │ ├── TestRetrofitActivity.kt │ │ │ │ │ ├── UrlConstant.kt │ │ │ │ │ ├── WangYiNewsWebviewActivity.kt │ │ │ │ │ └── bean │ │ │ │ │ │ ├── NewsListBean.kt │ │ │ │ │ │ └── WeatherBean.kt │ │ │ │ ├── CookieJarManage.kt │ │ │ │ ├── ExceptionUtil.kt │ │ │ │ ├── RetrofitFactory.kt │ │ │ │ ├── SSLSocketFactoryUtil.kt │ │ │ │ ├── SchedulerUtil.kt │ │ │ │ ├── function │ │ │ │ │ └── RetryWithDelay.kt │ │ │ │ ├── interceptor │ │ │ │ │ ├── HttpCacheInterceptor.kt │ │ │ │ │ ├── HttpLogInterceptor.kt │ │ │ │ │ └── MaxRetryInterceptor.kt │ │ │ │ └── model │ │ │ │ │ ├── BaseListResponse.kt │ │ │ │ │ └── BaseResponse.kt │ │ │ ├── mvc │ │ │ │ ├── AATest │ │ │ │ │ ├── TestActivityMvc.kt │ │ │ │ │ ├── TestFragmentMvc.kt │ │ │ │ │ ├── TestMvcActivity.kt │ │ │ │ │ ├── TestMvcFragment.kt │ │ │ │ │ ├── TestMvcListActivity.kt │ │ │ │ │ ├── TestMvcListFragment.kt │ │ │ │ │ ├── TestWebviewActivity.kt │ │ │ │ │ ├── adapter │ │ │ │ │ │ └── NewsListAdapter.kt │ │ │ │ │ ├── convert │ │ │ │ │ │ ├── NewsFunction.kt │ │ │ │ │ │ └── WeatherFunction.kt │ │ │ │ │ ├── entity │ │ │ │ │ │ ├── NewsListBean.kt │ │ │ │ │ │ └── WeatherBean.kt │ │ │ │ │ └── server │ │ │ │ │ │ ├── ApiHelper.kt │ │ │ │ │ │ ├── ApiService.kt │ │ │ │ │ │ └── Config.kt │ │ │ │ ├── BaseActivity.kt │ │ │ │ ├── BaseFragment.kt │ │ │ │ ├── BaseListActivity.kt │ │ │ │ ├── BaseListFragment.kt │ │ │ │ ├── IBaseListView.kt │ │ │ │ ├── IBaseView.kt │ │ │ │ ├── ImageInterface.kt │ │ │ │ ├── WebviewActivity.kt │ │ │ │ ├── WebviewFragment.kt │ │ │ │ └── extra │ │ │ │ │ ├── RecyclerView │ │ │ │ │ ├── CustomLoadMoreView.kt │ │ │ │ │ └── LoadMoreAdapter.kt │ │ │ │ │ └── http │ │ │ │ │ └── CustomObserver.kt │ │ │ ├── mvp │ │ │ │ ├── AATest │ │ │ │ │ ├── TestActivityMvp.kt │ │ │ │ │ ├── TestFragmentMvp.kt │ │ │ │ │ ├── listType │ │ │ │ │ │ ├── TestMvpListActivity.kt │ │ │ │ │ │ ├── TestMvpListFragment.kt │ │ │ │ │ │ ├── TestMvpListModel.kt │ │ │ │ │ │ ├── TestMvpListPresenter.kt │ │ │ │ │ │ └── TestMvpListView.kt │ │ │ │ │ └── notListType │ │ │ │ │ │ ├── TestMvpActivity.kt │ │ │ │ │ │ ├── TestMvpFragment.kt │ │ │ │ │ │ ├── TestMvpModel.kt │ │ │ │ │ │ ├── TestMvpPresenter.kt │ │ │ │ │ │ └── TestMvpView.kt │ │ │ │ ├── BaseActivity.kt │ │ │ │ ├── BaseFragment.kt │ │ │ │ ├── BaseListActivity.kt │ │ │ │ ├── BaseListFragment.kt │ │ │ │ ├── BaseListPresenter.kt │ │ │ │ ├── BasePresenter.kt │ │ │ │ ├── CommonBaseActivity.kt │ │ │ │ ├── CommonBaseFragment.kt │ │ │ │ ├── IBaseListView.kt │ │ │ │ ├── IBaseView.kt │ │ │ │ ├── extra │ │ │ │ │ └── http │ │ │ │ │ │ └── CustomObserver.kt │ │ │ │ └── 注意点.md │ │ │ ├── mvvm │ │ │ │ ├── AATest │ │ │ │ │ ├── TestActivityMvvm.kt │ │ │ │ │ ├── TestFragmentMvvm.kt │ │ │ │ │ ├── convert │ │ │ │ │ │ ├── CustomRequestBodyConverter.kt │ │ │ │ │ │ ├── NewsConverterFactory.kt │ │ │ │ │ │ ├── NewsResponseBodyConverter.kt │ │ │ │ │ │ ├── WeatherConverterFactory.kt │ │ │ │ │ │ └── WeatherResponseBodyConverter.kt │ │ │ │ │ ├── listType │ │ │ │ │ │ ├── TestMvvmListActivity.kt │ │ │ │ │ │ ├── TestMvvmListActivityViewModel.kt │ │ │ │ │ │ ├── TestMvvmListFragment.kt │ │ │ │ │ │ └── TestMvvmListFragmentViewModel.kt │ │ │ │ │ ├── notListType │ │ │ │ │ │ ├── TestMvvmActivity.kt │ │ │ │ │ │ ├── TestMvvmActivityViewModel.kt │ │ │ │ │ │ ├── TestMvvmFragment.kt │ │ │ │ │ │ └── TestMvvmFragmentViewModel.kt │ │ │ │ │ └── server │ │ │ │ │ │ ├── ApiHelper.kt │ │ │ │ │ │ ├── ApiService.kt │ │ │ │ │ │ └── Config.kt │ │ │ │ ├── BaseActivity.kt │ │ │ │ ├── BaseFragment.kt │ │ │ │ ├── BaseListActivity.kt │ │ │ │ ├── BaseListFragment.kt │ │ │ │ ├── BaseListViewModel.kt │ │ │ │ ├── BaseViewModel.kt │ │ │ │ ├── BaseViewModelWithData.kt │ │ │ │ ├── CommonBaseActivity.kt │ │ │ │ ├── CommonBaseFragment.kt │ │ │ │ ├── IBaseListView.kt │ │ │ │ ├── IBaseView.kt │ │ │ │ └── extra │ │ │ │ │ └── LiveDataEntity │ │ │ │ │ ├── DialogConfig.kt │ │ │ │ │ └── ErrorResponse.kt │ │ │ └── permission │ │ │ │ ├── PermissionFrameActivity.kt │ │ │ │ └── PermissionRequestActivity.kt │ │ │ ├── util │ │ │ ├── AlertDialogUtil.kt │ │ │ ├── ApkDownloadUtil.kt │ │ │ ├── AudioUtil.kt │ │ │ ├── BrightnessUtil.kt │ │ │ ├── ByteUnit.kt │ │ │ ├── CPUUtil.kt │ │ │ ├── CacheUtil.kt │ │ │ ├── CapturePicture │ │ │ │ ├── CapturePictureUtil.kt │ │ │ │ ├── TestCaptureGridViewActivity.kt │ │ │ │ ├── TestCaptureListViewActivity.kt │ │ │ │ ├── TestCaptureRecyclerViewActivity.kt │ │ │ │ └── TestCaptureWebViewActivity.kt │ │ │ ├── CheckFastClickUtil.kt │ │ │ ├── CleanUtil.kt │ │ │ ├── CommonLayoutUtil.kt │ │ │ ├── CrashHandler.kt │ │ │ ├── DataDueUtil.kt │ │ │ ├── DateUtil.kt │ │ │ ├── DeviceUtil.kt │ │ │ ├── DigitalUtil.kt │ │ │ ├── DrawableUtil.kt │ │ │ ├── EncodeUtil.kt │ │ │ ├── ExtraUtil.kt │ │ │ ├── FileUtil.kt │ │ │ ├── IOUtil.kt │ │ │ ├── IntentUtil.kt │ │ │ ├── JsonUtil.kt │ │ │ ├── KeyboardUtil.kt │ │ │ ├── LayoutParamsUtil.kt │ │ │ ├── LogUtil.kt │ │ │ ├── NetReceiver.kt │ │ │ ├── NetworkUtil.kt │ │ │ ├── NotificationUtil.kt │ │ │ ├── OnAppBarStateChangeListener.kt │ │ │ ├── OnMultiClickListener.kt │ │ │ ├── PhoneUtil.kt │ │ │ ├── PickerViewUtil.kt │ │ │ ├── PinyinUtil.kt │ │ │ ├── SDCardUtil.kt │ │ │ ├── SPUtil.kt │ │ │ ├── ScreenUtil.kt │ │ │ ├── ShellUtil.kt │ │ │ ├── SizeUtil.kt │ │ │ ├── StatusBar │ │ │ │ ├── StatusBarUtil.kt │ │ │ │ └── TestStatusBarUtilActivity.kt │ │ │ ├── StringUtil.kt │ │ │ ├── TestUtilActivity.kt │ │ │ ├── ToastUtil.kt │ │ │ ├── TransformUtil.kt │ │ │ ├── VibrationUtil.kt │ │ │ ├── ViewExt.kt │ │ │ ├── ZipUtil.kt │ │ │ ├── activity │ │ │ │ ├── ActivityUtil.kt │ │ │ │ └── TestJumpActivity.kt │ │ │ ├── app │ │ │ │ ├── AATest │ │ │ │ │ ├── AppAdapter.kt │ │ │ │ │ └── TestAppListActivity.kt │ │ │ │ ├── AppInfo.kt │ │ │ │ └── AppUtil.kt │ │ │ ├── bitmap │ │ │ │ ├── BitmapUtil.kt │ │ │ │ └── TestBitmapActivity.kt │ │ │ ├── code │ │ │ │ ├── BarCodeUtil.kt │ │ │ │ ├── QRCodeUtil.kt │ │ │ │ └── TestCodeUtilActivity.kt │ │ │ ├── encrypt │ │ │ │ ├── AESCBCUtil.kt │ │ │ │ ├── AESUtil.kt │ │ │ │ ├── Base64.kt │ │ │ │ ├── DESCBCUtil.kt │ │ │ │ ├── DESUtil.kt │ │ │ │ ├── MessageDigestUtil.kt │ │ │ │ ├── RSAUtil.kt │ │ │ │ └── SingtureUtil.kt │ │ │ ├── glide │ │ │ │ ├── GlideUtil.kt │ │ │ │ ├── SectionRoundedCorners.kt │ │ │ │ └── TestGlideActivity.kt │ │ │ ├── location │ │ │ │ ├── LocationService.kt │ │ │ │ └── LocationUtil.kt │ │ │ ├── permission │ │ │ │ ├── PermissionUtil.kt │ │ │ │ └── TestPermissionActivity.kt │ │ │ ├── regex │ │ │ │ ├── RegexConstant.kt │ │ │ │ └── RegexUtil.kt │ │ │ ├── service │ │ │ │ ├── ServiceUtil.kt │ │ │ │ └── TestService.kt │ │ │ └── threadPool │ │ │ │ ├── AATest │ │ │ │ ├── CalculateTask.kt │ │ │ │ └── TestThreadPoolUtilActivity.kt │ │ │ │ ├── StepThread.kt │ │ │ │ ├── ThreadPoolManager.kt │ │ │ │ └── ThreadPoolUtil.kt │ │ │ └── widget │ │ │ ├── ArcView.kt │ │ │ ├── CustomViewPager.kt │ │ │ ├── DashLine.kt │ │ │ ├── ExpandTextView │ │ │ ├── BoldInfo.kt │ │ │ ├── ColorInfo.kt │ │ │ └── ExpandTextView.kt │ │ │ ├── FloatWindow │ │ │ ├── NeedPermission │ │ │ │ ├── AATest │ │ │ │ │ ├── TestFloatPageOneActivity.kt │ │ │ │ │ ├── TestFloatPageThreeActivity.kt │ │ │ │ │ └── TestFloatPageTwoActivity.kt │ │ │ │ ├── FloatActivity.kt │ │ │ │ ├── FloatLifecycle.kt │ │ │ │ ├── FloatPermissionUtil.kt │ │ │ │ ├── FloatWindow.kt │ │ │ │ ├── IFloatWindow.kt │ │ │ │ ├── IFloatWindowImpl.kt │ │ │ │ ├── MoveType.kt │ │ │ │ ├── OnPermissionListener.kt │ │ │ │ ├── OnViewStateListener.kt │ │ │ │ ├── ScreenType.kt │ │ │ │ └── compat │ │ │ │ │ └── MIUI.kt │ │ │ ├── NoPermission │ │ │ │ ├── AATest │ │ │ │ │ └── TestFloatPageActivity.kt │ │ │ │ ├── FloatWindow.kt │ │ │ │ ├── IFloatWindow.kt │ │ │ │ ├── MoveType.kt │ │ │ │ └── ScreenType.kt │ │ │ └── TestFloatActivity.kt │ │ │ ├── IndicatorLayout.kt │ │ │ ├── InputLayout.kt │ │ │ ├── LetterIndexBar │ │ │ ├── BubbleLetterIndexBar.kt │ │ │ ├── LetterIndexBar.kt │ │ │ └── TestLetterIndexBarActivity.kt │ │ │ ├── LineChart │ │ │ ├── TestLineChartActivity.kt │ │ │ ├── type1 │ │ │ │ └── LineChart.kt │ │ │ └── type2 │ │ │ │ └── LineChart.kt │ │ │ ├── LoadingDialog │ │ │ ├── LoadingDialog.kt │ │ │ └── LoadingView.kt │ │ │ ├── LoadingLayout │ │ │ ├── LoadingLayout.kt │ │ │ └── TestLoadingLayoutActivity.kt │ │ │ ├── MaxHeightRecyclerView.kt │ │ │ ├── NestedWebView.kt │ │ │ ├── PasswordEditText.kt │ │ │ ├── PhotoViewer │ │ │ ├── PhotoViewActivity.kt │ │ │ ├── PhotoViewAdapter.kt │ │ │ ├── helper │ │ │ │ └── CustomGestureDetector.kt │ │ │ ├── listener │ │ │ │ ├── OnGestureListener.kt │ │ │ │ ├── OnMatrixChangedListener.kt │ │ │ │ ├── OnOutsidePhotoTapListener.kt │ │ │ │ ├── OnPhotoTapListener.kt │ │ │ │ ├── OnScaleChangedListener.kt │ │ │ │ ├── OnSingleFlingListener.kt │ │ │ │ ├── OnViewDragListener.kt │ │ │ │ └── OnViewTapListener.kt │ │ │ └── widget │ │ │ │ ├── PhotoView.kt │ │ │ │ ├── PhotoViewAttacher.kt │ │ │ │ └── PhotoViewPager.kt │ │ │ ├── PicGetterDialog │ │ │ ├── AATest │ │ │ │ ├── CustomPicGetterDialog.kt │ │ │ │ └── TestPicGetterDialogActivity.kt │ │ │ ├── BasePicGetterDialog.kt │ │ │ ├── OnPicGetterListener.kt │ │ │ ├── PicGetterDialog.kt │ │ │ └── 说明.md │ │ │ ├── PieChart │ │ │ ├── PieData.kt │ │ │ ├── TestPieChartActivity.kt │ │ │ ├── type1 │ │ │ │ └── PieChart.kt │ │ │ └── type2 │ │ │ │ └── PieChart.kt │ │ │ ├── PopupWindow │ │ │ ├── AATest │ │ │ │ ├── PopupWindowAdapter.kt │ │ │ │ └── TestPopupWindowActivity.kt │ │ │ ├── CommonPopupWindow.kt │ │ │ └── WindowHelper.kt │ │ │ ├── ProgressBar │ │ │ ├── CircleProgressBar.kt │ │ │ └── TestProgressBarActivity.kt │ │ │ ├── RecyclerView │ │ │ ├── AATest │ │ │ │ ├── TestFooterAdapter.kt │ │ │ │ ├── TestFooterAdapterActivity.kt │ │ │ │ ├── TestHeaderAdapter.kt │ │ │ │ ├── TestHeaderAdapterActivity.kt │ │ │ │ ├── TestLoadMoreWrapper.kt │ │ │ │ ├── TestLoadMoreWrapperActivity.kt │ │ │ │ ├── TestMultiAdapter.kt │ │ │ │ ├── TestMultiAdapterActivity.kt │ │ │ │ ├── TestMultiLoadMoreAdapter.kt │ │ │ │ ├── TestMultiLoadMoreAdapterActivity.kt │ │ │ │ ├── TestRecyclerViewActivity.kt │ │ │ │ ├── TestSingleAdapter.kt │ │ │ │ ├── TestSingleAdapterActivity.kt │ │ │ │ ├── TestSingleLoadMoreAdapter.kt │ │ │ │ ├── TestSingleLoadMoreAdapterActivity.kt │ │ │ │ └── entity │ │ │ │ │ ├── DateBean.kt │ │ │ │ │ ├── DetailBean.kt │ │ │ │ │ └── MonthBean.kt │ │ │ ├── BaseAdapter.kt │ │ │ ├── LoadMoreAdapter.kt │ │ │ ├── LoadMoreListener.kt │ │ │ ├── LoadMoreWrapper.kt │ │ │ ├── MultiViewType.kt │ │ │ └── ViewHolder.kt │ │ │ ├── RoundImageView.kt │ │ │ ├── ScrollTextView.kt │ │ │ ├── SearchLayout.kt │ │ │ ├── SuffixTextView.kt │ │ │ ├── TestSingleWidgetActivity.kt │ │ │ ├── TitleBar.kt │ │ │ ├── VerificationCodeEditText.kt │ │ │ ├── ViewHolder.kt │ │ │ └── dialog │ │ │ ├── BaseDialog.kt │ │ │ ├── CommonDialog.kt │ │ │ ├── ConfirmDialog.kt │ │ │ └── TestDialogActivity.kt │ └── res │ │ ├── layout │ │ ├── activity_capture.xml │ │ ├── activity_common_layout.xml │ │ ├── activity_guide.xml │ │ ├── activity_list_layout.xml │ │ ├── activity_main.xml │ │ ├── activity_photo_view.xml │ │ ├── activity_scan.xml │ │ ├── activity_test_adapter.xml │ │ ├── activity_test_bitmap.xml │ │ ├── activity_test_capture_gridview.xml │ │ ├── activity_test_capture_listview.xml │ │ ├── activity_test_capture_recyclerview.xml │ │ ├── activity_test_capture_webview.xml │ │ ├── activity_test_code_util.xml │ │ ├── activity_test_fragment.xml │ │ ├── activity_test_glide.xml │ │ ├── activity_test_letter_index_bar.xml │ │ ├── activity_test_line_chart.xml │ │ ├── activity_test_loading_layout.xml │ │ ├── activity_test_mvc.xml │ │ ├── activity_test_mvc_list.xml │ │ ├── activity_test_pic_getter_dialog.xml │ │ ├── activity_test_pie_chart.xml │ │ ├── activity_test_popup_window.xml │ │ ├── activity_test_progress_bar.xml │ │ ├── activity_test_single_widget.xml │ │ ├── activity_weather.xml │ │ ├── activity_webview.xml │ │ ├── fragment_frame.xml │ │ ├── fragment_test_mvc.xml │ │ ├── fragment_test_mvc_list.xml │ │ ├── fragment_util.xml │ │ ├── fragment_webview.xml │ │ ├── fragment_widget.xml │ │ └── view_load_more.xml │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── android │ └── basicproject │ └── ExampleUnitTest.kt ├── settings.gradle └── universal ├── .gitignore ├── BasicProject.jks ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── android │ └── universal │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── assets │ ├── fonts │ │ └── fonts.ttf │ └── test_install.apk ├── java │ └── com │ │ └── android │ │ └── universal │ │ ├── TestSystemWidgetActivity.kt │ │ └── TestSystemWidgetFragment.kt └── res │ ├── anim │ ├── alpha_in_150.xml │ ├── alpha_in_300.xml │ ├── alpha_out_150.xml │ ├── alpha_out_300.xml │ ├── scale_bottom_in.xml │ ├── scale_bottom_out.xml │ ├── scale_center_in.xml │ ├── scale_center_out.xml │ ├── scale_left_in.xml │ ├── scale_left_out.xml │ ├── scale_right_in.xml │ ├── scale_right_out.xml │ ├── scale_top_in.xml │ ├── scale_top_out.xml │ ├── slide_left_in.xml │ ├── slide_left_out.xml │ ├── slide_right_in.xml │ ├── slide_right_out.xml │ ├── translate_bottom_in.xml │ ├── translate_bottom_out.xml │ ├── translate_left_in.xml │ ├── translate_left_out.xml │ ├── translate_right_in.xml │ ├── translate_right_out.xml │ ├── translate_top_in.xml │ └── translate_top_out.xml │ ├── color │ ├── selector_tab_text_color.xml │ └── selector_toggle_button_text_color.xml │ ├── drawable-xhdpi │ ├── ic_add.png │ ├── ic_back.png │ ├── ic_bg.png │ ├── ic_bitmap.jpg │ ├── ic_check.png │ ├── ic_clear.png │ ├── ic_coupon_btn.png │ ├── ic_coupon_header.png │ ├── ic_empty_data.png │ ├── ic_face1.png │ ├── ic_face2.png │ ├── ic_face3.png │ ├── ic_flashlight_off.png │ ├── ic_flashlight_on.png │ ├── ic_frame_not_selected.png │ ├── ic_frame_selected.png │ ├── ic_guide_bg.png │ ├── ic_guide_one.png │ ├── ic_guide_three.png │ ├── ic_guide_two.png │ ├── ic_letter_bubble.png │ ├── ic_load_empty.png │ ├── ic_load_fail.png │ ├── ic_load_loading.png │ ├── ic_more.png │ ├── ic_msg.png │ ├── ic_photo_close.png │ ├── ic_photo_download.png │ ├── ic_photo_load_fail.png │ ├── ic_qq.png │ ├── ic_query.png │ ├── ic_scan_grid.png │ ├── ic_search_clear.png │ ├── ic_search_search.png │ ├── ic_settings.png │ ├── ic_status_bar.jpeg │ ├── ic_uncheck.png │ ├── ic_util_not_selected.png │ ├── ic_util_selected.png │ ├── ic_warn.png │ ├── ic_weibo.png │ ├── ic_weixin.png │ ├── ic_widget_not_selected.png │ └── ic_widget_selected.png │ ├── drawable │ ├── layer_list_bg.xml │ ├── layer_list_input_layout.xml │ ├── layer_list_progress_drawable.xml │ ├── layer_list_shadow_bg1.xml │ ├── layer_list_shadow_bg2.xml │ ├── loading_progressbar_bg.xml │ ├── selector_bottom_frame.xml │ ├── selector_bottom_util.xml │ ├── selector_bottom_widget.xml │ ├── selector_btn_bg.xml │ ├── selector_flash_light_switch.xml │ ├── selector_gray_item_layout_bg.xml │ ├── selector_guide_indicator.xml │ ├── selector_guide_use_btn_bg.xml │ ├── selector_item_check_btn.xml │ ├── selector_item_layout_bg.xml │ ├── selector_tab_text_color.xml │ ├── selector_toggle_button_bg.xml │ ├── shape_confirm_dialog.xml │ ├── shape_corners_10_solid_000000.xml │ ├── shape_corners_15_solid_ffffff.xml │ ├── shape_corners_15_solid_transparent.xml │ ├── shape_corners_17_solid_66000000.xml │ ├── shape_coupon_dialog.xml │ ├── shape_cursor_drawable.xml │ ├── shape_indicator_bg.xml │ ├── shape_loading_btn_bg.xml │ ├── shape_loading_dialog_bg.xml │ ├── shape_oval_size_34_solid_66000000.xml │ ├── shape_oval_size_34_solid_db4b3c.xml │ ├── shape_photo_view_progress_bg.xml │ ├── shape_progressbar_bg.xml │ ├── shape_progressbar_progress.xml │ ├── shape_search_layout.xml │ ├── shape_size_2_solid_0071ff.xml │ └── shape_spannable_block.xml │ ├── layout │ ├── activity_test_system_widget.xml │ ├── dialog_app_detail.xml │ ├── dialog_confirm.xml │ ├── dialog_custom_pic_getter.xml │ ├── dialog_loading.xml │ ├── dialog_loading_layout.xml │ ├── dialog_pic_getter.xml │ ├── fragment_test_system_widget1.xml │ ├── fragment_test_system_widget2.xml │ ├── fragment_test_system_widget3.xml │ ├── fragment_test_system_widget4.xml │ ├── fragment_test_system_widget5.xml │ ├── fragment_test_system_widget6.xml │ ├── fragment_test_system_widget7.xml │ ├── fragment_test_system_widget8.xml │ ├── item_detail.xml │ ├── item_header.xml │ ├── item_image_with_text.xml │ ├── item_month.xml │ ├── item_photo_view_pager.xml │ ├── item_popup_window.xml │ ├── item_test_capture.xml │ ├── item_test_load_more.xml │ ├── item_text_with_checkbox.xml │ ├── item_text_with_image.xml │ ├── layout_comment_dialog.xml │ ├── layout_coupon_dialog.xml │ ├── layout_empty_view.xml │ ├── layout_float.xml │ ├── layout_guide_one.xml │ ├── layout_guide_three.xml │ ├── layout_guide_two.xml │ ├── layout_image.xml │ ├── layout_input.xml │ ├── layout_loading.xml │ ├── layout_net_error.xml │ ├── layout_popup_window_full.xml │ ├── layout_popup_window_to_bottom1.xml │ ├── layout_popup_window_to_bottom2.xml │ ├── layout_popup_window_to_left_or_right.xml │ ├── layout_popup_window_to_top.xml │ ├── layout_recycler_view.xml │ ├── layout_refresh_footer.xml │ ├── layout_search.xml │ ├── layout_share_dialog.xml │ ├── layout_tab_content.xml │ ├── layout_title_bar.xml │ └── layout_toast.xml │ ├── mipmap-hdpi │ └── ic_logo.png │ ├── mipmap-mdpi │ └── ic_logo.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_logo.png │ ├── mipmap-xxhdpi │ └── ic_logo.png │ ├── mipmap-xxxhdpi │ └── ic_logo.png │ ├── raw │ ├── beep.mp3 │ ├── hex_alpha_table │ └── notification.mp3 │ ├── values │ ├── arrays.xml │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── ids.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ ├── network_security_config.xml │ └── provider_paths.xml └── test └── java └── com └── android └── universal └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /.idea/* 3 | .gradle 4 | /local.properties 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /apk/Java_release_v1.0.0(002).apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/apk/Java_release_v1.0.0(002).apk -------------------------------------------------------------------------------- /apk/Kotlin_release_v1.0.0(001).apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/apk/Kotlin_release_v1.0.0(001).apk -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # Kotlin code style for this project: "official" or "obsolete": 15 | kotlin.code.style=official 16 | android.useAndroidX=true 17 | android.enableJetifier=true 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Oct 19 16:21:05 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip 7 | -------------------------------------------------------------------------------- /java/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /java/src/androidTest/java/com/android/java/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.android.java; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.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.android.java.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/base/DontSwipeBack.java: -------------------------------------------------------------------------------- 1 | package com.android.base; 2 | 3 | /** 4 | * Created by xuzhb on 2020/12/30 5 | * Desc:不需要侧滑退出Activity 6 | */ 7 | public interface DontSwipeBack { 8 | } 9 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/TestLeakActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.frame; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | 6 | import com.android.frame.mvc.BaseActivity; 7 | import com.android.java.R; 8 | import com.android.java.databinding.ActivityCommonLayoutBinding; 9 | import com.android.util.CommonLayoutUtil; 10 | 11 | /** 12 | * Created by xuzhb on 2019/11/2 13 | * Desc:测试内存泄漏 14 | */ 15 | public class TestLeakActivity extends BaseActivity { 16 | 17 | private static Context mContext; 18 | 19 | @Override 20 | public void handleView(Bundle savedInstanceState) { 21 | CommonLayoutUtil.initCommonLayout(this, "测试内存泄漏"); 22 | mContext = this; //测试内存泄漏 23 | } 24 | 25 | @Override 26 | public void initListener() { 27 | 28 | } 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/http/AATest/UrlConstant.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.AATest; 2 | 3 | /** 4 | * Created by xuzhb on 2019/10/26 5 | * Desc: 6 | */ 7 | public class UrlConstant { 8 | 9 | public static final String BAIDU_URL = "https://www.baidu.com/"; 10 | 11 | public static final String WEATHER_URL = "http://wthrcdn.etouch.cn/"; 12 | 13 | public static final String NEWS_URL = "https://api.apiopen.top/"; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/http/SchedulerUtil.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.http; 2 | 3 | import io.reactivex.Observable; 4 | import io.reactivex.ObservableSource; 5 | import io.reactivex.ObservableTransformer; 6 | import io.reactivex.android.schedulers.AndroidSchedulers; 7 | import io.reactivex.schedulers.Schedulers; 8 | 9 | /** 10 | * Created by xuzhb on 2019/10/26 11 | * Desc:简化subscribeOn和observeOn调用 12 | */ 13 | public class SchedulerUtil { 14 | 15 | public static ObservableTransformer ioToMain() { 16 | return new ObservableTransformer() { 17 | @Override 18 | public ObservableSource apply(Observable upstream) { 19 | return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); 20 | } 21 | }; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/http/converter/说明.md: -------------------------------------------------------------------------------- 1 | # 自定义GsonConverter解决服务器返回数据格式不一致问题 2 | 参考: 3 | https://blog.csdn.net/Z_DingHao/article/details/78602950 4 | https://blog.csdn.net/u010386612/article/details/67637695 5 | https://blog.csdn.net/w525721508/article/details/78018207 6 | ## GsonConverterFactory转换原理 7 | 相关的三个类: 8 | GsonConverterFactory 9 | GsonRequestBodyConverter:POST请求时将请求的实体转转化成Json 10 | GsonResponseBodyConverter:接收服务器返回数据时将Json转化成对应的实体 11 | 重写GsonResponseBodyConverter转换逻辑即可 -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/http/model/BaseResponse.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by xuzhb on 2019/10/26 7 | * Desc:bean基类,非列表类型 8 | */ 9 | public class BaseResponse implements Serializable { 10 | 11 | private int code; 12 | private String msg; 13 | private T data; 14 | 15 | public int getCode() { 16 | return code; 17 | } 18 | 19 | public void setCode(int code) { 20 | this.code = code; 21 | } 22 | 23 | public String getMsg() { 24 | return msg; 25 | } 26 | 27 | public void setMsg(String msg) { 28 | this.msg = msg; 29 | } 30 | 31 | public T getData() { 32 | return data; 33 | } 34 | 35 | public void setData(T data) { 36 | this.data = data; 37 | } 38 | 39 | public boolean isSuccess() { 40 | return this.code == 200; 41 | } 42 | 43 | public boolean isTokenOut() { //登录失效 44 | return this.code == -111; //这里假设code是-111 45 | } 46 | 47 | public String getMessage() { 48 | return msg; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvc/AATest/entity/NewsListBean.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by xuzhb on 2021/1/1 7 | * Desc: 8 | */ 9 | public class NewsListBean implements Serializable { 10 | 11 | private String path; 12 | private String image; 13 | private String title; 14 | private String passtime; 15 | 16 | public String getPath() { 17 | return path; 18 | } 19 | 20 | public void setPath(String path) { 21 | this.path = path; 22 | } 23 | 24 | public String getImage() { 25 | return image; 26 | } 27 | 28 | public void setImage(String image) { 29 | this.image = image; 30 | } 31 | 32 | public String getTitle() { 33 | return title; 34 | } 35 | 36 | public void setTitle(String title) { 37 | this.title = title; 38 | } 39 | 40 | public String getPasstime() { 41 | return passtime; 42 | } 43 | 44 | public void setPasstime(String passtime) { 45 | this.passtime = passtime; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvc/AATest/server/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.server; 2 | 3 | import io.reactivex.Observable; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.http.Field; 6 | import retrofit2.http.FormUrlEncoded; 7 | import retrofit2.http.GET; 8 | import retrofit2.http.POST; 9 | import retrofit2.http.Query; 10 | 11 | /** 12 | * Created by xuzhb on 2021/1/1 13 | * Desc: 14 | */ 15 | public interface ApiService { 16 | 17 | //获取天气信息,@Query,GET请求 18 | @GET("weather_mini") 19 | Observable getWeatherByQuery(@Query("city") String city); 20 | 21 | //获取网易新闻,@Field,POST请求 22 | @FormUrlEncoded 23 | @POST("getWangYiNews") 24 | Observable getWangYiNewsByField(@Field("page") int page, @Field("count") int count); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvc/AATest/server/Config.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.server; 2 | 3 | /** 4 | * Created by xuzhb on 2021/1/1 5 | * Desc: 6 | */ 7 | public class Config { 8 | 9 | public static final String WEATHER_URL = "http://wthrcdn.etouch.cn/"; 10 | 11 | public static final String NEWS_URL = "https://api.apiopen.top/"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvc/IBaseListView.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by xuzhb on 2021/8/13 7 | */ 8 | public interface IBaseListView extends IBaseView { 9 | 10 | /** 11 | * 获取加载的起始页码 12 | */ 13 | int getFirstPage(); 14 | 15 | /** 16 | * 是否是首次加载 17 | */ 18 | boolean isFirstLoad(); 19 | 20 | /** 21 | * 获取一页加载的个数 22 | */ 23 | int getLoadSize(); 24 | 25 | /** 26 | * 显示数据 27 | */ 28 | void showData(int page, List list); 29 | 30 | /** 31 | * 处理数据 32 | */ 33 | List convertData(List response); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvc/extra/RecyclerView/LoadMoreAdapter.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.extra.RecyclerView; 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter; 4 | import com.chad.library.adapter.base.module.LoadMoreModule; 5 | import com.chad.library.adapter.base.viewholder.BaseViewHolder; 6 | 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Created by xuzhb on 2020/12/31 13 | * Desc:上拉加载更多 14 | */ 15 | public abstract class LoadMoreAdapter extends BaseQuickAdapter implements LoadMoreModule { 16 | 17 | public LoadMoreAdapter(int layoutResId) { 18 | super(layoutResId); 19 | } 20 | 21 | public LoadMoreAdapter(int layoutResId, @Nullable List data) { 22 | super(layoutResId, data); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/AATest/listType/TestMvpListView.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.listType; 2 | 3 | import com.android.frame.mvc.AATest.entity.NewsListBean; 4 | import com.android.frame.mvp.IBaseListView; 5 | 6 | /** 7 | * Created by xuzhb on 2021/1/4 8 | * Desc: 9 | */ 10 | public interface TestMvpListView extends IBaseListView { 11 | } 12 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/AATest/notListType/TestMvpModel.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.notListType; 2 | 3 | import com.android.frame.http.RetrofitFactory; 4 | import com.android.frame.http.SchedulerUtil; 5 | import com.android.frame.http.model.BaseResponse; 6 | import com.android.frame.mvc.AATest.convert.WeatherFunction; 7 | import com.android.frame.mvc.AATest.entity.WeatherBean; 8 | import com.android.frame.mvc.AATest.server.ApiService; 9 | import com.android.frame.mvc.AATest.server.Config; 10 | 11 | import java.util.concurrent.TimeUnit; 12 | 13 | import io.reactivex.Observable; 14 | 15 | /** 16 | * Created by xuzhb on 2021/1/4 17 | * Desc: 18 | */ 19 | public class TestMvpModel { 20 | 21 | public Observable> getWeatherInfo(String city) { 22 | return RetrofitFactory.getInstance().createService(ApiService.class, Config.WEATHER_URL, true) 23 | .getWeatherByQuery(city) 24 | .delay(1, TimeUnit.SECONDS) //模拟延迟一段时间后请求到数据的情况 25 | .map(new WeatherFunction()) 26 | .compose(SchedulerUtil.ioToMain()); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/AATest/notListType/TestMvpView.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.notListType; 2 | 3 | import com.android.frame.mvc.AATest.entity.WeatherBean; 4 | import com.android.frame.mvp.IBaseView; 5 | 6 | /** 7 | * Created by xuzhb on 2021/1/4 8 | * Desc: 9 | */ 10 | public interface TestMvpView extends IBaseView { 11 | 12 | void showWeatherInfo(String city, WeatherBean bean); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp; 2 | 3 | /** 4 | * Created by xuzhb on 2020/1/5 5 | * Desc:MVP中的基类Presenter 6 | */ 7 | public class BasePresenter { 8 | 9 | protected V mView; 10 | 11 | //绑定View 12 | public void attachView(V view) { 13 | this.mView = view; 14 | } 15 | 16 | //解绑View 17 | public void detachView() { 18 | this.mView = null; 19 | } 20 | 21 | public boolean isAttach() { 22 | return mView != null; 23 | } 24 | 25 | //加载数据,进入页面时默认就会进行加载,请务必重写refreshData,当加载失败点击重试或者下拉刷新时会调用这个方法 26 | public void refreshData() { 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/CommonBaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp; 2 | 3 | import androidx.viewbinding.ViewBinding; 4 | 5 | /** 6 | * Created by xuzhb on 2020/1/8 7 | * Desc:不需要额外声明View和Presenter的Activity的父类 8 | */ 9 | public abstract class CommonBaseActivity extends BaseActivity> implements IBaseView { 10 | 11 | @Override 12 | public BasePresenter getPresenter() { 13 | return new BasePresenter<>(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/CommonBaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp; 2 | 3 | import androidx.viewbinding.ViewBinding; 4 | 5 | /** 6 | * Created by xuzhb on 2020/1/8 7 | * Desc:不需要额外声明View和Presenter的Fragment的父类 8 | */ 9 | public abstract class CommonBaseFragment extends BaseFragment> implements IBaseView { 10 | 11 | @Override 12 | public BasePresenter getPresenter() { 13 | return new BasePresenter<>(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/IBaseListView.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by xuzhb on 2020/7/22 7 | * Desc:列表数据对应的基类View 8 | */ 9 | public interface IBaseListView extends IBaseView { 10 | 11 | /** 12 | * 获取当前加载的页码 13 | */ 14 | int getCurrentPage(); 15 | 16 | /** 17 | * 设置当前加载的页码 18 | */ 19 | void setCurrentPage(int page); 20 | 21 | /** 22 | * 获取加载的起始页码 23 | */ 24 | int getFirstPage(); 25 | 26 | /** 27 | * 是否是首次加载 28 | */ 29 | boolean isFirstLoad(); 30 | 31 | /** 32 | * 获取一页加载的个数 33 | */ 34 | int getLoadSize(); 35 | 36 | /** 37 | * 显示数据 38 | */ 39 | void showData(int page, List list); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvp/注意点.md: -------------------------------------------------------------------------------- 1 | BaseCompatActivity:基类Activity 2 | BaseFragment:基类Fragment 3 | IBaseView:基类View 4 | BasePresenter:基类Presenter 5 | CommonBaseActivity:不需要额外声明View和Presenter的Activity父类 6 | CommonBaseFragment:不需要额外声明View和Presenter的Fragment父类 7 | LoadingDialog:自定义加载框 8 | CustomObserver:自定义Observer,加入加载框和网络错误的处理 9 | NetReceiver:广播监听网络变化,动态注册 10 | activity_list_layout:通用的列表布局,包括标题栏和layout_net_error和layout_recycler_view 11 | layout_net_error:网络错误提示布局 12 | layout_recycler_view:通用的列表刷新子布局,包括一个SwipeRefreshLayout和一个RecyclerView 13 | 14 | 集成时注意: 15 | 1、实现BaseCompatActivity和BaseFragment的gotoLogin()方法 16 | 2、处理CustomObserver中登录失效的code,目前暂定登录过期的code是-1001 17 | 3、处理基类Bean,即BaseResponse和BaseListResponse的结构 18 | 4、处理基类Bean接口请求成功的code,目前暂定接口请求成功的code是200 19 | 20 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvvm/AATest/listType/TestMvvmListFragmentViewModel.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.listType; 2 | 3 | import com.android.frame.mvc.AATest.entity.NewsListBean; 4 | import com.android.frame.mvvm.AATest.server.ApiHelper; 5 | import com.android.frame.mvvm.BaseListViewModel; 6 | 7 | /** 8 | * Created by xuzhb on 2021/8/9 9 | * Desc: 10 | */ 11 | public class TestMvvmListFragmentViewModel extends BaseListViewModel { 12 | 13 | //第一种写法 14 | // @Override 15 | // public Observable> loadDataFromServer(int page, int count) { 16 | // return ApiHelper.getWangYiNewsByField(page, count); 17 | // } 18 | 19 | //第二种写法 20 | //如果只是从服务器获取并展示列表数据,那么采用第一种写法重写loadDataFromServer返回相应的接口即可 21 | //但如果有需要处理其他逻辑,那么就需要重写loadData,并且在获取到数据后重写对应Activity的observerListDataChange方法, 22 | //在里面调用showData展示列表数据 23 | @Override 24 | public void loadData(int page, int count, boolean showLoadLayout, boolean showLoadingDialog) { 25 | launch(ApiHelper.getWangYiNewsByField(page, count), successData, errorData, false, page == 1); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvvm/AATest/notListType/TestMvvmActivityViewModel.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.notListType; 2 | 3 | import com.android.frame.http.model.BaseResponse; 4 | import com.android.frame.mvc.AATest.entity.WeatherBean; 5 | import com.android.frame.mvvm.AATest.server.ApiHelper; 6 | import com.android.frame.mvvm.BaseViewModelWithData; 7 | 8 | /** 9 | * Created by xuzhb on 2021/8/9 10 | * Desc:BaseViewModelWithData的使用,简化了很多,BaseViewModel的使用参见TestMvvmFragmentViewModel 11 | */ 12 | public class TestMvvmActivityViewModel extends BaseViewModelWithData> { 13 | 14 | public void showWeatherInfo(String city) { 15 | launchMain(ApiHelper.getWeatherByQuery(city)); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvvm/AATest/server/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.server; 2 | 3 | import com.android.frame.http.model.BaseListResponse; 4 | import com.android.frame.http.model.BaseResponse; 5 | import com.android.frame.mvc.AATest.entity.NewsListBean; 6 | import com.android.frame.mvc.AATest.entity.WeatherBean; 7 | 8 | import io.reactivex.Observable; 9 | import retrofit2.http.Field; 10 | import retrofit2.http.FormUrlEncoded; 11 | import retrofit2.http.GET; 12 | import retrofit2.http.POST; 13 | import retrofit2.http.Query; 14 | 15 | /** 16 | * Created by xuzhb on 2021/8/10 17 | * Desc: 18 | */ 19 | public interface ApiService { 20 | 21 | //获取天气信息,@Query,GET请求 22 | @GET("weather_mini") 23 | Observable> getWeatherByQuery(@Query("city") String city); 24 | 25 | //获取网易新闻,@Field,POST请求 26 | @FormUrlEncoded 27 | @POST("getWangYiNews") 28 | Observable> getWangYiNewsByField(@Field("page") int page, @Field("count") int count); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvvm/AATest/server/Config.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.server; 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/10 5 | * Desc: 6 | */ 7 | public class Config { 8 | 9 | public static final String WEATHER_URL = "http://wthrcdn.etouch.cn/"; 10 | 11 | public static final String NEWS_URL = "https://api.apiopen.top/"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvvm/IBaseListView.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by xuzhb on 2021/8/9 7 | */ 8 | public interface IBaseListView extends IBaseView { 9 | 10 | /** 11 | * 获取加载的起始页码 12 | */ 13 | int getFirstPage(); 14 | 15 | /** 16 | * 是否是首次加载 17 | */ 18 | boolean isFirstLoad(); 19 | 20 | /** 21 | * 获取一页加载的个数 22 | */ 23 | int getLoadSize(); 24 | 25 | /** 26 | * 显示数据 27 | */ 28 | void showData(int page, List list); 29 | 30 | /** 31 | * 处理数据 32 | */ 33 | List convertData(List response); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/frame/mvvm/extra/LiveDataEntity/DialogConfig.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.extra.LiveDataEntity; 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/9 5 | * Desc:对话框配置信息 6 | */ 7 | public class DialogConfig { 8 | 9 | private String message; 10 | private boolean cancelable; 11 | 12 | public DialogConfig(String message, boolean cancelable) { 13 | this.message = message; 14 | this.cancelable = cancelable; 15 | } 16 | 17 | public String getMessage() { 18 | return message; 19 | } 20 | 21 | public void setMessage(String message) { 22 | this.message = message; 23 | } 24 | 25 | public boolean isCancelable() { 26 | return cancelable; 27 | } 28 | 29 | public void setCancelable(boolean cancelable) { 30 | this.cancelable = cancelable; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/util/HandlerUtil.java: -------------------------------------------------------------------------------- 1 | package com.android.util; 2 | 3 | import android.os.Handler; 4 | import android.os.Message; 5 | 6 | import java.lang.ref.WeakReference; 7 | 8 | /** 9 | * Created by xuzhb on 2021/1/13 10 | * Desc:Handler工具类 11 | */ 12 | public final class HandlerUtil { 13 | 14 | private HandlerUtil() { 15 | } 16 | 17 | public static class HandlerHolder extends Handler { 18 | WeakReference mListenerWeakReference; 19 | 20 | /** 21 | * 使用必读:推荐在Activity或者Activity内部持有类中实现该接口,不要使用匿名类,可能会被GC 22 | * 23 | * @param listener 收到消息回调接口 24 | */ 25 | public HandlerHolder(Callback listener) { 26 | mListenerWeakReference = new WeakReference<>(listener); 27 | } 28 | 29 | @Override 30 | public void handleMessage(Message msg) { 31 | if (mListenerWeakReference != null && mListenerWeakReference.get() != null) { 32 | mListenerWeakReference.get().handleMessage(msg); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /java/src/main/java/com/android/util/NetReceiver.java: -------------------------------------------------------------------------------- 1 | package com.android.util; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | 8 | /** 9 | * Created by xuzhb on 2020/1/5 10 | * Desc:监听网络变化 11 | */ 12 | public class NetReceiver extends BroadcastReceiver { 13 | 14 | @Override 15 | public void onReceive(Context context, Intent intent) { 16 | if (intent != null) { 17 | if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { 18 | mListener.onNetChange(NetworkUtil.isConnected(context)); 19 | } 20 | } 21 | } 22 | 23 | public interface OnNetChangeListener { 24 | void onNetChange(boolean isConnected); 25 | } 26 | 27 | private OnNetChangeListener mListener; 28 | 29 | public void setOnNetChangeListener(OnNetChangeListener listener) { 30 | this.mListener = listener; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/util/SystemUtil.java: -------------------------------------------------------------------------------- 1 | package com.android.util; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageManager; 6 | 7 | /** 8 | * Created by xuzhb on 2019/12/7 9 | * Desc:系统工具 10 | */ 11 | public class SystemUtil { 12 | 13 | private static final String TAG = "SystemUtil"; 14 | 15 | //获取应用UID 16 | public static int getUid(Context context, String packageName) { 17 | int uid = -1; 18 | try { 19 | PackageManager pm = context.getPackageManager(); 20 | ApplicationInfo ai = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); 21 | uid = ai.uid; 22 | LogUtil.i(TAG, "label:" + ai.loadLabel(pm) + "\tuid:" + ai.uid); 23 | } catch (PackageManager.NameNotFoundException e) { 24 | e.printStackTrace(); 25 | } 26 | return uid; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/util/app/AATest/AppAdapter.java: -------------------------------------------------------------------------------- 1 | package com.android.util.app.AATest; 2 | 3 | import android.content.Context; 4 | import com.android.java.R; 5 | import com.android.util.app.AppInfo; 6 | import com.android.widget.RecyclerView.BaseAdapter; 7 | import com.android.widget.RecyclerView.ViewHolder; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Created by xuzhb on 2020/2/5 13 | * Desc: 14 | */ 15 | public class AppAdapter extends BaseAdapter { 16 | 17 | public AppAdapter(Context context, List dataList) { 18 | super(context, dataList, R.layout.item_image_with_text); 19 | } 20 | 21 | @Override 22 | protected void bindData(ViewHolder holder, AppInfo data, int position) { 23 | holder.setImageDrawable(R.id.item_iv, data.getIcon()) 24 | .setText(R.id.item_tv, data.getLabel()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/util/threadPool/StepThread.java: -------------------------------------------------------------------------------- 1 | package com.android.util.threadPool; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | /** 6 | * Created by xuzhb on 2020/4/5 7 | * Desc:封装Callable接口 8 | */ 9 | public abstract class StepThread implements Callable { 10 | 11 | //初始化 12 | public abstract void init() throws Exception; 13 | 14 | //执行任务并返回最终结果 15 | public abstract V execute() throws Exception; 16 | 17 | //发生异常时回调 18 | public abstract void onError(Exception e); 19 | 20 | //可以做一些最终的资源释放 21 | public abstract void onDestory(); 22 | 23 | @Override 24 | public V call() throws Exception { 25 | try { 26 | init(); 27 | return execute(); 28 | } catch (Exception e) { 29 | onError(e); 30 | } finally { 31 | onDestory(); 32 | } 33 | return null; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/AATest/TestFloatPageTwoActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission.AATest; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.android.frame.mvc.BaseActivity; 6 | import com.android.java.databinding.ActivityCommonLayoutBinding; 7 | import com.android.util.CommonLayoutUtil; 8 | 9 | /** 10 | * Created by xuzhb on 2021/3/10 11 | * Desc: 12 | */ 13 | public class TestFloatPageTwoActivity extends BaseActivity { 14 | 15 | @Override 16 | public void handleView(Bundle savedInstanceState) { 17 | CommonLayoutUtil.initCommonLayout(this, "悬浮窗页面二", false, true, "跳转到悬浮窗页面三"); 18 | binding.tv.setText("悬浮窗A不在页面二显示"); 19 | } 20 | 21 | @Override 22 | public void initListener() { 23 | binding.btn1.setOnClickListener(v -> { 24 | startActivity(TestFloatPageThreeActivity.class); 25 | }); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/IFloatWindow.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/8 7 | * Desc: 8 | */ 9 | public interface IFloatWindow { 10 | 11 | void show(); 12 | 13 | void hide(); 14 | 15 | boolean isShowing(); 16 | 17 | int getX(); 18 | 19 | int getY(); 20 | 21 | void updateX(int x); 22 | 23 | /** 24 | * 更新x坐标 25 | * 26 | * @param screenType 以屏幕宽度或屏幕高度为基准 27 | * @param ratio 占比 28 | */ 29 | void updateX(@ScreenType.screenType int screenType, float ratio); 30 | 31 | void updateY(int y); 32 | 33 | /** 34 | * 更新y坐标 35 | * 36 | * @param screenType 以屏幕宽度或屏幕高度为基准 37 | * @param ratio 占比 38 | */ 39 | void updateY(@ScreenType.screenType int screenType, float ratio); 40 | 41 | void updateXY(int x, int y); 42 | 43 | View getView(); 44 | 45 | //使用FloatWindow.destroy()来取消弹窗,不要手动调用下面的方法 46 | @Deprecated 47 | void dismiss(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/MoveType.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission; 2 | 3 | import androidx.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | * Created by xuzhb on 2021/3/8 10 | * Desc:移动方式 11 | */ 12 | public class MoveType { 13 | 14 | public static final int inactive = 1; //不可移动 15 | public static final int active = 2; //可移动 16 | public static final int slide = 3; //移动松手后贴边 17 | public static final int back = 4; //移动松手后回到原来的位置 18 | 19 | @IntDef({inactive, active, slide, back}) 20 | @Retention(RetentionPolicy.SOURCE) 21 | @interface moveType { 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/OnPermissionListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission; 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/8 5 | * Desc:权限申请结果回调 6 | */ 7 | public interface OnPermissionListener { 8 | 9 | //授权成功 10 | void onSuccess(); 11 | 12 | //授权失败 13 | void onFailure(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/OnViewListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission; 2 | 3 | import android.view.View; 4 | 5 | import com.android.widget.ViewHolder; 6 | 7 | /** 8 | * Created by xuzhb on 2021/3/11 9 | * Desc:设置contentView上控件的事件监听 10 | */ 11 | public interface OnViewListener { 12 | void onView(ViewHolder holder, View view); 13 | } 14 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/OnViewStateListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission; 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/8 5 | * Desc:状态改变监听 6 | */ 7 | public interface OnViewStateListener { 8 | 9 | void onPositionUpdate(int x, int y); 10 | 11 | void onShow(); 12 | 13 | void onHide(); 14 | 15 | void onDismiss(); 16 | 17 | void onMoveAnimStart(); 18 | 19 | void onMoveAnimEnd(); 20 | 21 | void onBackToDesktop(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NeedPermission/ScreenType.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission; 2 | 3 | import androidx.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | * Created by xuzhb on 2021/3/8 10 | * Desc:选择以屏幕宽度或屏幕高度为基准 11 | */ 12 | public class ScreenType { 13 | public static final int width = 0; 14 | public static final int height = 1; 15 | 16 | @IntDef({width, height}) 17 | @Retention(RetentionPolicy.SOURCE) 18 | @interface screenType { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NoPermission/MoveType.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NoPermission; 2 | 3 | import androidx.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | * Created by xuzhb on 2021/3/8 10 | * Desc:移动方式 11 | */ 12 | public class MoveType { 13 | 14 | public static final int inactive = 1; //不可移动 15 | public static final int active = 2; //可移动 16 | public static final int slide = 3; //移动松手后贴边 17 | public static final int back = 4; //移动松手后回到原来的位置 18 | 19 | @IntDef({inactive, active, slide, back}) 20 | @Retention(RetentionPolicy.SOURCE) 21 | @interface moveType { 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NoPermission/OnViewListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NoPermission; 2 | 3 | import android.view.View; 4 | 5 | import com.android.widget.ViewHolder; 6 | 7 | /** 8 | * Created by xuzhb on 2021/3/18 9 | * Desc:设置contentView上控件的事件监听 10 | */ 11 | public interface OnViewListener { 12 | void onView(ViewHolder holder, View view); 13 | } 14 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/NoPermission/ScreenType.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NoPermission; 2 | 3 | import androidx.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | * Created by xuzhb on 2021/3/8 10 | * Desc:选择以屏幕宽度或屏幕高度为基准 11 | */ 12 | public class ScreenType { 13 | public static final int width = 0; 14 | public static final int height = 1; 15 | 16 | @IntDef({width, height}) 17 | @Retention(RetentionPolicy.SOURCE) 18 | @interface screenType { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/FloatWindow/TestFloatActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.android.frame.mvc.BaseActivity; 6 | import com.android.java.databinding.ActivityCommonLayoutBinding; 7 | import com.android.util.CommonLayoutUtil; 8 | import com.android.widget.FloatWindow.NeedPermission.AATest.TestFloatPageOneActivity; 9 | import com.android.widget.FloatWindow.NoPermission.AATest.TestFloatPageActivity; 10 | 11 | /** 12 | * Created by xuzhb on 2021/3/22 13 | * Desc: 14 | */ 15 | public class TestFloatActivity extends BaseActivity { 16 | @Override 17 | public void handleView(Bundle savedInstanceState) { 18 | CommonLayoutUtil.initCommonLayout(this, "悬浮窗", "申请权限", "无需权限"); 19 | } 20 | 21 | @Override 22 | public void initListener() { 23 | binding.btn1.setOnClickListener(v -> { 24 | startActivity(TestFloatPageOneActivity.class); 25 | }); 26 | binding.btn2.setOnClickListener(v -> { 27 | TestFloatPageActivity.start(this, 1); 28 | }); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnGestureListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | /** 4 | * Created by xuzhb on 2021/1/6 5 | * Desc:手势监听 6 | */ 7 | public interface OnGestureListener { 8 | 9 | /** 10 | * 拖动 11 | * 12 | * @param dx 水平方向上拖动的距离 13 | * @param dy 竖直方向上拖动的距离 14 | */ 15 | void onDrag(float dx, float dy); 16 | 17 | /** 18 | * 快速滑动 19 | * 20 | * @param startX 滑动起点的x坐标 21 | * @param startY 滑动起点的y坐标 22 | * @param velocityX 水平方向上滑动的速度 23 | * @param velocityY 竖直方向上滑动的速度 24 | */ 25 | void onFling(float startX, float startY, float velocityX, float velocityY); 26 | 27 | /** 28 | * 缩放 29 | * 30 | * @param scaleFactor 缩放因子 31 | * @param focusX 组成该手势的两个触点的中点的x坐标,单位是像素 32 | * @param focusY 组成该手势的两个触点的中点的y坐标,单位是像素 33 | */ 34 | void onScale(float scaleFactor, float focusX, float focusY); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnMatrixChangedListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | import android.graphics.RectF; 4 | 5 | /** 6 | * Created by xuzhb on 2021/1/6 7 | * Desc:View的Matrix矩阵变化监听 8 | */ 9 | public interface OnMatrixChangedListener { 10 | 11 | /** 12 | * 当View的边界发生变化时回调 13 | * 14 | * @param rect View的新边界 15 | */ 16 | void onMatrixChanged(RectF rect); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnOutsidePhotoTapListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | import android.widget.ImageView; 4 | 5 | /** 6 | * Created by xuzhb on 2021/1/6 7 | * Desc:图片外部区域点击事件监听 8 | */ 9 | public interface OnOutsidePhotoTapListener { 10 | 11 | /** 12 | * 点击图片外部区域时回调 13 | */ 14 | void onOutsidePhotoTap(ImageView imageView); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnPhotoTapListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | import android.widget.ImageView; 4 | 5 | /** 6 | * Created by xuzhb on 2021/1/6 7 | * Desc:图片单击事件监听 8 | */ 9 | public interface OnPhotoTapListener { 10 | 11 | /** 12 | * 点击图片区域以内时回调,图片区域以外不会回调 13 | * 14 | * @param imageView 点击的图片 15 | * @param x 点击的位置x坐标 16 | * @param y 点击的位置y坐标 17 | * @param xOffset 点击的位置相对于左上角的横向偏移量,百分比形式 18 | * @param yOffset 点击的位置相对于左上角的纵向偏移量,百分比形式 19 | */ 20 | void onPhotoTap(ImageView imageView, float x, float y, float xOffset, float yOffset); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnScaleChangedListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | /** 4 | * Created by xuzhb on 2021/1/6 5 | * Desc:图片缩放监听 6 | */ 7 | public interface OnScaleChangedListener { 8 | 9 | /** 10 | * 图片缩放时回调 11 | * 12 | * @param scaleFactor 缩放因子(小于1时缩小,大于1时放大) 13 | * @param focusX 缩放焦点的x坐标 14 | * @param focusY 缩放焦点的y坐标 15 | */ 16 | void onScaleChange(float scaleFactor, float focusX, float focusY); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnSingleFlingListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | import android.view.MotionEvent; 4 | 5 | /** 6 | * Created by xuzhb on 2021/1/6 7 | * Desc:快速滑动监听 8 | */ 9 | public interface OnSingleFlingListener { 10 | 11 | /** 12 | * 快速滑动时回调 13 | * 14 | * @param event1 首次接触时的MotionEvent 15 | * @param event2 最后一次接触时的MotionEvent 16 | * @param velocityX 水平滑动的速度 17 | * @param velocityY 竖直滑动的速度 18 | */ 19 | boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnViewDragListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | /** 4 | * Created by xuzhb on 2021/1/8 5 | * Desc:图片拖动监听 6 | */ 7 | public interface OnViewDragListener { 8 | 9 | /** 10 | * 拖动图片时回调,当缩放图片时不会触发次回调 11 | * 12 | * @param dx 水平方向上拖动的距离 13 | * @param dy 竖直方向上拖动的距离 14 | */ 15 | void onDrag(float dx, float dy); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/listener/OnViewTapListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by xuzhb on 2021/1/8 7 | * Desc:ImageView点击事件监听 8 | */ 9 | public interface OnViewTapListener { 10 | 11 | /** 12 | * ImageView点击时回调 13 | * 14 | * @param view 点击的ImageView 15 | * @param x 点击的X坐标 16 | * @param y 点击的Y坐标 17 | */ 18 | void onViewTap(View view, float x, float y); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PhotoViewer/widget/PhotoViewPager.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.MotionEvent; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | import androidx.viewpager.widget.ViewPager; 10 | 11 | /** 12 | * Created by xuzhb on 2021/1/12 13 | */ 14 | public class PhotoViewPager extends ViewPager { 15 | 16 | public PhotoViewPager(@NonNull Context context) { 17 | super(context); 18 | } 19 | 20 | public PhotoViewPager(@NonNull Context context, @Nullable AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | @Override 25 | public boolean onInterceptTouchEvent(MotionEvent ev) { 26 | try { 27 | return super.onInterceptTouchEvent(ev); 28 | } catch (Exception e) { 29 | return false; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PicGetterDialog/AATest/CustomPicGetterDialog.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PicGetterDialog.AATest; 2 | 3 | import android.app.Dialog; 4 | import com.android.java.R; 5 | import com.android.widget.PicGetterDialog.BasePicGetterDialog; 6 | import com.android.widget.ViewHolder; 7 | 8 | /** 9 | * Created by xuzhb on 2020/1/27 10 | * Desc: 11 | */ 12 | public class CustomPicGetterDialog extends BasePicGetterDialog { 13 | 14 | public static CustomPicGetterDialog newInstance() { 15 | return new CustomPicGetterDialog(); 16 | } 17 | 18 | @Override 19 | public int getLayoutId() { 20 | return R.layout.dialog_custom_pic_getter; 21 | } 22 | 23 | @Override 24 | public void convertView(ViewHolder holder, Dialog dialog) { 25 | holder.setOnClickListener(R.id.camera_btn, v -> { 26 | openCamera(); //拍照 27 | }); 28 | holder.setOnClickListener(R.id.gallery_btn, v -> { 29 | openGallery(); //从相册选取照片 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PicGetterDialog/OnPicGetterListener.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PicGetterDialog; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | /** 6 | * Create by xuzhb on 2020/1/23 7 | * Desc: 8 | */ 9 | public interface OnPicGetterListener { 10 | 11 | /** 12 | * 图片获取成功 13 | * 14 | * @param bitmap 图片 15 | * @param picPath 图片路径 16 | */ 17 | void onSuccess(Bitmap bitmap, String picPath); 18 | 19 | /** 20 | * 图片获取失败 21 | * 22 | * @param errorMsg 错误信息 23 | */ 24 | void onFailure(String errorMsg); 25 | 26 | /** 27 | * 取消图片获取 28 | */ 29 | void onCancel(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PicGetterDialog/PicGetterDialog.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PicGetterDialog; 2 | 3 | import android.app.Dialog; 4 | import com.android.java.R; 5 | import com.android.widget.ViewHolder; 6 | 7 | /** 8 | * Create by xuzhb on 2020/1/22 9 | * Desc:拍照或从相册选取选择框 10 | */ 11 | public class PicGetterDialog extends BasePicGetterDialog { 12 | 13 | public static PicGetterDialog newInstance() { 14 | return new PicGetterDialog(); 15 | } 16 | 17 | @Override 18 | public int getLayoutId() { 19 | return R.layout.dialog_pic_getter; 20 | } 21 | 22 | @Override 23 | public void convertView(ViewHolder holder, Dialog dialog) { 24 | holder.setOnClickListener(R.id.camera_tv, v -> { 25 | openCamera(); //拍照 26 | }); 27 | holder.setOnClickListener(R.id.gallery_tv, v -> { 28 | openGallery(); //从相册选取照片 29 | }); 30 | holder.setOnClickListener(R.id.cancel_tv, v -> { 31 | onCancel(getDialog()); //取消弹窗 32 | dismiss(); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PicGetterDialog/说明.md: -------------------------------------------------------------------------------- 1 | 集成: 2 | 1、build.gradle导入图片裁剪框架'com.yalantis:ucrop:2.2.0' 3 | 2、AndroidManifest配置相应的fileprovider和UCropActivity 4 | 3、混淆 5 | -dontwarn com.yalantis.ucrop** 6 | -keep class com.yalantis.ucrop** { *; } 7 | -keep interface com.yalantis.ucrop** { *; } 8 | 9 | 相关类: 10 | 1、dialog_pic_getter:弹窗布局 11 | 2、pic_getter_file_paths:fileprovider配置,Android 7.0以上的系统需要使用FileProvider兼容拍照 12 | 3、PicProvider:fileprovider 13 | 4、BasePicGetterDialog 14 | 5、PicGetterDialog 15 | 6、OnPicGetterListener 16 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PopupWindow/AATest/PopupWindowAdapter.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PopupWindow.AATest; 2 | 3 | import android.content.Context; 4 | import com.android.java.R; 5 | import com.android.widget.RecyclerView.BaseAdapter; 6 | import com.android.widget.RecyclerView.ViewHolder; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Create by xuzhb on 2020/1/21 12 | * Desc: 13 | */ 14 | public class PopupWindowAdapter extends BaseAdapter { 15 | 16 | public PopupWindowAdapter(Context context, List dataList) { 17 | super(context, dataList, R.layout.item_popup_window); 18 | } 19 | 20 | @Override 21 | protected void bindData(ViewHolder holder, String data, int position) { 22 | holder.setText(R.id.item_tv, data); 23 | if (position == getItemCount() - 1) { 24 | holder.setViewGone(R.id.divider_line); 25 | } else { 26 | holder.setViewVisible(R.id.divider_line); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/PopupWindow/WindowHelper.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.PopupWindow; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | import android.view.WindowManager; 6 | 7 | import androidx.annotation.FloatRange; 8 | 9 | /** 10 | * Create by xuzhb on 2020/1/21 11 | * Desc:Window辅助类,实现背景灰色效果 12 | */ 13 | public class WindowHelper { 14 | 15 | private Activity mActivity; 16 | 17 | public WindowHelper(Activity activity) { 18 | this.mActivity = activity; 19 | } 20 | 21 | //设置外部区域背景透明度,0:完全不透明,1:完全透明 22 | public void setBackGroundAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) { 23 | Window window = mActivity.getWindow(); 24 | WindowManager.LayoutParams lp = window.getAttributes(); 25 | lp.alpha = alpha; 26 | window.setAttributes(lp); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/ProgressBar/TestProgressBarActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.ProgressBar; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | 6 | import com.android.frame.mvc.BaseActivity; 7 | import com.android.java.databinding.ActivityTestProgressBarBinding; 8 | 9 | /** 10 | * Created by xuzhb on 2020/7/11 11 | * Desc: 12 | */ 13 | public class TestProgressBarActivity extends BaseActivity { 14 | @Override 15 | public void handleView(Bundle savedInstanceState) { 16 | int[] rindColorArray = new int[]{Color.parseColor("#0888FF"), Color.parseColor("#6CD0FF")}; 17 | binding.arcAv1.startRotate(); 18 | binding.arcAv2.setRindColorArray(rindColorArray); 19 | binding.arcAv2.startRotate(); 20 | } 21 | 22 | @Override 23 | public void initListener() { 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/RecyclerView/AATest/entity/DateBean.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Create by xuzhb on 2020/1/21 7 | * Desc: 8 | */ 9 | public class DateBean implements Serializable { 10 | 11 | private String date; 12 | 13 | public DateBean(String date) { 14 | this.date = date; 15 | } 16 | 17 | public String getDate() { 18 | return date; 19 | } 20 | 21 | public void setDate(String date) { 22 | this.date = date; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/RecyclerView/AATest/entity/DetailBean.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Create by xuzhb on 2020/1/21 7 | * Desc: 8 | */ 9 | public class DetailBean implements Serializable { 10 | 11 | private String detail; 12 | private String time; 13 | 14 | public DetailBean(String detail, String time) { 15 | this.detail = detail; 16 | this.time = time; 17 | } 18 | 19 | public String getDetail() { 20 | return detail; 21 | } 22 | 23 | public void setDetail(String detail) { 24 | this.detail = detail; 25 | } 26 | 27 | public String getTime() { 28 | return time; 29 | } 30 | 31 | public void setTime(String time) { 32 | this.time = time; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/RecyclerView/AATest/entity/MonthBean.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Create by xuzhb on 2020/1/21 7 | * Desc: 8 | */ 9 | public class MonthBean implements Serializable { 10 | 11 | private String month; 12 | private String count; 13 | 14 | public MonthBean(String month, String count) { 15 | this.month = month; 16 | this.count = count; 17 | } 18 | 19 | public String getMonth() { 20 | return month; 21 | } 22 | 23 | public void setMonth(String month) { 24 | this.month = month; 25 | } 26 | 27 | public String getCount() { 28 | return count; 29 | } 30 | 31 | public void setCount(String count) { 32 | this.count = count; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/RecyclerView/MultiViewType.java: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView; 2 | 3 | /** 4 | * Create by xuzhb on 2020/1/20 5 | * Desc:RecyclerView实现多种Item布局 6 | */ 7 | public interface MultiViewType { 8 | 9 | /** 10 | * 实现多种item布局 11 | * 12 | * @param data Item对应的数据 13 | * @param position Item的位置 14 | * @param totalCount Item的总数 15 | * @return Item对应的布局类型,使用布局的id进行区分 16 | */ 17 | int getLayoutId(T data, int position, int totalCount); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /java/src/main/java/com/android/widget/ScrollTextView.java: -------------------------------------------------------------------------------- 1 | package com.android.widget; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.appcompat.widget.AppCompatTextView; 8 | 9 | /** 10 | * Created by xuzhb on 2020/1/6 11 | * Desc:TextView文字滚动显示,即跑马灯效果(不需要获取焦点) 12 | */ 13 | public class ScrollTextView extends AppCompatTextView { 14 | 15 | public ScrollTextView(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public ScrollTextView(Context context, AttributeSet attrs) { 20 | this(context, attrs, 0); 21 | } 22 | 23 | public ScrollTextView(Context context, AttributeSet attrs, int defStyleAttr) { 24 | super(context, attrs, defStyleAttr); 25 | initView(); 26 | } 27 | 28 | private void initView() { 29 | setSingleLine(true); 30 | setEllipsize(TextUtils.TruncateAt.MARQUEE); //设置跑马灯效果 31 | setMarqueeRepeatLimit(-1); //设置循环滚动为无限循环 32 | } 33 | 34 | @Override 35 | public boolean isFocused() { 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_list_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_test_bitmap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_test_capture_gridview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_test_capture_listview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_test_capture_recyclerview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_test_capture_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_test_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /java/src/main/res/layout/activity_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /java/src/main/res/layout/fragment_test_mvc.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /java/src/main/res/layout/fragment_test_mvc_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /java/src/main/res/layout/fragment_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /java/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Java 3 | 4 | -------------------------------------------------------------------------------- /java/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /java/src/test/java/com/android/java/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.android.java; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /kotlin/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /kotlin/src/androidTest/java/com/android/basicproject/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.android.basicproject 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.android.basicproject", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/base/DontSwipeBack.kt: -------------------------------------------------------------------------------- 1 | package com.android.base 2 | 3 | /** 4 | * Created by xuzhb on 2020/11/4 5 | * Desc:不需要侧滑退出Activity 6 | */ 7 | interface DontSwipeBack -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/TestLeakActivity.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import com.android.basicproject.databinding.ActivityCommonLayoutBinding 6 | import com.android.frame.mvc.BaseActivity 7 | import com.android.util.initCommonLayout 8 | 9 | /** 10 | * Created by xuzhb on 2019/8/31 11 | * Desc:测试内存泄漏 12 | */ 13 | class TestLeakActivity : BaseActivity() { 14 | 15 | companion object { 16 | var mContext: Context? = null 17 | } 18 | 19 | override fun handleView(savedInstanceState: Bundle?) { 20 | mContext = this //测试内存泄漏 21 | initCommonLayout(this, "测试内存泄漏") 22 | } 23 | 24 | override fun initListener() { 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/camera/zxing/util/QRConstant.java: -------------------------------------------------------------------------------- 1 | package com.android.frame.camera.zxing.util; 2 | 3 | /** 4 | * Created by xuzhb on 2019/11/16 5 | * Desc: 6 | */ 7 | public class QRConstant { 8 | 9 | public static final String SCAN_QRCODE_RESULT = "SCAN_QRCODE_RESULT"; //扫描结果 10 | 11 | } 12 | -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/guide/SimpleViewAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.guide 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import androidx.viewpager.widget.PagerAdapter 6 | 7 | /** 8 | * Created by xuzhb on 2020/12/28 9 | * Desc: 10 | */ 11 | class SimpleViewAdapter(private val viewList: MutableList) : PagerAdapter() { 12 | 13 | //view是否由对象产生,官方写view == `object`即可 14 | override fun isViewFromObject(view: View, `object`: Any): Boolean = view == `object` 15 | 16 | //数据源的数目 17 | override fun getCount(): Int = viewList.size 18 | 19 | //销毁一个页卡(即ViewPager的一个item) 20 | override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { 21 | container.removeView(viewList[position]) 22 | } 23 | 24 | //对应页卡添加上数据 25 | override fun instantiateItem(container: ViewGroup, position: Int): Any { 26 | container.addView(viewList[position]) //千万别忘记添加到container 27 | return viewList[position] 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/AATest/UrlConstant.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.AATest 2 | 3 | /** 4 | * Created by xuzhb on 2019/8/9 5 | * Desc: 6 | */ 7 | object UrlConstant { 8 | 9 | const val BAIDU_URL = "https://www.baidu.com/" 10 | 11 | const val WEATHER_URL = "http://wthrcdn.etouch.cn/" 12 | 13 | const val NEWS_URL = "https://api.apiopen.top/" 14 | 15 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/AATest/bean/NewsListBean.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.AATest.bean 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2019/10/27 7 | * Desc: 8 | */ 9 | data class NewsListBean( 10 | val code: Int, 11 | val message: String, 12 | val result: MutableList? 13 | ) : Serializable { 14 | data class ResultBean( 15 | val path: String, 16 | val image: String, 17 | val title: String, 18 | val passtime: String 19 | ) : Serializable 20 | 21 | fun isSuccess(): Boolean = code == 200 22 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/CookieJarManage.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http 2 | 3 | import okhttp3.Cookie 4 | import okhttp3.CookieJar 5 | import okhttp3.HttpUrl 6 | 7 | /** 8 | * Created by xuzhb on 2019/8/8 9 | * Desc:持久化Cookie管理 10 | */ 11 | class CookieJarManage : CookieJar { 12 | 13 | companion object { 14 | //单例对象 15 | val instance = SingleTonHolder.holder 16 | } 17 | 18 | //静态内部类单例模式 19 | private object SingleTonHolder { 20 | val holder = CookieJarManage() 21 | } 22 | 23 | private val cookieStore = HashMap>() 24 | 25 | //网路访问后将服务器返回的cookies和对应的url存储在cookieStore中 26 | override fun saveFromResponse(url: HttpUrl, cookies: MutableList) { 27 | cookieStore.put(url.host(), cookies) 28 | } 29 | 30 | //网路访问开始的时候,根据访问的url去查找cookie,然后将cokies放到请求头里面 31 | override fun loadForRequest(url: HttpUrl): MutableList = 32 | cookieStore.get(url.host()) ?: mutableListOf() //cookieStore.get(url)为null时返回mutableListOf() 33 | 34 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/SchedulerUtil.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http 2 | 3 | import io.reactivex.ObservableTransformer 4 | import io.reactivex.android.schedulers.AndroidSchedulers 5 | import io.reactivex.schedulers.Schedulers 6 | 7 | /** 8 | * Created by xuzhb on 2019/8/8 9 | * Desc:简化subscribeOn和observeOn调用 10 | */ 11 | object SchedulerUtil { 12 | 13 | fun ioToMain(): ObservableTransformer { 14 | return ObservableTransformer { observable -> 15 | observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) 16 | } 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/interceptor/MaxRetryInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.interceptor 2 | 3 | import com.android.util.LogUtil 4 | import okhttp3.Interceptor 5 | import okhttp3.Response 6 | 7 | /** 8 | * Created by xuzhb on 2020/8/9 9 | * Desc:限制最多重试次数的拦截器 10 | */ 11 | class MaxRetryInterceptor(private val maxRetryCount: Int) : Interceptor { 12 | 13 | companion object { 14 | private const val TAG = "MaxRetryInterceptor" 15 | } 16 | 17 | private var retryCount = 1 18 | 19 | override fun intercept(chain: Interceptor.Chain): Response { 20 | val request = chain.request() 21 | LogUtil.w(TAG, "retry count:$retryCount") 22 | var response = chain.proceed(request) //默认请求1次 23 | while (!response.isSuccessful && retryCount < maxRetryCount) { 24 | retryCount++ 25 | LogUtil.w(TAG, "retry count:$retryCount") 26 | response = chain.proceed(request) //重试 27 | } 28 | return response 29 | } 30 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/model/BaseListResponse.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.model 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2019/8/8 7 | * Desc:bean基类,列表类型 8 | */ 9 | class BaseListResponse( 10 | val code: Int, 11 | val msg: String, 12 | val data: MutableList? 13 | ) : Serializable { 14 | fun isSuccess(): Boolean = code == 200 15 | fun isTokenOut(): Boolean = code == -111 //登录失效,假设code是-111 16 | fun getMessage(): String = msg 17 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/http/model/BaseResponse.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.http.model 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2019/8/8 7 | * Desc:bean基类,非列表类型 8 | */ 9 | class BaseResponse( 10 | val code: Int, 11 | val msg: String, 12 | val data: T? 13 | ) : Serializable { 14 | fun isSuccess(): Boolean = code == 200 15 | fun isTokenOut(): Boolean = code == -111 //登录失效,假设code是-111 16 | fun getMessage(): String = msg 17 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/AATest/TestFragmentMvc.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest 2 | 3 | import android.os.Bundle 4 | import com.android.basicproject.R 5 | import com.android.basicproject.databinding.ActivityTestFragmentBinding 6 | import com.android.frame.mvc.BaseActivity 7 | 8 | /** 9 | * Created by xuzhb on 2020/12/30 10 | * Desc: 11 | */ 12 | class TestFragmentMvc : BaseActivity() { 13 | 14 | override fun handleView(savedInstanceState: Bundle?) { 15 | when (intent.getIntExtra("fragment_type", 1)) { 16 | 1 -> { 17 | mTitleBar?.titleText = "基类Fragment(MVC)" 18 | supportFragmentManager.beginTransaction().add(R.id.content_fl, TestMvcFragment.newInstance()).commit() 19 | } 20 | 2 -> { 21 | mTitleBar?.titleText = "列表Fragment(MVC)" 22 | supportFragmentManager.beginTransaction().add(R.id.content_fl, TestMvcListFragment.newInstance()).commit() 23 | } 24 | } 25 | } 26 | 27 | override fun initListener() { 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/AATest/adapter/NewsListAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.adapter 2 | 3 | import com.android.basicproject.R 4 | import com.android.frame.mvc.AATest.entity.NewsListBean 5 | import com.android.frame.mvc.extra.RecyclerView.LoadMoreAdapter 6 | import com.android.util.SizeUtil 7 | import com.android.util.glide.GlideUtil 8 | import com.bumptech.glide.load.resource.bitmap.RoundedCorners 9 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 10 | 11 | /** 12 | * Created by xuzhb on 2020/12/30 13 | * Desc: 14 | */ 15 | class NewsListAdapter : LoadMoreAdapter(R.layout.item_test_load_more) { 16 | override fun convert(holder: BaseViewHolder, item: NewsListBean) { 17 | GlideUtil.showImageFromUrl(holder.getView(R.id.image_iv), item.image, RoundedCorners(SizeUtil.dp2pxInt(6f))) 18 | holder.setText(R.id.title_tv, item.title).setText(R.id.time_tv, item.passtime) 19 | } 20 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/AATest/entity/NewsListBean.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2020/12/30 7 | * Desc: 8 | */ 9 | data class NewsListBean( 10 | val path: String, 11 | val image: String, 12 | val title: String, 13 | val passtime: String 14 | ) : Serializable -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/AATest/entity/WeatherBean.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2020/12/30 7 | * Desc: 8 | */ 9 | data class WeatherBean( 10 | val yesterday: YesterdayBean, 11 | val city: String, 12 | val forecast: List, 13 | val ganmao: String, 14 | val wendu: String 15 | ) : Serializable { 16 | 17 | data class YesterdayBean( 18 | val date: String, 19 | val high: String, 20 | val fx: String, 21 | val low: String, 22 | val fl: String, 23 | val type: String 24 | ) : Serializable 25 | 26 | data class ForecastBean( 27 | val date: String, 28 | val high: String, 29 | val fengli: String, 30 | val low: String, 31 | val fengxiang: String, 32 | val type: String 33 | ) : Serializable 34 | 35 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/AATest/server/ApiService.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.server 2 | 3 | import io.reactivex.Observable 4 | import okhttp3.ResponseBody 5 | import retrofit2.http.* 6 | 7 | /** 8 | * Created by xuzhb on 2020/7/29 9 | * Desc: 10 | */ 11 | interface ApiService { 12 | 13 | //获取天气信息,@Query,GET请求 14 | @GET("weather_mini") 15 | fun getWeatherByQuery(@Query("city") city: String): Observable 16 | 17 | //获取网易新闻,@Field,POST请求 18 | @FormUrlEncoded 19 | @POST("getWangYiNews") 20 | fun getWangYiNewsByField(@Field("page") page: Int, @Field("count") count: Int): Observable 21 | 22 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/AATest/server/Config.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.AATest.server 2 | 3 | /** 4 | * Created by xuzhb on 2020/12/30 5 | * Desc: 6 | */ 7 | object Config { 8 | 9 | const val WEATHER_URL = "http://wthrcdn.etouch.cn/" 10 | 11 | const val NEWS_URL = "https://api.apiopen.top/" 12 | 13 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/IBaseListView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/13 5 | */ 6 | interface IBaseListView : IBaseView { 7 | 8 | /** 9 | * 获取加载的起始页码 10 | */ 11 | fun getFirstPage(): Int 12 | 13 | /** 14 | * 是否是首次加载 15 | */ 16 | fun isFirstLoad(): Boolean 17 | 18 | /** 19 | * 获取一页加载的个数 20 | */ 21 | fun getLoadSize(): Int 22 | 23 | /** 24 | * 显示数据 25 | */ 26 | fun showData(page: Int, list: MutableList?) 27 | 28 | /** 29 | * 处理数据 30 | */ 31 | fun convertData(response: MutableList?): MutableList? 32 | 33 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/extra/RecyclerView/CustomLoadMoreView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.extra.RecyclerView 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import com.android.basicproject.R 7 | import com.chad.library.adapter.base.loadmore.BaseLoadMoreView 8 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 9 | 10 | /** 11 | * Created by xuzhb on 2020/7/29 12 | * Desc:自定义加载更多的脚布局 13 | */ 14 | class CustomLoadMoreView : BaseLoadMoreView() { 15 | 16 | override fun getLoadComplete(holder: BaseViewHolder): View = holder.getView(R.id.complete_fl) 17 | 18 | override fun getLoadEndView(holder: BaseViewHolder): View = holder.getView(R.id.end_fl) 19 | 20 | override fun getLoadFailView(holder: BaseViewHolder): View = holder.getView(R.id.fail_fl) 21 | 22 | override fun getLoadingView(holder: BaseViewHolder): View = holder.getView(R.id.loading_ll) 23 | 24 | override fun getRootView(parent: ViewGroup): View = 25 | LayoutInflater.from(parent.context).inflate(R.layout.view_load_more, parent, false); 26 | 27 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvc/extra/RecyclerView/LoadMoreAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvc.extra.RecyclerView 2 | 3 | import androidx.annotation.LayoutRes 4 | import com.chad.library.adapter.base.BaseQuickAdapter 5 | import com.chad.library.adapter.base.module.LoadMoreModule 6 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 7 | 8 | /** 9 | * Created by xuzhb on 2020/7/28 10 | * Desc:上拉加载更多 11 | */ 12 | abstract class LoadMoreAdapter @JvmOverloads constructor( 13 | @LayoutRes private val layoutResId: Int, 14 | data: MutableList? = null 15 | ) : BaseQuickAdapter(layoutResId, data), LoadMoreModule -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/AATest/listType/TestMvpListModel.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.listType 2 | 3 | import com.android.frame.http.RetrofitFactory 4 | import com.android.frame.http.SchedulerUtil 5 | import com.android.frame.http.model.BaseListResponse 6 | import com.android.frame.mvc.AATest.convert.NewsFunction 7 | import com.android.frame.mvc.AATest.entity.NewsListBean 8 | import com.android.frame.mvc.AATest.server.ApiService 9 | import com.android.frame.mvc.AATest.server.Config 10 | import io.reactivex.Observable 11 | import java.util.concurrent.TimeUnit 12 | 13 | /** 14 | * Created by xuzhb on 2021/1/5 15 | * Desc: 16 | */ 17 | class TestMvpListModel { 18 | 19 | fun getWangYiNewsByField(page: Int, count: Int): Observable> { 20 | return RetrofitFactory.instance.createService(ApiService::class.java, Config.NEWS_URL) 21 | .getWangYiNewsByField(page, count) 22 | .delay(1, TimeUnit.SECONDS) //模拟延迟一段时间后请求到数据的情况 23 | .map(NewsFunction()) 24 | .compose(SchedulerUtil.ioToMain()) 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/AATest/listType/TestMvpListView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.listType 2 | 3 | import com.android.frame.mvc.AATest.entity.NewsListBean 4 | import com.android.frame.mvp.IBaseListView 5 | 6 | /** 7 | * Created by xuzhb on 2021/1/5 8 | * Desc: 9 | */ 10 | interface TestMvpListView : IBaseListView { 11 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/AATest/notListType/TestMvpModel.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.notListType 2 | 3 | import com.android.frame.http.RetrofitFactory 4 | import com.android.frame.http.SchedulerUtil 5 | import com.android.frame.http.model.BaseResponse 6 | import com.android.frame.mvc.AATest.convert.WeatherFunction 7 | import com.android.frame.mvc.AATest.entity.WeatherBean 8 | import com.android.frame.mvc.AATest.server.ApiService 9 | import com.android.frame.mvc.AATest.server.Config 10 | import io.reactivex.Observable 11 | import java.util.concurrent.TimeUnit 12 | 13 | /** 14 | * Created by xuzhb on 2021/1/5 15 | * Desc: 16 | */ 17 | class TestMvpModel { 18 | 19 | fun getWeatherInfo(city: String): Observable> { 20 | return RetrofitFactory.instance.createService(ApiService::class.java, Config.WEATHER_URL, cache = true) 21 | .getWeatherByQuery(city) 22 | .delay(1, TimeUnit.SECONDS) //模拟延迟一段时间后请求到数据的情况 23 | .map(WeatherFunction()) 24 | .compose(SchedulerUtil.ioToMain()) 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/AATest/notListType/TestMvpView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp.AATest.notListType 2 | 3 | import com.android.frame.mvc.AATest.entity.WeatherBean 4 | import com.android.frame.mvp.IBaseView 5 | 6 | /** 7 | * Created by xuzhb on 2021/1/5 8 | * Desc: 9 | */ 10 | interface TestMvpView : IBaseView { 11 | 12 | fun showWeatherInfo(city: String, bean: WeatherBean?) 13 | 14 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/BasePresenter.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp 2 | 3 | /** 4 | * Created by xuzhb on 2019/12/29 5 | * Desc:MVP中的基类Presenter 6 | */ 7 | open class BasePresenter { 8 | 9 | protected var mView: V? = null 10 | 11 | //绑定View 12 | fun attachView(view: V) { 13 | this.mView = view 14 | } 15 | 16 | //解绑View 17 | fun detachView() { 18 | this.mView = null 19 | } 20 | 21 | fun isAttach(): Boolean { 22 | return mView != null 23 | } 24 | 25 | //加载数据,进入页面时默认就会进行加载,请务必重写refreshData,当加载失败点击重试或者下拉刷新时会调用这个方法 26 | open fun refreshData() { 27 | 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/CommonBaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp 2 | 3 | import androidx.viewbinding.ViewBinding 4 | 5 | /** 6 | * Created by xuzhb on 2019/12/29 7 | * Desc:不需要额外声明View和Presenter的Activity的父类 8 | */ 9 | abstract class CommonBaseActivity : BaseActivity>(), IBaseView { 10 | override fun getPresenter(): BasePresenter = BasePresenter() 11 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/CommonBaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp 2 | 3 | import androidx.viewbinding.ViewBinding 4 | 5 | /** 6 | * Created by xuzhb on 2019/12/29 7 | * Desc:不需要额外声明View和Presenter的Fragment的父类 8 | */ 9 | abstract class CommonBaseFragment : BaseFragment>(), IBaseView { 10 | override fun getPresenter(): BasePresenter = BasePresenter() 11 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/IBaseListView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvp 2 | 3 | /** 4 | * Created by xuzhb on 2020/7/22 5 | * Desc:列表数据对应的基类View 6 | */ 7 | interface IBaseListView : IBaseView { 8 | 9 | /** 10 | * 获取当前加载的页码 11 | */ 12 | fun getCurrentPage(): Int 13 | 14 | /** 15 | * 设置当前加载的页码 16 | */ 17 | fun setCurrentPage(page: Int) 18 | 19 | /** 20 | * 获取加载的起始页码 21 | */ 22 | fun getFirstPage(): Int 23 | 24 | /** 25 | * 是否是首次加载 26 | */ 27 | fun isFirstLoad(): Boolean 28 | 29 | /** 30 | * 获取一页加载的个数 31 | */ 32 | fun getLoadSize(): Int 33 | 34 | /** 35 | * 显示数据 36 | */ 37 | fun showData(page: Int, list: MutableList?) 38 | 39 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvp/注意点.md: -------------------------------------------------------------------------------- 1 | BaseCompatActivity:基类Activity 2 | BaseFragment:基类Fragment 3 | IBaseView:基类View 4 | BasePresenter:基类Presenter 5 | CommonBaseActivity:不需要额外声明View和Presenter的Activity父类 6 | CommonBaseFragment:不需要额外声明View和Presenter的Fragment父类 7 | LoadingDialog:自定义加载框 8 | CustomObserver:自定义Observer,加入加载框和网络错误的处理 9 | NetReceiver:广播监听网络变化,动态注册 10 | activity_list_layout:通用的列表布局,包括标题栏和layout_net_error和layout_recycler_view 11 | layout_net_error:网络错误提示布局 12 | layout_recycler_view:通用的列表刷新子布局,包括一个SwipeRefreshLayout和一个RecyclerView 13 | 14 | 集成时注意: 15 | 1、实现BaseCompatActivity和BaseFragment的gotoLogin()方法 16 | 2、处理CustomObserver中登录失效的code,目前暂定登录过期的code是-1001 17 | 3、处理基类Bean,即BaseResponse和BaseListResponse的结构 18 | 4、处理基类Bean接口请求成功的code,目前暂定接口请求成功的code是200 19 | 20 | -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/AATest/convert/CustomRequestBodyConverter.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.convert 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.TypeAdapter 5 | import okhttp3.MediaType 6 | import okhttp3.RequestBody 7 | import okio.Buffer 8 | import retrofit2.Converter 9 | import java.io.OutputStreamWriter 10 | import java.nio.charset.Charset 11 | 12 | /** 13 | * Created by xuzhb on 2021/8/6 14 | * Desc: 15 | */ 16 | class CustomRequestBodyConverter(val gson: Gson, val adapter: TypeAdapter) : Converter { 17 | 18 | private val MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8") 19 | private val UTF_8 = Charset.forName("UTF-8") 20 | 21 | override fun convert(value: T): RequestBody? { 22 | val buffer = Buffer() 23 | val writer = OutputStreamWriter(buffer.outputStream(), UTF_8) 24 | val jsonWriter = gson.newJsonWriter(writer) 25 | adapter.write(jsonWriter, value) 26 | jsonWriter.close() 27 | return RequestBody.create(MEDIA_TYPE, buffer.readByteString()) 28 | } 29 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/AATest/notListType/TestMvvmActivityViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.notListType 2 | 3 | import com.android.frame.http.model.BaseResponse 4 | import com.android.frame.mvc.AATest.entity.WeatherBean 5 | import com.android.frame.mvvm.AATest.server.ApiHelper 6 | import com.android.frame.mvvm.BaseViewModelWithData 7 | 8 | /** 9 | * Created by xuzhb on 2021/8/6 10 | * Desc:BaseViewModelWithData的使用,简化了很多,BaseViewModel的使用参见TestMvvmFragmentViewModel 11 | */ 12 | class TestMvvmActivityViewModel : BaseViewModelWithData>() { 13 | 14 | fun showWeatherInfo(city: String) { 15 | launchMain({ ApiHelper.getWeatherByQuery(city) }) 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/AATest/server/ApiService.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.server 2 | 3 | import com.android.frame.http.model.BaseListResponse 4 | import com.android.frame.http.model.BaseResponse 5 | import com.android.frame.mvc.AATest.entity.NewsListBean 6 | import com.android.frame.mvc.AATest.entity.WeatherBean 7 | import retrofit2.http.* 8 | 9 | /** 10 | * Created by xuzhb on 2021/8/6 11 | * Desc: 12 | */ 13 | interface ApiService { 14 | 15 | //获取天气信息,@Query,GET请求 16 | @GET("weather_mini") 17 | suspend fun getWeatherByQuery(@Query("city") city: String): BaseResponse 18 | 19 | //获取网易新闻,@Field,POST请求 20 | @FormUrlEncoded 21 | @POST("getWangYiNews") 22 | suspend fun getWangYiNewsByField(@Field("page") page: Int, @Field("count") count: Int): BaseListResponse 23 | 24 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/AATest/server/Config.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.AATest.server 2 | 3 | /** 4 | * Created by xuzhb on 2020/12/30 5 | * Desc: 6 | */ 7 | object Config { 8 | 9 | const val WEATHER_URL = "http://wthrcdn.etouch.cn/" 10 | 11 | const val NEWS_URL = "https://api.apiopen.top/" 12 | 13 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/BaseListViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.android.frame.http.model.BaseListResponse 5 | import com.android.frame.mvvm.extra.LiveDataEntity.ErrorResponse 6 | import kotlinx.coroutines.CoroutineScope 7 | 8 | /** 9 | * Created by xuzhb on 2021/8/7 10 | * Desc:列表数据对应的基类ViewModel 11 | */ 12 | open class BaseListViewModel : BaseViewModel() { 13 | 14 | var successData = MutableLiveData>() 15 | var errorData = MutableLiveData>>() 16 | 17 | //分页加载 18 | open fun loadData( 19 | page: Int, 20 | count: Int, 21 | showLoadLayout: Boolean = true, //是否显示加载状态布局 22 | showLoadingDialog: Boolean = false 23 | ) { 24 | loadDataFromServer(page, count)?.let { 25 | launch(it, successData, errorData, showLoadLayout, showLoadingDialog) 26 | } 27 | } 28 | 29 | //从服务器按页加载数据 30 | open fun loadDataFromServer(page: Int, count: Int): (suspend CoroutineScope.() -> BaseListResponse)? = null 31 | 32 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/BaseViewModelWithData.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.android.frame.mvvm.extra.LiveDataEntity.ErrorResponse 5 | import kotlinx.coroutines.CoroutineScope 6 | 7 | /** 8 | * Created by xuzhb on 2021/8/7 9 | * Desc:基类ViewModel的进一步封装,携带数据结构,包含了主接口的请求方法, 10 | * 可以通过successData处理请求成功的情况,通过errorData处理请求失败的情况 11 | */ 12 | abstract class BaseViewModelWithData : BaseViewModel() { 13 | 14 | var successData = MutableLiveData() 15 | var errorData = MutableLiveData>() 16 | 17 | //请求主接口 18 | fun launchMain( 19 | block: suspend CoroutineScope.() -> T, //请求接口方法,T表示data实体泛型 20 | showLoadLayout: Boolean = true, //是否显示加载状态布局 21 | showLoadingDialog: Boolean = false, //是否显示加载弹窗 22 | message: String = "加载中", //加载弹窗的提示文本 23 | cancelable: Boolean = true //加载弹窗是否可以点击取消 24 | ) { 25 | launch(block, successData, errorData, showLoadLayout, showLoadingDialog, message, cancelable, true) 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/CommonBaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm 2 | 3 | import android.view.LayoutInflater 4 | import androidx.lifecycle.ViewModelProvider 5 | import androidx.viewbinding.ViewBinding 6 | import java.lang.reflect.ParameterizedType 7 | 8 | /** 9 | * Created by xuzhb on 2021/8/6 10 | * Desc:不需要额外声明ViewModel的Activity的父类 11 | */ 12 | abstract class CommonBaseActivity : BaseActivity(), IBaseView { 13 | 14 | override fun initViewBindingAndViewModel() { 15 | val superclass = javaClass.genericSuperclass 16 | val vbClass = (superclass as ParameterizedType).actualTypeArguments[0] as Class 17 | val method = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java) 18 | binding = method.invoke(null, layoutInflater) as VB 19 | viewModel = ViewModelProvider(this).get((BaseViewModel())::class.java) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/CommonBaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm 2 | 3 | import android.view.LayoutInflater 4 | import androidx.lifecycle.ViewModelProvider 5 | import androidx.viewbinding.ViewBinding 6 | import java.lang.reflect.ParameterizedType 7 | 8 | /** 9 | * Created by xuzhb on 2021/8/7 10 | * Desc:不需要额外声明ViewModel的Fragment的父类 11 | */ 12 | abstract class CommonBaseFragment : BaseFragment(), IBaseView { 13 | 14 | override fun initViewBindingAndViewModel() { 15 | val superclass = javaClass.genericSuperclass 16 | val vbClass = (superclass as ParameterizedType).actualTypeArguments[0] as Class 17 | val method = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java) 18 | binding = method.invoke(null, layoutInflater) as VB 19 | viewModel = ViewModelProvider(this).get((BaseViewModel())::class.java) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/IBaseListView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/7 5 | */ 6 | interface IBaseListView : IBaseView { 7 | 8 | /** 9 | * 获取加载的起始页码 10 | */ 11 | fun getFirstPage(): Int 12 | 13 | /** 14 | * 是否是首次加载 15 | */ 16 | fun isFirstLoad(): Boolean 17 | 18 | /** 19 | * 获取一页加载的个数 20 | */ 21 | fun getLoadSize(): Int 22 | 23 | /** 24 | * 显示数据 25 | */ 26 | fun showData(page: Int, list: MutableList?) 27 | 28 | /** 29 | * 处理数据 30 | */ 31 | fun convertData(response: MutableList?): MutableList? 32 | 33 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/IBaseView.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/5 5 | */ 6 | interface IBaseView { 7 | 8 | /** 9 | * 显示加载弹窗,表示正在加载数据 10 | * @param message 加载中的文本提示 11 | * @param cancelable 用户是否可取消加载弹窗,默认可以 12 | */ 13 | fun showLoadingDialog(message: String = "加载中", cancelable: Boolean = true) 14 | 15 | /** 16 | * 显示加载状态布局,表示正在加载数据,一般和showLoadingDialog只有一个会出现 17 | */ 18 | fun showLoadingLayout() 19 | 20 | /** 21 | * 数据加载完成,此时可以做一些通用的处理,如取消加载弹窗、完成下拉刷新动作等 22 | * @param isError 数据是否加载成功,为true时表示数据加载失败 23 | */ 24 | fun loadFinish(isError: Boolean) 25 | 26 | /** 27 | * 显示Toast 28 | * @param text 提示的文本内容 29 | * @param isCenter 是否居中显示,true表示居中显示,默认为false 30 | * @param longToast 显示长Toast还是短Toast,默认为Toast.LENGTH_SHORT,即短Toast 31 | */ 32 | fun showToast(text: CharSequence, isCenter: Boolean = true, longToast: Boolean = false) 33 | 34 | /** 35 | * 跳转到登录界面 36 | */ 37 | fun gotoLogin() 38 | 39 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/extra/LiveDataEntity/DialogConfig.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.extra.LiveDataEntity 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/5 5 | * Desc:对话框配置信息 6 | */ 7 | data class DialogConfig( 8 | val message: String, 9 | val cancelable: Boolean 10 | ) 11 | -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/frame/mvvm/extra/LiveDataEntity/ErrorResponse.kt: -------------------------------------------------------------------------------- 1 | package com.android.frame.mvvm.extra.LiveDataEntity 2 | 3 | /** 4 | * Created by xuzhb on 2021/8/5 5 | * Desc:接口请求失败结果 6 | * 接口请求失败分为两种情况:一种是接口自己返回失败结果,此时isException为false, 7 | * 另一种是接口访问异常,如网络无连接导致无法访问,此时isException为true 8 | */ 9 | data class ErrorResponse( 10 | val isException: Boolean, //访问接口是否发生异常,true时exception不为空,false时response不为空 11 | val message: String, //错误信息 12 | val exception: Throwable?, //异常信息,此时isException为true 13 | val response: T? //接口返回结果,此时isException为false 14 | ) -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/util/ByteUnit.kt: -------------------------------------------------------------------------------- 1 | package com.android.util 2 | 3 | import androidx.annotation.StringDef 4 | import kotlin.math.pow 5 | 6 | /** 7 | * Created by xuzhb on 2020/12/1 8 | * Desc:流量的单位 9 | */ 10 | object ByteUnit { 11 | 12 | const val B = "byte" 13 | const val KB = "kb" 14 | const val MB = "mb" 15 | const val GB = "gb" 16 | 17 | @StringDef(B, KB, MB, GB) 18 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 19 | annotation class ByteUnitDef 20 | 21 | private const val UNIT = 1024.0 22 | 23 | fun convertByteUnit(totalBytes: Double, @ByteUnitDef unit: String): Double { 24 | var totalBytes = totalBytes 25 | if (totalBytes > 0) { 26 | when (unit) { 27 | KB -> totalBytes /= UNIT.pow(1.0) 28 | MB -> totalBytes /= UNIT.pow(2.0) 29 | GB -> totalBytes /= UNIT.pow(3.0) 30 | } 31 | } 32 | return totalBytes 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/util/CapturePicture/TestCaptureWebViewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.android.util.CapturePicture 2 | 3 | import android.os.Bundle 4 | import com.android.basicproject.databinding.ActivityTestCaptureWebviewBinding 5 | import com.android.frame.mvc.BaseActivity 6 | import com.android.util.bitmap.BitmapUtil 7 | 8 | /** 9 | * Created by xuzhb on 2021/5/13 10 | * Desc: 11 | */ 12 | class TestCaptureWebViewActivity : BaseActivity() { 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | CapturePictureUtil.enableSlowWholeDocumentDraw() 16 | super.onCreate(savedInstanceState) 17 | } 18 | 19 | override fun handleView(savedInstanceState: Bundle?) { 20 | binding.webView.loadUrl("https://xw.qq.com/") 21 | } 22 | 23 | override fun initListener() { 24 | mTitleBar?.setOnRightTextClickListener { 25 | val bitmap = CapturePictureUtil.captureByWebView(binding.webView) 26 | BitmapUtil.saveBitmapToGallery(this, bitmap, "WebView截图") 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/util/NetReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.android.util 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.net.ConnectivityManager 7 | import com.android.util.NetworkUtil 8 | 9 | /** 10 | * Created by xuzhb on 2019/12/29 11 | * Desc:监听网络变化 12 | */ 13 | class NetReceiver : BroadcastReceiver() { 14 | 15 | override fun onReceive(context: Context?, intent: Intent?) { 16 | if ((ConnectivityManager.CONNECTIVITY_ACTION).equals(intent?.action)) { 17 | mOnNetChangeListener?.invoke(NetworkUtil.isConnected(context!!)) 18 | } 19 | } 20 | 21 | private var mOnNetChangeListener: ((isConnected: Boolean) -> Unit)? = null 22 | 23 | fun setOnNetChangeListener(listener: ((isConnected: Boolean) -> Unit)) { 24 | this.mOnNetChangeListener = listener 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/util/app/AATest/AppAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.android.util.app.AATest 2 | 3 | import android.content.Context 4 | import com.android.basicproject.R 5 | import com.android.util.app.AppInfo 6 | import com.android.widget.RecyclerView.BaseAdapter 7 | import com.android.widget.RecyclerView.ViewHolder 8 | 9 | /** 10 | * Created by xuzhb on 2020/12/3 11 | * Desc: 12 | */ 13 | class AppAdapter(context: Context, list: MutableList) : BaseAdapter(context, list, R.layout.item_image_with_text) { 14 | override fun bindData(holder: ViewHolder, data: AppInfo, position: Int) { 15 | holder.setImageDrawable(R.id.item_iv, data.icon!!) 16 | .setText(R.id.item_tv, data.label) 17 | } 18 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/util/app/AppInfo.kt: -------------------------------------------------------------------------------- 1 | package com.android.util.app 2 | 3 | import android.graphics.drawable.Drawable 4 | 5 | /** 6 | * Created by xuzhb on 2020/11/17 7 | * Desc:应用信息类 8 | */ 9 | data class AppInfo( 10 | val uid: Int = 0, //应用UID 11 | val label: String? = null, //应用标签,即名称 12 | val icon: Drawable? = null, //应用图片 13 | val packageName: String? = null, //应用包名 14 | val apkPath: String? = null, //应用路径 15 | val versionName: String? = null, //应用版本号 16 | val versionCode: Int = 0, //应用版本码 17 | val isSystemApp: Boolean = false //是否是系统App 18 | ) -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/util/threadPool/StepThread.kt: -------------------------------------------------------------------------------- 1 | package com.android.util.threadPool 2 | 3 | import java.util.concurrent.Callable 4 | 5 | /** 6 | * Created by xuzhb on 2020/12/8 7 | * Desc:封装Callable接口 8 | */ 9 | abstract class StepThread : Callable { 10 | 11 | //初始化 12 | @Throws(Exception::class) 13 | abstract fun init() 14 | 15 | //执行任务并返回最终结果 16 | @Throws(Exception::class) 17 | abstract fun execute(): V 18 | 19 | //发生异常时回调 20 | abstract fun onError(e: Exception?) 21 | 22 | //可以做一些最终的资源释放 23 | abstract fun onDestory() 24 | 25 | @Throws(Exception::class) 26 | override fun call(): V? { 27 | try { 28 | init() 29 | return execute() 30 | } catch (e: Exception) { 31 | onError(e) 32 | } finally { 33 | onDestory() 34 | } 35 | return null 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/ExpandTextView/BoldInfo.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.ExpandTextView 2 | 3 | /** 4 | * Created by xuzhb on 2024/5/22 5 | * Desc:字体加粗索引 6 | */ 7 | data class BoldInfo( 8 | val startPosition: Int, //加粗起始位置 9 | val endPosition: Int //加粗结束位置 10 | ) { 11 | fun isActive(position: Int) = position in startPosition..endPosition 12 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/ExpandTextView/ColorInfo.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.ExpandTextView 2 | 3 | import androidx.annotation.ColorInt 4 | 5 | /** 6 | * Created by xuzhb on 2024/5/22 7 | * Desc:字体变色 8 | */ 9 | data class ColorInfo( 10 | val startPosition: Int, //变色起始位置 11 | val endPosition: Int, //变色结束位置 12 | @ColorInt val color: Int //字体颜色 13 | ) { 14 | fun isActive(position: Int) = position in startPosition..endPosition 15 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NeedPermission/AATest/TestFloatPageTwoActivity.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission.AATest 2 | 3 | import android.os.Bundle 4 | import com.android.basicproject.databinding.ActivityCommonLayoutBinding 5 | import com.android.frame.mvc.BaseActivity 6 | import com.android.util.initCommonLayout 7 | 8 | /** 9 | * Created by xuzhb on 2021/3/30 10 | * Desc: 11 | */ 12 | class TestFloatPageTwoActivity : BaseActivity() { 13 | 14 | override fun handleView(savedInstanceState: Bundle?) { 15 | initCommonLayout(this, "悬浮窗页面二", false, true, "跳转到悬浮窗页面三") 16 | binding.tv.text = "悬浮窗A不在页面二显示" 17 | } 18 | 19 | override fun initListener() { 20 | binding.btn1.setOnClickListener { 21 | startActivity(TestFloatPageThreeActivity::class.java) 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NeedPermission/IFloatWindow.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission 2 | 3 | import android.view.View 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/29 7 | * Desc: 8 | */ 9 | interface IFloatWindow { 10 | 11 | fun show() 12 | 13 | fun hide() 14 | 15 | fun isShowing(): Boolean 16 | 17 | fun getX(): Int 18 | 19 | fun getY(): Int 20 | 21 | fun updateX(x: Int) 22 | 23 | /** 24 | * 更新x坐标 25 | * 26 | * @param screenType 以屏幕宽度或屏幕高度为基准 27 | * @param ratio 占比 28 | */ 29 | fun updateX(@ScreenType.screenType screenType: Int, ratio: Float) 30 | 31 | fun updateY(y: Int) 32 | 33 | /** 34 | * 更新y坐标 35 | * 36 | * @param screenType 以屏幕宽度或屏幕高度为基准 37 | * @param ratio 占比 38 | */ 39 | fun updateY(@ScreenType.screenType screenType: Int, ratio: Float) 40 | 41 | fun updateXY(x: Int, y: Int) 42 | 43 | fun getView(): View? 44 | 45 | //使用FloatWindow.destroy()来取消弹窗,不要手动调用下面的方法 46 | @Deprecated("Please use destroy") 47 | fun dismiss() 48 | 49 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NeedPermission/MoveType.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission 2 | 3 | import androidx.annotation.IntDef 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/29 7 | * Desc: 8 | */ 9 | object MoveType { 10 | const val inactive = 1 //不可移动 11 | const val active = 2 //可移动 12 | const val slide = 3 //移动松手后贴边 13 | const val back = 4 //移动松手后回到原来的位置 14 | 15 | @IntDef(inactive, active, slide, back) 16 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 17 | internal annotation class moveType 18 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NeedPermission/OnPermissionListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/29 5 | * Desc:权限申请结果回调 6 | */ 7 | interface OnPermissionListener { 8 | 9 | //授权成功 10 | fun onSuccess() 11 | 12 | //授权失败 13 | fun onFailure() 14 | 15 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NeedPermission/OnViewStateListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/29 5 | * Desc:状态改变监听 6 | */ 7 | interface OnViewStateListener { 8 | 9 | fun onPositionUpdate(x: Int, y: Int) 10 | 11 | fun onShow() 12 | 13 | fun onHide() 14 | 15 | fun onDismiss() 16 | 17 | fun onMoveAnimStart() 18 | 19 | fun onMoveAnimEnd() 20 | 21 | fun onBackToDesktop() 22 | 23 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NeedPermission/ScreenType.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NeedPermission 2 | 3 | import androidx.annotation.IntDef 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/29 7 | * Desc:选择以屏幕宽度或屏幕高度为基准 8 | */ 9 | object ScreenType { 10 | const val width = 0 11 | const val height = 1 12 | 13 | @IntDef(width, height) 14 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 15 | internal annotation class screenType 16 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NoPermission/MoveType.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NoPermission 2 | 3 | import androidx.annotation.IntDef 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/25 7 | * Desc:移动方式 8 | */ 9 | object MoveType { 10 | const val inactive = 1 //不可移动 11 | const val active = 2 //可移动 12 | const val slide = 3 //移动松手后贴边 13 | const val back = 4 //移动松手后回到原来的位置 14 | 15 | @IntDef(inactive, active, slide, back) 16 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 17 | internal annotation class moveType 18 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/NoPermission/ScreenType.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow.NoPermission 2 | 3 | import androidx.annotation.IntDef 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/25 7 | * Desc:选择以屏幕宽度或屏幕高度为基准 8 | */ 9 | object ScreenType { 10 | const val width = 0 11 | const val height = 1 12 | 13 | @IntDef(width, height) 14 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 15 | internal annotation class screenType 16 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/FloatWindow/TestFloatActivity.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.FloatWindow 2 | 3 | import android.os.Bundle 4 | import com.android.basicproject.databinding.ActivityCommonLayoutBinding 5 | import com.android.frame.mvc.BaseActivity 6 | import com.android.util.initCommonLayout 7 | import com.android.widget.FloatWindow.NeedPermission.AATest.TestFloatPageOneActivity 8 | import com.android.widget.FloatWindow.NoPermission.AATest.TestFloatPageActivity 9 | 10 | /** 11 | * Created by xuzhb on 2021/3/25 12 | * Desc: 13 | */ 14 | class TestFloatActivity : BaseActivity() { 15 | 16 | override fun handleView(savedInstanceState: Bundle?) { 17 | initCommonLayout(this, "悬浮窗", "申请权限", "无需权限") 18 | } 19 | 20 | override fun initListener() { 21 | binding.btn1.setOnClickListener { 22 | startActivity(TestFloatPageOneActivity::class.java) 23 | } 24 | binding.btn2.setOnClickListener { 25 | TestFloatPageActivity.start(this, 1) 26 | } 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnGestureListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/30 5 | * Desc:手势监听 6 | */ 7 | interface OnGestureListener { 8 | 9 | /** 10 | * 拖动 11 | * 12 | * @param dx 水平方向上拖动的距离 13 | * @param dy 竖直方向上拖动的距离 14 | */ 15 | fun onDrag(dx: Float, dy: Float) 16 | 17 | /** 18 | * 快速滑动 19 | * 20 | * @param startX 滑动起点的x坐标 21 | * @param startY 滑动起点的y坐标 22 | * @param velocityX 水平方向上滑动的速度 23 | * @param velocityY 竖直方向上滑动的速度 24 | */ 25 | fun onFling(startX: Float, startY: Float, velocityX: Float, velocityY: Float) 26 | 27 | /** 28 | * 缩放 29 | * 30 | * @param scaleFactor 缩放因子 31 | * @param focusX 组成该手势的两个触点的中点的x坐标,单位是像素 32 | * @param focusY 组成该手势的两个触点的中点的y坐标,单位是像素 33 | */ 34 | fun onScale(scaleFactor: Float, focusX: Float, focusY: Float) 35 | 36 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnMatrixChangedListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | import android.graphics.RectF 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/30 7 | * Desc:View的Matrix矩阵变化监听 8 | */ 9 | interface OnMatrixChangedListener { 10 | 11 | /** 12 | * 当View的边界发生变化时回调 13 | * 14 | * @param rect View的新边界 15 | */ 16 | fun onMatrixChanged(rectF: RectF) 17 | 18 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnOutsidePhotoTapListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | import android.widget.ImageView 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/30 7 | * Desc:图片外部区域点击事件监听 8 | */ 9 | interface OnOutsidePhotoTapListener { 10 | 11 | /** 12 | * 点击图片外部区域时回调 13 | */ 14 | fun onOutsidePhotoTap(imageView: ImageView) 15 | 16 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnPhotoTapListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | import android.widget.ImageView 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/30 7 | * Desc:图片单击事件监听 8 | */ 9 | interface OnPhotoTapListener { 10 | 11 | /** 12 | * 点击图片区域以内时回调,图片区域以外不会回调 13 | * 14 | * @param imageView 点击的图片 15 | * @param x 点击的位置x坐标 16 | * @param y 点击的位置y坐标 17 | * @param xOffset 点击的位置相对于左上角的横向偏移量,百分比形式 18 | * @param yOffset 点击的位置相对于左上角的纵向偏移量,百分比形式 19 | */ 20 | fun onPhotoTap(imageView: ImageView, x: Float, y: Float, xOffset: Float, yOffset: Float) 21 | 22 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnScaleChangedListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/30 5 | * Desc:图片缩放监听 6 | */ 7 | interface OnScaleChangedListener { 8 | 9 | /** 10 | * 图片缩放时回调 11 | * 12 | * @param scaleFactor 缩放因子(小于1时缩小,大于1时放大) 13 | * @param focusX 缩放焦点的x坐标 14 | * @param focusY 缩放焦点的y坐标 15 | */ 16 | fun onScaleChange(scaleFactor: Float, focusX: Float, focusY: Float) 17 | 18 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnSingleFlingListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | import android.view.MotionEvent 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/30 7 | * Desc:快速滑动监听 8 | */ 9 | interface OnSingleFlingListener { 10 | 11 | /** 12 | * 快速滑动时回调 13 | * 14 | * @param event1 首次接触时的MotionEvent 15 | * @param event2 最后一次接触时的MotionEvent 16 | * @param velocityX 水平滑动的速度 17 | * @param velocityY 竖直滑动的速度 18 | */ 19 | fun onFling(event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float): Boolean 20 | 21 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnViewDragListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | /** 4 | * Created by xuzhb on 2021/3/30 5 | * Desc:图片拖动监听 6 | */ 7 | interface OnViewDragListener { 8 | 9 | /** 10 | * 拖动图片时回调,当缩放图片时不会触发次回调 11 | * 12 | * @param dx 水平方向上拖动的距离 13 | * @param dy 竖直方向上拖动的距离 14 | */ 15 | fun onDrag(dx: Float, dy: Float) 16 | 17 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/listener/OnViewTapListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.listener 2 | 3 | import android.view.View 4 | 5 | /** 6 | * Created by xuzhb on 2021/3/30 7 | * Desc:ImageView点击事件监听 8 | */ 9 | interface OnViewTapListener { 10 | 11 | /** 12 | * ImageView点击时回调 13 | * 14 | * @param view 点击的ImageView 15 | * @param x 点击的X坐标 16 | * @param y 点击的Y坐标 17 | */ 18 | fun onViewTap(view: View, x: Float, y: Float) 19 | 20 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PhotoViewer/widget/PhotoViewPager.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PhotoViewer.widget 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import androidx.viewpager.widget.ViewPager 7 | 8 | /** 9 | * Created by xuzhb on 2021/3/30 10 | */ 11 | class PhotoViewPager @JvmOverloads constructor( 12 | context: Context, attrs: AttributeSet? = null 13 | ) : ViewPager(context, attrs) { 14 | 15 | override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { 16 | return try { 17 | super.onInterceptTouchEvent(ev) 18 | } catch (e: Exception) { 19 | false 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PicGetterDialog/AATest/CustomPicGetterDialog.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PicGetterDialog.AATest 2 | 3 | import android.app.Dialog 4 | import com.android.basicproject.R 5 | import com.android.widget.PicGetterDialog.BasePicGetterDialog 6 | import com.android.widget.ViewHolder 7 | 8 | /** 9 | * Created by xuzhb on 2020/1/28 10 | * Desc: 11 | */ 12 | class CustomPicGetterDialog : BasePicGetterDialog() { 13 | 14 | override fun getLayoutId(): Int = R.layout.dialog_custom_pic_getter 15 | 16 | override fun convertView(holder: ViewHolder, dialog: Dialog?) { 17 | holder.setOnClickListener(R.id.camera_btn) { 18 | openCamera() //拍照 19 | } 20 | holder.setOnClickListener(R.id.gallery_btn) { 21 | openGallery() //从相册选取照片 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PicGetterDialog/OnPicGetterListener.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PicGetterDialog 2 | 3 | import android.graphics.Bitmap 4 | 5 | /** 6 | * Created by xuzhb on 2020/1/27 7 | * Desc: 8 | */ 9 | interface OnPicGetterListener { 10 | 11 | /** 12 | * 图片获取成功 13 | * 14 | * @param bitmap 图片 15 | * @param picPath 图片路径 16 | */ 17 | fun onSuccess(bitmap: Bitmap?, picPath: String?) 18 | 19 | /** 20 | * 图片获取失败 21 | * 22 | * @param errorMsg 错误信息 23 | */ 24 | fun onFailure(errorMsg: String?) 25 | 26 | 27 | /** 28 | * 取消图片获取 29 | */ 30 | fun onCancel() 31 | 32 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PicGetterDialog/PicGetterDialog.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PicGetterDialog 2 | 3 | import android.app.Dialog 4 | import com.android.basicproject.R 5 | import com.android.widget.ViewHolder 6 | 7 | /** 8 | * Created by xuzhb on 2020/1/27 9 | * Desc:拍照或从相册选取选择框 10 | */ 11 | class PicGetterDialog : BasePicGetterDialog() { 12 | 13 | override fun getLayoutId(): Int = R.layout.dialog_pic_getter 14 | 15 | override fun convertView(holder: ViewHolder, dialog: Dialog?) { 16 | holder.setOnClickListener(R.id.camera_tv) { 17 | openCamera() //拍照 18 | } 19 | holder.setOnClickListener(R.id.gallery_tv) { 20 | openGallery() //从相册选取照片 21 | } 22 | holder.setOnClickListener(R.id.cancel_tv) { 23 | getDialog()?.let { 24 | onCancel(it) //取消弹窗 25 | dismiss() 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PicGetterDialog/说明.md: -------------------------------------------------------------------------------- 1 | 集成: 2 | 1、build.gradle导入图片裁剪框架'com.yalantis:ucrop:2.2.0' 3 | 2、AndroidManifest配置相应的fileprovider和UCropActivity 4 | 3、混淆 5 | -dontwarn com.yalantis.ucrop** 6 | -keep class com.yalantis.ucrop** { *; } 7 | -keep interface com.yalantis.ucrop** { *; } 8 | 9 | 相关类: 10 | 1、dialog_pic_getter:弹窗布局 11 | 2、pic_getter_file_paths:fileprovider配置,Android 7.0以上的系统需要使用FileProvider兼容拍照 12 | 3、PicProvider:fileprovider 13 | 4、BasePicGetterDialog 14 | 5、PicGetterDialog 15 | 6、OnPicGetterListener 16 | -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PieChart/PieData.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PieChart 2 | 3 | /** 4 | * Created by xuzhb on 2019/10/15 5 | * Desc: 6 | */ 7 | data class PieData( 8 | val value: Float, 9 | val color: Int, 10 | val label: String 11 | ) -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PopupWindow/AATest/PopupWindowAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PopupWindow.AATest 2 | 3 | import android.content.Context 4 | import com.android.basicproject.R 5 | import com.android.widget.RecyclerView.BaseAdapter 6 | import com.android.widget.RecyclerView.ViewHolder 7 | 8 | /** 9 | * Created by xuzhb on 2019/9/1 10 | * Desc: 11 | */ 12 | class PopupWindowAdapter(context: Context, list: MutableList) : 13 | BaseAdapter(context, list, R.layout.item_popup_window) { 14 | 15 | override fun bindData(holder: ViewHolder, data: String, position: Int) { 16 | holder.setText(R.id.item_tv, data) 17 | if (position == itemCount - 1) { 18 | holder.setViewGone(R.id.divider_line) 19 | } else { 20 | holder.setViewVisible(R.id.divider_line) 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/PopupWindow/WindowHelper.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.PopupWindow 2 | 3 | import android.app.Activity 4 | import androidx.annotation.FloatRange 5 | 6 | /** 7 | * Created by xuzhb on 2019/9/3 8 | * Desc:Window辅助类,实现背景灰色效果 9 | */ 10 | class WindowHelper(private var mActivity: Activity) { 11 | 12 | //设置外部区域背景透明度,0:完全不透明,1:完全透明 13 | fun setBackGroundAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) { 14 | val window = mActivity.window 15 | val lp = window.attributes 16 | lp.alpha = alpha 17 | window.attributes = lp 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/RecyclerView/AATest/TestLoadMoreWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest 2 | 3 | import android.content.Context 4 | import android.widget.ImageView 5 | import com.android.base.BaseApplication 6 | import com.android.basicproject.R 7 | import com.android.frame.http.AATest.bean.NewsListBean 8 | import com.android.widget.RecyclerView.BaseAdapter 9 | import com.android.widget.RecyclerView.ViewHolder 10 | import com.bumptech.glide.Glide 11 | 12 | /** 13 | * Created by xuzhb on 2019/10/29 14 | * Desc:上拉加载更多 15 | */ 16 | class TestLoadMoreWrapper(context: Context, list: MutableList) : 17 | BaseAdapter(context, list, R.layout.item_test_load_more) { 18 | override fun bindData(holder: ViewHolder, data: NewsListBean.ResultBean, position: Int) { 19 | val imageIv: ImageView = holder.getView(R.id.image_iv)!! 20 | Glide.with(BaseApplication.instance).load(data.image).into(imageIv) 21 | holder.setText(R.id.title_tv, data.title).setText(R.id.time_tv, data.passtime) 22 | } 23 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/RecyclerView/AATest/TestSingleLoadMoreAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest 2 | 3 | import android.content.Context 4 | import android.widget.ImageView 5 | import com.android.base.BaseApplication 6 | import com.android.basicproject.R 7 | import com.android.frame.http.AATest.bean.NewsListBean 8 | import com.android.widget.RecyclerView.LoadMoreAdapter 9 | import com.android.widget.RecyclerView.ViewHolder 10 | import com.bumptech.glide.Glide 11 | 12 | /** 13 | * Created by xuzhb on 2020/1/13 14 | * Desc:单布局上拉加载更多 15 | */ 16 | class TestSingleLoadMoreAdapter(context: Context, list: MutableList) : 17 | LoadMoreAdapter(context, list, R.layout.item_test_load_more) { 18 | override fun bindData(holder: ViewHolder, data: NewsListBean.ResultBean, position: Int) { 19 | val imageIv: ImageView = holder.getView(R.id.image_iv)!! 20 | Glide.with(BaseApplication.instance).load(data.image).into(imageIv) 21 | holder.setText(R.id.title_tv, data.title).setText(R.id.time_tv, data.passtime) 22 | } 23 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/RecyclerView/AATest/entity/DateBean.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2020/1/15 7 | * Desc: 8 | */ 9 | data class DateBean( 10 | val date: String 11 | ) : Serializable -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/RecyclerView/AATest/entity/DetailBean.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2019/11/17 7 | * Desc: 8 | */ 9 | data class DetailBean( 10 | val detail: String, 11 | val time: String 12 | ) : Serializable -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/RecyclerView/AATest/entity/MonthBean.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView.AATest.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by xuzhb on 2019/11/17 7 | * Desc: 8 | */ 9 | data class MonthBean( 10 | val month: String, 11 | val count: String 12 | ) : Serializable -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/RecyclerView/MultiViewType.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.RecyclerView 2 | 3 | /** 4 | * Created by xuzhb on 2019/7/30 5 | * Desc:RecyclerView实现多种Item布局 6 | */ 7 | interface MultiViewType { 8 | 9 | /** 10 | * 实现多种Item布局 11 | * 12 | * @param data Item对应的数据 13 | * @param position Item的位置 14 | * @param totalCount Item的总数 15 | * @return Item对应的布局类型,使用布局的id进行区分 16 | */ 17 | fun getLayoutId(data: T, position: Int, totalCount: Int): Int 18 | 19 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/ScrollTextView.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget 2 | 3 | import android.content.Context 4 | import android.text.TextUtils 5 | import android.util.AttributeSet 6 | import androidx.annotation.AttrRes 7 | import androidx.appcompat.widget.AppCompatTextView 8 | 9 | /** 10 | * Created by xuzhb on 2020/1/7 11 | * Desc:TextView文字滚动显示,即跑马灯效果(不需要获取焦点) 12 | */ 13 | class ScrollTextView @JvmOverloads constructor( 14 | context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttrs: Int = 0 15 | ) : AppCompatTextView(context, attrs, defStyleAttrs) { 16 | 17 | init { 18 | setSingleLine(true) 19 | ellipsize = TextUtils.TruncateAt.MARQUEE //设置跑马灯效果 20 | marqueeRepeatLimit = -1 //设置循环滚动为无限循环 21 | } 22 | 23 | override fun isFocused(): Boolean = true 24 | 25 | } -------------------------------------------------------------------------------- /kotlin/src/main/java/com/android/widget/dialog/CommonDialog.kt: -------------------------------------------------------------------------------- 1 | package com.android.widget.dialog 2 | 3 | import androidx.annotation.LayoutRes 4 | import androidx.fragment.app.DialogFragment 5 | import com.android.widget.ViewHolder 6 | 7 | /** 8 | * Created by xuzhb on 2019/10/22 9 | * Desc:通用的Dialog,可以实现不同布局的Dialog 10 | */ 11 | class CommonDialog : BaseDialog() { 12 | 13 | companion object { 14 | fun newInstance(): CommonDialog = CommonDialog() 15 | } 16 | 17 | private var mListener: ((holder: ViewHolder, dialog: DialogFragment?) -> Unit)? = null 18 | 19 | //设置dialog的布局 20 | fun setLayoutId(@LayoutRes layoutId: Int): CommonDialog { 21 | this.mLayoutId = layoutId 22 | return this 23 | } 24 | 25 | //设置事件监听 26 | fun setOnViewListener(listener: (holder: ViewHolder, dialog: DialogFragment?) -> Unit): CommonDialog { 27 | this.mListener = listener 28 | return this 29 | } 30 | 31 | override fun getLayoutId(): Int = mLayoutId 32 | 33 | override fun convertView(holder: ViewHolder, dialog: DialogFragment?) { 34 | mListener?.invoke(holder, dialog) 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_list_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_bitmap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_capture_gridview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_capture_listview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_capture_recyclerview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_capture_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_test_pie_chart.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 21 | 22 | 27 | 28 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/activity_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/fragment_test_mvc.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/fragment_test_mvc_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kotlin/src/main/res/layout/fragment_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kotlin/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Kotlin 3 | 4 | -------------------------------------------------------------------------------- /kotlin/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kotlin/src/test/java/com/android/basicproject/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.android.basicproject 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':kotlin', ':java', ':universal' 2 | -------------------------------------------------------------------------------- /universal/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /universal/BasicProject.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/BasicProject.jks -------------------------------------------------------------------------------- /universal/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 | -------------------------------------------------------------------------------- /universal/src/androidTest/java/com/android/universal/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.android.universal; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.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.android.universal.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /universal/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /universal/src/main/assets/fonts/fonts.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/assets/fonts/fonts.ttf -------------------------------------------------------------------------------- /universal/src/main/assets/test_install.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/assets/test_install.apk -------------------------------------------------------------------------------- /universal/src/main/res/anim/alpha_in_150.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/alpha_in_300.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/alpha_out_150.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/alpha_out_300.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_center_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_center_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_top_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/scale_top_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/slide_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/slide_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/slide_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/slide_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_top_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /universal/src/main/res/anim/translate_top_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /universal/src/main/res/color/selector_tab_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/color/selector_toggle_button_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_add.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_back.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_bg.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_bitmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_bitmap.jpg -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_check.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_clear.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_coupon_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_coupon_btn.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_coupon_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_coupon_header.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_empty_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_empty_data.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_face1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_face1.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_face2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_face2.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_face3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_face3.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_flashlight_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_flashlight_off.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_flashlight_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_flashlight_on.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_frame_not_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_frame_not_selected.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_frame_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_frame_selected.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_guide_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_guide_bg.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_guide_one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_guide_one.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_guide_three.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_guide_three.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_guide_two.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_guide_two.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_letter_bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_letter_bubble.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_load_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_load_empty.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_load_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_load_fail.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_load_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_load_loading.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_more.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_msg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_msg.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_photo_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_photo_close.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_photo_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_photo_download.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_photo_load_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_photo_load_fail.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_qq.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_query.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_scan_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_scan_grid.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_search_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_search_clear.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_search_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_search_search.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_settings.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_status_bar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_status_bar.jpeg -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_uncheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_uncheck.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_util_not_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_util_not_selected.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_util_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_util_selected.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_warn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_warn.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_weibo.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_weixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_weixin.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_widget_not_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_widget_not_selected.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable-xhdpi/ic_widget_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuzhb24/BasicProject/5d6e0bd09391d5326c39172295fcb30186cba7d3/universal/src/main/res/drawable-xhdpi/ic_widget_selected.png -------------------------------------------------------------------------------- /universal/src/main/res/drawable/layer_list_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/layer_list_input_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/layer_list_progress_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/loading_progressbar_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_bottom_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_bottom_util.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_bottom_widget.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_flash_light_switch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_gray_item_layout_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_guide_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_guide_use_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_item_check_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_item_layout_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_tab_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/selector_toggle_button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_confirm_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_corners_10_solid_000000.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_corners_15_solid_ffffff.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_corners_15_solid_transparent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_corners_17_solid_66000000.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_coupon_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_cursor_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_indicator_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_loading_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_loading_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_oval_size_34_solid_66000000.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_oval_size_34_solid_db4b3c.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_photo_view_progress_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_progressbar_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_progressbar_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_search_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_size_2_solid_0071ff.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /universal/src/main/res/drawable/shape_spannable_block.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /universal/src/main/res/layout/dialog_app_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |