From f4cec991ed2aef3ce5c760c1566bb48c894d8a64 Mon Sep 17 00:00:00 2001 From: free will <2647778488@qq.com> Date: Thu, 24 Jun 2021 19:21:29 +0800 Subject: [PATCH] =?UTF-8?q?add=20many:=E8=A7=A3=E5=86=B3=E4=BA=86=E8=8B=A5?= =?UTF-8?q?=E5=B9=B2bug=EF=BC=8C=E6=88=90=E5=8A=9F=E8=B7=91=E8=B5=B7?= =?UTF-8?q?=E6=9D=A5=E4=BA=86=E7=95=8C=E9=9D=A2=E3=80=82=E6=9C=80=E5=A4=A7?= =?UTF-8?q?=E7=9A=84=E4=B8=80=E4=B8=AA=E6=94=B9=E5=8F=98=E6=98=AF=E5=B0=86?= =?UTF-8?q?quick=5Fandroid=E5=BA=93=E7=94=B1=E4=BA=91=E7=AB=AF=E5=BA=93?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E4=BA=86=E6=9C=AC=E5=9C=B0=E5=BA=93=EF=BC=8C?= =?UTF-8?q?=E7=84=B6=E5=90=8E=E6=B3=A8=E9=87=8A=E6=8E=89=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=8A=A5=E9=94=99=E4=B8=94=E6=B2=A1=E6=9C=89=E7=94=A8?= =?UTF-8?q?=E5=88=B0=E7=9A=84=E4=BB=A3=E7=A0=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 58 +-- app/src/main/AndroidManifest.xml | 39 +- .../java/com/pkusz/min_vpn_client/APP.java | 20 + .../activity/base/MINVpnBaseActivity.java | 15 +- .../activity/welcome/WelcomeActivity.java | 20 +- .../extensions/ActivityExtensions.kt | 26 ++ .../extensions/ContextExtensions.kt | 10 + .../extensions/FileUtilsExtensions.kt | 37 ++ .../pkusz/min_vpn_client/extensions/README.md | 3 + .../{ => model}/Request_API.java | 3 +- build.gradle | 39 +- gradle.properties | 5 +- quick_android_base/.gitignore | 1 + quick_android_base/README.md | 161 ++++++++ quick_android_base/build.gradle | 84 ++++ quick_android_base/proguard-rules.pro | 177 +++++++++ .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 12 + .../src/main/java/NetworkUtil.kt | 69 ++++ .../quick_android_base/MyAppGlideModule.kt | 7 + .../qjm253/quick_android_base/QuickAndroid.kt | 41 ++ .../base/activity/BaseQuickAndroidActivity.kt | 110 ++++++ .../base/fragment/BaseQuickAndroidFragment.kt | 191 +++++++++ .../extensions/ActivityExtensions.kt | 41 ++ .../extensions/AnyExtensions.kt | 12 + .../extensions/ContextExtension.kt | 149 +++++++ .../extensions/FloatExtensions.kt | 20 + .../extensions/FragmentManagerExtensions.kt | 44 +++ .../extensions/ImageViewExtensions.kt | 63 +++ .../extensions/LoggerExtensions.kt | 29 ++ .../extensions/LongExtensions.kt | 48 +++ .../extensions/MathExtension.kt | 13 + .../extensions/MotionEventExtension.kt | 20 + .../extensions/MyDelegates.kt | 39 ++ .../extensions/TextViewExtensions.kt | 37 ++ .../extensions/ViewExtension.kt | 123 ++++++ .../quick_android_base/model/SystemInfo.kt | 16 + .../quick_android_base/params/IntentParam.kt | 76 ++++ .../util/AccountValidatorUtil.kt | 128 ++++++ .../util/ContentUriUtil.java | 366 ++++++++++++++++++ .../quick_android_base/util/DisplayUtils.java | 105 +++++ .../quick_android_base/util/FileUtils.kt | 118 ++++++ .../quick_android_base/util/GenerateId.kt | 30 ++ .../quick_android_base/util/GsonUtil.kt | 78 ++++ .../util/RxSchedulersHelper.kt | 41 ++ .../quick_android_base/util/SpUtils.java | 303 +++++++++++++++ .../quick_android_base/util/SpannableUtil.kt | 85 ++++ .../util/SystemInfoHelper.kt | 88 +++++ .../util/notification/MyNotificationUtil.kt | 162 ++++++++ .../src/main/res/drawable/logo.png | Bin 0 -> 2903 bytes .../src/main/res/values/strings.xml | 3 + .../quick_android_base/ExampleUnitTest.java | 17 + quick_android_custom_view/.gitignore | 1 + quick_android_custom_view/build.gradle | 40 ++ quick_android_custom_view/proguard-rules.pro | 21 + .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 2 + .../DrawableButton.kt | 102 +++++ .../DrawableEditText.kt | 75 ++++ .../DrawableTextView.kt | 76 ++++ .../custom_drawable_size_view/SizeWrap.kt | 37 ++ .../other/ClearAbleEditText.kt | 74 ++++ .../other/LineMenu.kt | 37 ++ .../other/LineMenuItem.kt | 271 +++++++++++++ .../other/LineMenuSwitch.kt | 154 ++++++++ .../other/NoneScrollViewPager.kt | 58 +++ .../tin_view/TinButton.kt | 112 ++++++ .../tin_view/TinEditText.kt | 146 +++++++ .../tin_view/TinImageView.kt | 65 ++++ .../tin_view/TinTextView.kt | 114 ++++++ .../src/main/res/drawable/blue_thumb.xml | 14 + .../src/main/res/drawable/blue_track.xml | 11 + .../src/main/res/drawable/gray_thumb.xml | 14 + .../src/main/res/drawable/gray_track.xml | 11 + .../src/main/res/drawable/icon_arrow.png | Bin 0 -> 992 bytes .../src/main/res/drawable/menu.png | Bin 0 -> 1921 bytes .../src/main/res/drawable/switch_thumb.xml | 5 + .../src/main/res/drawable/switch_track.xml | 5 + .../res/values/custom_drawable_size_view.xml | 89 +++++ .../src/main/res/values/line_menu.xml | 55 +++ .../quick_android_custom_view_color.xml | 13 + .../quick_android_custom_view_dimen.xml | 6 + .../src/main/res/values/strings.xml | 2 + .../src/main/res/values/tin_view.xml | 33 ++ .../ExampleUnitTest.java | 17 + quick_android_easy_bar/.gitignore | 1 + quick_android_easy_bar/build.gradle | 38 ++ quick_android_easy_bar/consumer-rules.pro | 0 quick_android_easy_bar/proguard-rules.pro | 21 + .../ExampleInstrumentedTest.kt | 24 ++ .../src/main/AndroidManifest.xml | 2 + .../qjm253/quick_android_easy_bar/EasyBar.kt | 354 +++++++++++++++++ .../EasyBarExtensions.kt | 89 +++++ .../src/main/res/drawable/back.png | Bin 0 -> 752 bytes .../src/main/res/values/colors.xml | 4 + .../values/quick_android_easy_bar_attrs.xml | 18 + .../src/main/res/values/strings.xml | 2 + .../quick_android_easy_bar/ExampleUnitTest.kt | 17 + quick_android_file_picker/.gitignore | 1 + quick_android_file_picker/README.md | 67 ++++ quick_android_file_picker/build.gradle | 45 +++ quick_android_file_picker/consumer-rules.pro | 0 quick_android_file_picker/proguard-rules.pro | 21 + .../ExampleInstrumentedTest.kt | 24 ++ .../src/main/AndroidManifest.xml | 2 + .../QuickAndroidFilePicker.kt | 50 +++ .../QuickAndroidFilePickerFragment.kt | 49 +++ .../model/FilePickerResult.kt | 8 + .../src/main/res/values/strings.xml | 2 + .../ExampleUnitTest.kt | 17 + quick_android_image_picker/.gitignore | 1 + quick_android_image_picker/README.md | 85 ++++ quick_android_image_picker/build.gradle | 50 +++ quick_android_image_picker/proguard-rules.pro | 26 ++ .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 14 + .../MyImagePicker.kt | 35 ++ .../QuickAndroidImagePicker.kt | 174 +++++++++ .../activity/QuickAndroidClipImageActivity.kt | 42 ++ .../fragment/QuickAndroidClipImageFragment.kt | 118 ++++++ .../views/ClipImageBorderView.kt | 107 +++++ .../views/ClipImageLayout.kt | 104 +++++ .../views/ClipZoomImageView.kt | 361 +++++++++++++++++ .../activity_quick_android_clip_image.xml | 29 ++ .../fragment_quick_android_clip_image.xml | 13 + .../src/main/res/values/strings.xml | 3 + .../ExampleUnitTest.java | 17 + quick_android_mvp/.gitignore | 1 + quick_android_mvp/README.md | 172 ++++++++ quick_android_mvp/build.gradle | 59 +++ quick_android_mvp/proguard-rules.pro | 34 ++ .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 2 + .../quick_android_mvp/QuickAndroidMVP.kt | 196 ++++++++++ .../activity/BaseQuickAndroidMVPActivity.kt | 69 ++++ .../fragment/BaseQuickAndroidMVPFragment.kt | 63 +++ .../quick_android_mvp/base/mvp/BaseModel.kt | 7 + .../base/mvp/BasePresenter.kt | 10 + .../quick_android_mvp/base/mvp/BaseView.kt | 43 ++ .../exceptions/MVPAPIResultDealException.kt | 9 + .../MVPAPIResultDealNeedRetryException.kt | 9 + .../exceptions/MVPExceptionWrapper.kt | 16 + .../inernet/QuickAndroidMVPAPIManager.kt | 84 ++++ .../inernet/rx/QuickAndroidMVPObserver.kt | 43 ++ .../inernet/rx/QuickAndroidMVPResultDeal.kt | 69 ++++ .../model/inernet/rx/RxExtensions.kt | 82 ++++ .../response/BaseQuickAndroidResponseBody.kt | 9 + .../src/main/res/values/strings.xml | 2 + .../quick_android_mvp/ExampleUnitTest.java | 17 + quick_android_qrcode/.gitignore | 1 + quick_android_qrcode/README.md | 51 +++ quick_android_qrcode/build.gradle | 42 ++ quick_android_qrcode/proguard-rules.pro | 21 + .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 9 + .../QuickAndroidQrCode.kt | 131 +++++++ .../activity/QuickAndroidQrCodeActivity.kt | 32 ++ .../fragment/QuickAndroidQrCodeFragment.kt | 132 +++++++ .../QuickAndroidQrCodeTransFragment.kt | 114 ++++++ .../model/QrCodeResult.kt | 9 + .../quick_android_qr_code_default_back.png | Bin 0 -> 752 bytes .../layout/activity_quick_android_qr_code.xml | 15 + .../layout/fragment_quick_android_qrcode.xml | 38 ++ .../src/main/res/values/strings.xml | 2 + .../quick_android_qrcode/ExampleUnitTest.java | 17 + quick_android_rx_permission/.gitignore | 1 + quick_android_rx_permission/README.md | 37 ++ quick_android_rx_permission/build.gradle | 40 ++ .../proguard-rules.pro | 21 + .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 2 + .../QuickAndroidRxPermission.kt | 65 ++++ .../QuickAndroidRxPermissionFragment.kt | 77 ++++ .../QuickAndroidRxPermissionItem.kt | 12 + .../src/main/res/values/strings.xml | 2 + .../ExampleUnitTest.java | 17 + quick_android_webview/.gitignore | 1 + quick_android_webview/README.md | 117 ++++++ quick_android_webview/build.gradle | 53 +++ quick_android_webview/libs/armeabi/liblbs.so | Bin 0 -> 15456 bytes quick_android_webview/libs/tbs_sdk.jar | Bin 0 -> 455877 bytes quick_android_webview/proguard-rules.pro | 21 + .../ExampleInstrumentedTest.java | 26 ++ .../src/main/AndroidManifest.xml | 11 + .../QuickAndroidWebview.kt | 18 + .../views/QuickAndroidWebview.kt | 180 +++++++++ .../web_bridge/QuickAndroidWebBridge.kt | 109 ++++++ .../src/main/res/values/strings.xml | 2 + .../ExampleUnitTest.java | 17 + settings.gradle | 9 + 190 files changed, 9647 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/pkusz/min_vpn_client/APP.java create mode 100644 app/src/main/java/com/pkusz/min_vpn_client/extensions/ActivityExtensions.kt create mode 100644 app/src/main/java/com/pkusz/min_vpn_client/extensions/ContextExtensions.kt create mode 100644 app/src/main/java/com/pkusz/min_vpn_client/extensions/FileUtilsExtensions.kt create mode 100644 app/src/main/java/com/pkusz/min_vpn_client/extensions/README.md rename app/src/main/java/com/pkusz/min_vpn_client/{ => model}/Request_API.java (98%) create mode 100644 quick_android_base/.gitignore create mode 100644 quick_android_base/README.md create mode 100644 quick_android_base/build.gradle create mode 100644 quick_android_base/proguard-rules.pro create mode 100644 quick_android_base/src/androidTest/java/cn/qjm253/quick_android_base/ExampleInstrumentedTest.java create mode 100644 quick_android_base/src/main/AndroidManifest.xml create mode 100644 quick_android_base/src/main/java/NetworkUtil.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/MyAppGlideModule.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/QuickAndroid.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/fragment/BaseQuickAndroidFragment.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ActivityExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/AnyExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ContextExtension.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FloatExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FragmentManagerExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ImageViewExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LoggerExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LongExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MathExtension.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MotionEventExtension.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MyDelegates.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/TextViewExtensions.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ViewExtension.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/model/SystemInfo.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/params/IntentParam.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/AccountValidatorUtil.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/ContentUriUtil.java create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/DisplayUtils.java create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/FileUtils.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GenerateId.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GsonUtil.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/RxSchedulersHelper.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpUtils.java create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpannableUtil.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SystemInfoHelper.kt create mode 100644 quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/notification/MyNotificationUtil.kt create mode 100644 quick_android_base/src/main/res/drawable/logo.png create mode 100644 quick_android_base/src/main/res/values/strings.xml create mode 100644 quick_android_base/src/test/java/cn/qjm253/quick_android_base/ExampleUnitTest.java create mode 100644 quick_android_custom_view/.gitignore create mode 100644 quick_android_custom_view/build.gradle create mode 100644 quick_android_custom_view/proguard-rules.pro create mode 100644 quick_android_custom_view/src/androidTest/java/cn/qjm253/quick_android_custom_view/ExampleInstrumentedTest.java create mode 100644 quick_android_custom_view/src/main/AndroidManifest.xml create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableButton.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableEditText.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableTextView.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/SizeWrap.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/ClearAbleEditText.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenu.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuItem.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuSwitch.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/NoneScrollViewPager.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinButton.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinEditText.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinImageView.kt create mode 100644 quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinTextView.kt create mode 100644 quick_android_custom_view/src/main/res/drawable/blue_thumb.xml create mode 100644 quick_android_custom_view/src/main/res/drawable/blue_track.xml create mode 100644 quick_android_custom_view/src/main/res/drawable/gray_thumb.xml create mode 100644 quick_android_custom_view/src/main/res/drawable/gray_track.xml create mode 100644 quick_android_custom_view/src/main/res/drawable/icon_arrow.png create mode 100644 quick_android_custom_view/src/main/res/drawable/menu.png create mode 100644 quick_android_custom_view/src/main/res/drawable/switch_thumb.xml create mode 100644 quick_android_custom_view/src/main/res/drawable/switch_track.xml create mode 100644 quick_android_custom_view/src/main/res/values/custom_drawable_size_view.xml create mode 100644 quick_android_custom_view/src/main/res/values/line_menu.xml create mode 100644 quick_android_custom_view/src/main/res/values/quick_android_custom_view_color.xml create mode 100644 quick_android_custom_view/src/main/res/values/quick_android_custom_view_dimen.xml create mode 100644 quick_android_custom_view/src/main/res/values/strings.xml create mode 100644 quick_android_custom_view/src/main/res/values/tin_view.xml create mode 100644 quick_android_custom_view/src/test/java/cn/qjm253/quick_android_custom_view/ExampleUnitTest.java create mode 100644 quick_android_easy_bar/.gitignore create mode 100644 quick_android_easy_bar/build.gradle create mode 100644 quick_android_easy_bar/consumer-rules.pro create mode 100644 quick_android_easy_bar/proguard-rules.pro create mode 100644 quick_android_easy_bar/src/androidTest/java/cn/qjm253/quick_android_easy_bar/ExampleInstrumentedTest.kt create mode 100644 quick_android_easy_bar/src/main/AndroidManifest.xml create mode 100644 quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBar.kt create mode 100644 quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBarExtensions.kt create mode 100644 quick_android_easy_bar/src/main/res/drawable/back.png create mode 100644 quick_android_easy_bar/src/main/res/values/colors.xml create mode 100644 quick_android_easy_bar/src/main/res/values/quick_android_easy_bar_attrs.xml create mode 100644 quick_android_easy_bar/src/main/res/values/strings.xml create mode 100644 quick_android_easy_bar/src/test/java/cn/qjm253/quick_android_easy_bar/ExampleUnitTest.kt create mode 100644 quick_android_file_picker/.gitignore create mode 100644 quick_android_file_picker/README.md create mode 100644 quick_android_file_picker/build.gradle create mode 100644 quick_android_file_picker/consumer-rules.pro create mode 100644 quick_android_file_picker/proguard-rules.pro create mode 100644 quick_android_file_picker/src/androidTest/java/com/example/quick_android_file_picker/ExampleInstrumentedTest.kt create mode 100644 quick_android_file_picker/src/main/AndroidManifest.xml create mode 100644 quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePicker.kt create mode 100644 quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePickerFragment.kt create mode 100644 quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/model/FilePickerResult.kt create mode 100644 quick_android_file_picker/src/main/res/values/strings.xml create mode 100644 quick_android_file_picker/src/test/java/com/example/quick_android_file_picker/ExampleUnitTest.kt create mode 100644 quick_android_image_picker/.gitignore create mode 100644 quick_android_image_picker/README.md create mode 100644 quick_android_image_picker/build.gradle create mode 100644 quick_android_image_picker/proguard-rules.pro create mode 100644 quick_android_image_picker/src/androidTest/java/cn/qjm253/quick_android_image_picker/ExampleInstrumentedTest.java create mode 100644 quick_android_image_picker/src/main/AndroidManifest.xml create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/MyImagePicker.kt create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/QuickAndroidImagePicker.kt create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/activity/QuickAndroidClipImageActivity.kt create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/fragment/QuickAndroidClipImageFragment.kt create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageBorderView.kt create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageLayout.kt create mode 100644 quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipZoomImageView.kt create mode 100644 quick_android_image_picker/src/main/res/layout/activity_quick_android_clip_image.xml create mode 100644 quick_android_image_picker/src/main/res/layout/fragment_quick_android_clip_image.xml create mode 100644 quick_android_image_picker/src/main/res/values/strings.xml create mode 100644 quick_android_image_picker/src/test/java/cn/qjm253/quick_android_image_picker/ExampleUnitTest.java create mode 100644 quick_android_mvp/.gitignore create mode 100644 quick_android_mvp/README.md create mode 100644 quick_android_mvp/build.gradle create mode 100644 quick_android_mvp/proguard-rules.pro create mode 100644 quick_android_mvp/src/androidTest/java/cn/qjm253/quick_android_mvp/ExampleInstrumentedTest.java create mode 100644 quick_android_mvp/src/main/AndroidManifest.xml create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/QuickAndroidMVP.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/activity/BaseQuickAndroidMVPActivity.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/fragment/BaseQuickAndroidMVPFragment.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseModel.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BasePresenter.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseView.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealException.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealNeedRetryException.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPExceptionWrapper.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/QuickAndroidMVPAPIManager.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPObserver.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPResultDeal.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/RxExtensions.kt create mode 100644 quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/response/BaseQuickAndroidResponseBody.kt create mode 100644 quick_android_mvp/src/main/res/values/strings.xml create mode 100644 quick_android_mvp/src/test/java/cn/qjm253/quick_android_mvp/ExampleUnitTest.java create mode 100644 quick_android_qrcode/.gitignore create mode 100644 quick_android_qrcode/README.md create mode 100644 quick_android_qrcode/build.gradle create mode 100644 quick_android_qrcode/proguard-rules.pro create mode 100644 quick_android_qrcode/src/androidTest/java/cn/qjm253/quick_android_qrcode/ExampleInstrumentedTest.java create mode 100644 quick_android_qrcode/src/main/AndroidManifest.xml create mode 100644 quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/QuickAndroidQrCode.kt create mode 100644 quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/activity/QuickAndroidQrCodeActivity.kt create mode 100644 quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeFragment.kt create mode 100644 quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeTransFragment.kt create mode 100644 quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/model/QrCodeResult.kt create mode 100644 quick_android_qrcode/src/main/res/drawable/quick_android_qr_code_default_back.png create mode 100644 quick_android_qrcode/src/main/res/layout/activity_quick_android_qr_code.xml create mode 100644 quick_android_qrcode/src/main/res/layout/fragment_quick_android_qrcode.xml create mode 100644 quick_android_qrcode/src/main/res/values/strings.xml create mode 100644 quick_android_qrcode/src/test/java/cn/qjm253/quick_android_qrcode/ExampleUnitTest.java create mode 100644 quick_android_rx_permission/.gitignore create mode 100644 quick_android_rx_permission/README.md create mode 100644 quick_android_rx_permission/build.gradle create mode 100644 quick_android_rx_permission/proguard-rules.pro create mode 100644 quick_android_rx_permission/src/androidTest/java/cn/qjm253/quick_android_rx_permission/ExampleInstrumentedTest.java create mode 100644 quick_android_rx_permission/src/main/AndroidManifest.xml create mode 100644 quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermission.kt create mode 100644 quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionFragment.kt create mode 100644 quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionItem.kt create mode 100644 quick_android_rx_permission/src/main/res/values/strings.xml create mode 100644 quick_android_rx_permission/src/test/java/cn/qjm253/quick_android_rx_permission/ExampleUnitTest.java create mode 100644 quick_android_webview/.gitignore create mode 100644 quick_android_webview/README.md create mode 100644 quick_android_webview/build.gradle create mode 100644 quick_android_webview/libs/armeabi/liblbs.so create mode 100644 quick_android_webview/libs/tbs_sdk.jar create mode 100644 quick_android_webview/proguard-rules.pro create mode 100644 quick_android_webview/src/androidTest/java/cn/qjm253/quick_android_webview/ExampleInstrumentedTest.java create mode 100644 quick_android_webview/src/main/AndroidManifest.xml create mode 100644 quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/QuickAndroidWebview.kt create mode 100644 quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/views/QuickAndroidWebview.kt create mode 100644 quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/web_bridge/QuickAndroidWebBridge.kt create mode 100644 quick_android_webview/src/main/res/values/strings.xml create mode 100644 quick_android_webview/src/test/java/cn/qjm253/quick_android_webview/ExampleUnitTest.java diff --git a/app/build.gradle b/app/build.gradle index d0e23b3..0b52b29 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,11 @@ -plugins { - id 'com.android.application' -} +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +//plugins { +// id 'com.android.application' +// id 'kotlin-android' +// id 'kotlin-android-extensions' +//} android { applicationVariants.all { variant -> @@ -71,15 +76,15 @@ android { dependencies { - testImplementation 'junit:junit:4.+' +// testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' compileOnly 'com.google.android.things:androidthings:1.0' - // 以下为旧版本VPN客户端的依赖库(去掉kotlin) + // 以下为旧版本VPN客户端的依赖库 implementation fileTree(dir: "libs", include: ["*.jar"]) -// implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.3.1' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.3.0' implementation "androidx.appcompat:appcompat:$androidx_base_version" implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation "androidx.recyclerview:recyclerview:$androidx_base_version" @@ -87,20 +92,28 @@ dependencies { implementation "org.jetbrains.anko:anko-commons:$anko_version" - // 所有的模块都依赖于 quick_android_base (必选) - implementation "com.github.SunnyQjm.quickandroid:quick_android_base:$quick_android_version" - implementation "com.github.SunnyQjm.quickandroid:quick_android_custom_view:$quick_android_version" - implementation "com.github.SunnyQjm.quickandroid:quick_android_easy_bar:$quick_android_version" - // 引入quick_android_mvp模块,来使用网络请求和MVP架构(可选) - implementation "com.github.SunnyQjm.quickandroid:quick_android_mvp:$quick_android_version" - // 引入quick_android_rx_permission模块,来接入链式调用动态请求权限的功能(可选) - implementation "com.github.SunnyQjm.quickandroid:quick_android_rx_permission:$quick_android_version" - // 引入quick_android_qrcode模块,来接入扫码功能(可选) - implementation "com.github.SunnyQjm.quickandroid:quick_android_qrcode:$quick_android_version" - // 引入quick_android_image_picker模块,来接入图片选择,图片裁剪等功能(可选) - implementation "com.github.SunnyQjm.quickandroid:quick_android_image_picker:$quick_android_version" - // 引入文件选择功能(调用系统的文件管理器) - implementation "com.github.SunnyQjm.quickandroid:quick_android_file_picker:$quick_android_version" +// // 所有的模块都依赖于 quick_android_base (必选) +// implementation "com.github.SunnyQjm.quickandroid:quick_android_base:$quick_android_version" +// implementation "com.github.SunnyQjm.quickandroid:quick_android_custom_view:$quick_android_version" +// implementation "com.github.SunnyQjm.quickandroid:quick_android_easy_bar:$quick_android_version" +// // 引入quick_android_mvp模块,来使用网络请求和MVP架构(可选) +// implementation "com.github.SunnyQjm.quickandroid:quick_android_mvp:$quick_android_version" +// // 引入quick_android_rx_permission模块,来接入链式调用动态请求权限的功能(可选) +// implementation "com.github.SunnyQjm.quickandroid:quick_android_rx_permission:$quick_android_version" +// // 引入quick_android_qrcode模块,来接入扫码功能(可选) +//// implementation "com.github.SunnyQjm.quickandroid:quick_android_qrcode:$quick_android_version" +//// // 引入quick_android_image_picker模块,来接入图片选择,图片裁剪等功能(可选) +//// implementation "com.github.SunnyQjm.quickandroid:quick_android_image_picker:$quick_android_version" +//// // 引入文件选择功能(调用系统的文件管理器) +//// implementation "com.github.SunnyQjm.quickandroid:quick_android_file_picker:$quick_android_version" + api project(path: ':quick_android_base') + api project(path: ':quick_android_custom_view') + api project(path: ':quick_android_easy_bar') + api project(path: ':quick_android_mvp') + api project(path: ':quick_android_rx_permission') +// api project(path: ':quick_android_qrcode') +// api project(path: ':quick_android_image_picker') +// api project(path: ':quick_android_file_picker') // loading button implementation 'br.com.simplepass:loading-button-android:2.2.0' @@ -121,13 +134,12 @@ dependencies { implementation "com.scwang.smartrefresh:SmartRefreshLayout:$smart_refresh_layout_version" implementation "com.scwang.smartrefresh:SmartRefreshHeader:$smart_refresh_layout_version" - // brvah implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.49-androidx' implementation 'com.google.android.material:material:1.3.0-alpha01' - testImplementation 'junit:junit:4.13.2' + testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index de96ad8..dd4f699 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,43 @@ - - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/pkusz/min_vpn_client/APP.java b/app/src/main/java/com/pkusz/min_vpn_client/APP.java new file mode 100644 index 0000000..4221480 --- /dev/null +++ b/app/src/main/java/com/pkusz/min_vpn_client/APP.java @@ -0,0 +1,20 @@ +package com.pkusz.min_vpn_client; +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 9:27 2021/6/24 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ + +import android.app.Application; + +public class APP extends Application { + @Override + public void onCreate() { + super.onCreate(); + + // 网络接口初始化 + // ... + } +} diff --git a/app/src/main/java/com/pkusz/min_vpn_client/activity/base/MINVpnBaseActivity.java b/app/src/main/java/com/pkusz/min_vpn_client/activity/base/MINVpnBaseActivity.java index fea39c7..167e2c0 100644 --- a/app/src/main/java/com/pkusz/min_vpn_client/activity/base/MINVpnBaseActivity.java +++ b/app/src/main/java/com/pkusz/min_vpn_client/activity/base/MINVpnBaseActivity.java @@ -9,10 +9,14 @@ package com.pkusz.min_vpn_client.activity.base; import android.widget.Toast; import org.greenrobot.eventbus.EventBus; -import cn.qjm253.quick_android_mvp.base.activity.BaseQuickAndroidMVPActivity; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; -public abstract class MINVpnBaseActivity> - extends BaseQuickAndroidMVPActivity +import cn.qjm253.quick_android_mvp.base.activity.BaseQuickAndroidMVPActivity; +import cn.qjm253.quick_android_mvp.base.mvp.BasePresenter; + +public abstract class MINVpnBaseActivity

> + extends BaseQuickAndroidMVPActivity

implements MINVpnBaseView{ public void showWarning(String msg){ @@ -37,6 +41,11 @@ public abstract class MINVpnBaseActivity - implements WelcomeActivityContract.View, BaseView { + implements WelcomeActivityContract.View{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -30,7 +35,20 @@ public class WelcomeActivity extends MINVpnBaseActivity() { + @Override + public void accept(Throwable throwable) throws Exception { + throwable.printStackTrace(); + } + }); + fingerprintAuthenticate(); + } + public void fingerprintAuthenticate(){ + System.out.println("指纹验证..."); } @NotNull diff --git a/app/src/main/java/com/pkusz/min_vpn_client/extensions/ActivityExtensions.kt b/app/src/main/java/com/pkusz/min_vpn_client/extensions/ActivityExtensions.kt new file mode 100644 index 0000000..8ae2e94 --- /dev/null +++ b/app/src/main/java/com/pkusz/min_vpn_client/extensions/ActivityExtensions.kt @@ -0,0 +1,26 @@ +package cn.qjm253.min_vpn.extensions + +import android.app.Activity +import android.graphics.Rect +import android.view.View +import cn.qjm253.quick_android_base.util.DisplayUtils + +fun Activity.listenKeyboardVisible(onChange: (isOpen: Boolean) -> Unit) { + val contentView = findViewById(android.R.id.content) + val activityRoot = window.decorView + + val rectR = Rect() + var lastOpenState = false + val visibleThreshold = DisplayUtils.dp2px(this, 100) + contentView.viewTreeObserver.addOnGlobalLayoutListener { + activityRoot.getWindowVisibleDisplayFrame(rectR) + val heightDiff = activityRoot.rootView.height - rectR.height() + + // 键盘是否弹出 + val isOpen = heightDiff > visibleThreshold + if (lastOpenState != isOpen) { + onChange(isOpen) + lastOpenState = isOpen + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pkusz/min_vpn_client/extensions/ContextExtensions.kt b/app/src/main/java/com/pkusz/min_vpn_client/extensions/ContextExtensions.kt new file mode 100644 index 0000000..c6093f9 --- /dev/null +++ b/app/src/main/java/com/pkusz/min_vpn_client/extensions/ContextExtensions.kt @@ -0,0 +1,10 @@ +package cn.qjm253.min_vpn.extensions + +import android.content.Context +import androidx.annotation.ColorRes +import androidx.core.content.ContextCompat + + +fun Context.easyGetColor(@ColorRes id: Int): Int { + return ContextCompat.getColor(this, id) +} \ No newline at end of file diff --git a/app/src/main/java/com/pkusz/min_vpn_client/extensions/FileUtilsExtensions.kt b/app/src/main/java/com/pkusz/min_vpn_client/extensions/FileUtilsExtensions.kt new file mode 100644 index 0000000..df9b785 --- /dev/null +++ b/app/src/main/java/com/pkusz/min_vpn_client/extensions/FileUtilsExtensions.kt @@ -0,0 +1,37 @@ +package cn.qjm253.min_vpn.extensions + +import android.content.Context +import android.os.Environment +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.util.FileUtils; +import java.io.File + +val FileUtils.appDataPath: String + get() { + //val sdDir = File(Environment.getDataDirectory().toString() + "/" + "MIN_VPN" + "/") + if(appContext == null) { + val sdDir = File(Environment.getDataDirectory().toString() + "/" + "MIN_VPN" + "/") + if (!sdDir.exists()) { + sdDir.mkdirs() + } + return sdDir.toString() + } else { + val sdDir = File(appContext!!.getDir("MIN_VPN", Context.MODE_PRIVATE).absolutePath) + if (!sdDir.exists()) { + sdDir.mkdirs() + } + return sdDir.toString() + } + } + +var appContext: Context? = null + get() { + return field + } + set(context: Context?) { + field = context + } + +fun FileUtils.init(context: Context) { + appContext = context +} \ No newline at end of file diff --git a/app/src/main/java/com/pkusz/min_vpn_client/extensions/README.md b/app/src/main/java/com/pkusz/min_vpn_client/extensions/README.md new file mode 100644 index 0000000..31f2264 --- /dev/null +++ b/app/src/main/java/com/pkusz/min_vpn_client/extensions/README.md @@ -0,0 +1,3 @@ +# extensions模块说明 +由于Kotlin的一些特性,例如可以直接扩展一些类的方法,故保留此部分的Kotlin代码。 +(旧版本与quick_android耦合得有些严重) \ No newline at end of file diff --git a/app/src/main/java/com/pkusz/min_vpn_client/Request_API.java b/app/src/main/java/com/pkusz/min_vpn_client/model/Request_API.java similarity index 98% rename from app/src/main/java/com/pkusz/min_vpn_client/Request_API.java rename to app/src/main/java/com/pkusz/min_vpn_client/model/Request_API.java index 5f3ef99..0df942d 100644 --- a/app/src/main/java/com/pkusz/min_vpn_client/Request_API.java +++ b/app/src/main/java/com/pkusz/min_vpn_client/model/Request_API.java @@ -1,4 +1,4 @@ -package com.pkusz.min_vpn_client; +package com.pkusz.min_vpn_client.model; /* * @Author: Wang Feng * @Description: @@ -15,7 +15,6 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; -//import cn.qjm253.min_vpn.model.request.BaseRequest; import com.pkusz.min_vpn_client.model.request.BaseRequest; import com.pkusz.min_vpn_client.utils.*; import common.LoggerHelper; diff --git a/build.gradle b/build.gradle index b705c87..ff99cc5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,39 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + // ----------start: 导入quickandroid到本地---------- + ext.kotlin_version = '1.3.72' + ext.okhttp_version = '4.0.0' + ext.persistent_cookie_jar_version = 'v1.0.1' + ext.retrofit_version = '2.6.0' + ext.gson_version = '2.8.6' + ext.glide_version = '4.9.0' + ext.easypermission_version = '3.0.0' + ext.bag_qrcode_zxing_version = '1.3.6' + ext.immersion_bar_version = '3.0.0-beta05' + ext.anko_version = '0.10.8' + ext.parallax_layout_version = '1.0' + ext.logger_vesion = '2.2.0' + ext.brvah_version = '2.9.46' + ext.quick_android_version = '0.1.2' + + ext.rx_android_version = '2.1.1' + ext.rx_java = '2.2.10' + ext.rx_kotlin = '2.2.0' + ext.rx_image_picker_version = '2.5.2' + + ext.appcompact_version = '1.1.0' + ext.constraintlayout_version = '1.1.3' + ext.junit_version = '4.13' + ext.test_runner_version = '1.2.0' + ext.espresso_core_version = '3.2.0' + ext.core_ktx_version = '1.3.0' + + ext.compile_sdk_version = 30 + ext.target_sdk_version = 30 + ext.min_sdk_version = 19 + // -------------end---------------- + + ext.kotlin_version = "1.3.72" ext.quick_android_version = 'v0.1.9' ext.anko_version = '0.10.8' ext.smart_refresh_layout_version = '1.1.0' @@ -11,10 +45,11 @@ buildscript { maven { url 'https://jitpack.io' } google() // jcenter() -// mavenCentral() + mavenCentral() } dependencies { classpath "com.android.tools.build:gradle:4.2.1" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -27,7 +62,7 @@ allprojects { maven { url 'http://maven.aliyun.com/nexus/content/groups/public'} maven { url 'https://jitpack.io' } google() -// mavenCentral() + mavenCentral() // jcenter() // Warning: this repository is going to shut down soon } } diff --git a/gradle.properties b/gradle.properties index 6826e61..6ac4212 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,4 +14,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app"s APK # https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true + +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/quick_android_base/.gitignore b/quick_android_base/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_base/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_base/README.md b/quick_android_base/README.md new file mode 100644 index 0000000..45c9593 --- /dev/null +++ b/quick_android_base/README.md @@ -0,0 +1,161 @@ +> ## quick_android_base 模块 +> +> 本模块提供了一些常用的工具库,一些常用的Kotlin扩展,以及一些基本功能的封装 + +- ### 初始化 + + ```kotlin + // 在Application中初始化 + QuickAndroid.init() + // 下面这一行输入你应用的英文名,便于为你的应用创建对应名字的应用文件夹等等 + .appName("your_app_name") + // 执行下面一行可以开启应用Activity的侧滑返回支持 + .enableParallaxBack(context) + ``` + + + +- ### 侧滑返回支持说明 + + 1. 所有需要支持侧滑返回的`Activity`都要继承 [BaseQuickAndroidActivity](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt>) ; + + 2. 如果继承自[BaseQuickAndroidActivity](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt>) 的`Activity`需要按业务需求开启和关闭业务需求,可以使用下面两个函数(下面两个函数定义在[BaseQuickAndroidActivity](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt>) 当中,所有集成自该类的Activity均可调用): + + ```kotlin + // 禁止侧滑返回 + disableParallaxBack() + + // 开启侧滑返回 + enableParallaxBack() + ``` + + 3. 本侧滑返回使用的是[ParallaxBackLayout](https://github.com/anzewei/ParallaxBackLayout),如果需要自定义侧滑模式,以及触发侧滑返回的位置等等,可以参考该库提供的配置。 + +- ### Glide支持 + + 1. `quick_android_base`库中已经包含了Glide依赖,引入本依赖库之后不需要再另外引入 + + 2. 当前`quick_android_base`中Glide的版本为`4.9.0` + + 3. 已经定义了[MyAppGlideModule](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/MyAppGlideModule.kt),不需要再定义,可以通过下面的方式使用 + + ```kotlin + GlideApp.with(context) + .load(url) + .into(imageView) + ``` + +- ### 动态权限请求支持 + + 本功能基于google开源的[easypermissions](https://github.com/googlesamples/easypermissions)进行,在所有继承自[BaseQuickAndroidActivity](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt>) 的Activity或者继承自[BaseQuickAndroidFragment](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/fragment/BaseQuickAndroidFragment.kt)的Fragment均可使用 + + - 动态请求权限 + + ```kotlin + easyRequestPermissions( + arrayof(Manifest.permissions.CAMERA), + R.string.require_camera_permission_tip, + 0 + ) + ``` + + - 复写如下函数 + + ```kotlin + /** + * 授权成功 + */ + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + when(requestCode) { + 0 -> { // 请求摄像头权限 + + } + } + } + + /** + * 授权失败 + */ + override fun onPermissionsDenied(requestCode: Int, perms: MutableList) { + + } + ``` + +- ### `quick_android_base`支持的其它特性 + + - 一些有用的工具类 [utils](https://github.com/SunnyQjm/quickandroid/tree/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util) + + - 一些有用的扩展 [extensions](https://github.com/SunnyQjm/quickandroid/tree/master/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions) + + - 便捷的页面跳转扩展(下面所有的扩展函数均可在所有Activity和Fragment中使用,只可在Kotlin项目中使用) + + ```kotlin + // 简单使用,跳转到一个Activity + jumpTo(MainActivity::class.java) + + // 跳转到一个Activity,并处理返回结果(requestCode = 0) + jumpForResult(MainACtivity::class.java, 0) + + // 跳转到一个Activity并传递参数 + jumpTo(MainActivity::class.java, + IntentParam() + .add("param1", 1) + .add("param2", "value2") + .add("param3", arrayof("1", "2", "3")) + ) + + // 跳转到一个Activity,传递参数并处理返回结果 + jumpTo(MainActivity::class.java, + 0, + IntentParam() + .add("param1", 1) + .add("param2", "value2") + .add("param3", arrayof("1", "2", "3")) + ) + ``` + + + +- ### `quick_android_base`引入的所有支持库 + + ```groovy + // gson + api "com.google.code.gson:gson:${gson_version}" + + // Glide + api "com.github.bumptech.glide:glide:${glide_version}" + kapt "com.github.bumptech.glide:compiler:${glide_version}" + + // Easypermission + api "pub.devrel:easypermissions:${easypermission_version}" + + // RxJava + // RxAndroid + api "io.reactivex.rxjava2:rxandroid:${rx_android_version}" + api "io.reactivex.rxjava2:rxjava:${rx_java}" + // RxKotlin + api "io.reactivex.rxjava2:rxkotlin:${rx_kotlin}" + + // BRVAHquick_android_base + api "com.github.CymChad:BaseRecyclerViewAdapterHelper:${brvah_version}" + + // Retrofit + api "com.squareup.retrofit2:retrofit:${retrofit_version}" + api "com.squareup.retrofit2:retrofit:${retrofit_version}" + api "com.squareup.retrofit2:adapter-rxjava2:${retrofit_version}" + api "com.squareup.retrofit2:converter-gson:${retrofit_version}" + + // Okhttp + api "com.squareup.okhttp3:okhttp:${okhttp_version}" + + // Logger + api "com.orhanobut:logger:${logger_vesion}" + + // ParallaxBackLayout + api "com.github.SunnyQjm:ParallaxBackLayout:${parallax_layout_version}" + + // ImmersionBar + api "com.gyf.immersionbar:immersionbar:${immersion_bar_version}" + ``` + + \ No newline at end of file diff --git a/quick_android_base/build.gradle b/quick_android_base/build.gradle new file mode 100644 index 0000000..82ca341 --- /dev/null +++ b/quick_android_base/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.library' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + implementation "androidx.constraintlayout:constraintlayout:${constraintlayout_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + // gson + api "com.google.code.gson:gson:${gson_version}" + + // Glide + api "com.github.bumptech.glide:glide:${glide_version}" + kapt "com.github.bumptech.glide:compiler:${glide_version}" + + + // Easypermission + api "pub.devrel:easypermissions:${easypermission_version}" + + // RxJava + // RxAndroid + api "io.reactivex.rxjava2:rxandroid:${rx_android_version}" + api "io.reactivex.rxjava2:rxjava:${rx_java}" + // RxKotlin + api "io.reactivex.rxjava2:rxkotlin:${rx_kotlin}" + + // BRVAH + api "com.github.CymChad:BaseRecyclerViewAdapterHelper:${brvah_version}" + + // Retrofit + api "com.squareup.retrofit2:retrofit:${retrofit_version}" + api "com.squareup.retrofit2:retrofit:${retrofit_version}" + api "com.squareup.retrofit2:adapter-rxjava2:${retrofit_version}" + api "com.squareup.retrofit2:converter-gson:${retrofit_version}" + + // Okhttp + api "com.squareup.okhttp3:okhttp:${okhttp_version}" + + // Logger + api "com.orhanobut:logger:${logger_vesion}" + + // ParallaxBackLayout + api "com.github.SunnyQjm:ParallaxBackLayout:${parallax_layout_version}" + + // ImmersionBar + api "com.gyf.immersionbar:immersionbar:${immersion_bar_version}" + + +} diff --git a/quick_android_base/proguard-rules.pro b/quick_android_base/proguard-rules.pro new file mode 100644 index 0000000..a9f634f --- /dev/null +++ b/quick_android_base/proguard-rules.pro @@ -0,0 +1,177 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# AndroidX +-keep class com.google.android.material.** {*;} +-keep class androidx.** {*;} +-keep public class * extends androidx.** +-keep interface androidx.** {*;} +-dontwarn com.google.android.material.** +-dontnote com.google.android.material.** +-dontwarn androidx.** + +# Glide +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep public enum com.bumptech.glide.load.ImageHeaderParser$** { + **[] $VALUES; + public *; +} + +# for DexGuard only +-keepresourcexmlelements manifest/application/meta-data@value=GlideModule + + + + +##---------------Begin: proguard configuration for Gson ---------- +# Gson uses generic type information stored in a class file when working with fields. Proguard +# removes such information by default, so configure it to keep all of it. +-keepattributes Signature + +# For using GSON @Expose annotation +-keepattributes *Annotation* + +# Gson specific classes +-dontwarn sun.misc.** +#-keep class com.google.gson.stream.** { *; } + +# Application classes that will be serialized/deserialized over Gson +#-keep class com.google.gson.examples.android.model.** { ; } + +# Prevent proguard from stripping interface information from TypeAdapterFactory, +# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) +-keep class * implements com.google.gson.TypeAdapterFactory +-keep class * implements com.google.gson.JsonSerializer +-keep class * implements com.google.gson.JsonDeserializer + +# Prevent R8 from leaving Data object members always null +-keepclassmembers,allowobfuscation class * { + @com.google.gson.annotations.SerializedName ; +} + +##---------------End: proguard configuration for Gson ---------- + + +##---------------Begin: BRVAH---------------## +-keep class com.chad.library.adapter.** { +*; +} +-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter +-keep public class * extends com.chad.library.adapter.base.BaseViewHolder +-keepclassmembers class **$** extends com.chad.library.adapter.base.BaseViewHolder { + (...); +} +##---------------End: BRVAH---------------## + + + +##---------------Begin: Okhttp---------------## +-dontwarn com.squareup.okhttp3.** +-keep class com.squareup.okhttp3.** { *;} +-dontwarn okio.** +##---------------End: Okhttp---------------## + + +##---------------Begin: RxJava RxAndroid---------------## +-dontwarn sun.misc.** +-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { + long producerIndex; + long consumerIndex; +} +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { + rx.internal.util.atomic.LinkedQueueNode producerNode; +} +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { + rx.internal.util.atomic.LinkedQueueNode consumerNode; +} +-dontnote rx.internal.util.PlatformDependent +##---------------End: RxJava RxAndroid---------------## + + +##---------------Begin: Junit---------------## +-keep class org.junit.** { *; } +-dontwarn org.junit.** + +-keep class junit.** { *; } +-dontwarn junit.** +##---------------End: Junit---------------## + + + +##---------------Begin: Retrofit---------------## + +# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and +# EnclosingMethod is required to use InnerClasses. +-keepattributes Signature, InnerClasses, EnclosingMethod + +# Retrofit does reflection on method and parameter annotations. +-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations + +# Retain service method parameters when optimizing. +-keepclassmembers,allowshrinking,allowobfuscation interface * { + @retrofit2.http.* ; +} + +# Ignore annotation used for build tooling. +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement + +# Ignore JSR 305 annotations for embedding nullability information. +-dontwarn javax.annotation.** + +# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath. +-dontwarn kotlin.Unit + +# Top-level functions that can only be used by Kotlin. +-dontwarn retrofit2.KotlinExtensions + +# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy +# and replaces all potential values with null. Explicitly keeping the interfaces prevents this. +-if interface * { @retrofit2.http.* ; } +-keep,allowobfuscation interface <1> + +##---------------End: Retrofit---------------## + + +##---------------Begin: Okhttp---------------## + +# JSR 305 annotations are for embedding nullability information. +-dontwarn javax.annotation.** + +# A resource is loaded with a relative path so the package of this class must be preserved. +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase + +# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. +-dontwarn org.codehaus.mojo.animal_sniffer.* + +# OkHttp platform used only on JVM and when Conscrypt dependency is available. +-dontwarn okhttp3.internal.platform.ConscryptPlatform + +##---------------Begin: End---------------## + +##---------------Begin: ParallaxBackLayout---------------## +-keep public enum com.github.anzewei.parallaxbacklayout.ParallaxBack$** { + **[] $VALUES; + public *; +} +##---------------End: ParallaxBackLayout---------------## + diff --git a/quick_android_base/src/androidTest/java/cn/qjm253/quick_android_base/ExampleInstrumentedTest.java b/quick_android_base/src/androidTest/java/cn/qjm253/quick_android_base/ExampleInstrumentedTest.java new file mode 100644 index 0000000..ac98954 --- /dev/null +++ b/quick_android_base/src/androidTest/java/cn/qjm253/quick_android_base/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package cn.qjm253.quick_android_base; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_base.test", appContext.getPackageName()); + } +} diff --git a/quick_android_base/src/main/AndroidManifest.xml b/quick_android_base/src/main/AndroidManifest.xml new file mode 100644 index 0000000..66c424a --- /dev/null +++ b/quick_android_base/src/main/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_base/src/main/java/NetworkUtil.kt b/quick_android_base/src/main/java/NetworkUtil.kt new file mode 100644 index 0000000..202977a --- /dev/null +++ b/quick_android_base/src/main/java/NetworkUtil.kt @@ -0,0 +1,69 @@ +//package cn.qjm253.quick_android_base.util +// +//import android.content.Context +//import android.net.ConnectivityManager +//import android.net.NetworkInfo +// +// +///** +// * 网络工具类 +// * Created by sunny on 18-2-23. +// */ +// +//class NetworkUtil(context: Context){ +// +// val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +// +// /** +// * 检测网络是否连接 +// * @return +// */ +// private fun checkNetworkState(): Boolean { +// var flag = false +// //得到网络连接信息 +// //去进行判断网络是否连接 +// if (manager.activeNetworkInfo != null) { +// flag = manager.activeNetworkInfo.isAvailable +// } +// return flag +// } +// +// /** +// * 判断是否连了wifi +// */ +// fun isWifiConnect(): Boolean{ +// val wifiState = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).state +// return wifiState == NetworkInfo.State.CONNECTED +// } +// +// /** +// * 获取当前网络的类型 +// */ +// fun getConnectedType(context: Context?): Int { +// if (context != null) { +// val mConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +// val mNetworkInfo = mConnectivityManager.activeNetworkInfo +// if (mNetworkInfo != null && mNetworkInfo.isAvailable) { +// return mNetworkInfo.type +// } +// } +// return -1 +// } +// +// +// /** +// * 是否是移动数据连接 +// */ +// fun isMobileConnected(context: Context?): Boolean { +// if (context != null) { +// val mConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager +// val mMobileNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) +// if (mMobileNetworkInfo != null) { +// return mMobileNetworkInfo.isAvailable +// } +// } +// return false +// } +// +// +//} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/MyAppGlideModule.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/MyAppGlideModule.kt new file mode 100644 index 0000000..983b0f5 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/MyAppGlideModule.kt @@ -0,0 +1,7 @@ +package cn.qjm253.quick_android_base + +import com.bumptech.glide.annotation.GlideModule +import com.bumptech.glide.module.AppGlideModule + +@GlideModule +class MyAppGlideModule : AppGlideModule() \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/QuickAndroid.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/QuickAndroid.kt new file mode 100644 index 0000000..860c45e --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/QuickAndroid.kt @@ -0,0 +1,41 @@ +package cn.qjm253.quick_android_base + +import android.app.Application +import android.content.Context +import com.github.anzewei.parallaxbacklayout.ParallaxHelper +import com.orhanobut.logger.AndroidLogAdapter +import com.orhanobut.logger.Logger + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +object QuickAndroid { + var APP_NAME = "QuickAndroid" + var enableParallaxBack = false + + fun appName(appName: String = "quick_android"): QuickAndroid { + APP_NAME = appName + return this + } + + fun init(): QuickAndroid { + Logger.addLogAdapter(AndroidLogAdapter()) + return this + } + + /** + * 开启侧滑 + * 如需修改侧滑触发的模式和位置,参看BaseQuickAndroidActivity + * @see cn.qjm253.quick_android_mvp.base.activity.BaseQuickAndroidActivity + */ + fun enableParallaxBack(context: Application): QuickAndroid { + /** + * 初始化侧滑操作 + * 需要在Application当中初始化 + */ + context.registerActivityLifecycleCallbacks(ParallaxHelper.getInstance()) + enableParallaxBack = true + return this + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt new file mode 100644 index 0000000..5dfa23e --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/activity/BaseQuickAndroidActivity.kt @@ -0,0 +1,110 @@ +package cn.qjm253.quick_android_base.base.activity + +import android.net.Uri +import android.os.Bundle +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.base.fragment.BaseQuickAndroidFragment +import com.github.anzewei.parallaxbacklayout.ParallaxBack +import com.github.anzewei.parallaxbacklayout.ParallaxHelper +import com.github.anzewei.parallaxbacklayout.widget.ParallaxBackLayout +import pub.devrel.easypermissions.EasyPermissions + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +@ParallaxBack +abstract class BaseQuickAndroidActivity : AppCompatActivity(), + EasyPermissions.PermissionCallbacks, BaseQuickAndroidFragment.OnFragmentInteractionListener { + + companion object { + const val EP_CAMERA = 1 + } + + /** + * 是否需要支持侧滑返回 + */ + open fun isNeedScrollBack() = true + + + /** + * 侧滑是否响应全屏 + * true => 全屏滑动都会触发侧滑 + * false => 边缘滑动才会触发侧滑 + */ + open fun isParallaxBackLayoutFullScreen() = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + if (QuickAndroid.enableParallaxBack) { // 手动开启侧滑才执行侧滑相关代码 + ParallaxHelper.getParallaxBackLayout(this, true)?.let { layout -> + // 设置侧滑的响应模式 + if (isParallaxBackLayoutFullScreen()) { + layout.setEdgeMode(ParallaxBackLayout.EDGE_MODE_FULL) + } else { + layout.setEdgeMode(ParallaxBackLayout.EDGE_MODE_DEFAULT) + } + + // 设置是否允许触发侧滑返回 + if (isNeedScrollBack()) { + layout.setEnableGesture(true) + } else { + layout.setEnableGesture(false) + } + } + } + } + + /** + * 禁止侧滑返回 + */ + fun disableParallaxBack() { + if(QuickAndroid.enableParallaxBack) { + ParallaxHelper.getParallaxBackLayout(this) + ?.setEnableGesture(false) + } + } + + /** + * 开启侧滑返回 + */ + fun enableParallaxBack() { + if(QuickAndroid.enableParallaxBack){ + ParallaxHelper.getParallaxBackLayout(this) + ?.setEnableGesture(true) + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + /** + * 授权成功 + */ + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + } + + /** + * 授权失败 + */ + override fun onPermissionsDenied(requestCode: Int, perms: MutableList) { + + } + + + open fun easyRequestPermissions(permissions: Array, @StringRes tip: Int, requestCode: Int) { + if (EasyPermissions.hasPermissions(this, *permissions)) { + onPermissionsGranted(requestCode, permissions.toMutableList()) + } else { + EasyPermissions.requestPermissions(this, getString(tip), requestCode, *permissions) + } + } + + override fun onFragmentInteraction(uri: Uri?) { + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/fragment/BaseQuickAndroidFragment.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/fragment/BaseQuickAndroidFragment.kt new file mode 100644 index 0000000..58534c7 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/base/fragment/BaseQuickAndroidFragment.kt @@ -0,0 +1,191 @@ +package cn.qjm253.quick_android_base.base.fragment + +import android.Manifest +import android.content.Context +import android.net.Uri +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.StringRes +import androidx.fragment.app.Fragment +import cn.qjm253.quick_android_base.R +import cn.qjm253.quick_android_base.base.activity.BaseQuickAndroidActivity +import cn.qjm253.quick_android_base.params.IntentParam +import pub.devrel.easypermissions.EasyPermissions + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +/** + * 支持在第一次创建视图时初始化,且不会重复添加导致重叠 + */ +abstract class BaseQuickAndroidFragment : Fragment(), EasyPermissions.PermissionCallbacks { + companion object { + private const val STATE_SAVE_IS_HIDDEN = "STATE_SAVE_IS_HIDDEN" + + fun newInstance_(clazz: Class, intentParam: IntentParam?): T { + val args = Bundle() + intentParam?.applyBundle(args) + val fragment = clazz.newInstance() + fragment.arguments = args + return fragment + } + } + + protected var mView: View? = null + protected var mListener: OnFragmentInteractionListener? = null + + // 当前视图是否构建完成 + private var prepare: Boolean = false + // 是否是第一次加载数据 + private var first: Boolean = true + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + //当页面重启时,Fragment会被保存回复,而此时再加载Fragment便会导致重叠 + if (savedInstanceState != null) { + val isHidden = savedInstanceState.getBoolean(STATE_SAVE_IS_HIDDEN) + val ft = fragmentManager?.beginTransaction() + if (isHidden) + ft?.hide(this) + else + ft?.show(this) + ft?.commit() + } + + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.putBoolean(STATE_SAVE_IS_HIDDEN, isHidden) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + if(mView == null) { + mView = inflater.inflate(getRes(), container, false) + } + + // 如果之前被添加过,则先移除 + if(mView?.parent != null) { + (mView?.parent as ViewGroup).removeView(mView) + } + return mView + } + + + + /** + * 当视图构建完成时会调用这个回调 + */ + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + if(!prepare) { + initView() + prepare = true + } + } + + + /** + * 下面的函数由系统调用 + * 在Fragment可见时加载数据 + * + * @param isVisibleToUser + */ + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + if(isVisibleToUser) { + onVisible() + } else { + onInvisible() + } + } + + + + protected open fun onInvisible() {} + + protected open fun onVisible() { + //加载数据 + if (prepare && first) { + first = false + initialLoadData() + } + } + + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is OnFragmentInteractionListener) { + mListener = context + } else { + throw RuntimeException("$context must implement OnFragmentInteractionListener") + } + } + + /** + * Fragment页面的布局文件 + */ + abstract fun getRes(): Int + + /** + * 视图初始化操作 + */ + abstract fun initView() + + /** + * 页面第一次加载时加载数据 + */ + abstract fun initialLoadData() + + /** + * This interface must be implemented by activities that contain this + * fragment to allow an interaction in this fragment to be communicated + * to the activity and potentially other fragments contained in that + * activity. + * + * + * See the Android Training lesson [Communicating with Other Fragments](http://developer.android.com/training/basics/fragments/communicating.html) for more information. + */ + interface OnFragmentInteractionListener { + // TODO: Update argument type and name + fun onFragmentInteraction(uri: Uri?) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + /** + * 授权成功 + */ + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + } + + /** + * 授权失败 + */ + override fun onPermissionsDenied(requestCode: Int, perms: MutableList) { + + } + + + open fun requestPermissions(permissions: Array, @StringRes tip: Int, requestCode: Int) { + activity?.let { + if(EasyPermissions.hasPermissions(it, *permissions)) { + onPermissionsGranted(requestCode, permissions.toMutableList()) + } else { + EasyPermissions.requestPermissions(this, getString(tip), requestCode, *permissions) + } + } + } + + + open fun requestCamera(@StringRes tip: Int = R.string.camera_permission_require) { + requestPermissions(arrayOf(Manifest.permission.CAMERA), tip, BaseQuickAndroidActivity.EP_CAMERA) + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ActivityExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ActivityExtensions.kt new file mode 100644 index 0000000..fdd3254 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ActivityExtensions.kt @@ -0,0 +1,41 @@ +package cn.qjm253.quick_android_base.extensions + +import android.app.Activity +import android.content.Context +import android.os.Build +import android.os.VibrationEffect +import android.os.Vibrator +import androidx.annotation.IdRes +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:52 + */ + +/** + * Activity触发震动的扩展 + * @param duration 震动持续时间 + * @param amplitude 震动的强度,限制在 1~255 之间 + */ +fun Activity.vibrator(duration: Long = 200, amplitude: Int = 100) { + val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + vibrator.vibrate(VibrationEffect.createOneShot(duration, amplitude)) + } else { + vibrator.vibrate(duration) + } +} + + +fun FragmentActivity.addFragmentToActivity(@IdRes fragmentLayoutId: Int, fragmentGenerator: () -> T): T { + var fragment = this.supportFragmentManager.findFragmentById(fragmentLayoutId) as? T + if(fragment == null) { + fragment = fragmentGenerator() + val transaction = supportFragmentManager.beginTransaction() + transaction.replace(fragmentLayoutId, fragment) + transaction.commit() + } + return fragment +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/AnyExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/AnyExtensions.kt new file mode 100644 index 0000000..52617a0 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/AnyExtensions.kt @@ -0,0 +1,12 @@ +package cn.qjm253.quick_android_base.extensions + +import cn.qjm253.quick_android_base.util.GsonUtil + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +fun Any.toJson(): String { + return GsonUtil.bean2Json(this) +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ContextExtension.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ContextExtension.kt new file mode 100644 index 0000000..791a406 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ContextExtension.kt @@ -0,0 +1,149 @@ +package cn.qjm253.quick_android_base.extensions + +import android.app.Activity +import android.app.DatePickerDialog +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import androidx.annotation.StringRes +import androidx.annotation.StyleRes +import androidx.core.content.ContextCompat +import android.view.View +import android.view.inputmethod.InputMethodManager +import android.widget.Toast +import androidx.fragment.app.Fragment +import cn.qjm253.quick_android_base.params.IntentParam +import java.util.* + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +fun Context.toast(info: String, duration: Int = Toast.LENGTH_SHORT) { + Toast.makeText(this, info, duration) + .show() +} + +fun Context.toast(@StringRes stringRes: Int, duration: Int = Toast.LENGTH_SHORT) { + Toast.makeText(this, stringRes, duration) + .show() +} + + +fun Context.jumpTo(cls: Class<*>, vararg flags: Int) { + val intent = Intent(this, cls) + flags.forEach { + intent.addFlags(it) + } + startActivity(intent) +} + + +fun Context.jumpTo(cls: Class<*>, intentParam: IntentParam? = null, vararg flags: Int) { + val intent = Intent(this, cls) + flags.forEach { + intent.addFlags(it) + } + intentParam?.applyParam(intent) + startActivity(intent) +} + +fun Activity.jumpForResult(cls: Class<*>, requestCode: Int = 0, intentParam: IntentParam? = null) { + val intent = Intent(this, cls) + intentParam?.applyParam(intent) + startActivityForResult(intent, requestCode) +} + + +fun Fragment.jumpForResult(cls: Class<*>, requestCode: Int, intentParam: IntentParam? = null) { + val intent = Intent(activity, cls) + intentParam?.applyParam(intent) + startActivityForResult(intent, requestCode) +} + +///////////////////////////////////////////////////////// +///////// 下面是软键盘相关的扩展 +//////////////////////////////////////////////////////// + +/** + * 切换状态,打开则关闭,关闭则打开 + */ +fun Context.changeSoftKeyboard() { + val im = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + + if (!im.isActive) + return + im.toggleSoftInput(0, 0) +} + +/** + * 隐藏软键盘 + */ +fun Context.hideSoftKeyboard(view: View) { + val im = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + if (!im.isActive) + return + //隐藏软键盘 // + im.hideSoftInputFromWindow(view.windowToken, 0) +} + +fun Context.showSoftKeyboard(view: View) { + val im = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + if (im.isActive) + return + im.showSoftInputFromInputMethod(view.windowToken, 0) +} + + +fun Context.showSelectDateDialog( + @StyleRes style: Int = android.R.style.Theme_DeviceDefault_Dialog, + listener: (View, Int, Int, Int) -> Unit = + { view, year, month, dayOfMonth -> } +) { + val c = Calendar.getInstance() + DatePickerDialog( + this, style, listener, c.get(Calendar.YEAR), + c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH) + ) + .show() +} + +fun Context.showSelectDateDialog( + @StyleRes style: Int = android.R.style.Theme_DeviceDefault_Dialog, + listener: (Long) -> Unit = + { time -> } +) { + val c = Calendar.getInstance() + DatePickerDialog( + this, style, { view, year, month, dayOfMonth -> + c.timeInMillis = 0 + c.set(Calendar.YEAR, year) + c.set(Calendar.MONTH, month) + c.set(Calendar.DAY_OF_MONTH, dayOfMonth) + listener(c.timeInMillis) + }, c.get(Calendar.YEAR), + c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH) + ) + .show() +} + + +fun Context.checkMyPermission(permission: String, granted: () -> Unit = {}, deny: () -> Unit = {}) { + if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) { + granted() + } else { + deny() + } +} + + +/** + * 不够位数的在前面补0,保留num的长度位数字 + * @param code + * @return + */ +private fun autoGenericCode(code: String, num: Int): String { + return String.format("%0" + num + "d", Integer.parseInt(code)) +} + diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FloatExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FloatExtensions.kt new file mode 100644 index 0000000..956c6e8 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FloatExtensions.kt @@ -0,0 +1,20 @@ +package cn.qjm253.quick_android_base.extensions + +import java.lang.StringBuilder +import java.math.RoundingMode +import java.text.DecimalFormat + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +fun Double.toFixed(num: Int): String { + val sb = StringBuilder("0.") + for(i in 1..num){ + sb.append("0") + } + val df = DecimalFormat(sb.toString()) + df.roundingMode = RoundingMode.HALF_UP; + return df.format(this) +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FragmentManagerExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FragmentManagerExtensions.kt new file mode 100644 index 0000000..9e1ceb7 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/FragmentManagerExtensions.kt @@ -0,0 +1,44 @@ +package cn.qjm253.quick_android_base.extensions + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager + +/** + * @author SunnyQjm + * @date 19-7-8 下午3:42 + */ + +fun FragmentManager.getLazySingleton(tag: String, clazz: Class): Lazy { + val fragmentManager = this + return object : Lazy { + private var t: T? = null + + private fun _getFragment(): T { + if(t == null) { + t = getFragment(tag, clazz, fragmentManager) + } + return t!! + } + + override val value: T + get() = _getFragment() + + override fun isInitialized(): Boolean { + return t != null + } + } +} + + +private fun getFragment(tag: String, clazz: Class, fragmentManager: FragmentManager): T { + var fragment: T? = fragmentManager.findFragmentByTag(tag) as? T + if (fragment == null) { + fragment = clazz.newInstance() + fragmentManager + .beginTransaction() + .add(fragment, tag) + .commitNow() + } + return fragment!! +} + diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ImageViewExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ImageViewExtensions.kt new file mode 100644 index 0000000..cce0168 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ImageViewExtensions.kt @@ -0,0 +1,63 @@ +package cn.qjm253.quick_android_base.extensions + +import android.annotation.SuppressLint +import android.graphics.Bitmap +import android.media.MediaMetadataRetriever +import androidx.annotation.DrawableRes +import android.widget.ImageView +import cn.qjm253.quick_android_base.GlideApp +import com.bumptech.glide.load.resource.bitmap.VideoDecoder.FRAME_OPTION +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation +import java.security.MessageDigest + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + + +fun ImageView.load(url: String) { + GlideApp.with(this) + .load(url) + .into(this) +} + +fun ImageView.loadCircle(url: String) { + GlideApp.with(this) + .load(url) + .circleCrop() + .into(this) +} + +fun ImageView.loadCircle(@DrawableRes res: Int) { + GlideApp.with(this) + .load(res) + .circleCrop() + .into(this) +} + +@SuppressLint("CheckResult") +fun ImageView.loadVideoFrame(url: String, frameTimeMicros: Long) { + val requestOptions = RequestOptions.frameOf(frameTimeMicros) + requestOptions.set(FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST); + requestOptions.transform(object : BitmapTransformation() { + override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap { + return toTransform + } + + override fun updateDiskCacheKey(messageDigest: MessageDigest) { + try { + messageDigest.update((context.packageName + "RotateTransform").toByteArray(charset("utf-8"))) + } catch (e: Exception) { + e.printStackTrace() + } + } + + }) + GlideApp.with(this) + .load(url) + .apply(requestOptions) + .into(this) +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LoggerExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LoggerExtensions.kt new file mode 100644 index 0000000..3934e91 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LoggerExtensions.kt @@ -0,0 +1,29 @@ +package cn.qjm253.quick_android_base.extensions + +import com.orhanobut.logger.Logger + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +fun String.e(vararg args: Any) { + Logger.e(this, args) +} + +fun Throwable.e(vararg args: Any) { + Logger.e(this, this.message ?: "", args) +} + + +fun String.i(vararg args: Any) { + Logger.i(this, args) +} + +fun String.d(vararg args: Any) { + Logger.d(this, args) +} + +fun String.json(vararg args: Any) { + Logger.json(this) +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LongExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LongExtensions.kt new file mode 100644 index 0000000..b13403c --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/LongExtensions.kt @@ -0,0 +1,48 @@ +package cn.qjm253.quick_android_base.extensions + +import java.util.* + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + + +fun Long.toYMD(): String { + val instance = Calendar.getInstance() + instance.timeInMillis = this + return "${instance.get(Calendar.YEAR)}" + + "-${instance.get(Calendar.MONTH) + 1}" + + "-${instance.get(Calendar.DAY_OF_MONTH)}" +} + +fun Long.toYMD_HM(): String { + val instance = Calendar.getInstance() + instance.timeInMillis = this + return "${instance.get(Calendar.YEAR)}" + + "-${instance.get(Calendar.MONTH) + 1}" + + "-${instance.get(Calendar.DAY_OF_MONTH)}" + + " ${instance.get(Calendar.HOUR_OF_DAY)}" + + ":${instance.get(Calendar.MINUTE)}" +} + +fun Long.toYMD_HMS(): String { + val instance = Calendar.getInstance() + instance.timeInMillis = this + return "${instance.get(Calendar.YEAR)}" + + "-${instance.get(Calendar.MONTH) + 1}" + + "-${instance.get(Calendar.DAY_OF_MONTH)}" + + " ${instance.get(Calendar.HOUR_OF_DAY)}" + + ":${instance.get(Calendar.MINUTE)}" + + ":${instance.get(Calendar.SECOND)}" +} + +fun String.toTimeStamp(): Long { + val arr = this.split('-') + val instance = Calendar.getInstance() + instance.timeInMillis = 0 + instance.set(Calendar.YEAR, arr[0].toInt()) + instance.set(Calendar.MONTH, arr[1].toInt() - 1) + instance.set(Calendar.DAY_OF_MONTH, arr[2].toInt()) + return instance.timeInMillis +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MathExtension.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MathExtension.kt new file mode 100644 index 0000000..5981753 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MathExtension.kt @@ -0,0 +1,13 @@ +package cn.qjm253.quick_android_base.extensions + +/** + * Created by sunny on 17-12-29. + */ + +fun easySin(angle: Float, radius:Int = 1): Double { + return Math.sin(Math.PI * angle / 180) * radius +} + +fun easyCos(angle: Float, radius: Int = 1): Double { + return Math.cos(Math.PI * angle / 180) * radius +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MotionEventExtension.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MotionEventExtension.kt new file mode 100644 index 0000000..203e8fe --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MotionEventExtension.kt @@ -0,0 +1,20 @@ +package cn.qjm253.quick_android_base.extensions + +import android.view.MotionEvent +import android.view.View + +/** + * + * Created by sunny on 18-1-2. + */ + +/** + * 该函数用来判断一个触摸事件是否发生在某个具体View的范围内 + */ +fun MotionEvent.isInView(view: View): Boolean { + val location = IntArray(2) + view.getLocationOnScreen(location) + val x = location[0] + val y = location[1] + return !(this.x < x || this.x > x + view.width || this.y < y || this.y > y + view.height) +} diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MyDelegates.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MyDelegates.kt new file mode 100644 index 0000000..2bd83f6 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/MyDelegates.kt @@ -0,0 +1,39 @@ +package cn.qjm253.quick_android_base.extensions + +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +/** + * Created by sunny on 17-12-28. + */ + +object MyDelegates{ + fun notNullAndOnlyInitFirstTime(): ReadWriteProperty = NotNullAndOnlyInitFirstTime() +} + +/** + * 本代理类代理的属性,不可为null,可延迟初始化,但是只会被初始化一次,第一次初始化之后的set操作都将被忽略 + */ +private class NotNullAndOnlyInitFirstTime : ReadWriteProperty { + private var value: T? = null + + /** + * get代理 + * @param thisRef 被代理的对象 + * @param property 保存了被代理对象的名字等 + */ + override fun getValue(thisRef: Any?, property: KProperty<*>): T = + value ?: throw IllegalStateException("${property.name} is not initialized!") + + /** + * set代理 + * @param thisRef 被代理的对象 + * @param property 保存了被代理对象的名字等 + * @param value 元数据 + */ + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { + if(this.value == null) + this.value = value + } + +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/TextViewExtensions.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/TextViewExtensions.kt new file mode 100644 index 0000000..82f29a8 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/TextViewExtensions.kt @@ -0,0 +1,37 @@ +package cn.qjm253.quick_android_base.extensions + +import android.annotation.SuppressLint +import android.os.Build +import android.text.Html +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.StringRes +import cn.qjm253.quick_android_base.util.SpannableUtil + +@SuppressLint("ResourceType") +fun TextView.setStyleText(text: String = this.text.toString(), @StringRes textRes: Int = -1, + isBold: Boolean = false, isItalic: Boolean = false, @ColorInt color: Int = -1, + @ColorRes colorRes: Int = -1) { + val t = if (textRes > 0) + context.getString(textRes) + else + text + var result: CharSequence = t + if (isBold) + result = SpannableUtil.bold(result) + if (isItalic) + result = SpannableUtil.italic(result) + if (color > 0 || colorRes > 0) + result = SpannableUtil.color(if (colorRes > 0) resources.getColor(colorRes) else color, result) + this.text = result +} + + +fun TextView.showHtml(html: String) { + this.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT) + } else { + Html.fromHtml(html) + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ViewExtension.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ViewExtension.kt new file mode 100644 index 0000000..ea04d95 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/extensions/ViewExtension.kt @@ -0,0 +1,123 @@ +package cn.qjm253.quick_android_base.extensions + +import android.animation.Animator +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.animation.ValueAnimator +import android.view.View + +/** + * Created by sunny on 17-12-29. + */ + +/************************************************************************* + * ObjectAnimator生成 + **************************************************************************/ + +fun View.scaleXAnimation(vararg values: Float): ObjectAnimator { + return ObjectAnimator.ofFloat(this, "scaleX", *values) +} + +fun View.scaleYAnimation(vararg values: Float): ObjectAnimator { + return ObjectAnimator.ofFloat(this, "scaleY", *values) +} + +fun View.rotationAnimation(vararg values: Float): ObjectAnimator { + return ObjectAnimator.ofFloat(this, "rotation", *values) +} + +fun View.transXAnimation(vararg values: Float): ObjectAnimator { + return ObjectAnimator.ofFloat(this, "translationX", *values) +} + +fun View.transYAnimation(vararg values: Float): ObjectAnimator { + return ObjectAnimator.ofFloat(this, "translationY", *values) +} + +fun View.alphaAnimation(vararg values: Float): ObjectAnimator { + return ObjectAnimator.ofFloat(this, "alpha", *values) +} +/************************************************************************* + * 属性动画 + **************************************************************************/ + +/** + * XY轴同比例缩放 + */ +fun View.scaleXY(vararg values: Float, duration: Long = 500): View { + val animatorSet = AnimatorSet() + animatorSet.setDuration(duration) + .play(this.scaleXAnimation(*values)) + .with(this.scaleYAnimation(*values)) + animatorSet.start() + return this +} + + + +/** + * 旋转 + */ +fun View.rotate(vararg values: Float, duration: Long = 500, repeatCount: Int = 0, + repeatMode: Int = ValueAnimator.RESTART): ObjectAnimator { + val animation = this.rotationAnimation(*values) + with(animation + .setDuration(duration)){ + this.repeatCount = repeatCount + this.repeatMode = repeatMode + start() + } + return animation +// return this +} + +/** + * 平移 + */ +fun View.transXY(transX: FloatArray = floatArrayOf(0f, 0f), transY: FloatArray = floatArrayOf(0f, 0f) + , duration: Long = 500): View { + val animatorSet = AnimatorSet() + animatorSet.setDuration(duration) + .play(this.transXAnimation(*transX)) + .with(this.transYAnimation(*transY)) + animatorSet + .start() + return this +} + +fun View.doAnim(floats: FloatArray = floatArrayOf(0f, 0f), callback: (value: Float) -> Unit = {}) { + val objAnim = ObjectAnimator.ofFloat(*floats) + objAnim.addUpdateListener { + val value = it.animatedValue as Float + callback(value) + } + objAnim.start() +} + +/** + * 多个属性动画并行运行 + */ +fun View.animer(vararg animations: ObjectAnimator, duration: Long, listener: Animator.AnimatorListener? = null) { + if (animations.isEmpty()) + return + val animatorSet = AnimatorSet() + val builder = animatorSet.setDuration(duration) + .play(animations[0]) + animations.filterIndexed { index, _ -> index != 0 } + .forEach { builder.with(it) } + if (listener != null) + animatorSet.addListener(listener) + animatorSet.start() + +} + +/** + * 平移旋转渐变组合动画 + */ +fun View.transRotateAlpha(transX: FloatArray = floatArrayOf(0f, 0f), transY: FloatArray = floatArrayOf(0f, 0f), + rotation: FloatArray = floatArrayOf(this.rotation, this.rotation), + alpha: FloatArray = floatArrayOf(this.alpha, this.alpha), duration: Long = 500, + listener: Animator.AnimatorListener? = null) { + this.animer(transXAnimation(*transX), transYAnimation(*transY), rotationAnimation(*rotation), + alphaAnimation(*alpha), duration = duration, listener = listener) +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/model/SystemInfo.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/model/SystemInfo.kt new file mode 100644 index 0000000..bb90251 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/model/SystemInfo.kt @@ -0,0 +1,16 @@ +package cn.qjm253.quick_android_base.model + +/** + * @author SunnyQjm + * @date 19-7-10 上午9:25 + */ + +data class SystemInfo( + val brand: String = "", + val model: String = "", + val hardware: String = "", + val sdkInt: Int = 22, + val release: String = "", + val statusBarHeight: Int = 0, + val systemLanguage: String = "" +) \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/params/IntentParam.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/params/IntentParam.kt new file mode 100644 index 0000000..3329d72 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/params/IntentParam.kt @@ -0,0 +1,76 @@ +package cn.qjm253.quick_android_base.params + +import android.content.Intent +import android.os.Bundle +import android.os.Parcelable +import java.io.Serializable + +/** + * Created by sunny on 18-1-28. + */ +class IntentParam(val keys: MutableList = mutableListOf(), + val values: MutableList = mutableListOf()) { + + fun add(key: String, value: Any?): IntentParam { + if(value == null) + return this + keys.add(key) + values.add(value) + return this + } + + fun applyParam(intent: Intent){ + for(i in 0 until keys.size){ + when(values[i]){ + is Boolean -> intent.putExtra(keys[i], values[i] as Boolean) + is Byte -> intent.putExtra(keys[i], values[i] as Byte) + is Char -> intent.putExtra(keys[i], values[i] as Char) + is Short -> intent.putExtra(keys[i], values[i] as Short) + is Int -> intent.putExtra(keys[i], values[i] as Int) + is Long -> intent.putExtra(keys[i], values[i] as Long) + is Float -> intent.putExtra(keys[i], values[i] as Float) + is Double -> intent.putExtra(keys[i], values[i] as Double) + is String -> intent.putExtra(keys[i], values[i] as String) + is CharSequence -> intent.putExtra(keys[i], values[i] as CharSequence) + is Parcelable -> intent.putExtra(keys[i], values[i] as Parcelable) + is BooleanArray -> intent.putExtra(keys[i], values[i] as BooleanArray) + is ByteArray -> intent.putExtra(keys[i], values[i] as ByteArray) + is CharArray -> intent.putExtra(keys[i], values[i] as CharArray) + is ShortArray -> intent.putExtra(keys[i], values[i] as ShortArray) + is IntArray -> intent.putExtra(keys[i], values[i] as IntArray) + is LongArray -> intent.putExtra(keys[i], values[i] as LongArray) + is FloatArray -> intent.putExtra(keys[i], values[i] as FloatArray) + is DoubleArray -> intent.putExtra(keys[i], values[i] as DoubleArray) + is Serializable -> intent.putExtra(keys[i], values[i] as Serializable) + is Array<*> -> intent.putExtra(keys[i], values[i] as Array) + } + } + } + + fun applyBundle(bundle: Bundle) { + for(i in 0 until keys.size){ + when(values[i]){ + is Boolean -> bundle.putBoolean(keys[i], values[i] as Boolean) + is Byte -> bundle.putByte(keys[i], values[i] as Byte) + is Char -> bundle.putChar(keys[i], values[i] as Char) + is Short -> bundle.putShort(keys[i], values[i] as Short) + is Int -> bundle.putInt(keys[i], values[i] as Int) + is Long -> bundle.putLong(keys[i], values[i] as Long) + is Float -> bundle.putFloat(keys[i], values[i] as Float) + is Double -> bundle.putDouble(keys[i], values[i] as Double) + is String -> bundle.putString(keys[i], values[i] as String) + is CharSequence -> bundle.putCharSequence(keys[i], values[i] as CharSequence) + is Parcelable -> bundle.putParcelable(keys[i], values[i] as Parcelable) + is BooleanArray -> bundle.putBooleanArray(keys[i], values[i] as BooleanArray) + is ByteArray -> bundle.putByteArray(keys[i], values[i] as ByteArray) + is CharArray -> bundle.putCharArray(keys[i], values[i] as CharArray) + is ShortArray -> bundle.putShortArray(keys[i], values[i] as ShortArray) + is IntArray -> bundle.putIntArray(keys[i], values[i] as IntArray) + is LongArray -> bundle.putLongArray(keys[i], values[i] as LongArray) + is FloatArray -> bundle.putFloatArray(keys[i], values[i] as FloatArray) + is DoubleArray -> bundle.putDoubleArray(keys[i], values[i] as DoubleArray) + is Serializable -> bundle.putSerializable(keys[i], values[i] as Serializable) + } + } + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/AccountValidatorUtil.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/AccountValidatorUtil.kt new file mode 100644 index 0000000..a9867c6 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/AccountValidatorUtil.kt @@ -0,0 +1,128 @@ +package cn.qjm253.quick_android_base.util + +import java.util.regex.Pattern + +/** + * 账户相关属性验证工具 + */ +object AccountValidatorUtil { + /** + * 正则表达式:验证用户名 + */ + val REGEX_USERNAME = "^[a-zA-Z]\\w{5,20}$" + + /** + * 正则表达式:验证密码 + */ + val REGEX_PASSWORD = "^[a-zA-Z0-9]{6,20}$" + + /** + * 正则表达式:验证手机号 + */ + val REGEX_MOBILE = "^((16[0-9])|(19[0-9])(17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$" + + /** + * 正则表达式:验证邮箱 + */ + val REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$" + + /** + * 正则表达式:验证汉字 + */ + val REGEX_CHINESE = "^[\u4e00-\u9fa5],{0,}$" + + /** + * 正则表达式:验证身份证 + */ + val REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)" + + /** + * 正则表达式:验证URL + */ + val REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?" + + /** + * 正则表达式:验证IP地址 + */ + val REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)" + + /** + * 校验用户名 + * + * @param username + * @return 校验通过返回true,否则返回false + */ + fun isUsername(username: String): Boolean { + return Pattern.matches(REGEX_USERNAME, username) + } + + /** + * 校验密码 + * + * @param password + * @return 校验通过返回true,否则返回false + */ + fun isPassword(password: String): Boolean { + return Pattern.matches(REGEX_PASSWORD, password) + } + + /** + * 校验手机号 + * + * @param mobile + * @return 校验通过返回true,否则返回false + */ + fun isMobile(mobile: String): Boolean { + return Pattern.matches(REGEX_MOBILE, mobile) + } + + /** + * 校验邮箱 + * + * @param email + * @return 校验通过返回true,否则返回false + */ + fun isEmail(email: String): Boolean { + return Pattern.matches(REGEX_EMAIL, email) + } + + /** + * 校验汉字 + * + * @param chinese + * @return 校验通过返回true,否则返回false + */ + fun isChinese(chinese: String): Boolean { + return Pattern.matches(REGEX_CHINESE, chinese) + } + + /** + * 校验身份证 + * + * @param idCard + * @return 校验通过返回true,否则返回false + */ + fun isIDCard(idCard: String): Boolean { + return Pattern.matches(REGEX_ID_CARD, idCard) + } + + /** + * 校验URL + * + * @param url + * @return 校验通过返回true,否则返回false + */ + fun isUrl(url: String): Boolean { + return Pattern.matches(REGEX_URL, url) + } + + /** + * 校验IP地址 + * + * @param ipAddr + * @return + */ + fun isIPAddr(ipAddr: String): Boolean { + return Pattern.matches(REGEX_IP_ADDR, ipAddr) + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/ContentUriUtil.java b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/ContentUriUtil.java new file mode 100644 index 0000000..69f6da2 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/ContentUriUtil.java @@ -0,0 +1,366 @@ +package cn.qjm253.quick_android_base.util; + +import android.annotation.SuppressLint; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; + +import androidx.loader.content.CursorLoader; + +import java.io.File; + +public class ContentUriUtil { + /** + * // * Get a file path from a Uri. This will get the the path for Storage Access + * // * Framework Documents, as well as the _data field for the MediaStore and + * // * other file-based ContentProviders. + * // * + * // * @param context The context. + * // * @param uri The Uri to query. + * // * @author paulburke + * // + */ +// public static String getPath(final Context context, final Uri uri) { +// +// final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; +// +// // DocumentProvider +// if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { +// // ExternalStorageProvider +// if (isExternalStorageDocument(uri)) { +// final String docId = DocumentsContract.getDocumentId(uri); +// final String[] split = docId.split(":"); +// final String type = split[0]; +// +// if ("primary".equalsIgnoreCase(type)) { +// return Environment.getExternalStorageDirectory() + "/" + split[1]; +// } +// +// // TODO handle non-primary volumes +// } +// // DownloadsProvider +// else if (isDownloadsDocument(uri)) { +// final String id = DocumentsContract.getDocumentId(uri); +// if (id.startsWith("raw:")) { +// return uri.getPath(); +// } +// final Uri contentUri = ContentUris.withAppendedId( +// Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); +// return getDataColumn(context, contentUri, null, null); +// } +// // MediaProvider +// else if (isMediaDocument(uri)) { +// final String docId = DocumentsContract.getDocumentId(uri); +// final String[] split = docId.split(":"); +// final String type = split[0]; +// +// Uri contentUri = null; +// if ("image".equals(type)) { +// contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; +// } else if ("video".equals(type)) { +// contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; +// } else if ("audio".equals(type)) { +// contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; +// } +// +// final String selection = "_id=?"; +// final String[] selectionArgs = new String[]{ +// split[1] +// }; +// +// return getDataColumn(context, contentUri, selection, selectionArgs); +// } +// } +// // MediaStore (and general) +// else if ("content".equalsIgnoreCase(uri.getScheme())) { +// +// // Return the remote address +// if (isGooglePhotosUri(uri)) +// return uri.getLastPathSegment(); +// +// return getDataColumn(context, uri, null, null); +// } +// // File +// else if ("file".equalsIgnoreCase(uri.getScheme())) { +// return uri.getPath(); +// } +// +// return null; +// } +// +// /** +// * * +// * Get the value of the data column for this Uri. This is useful for +// * MediaStore Uris, and other file-based ContentProviders. +// * +// * @param context The context. +// * @param uri The Uri to query. +// * @param selection (Optional) Filter used in the query. +// * @param selectionArgs (Optional) Selection arguments used in the query. +// * @return The value of the _data column, which is typically a file path. +// */ +// public static String getDataColumn(Context context, Uri uri, String selection, +// String[] selectionArgs) { +// +// Cursor cursor = null; +// final String column = "_data"; +// final String[] projection = { +// column +// }; +// +// try { +// cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, +// null); +// if (cursor != null && cursor.moveToFirst()) { +// final int index = cursor.getColumnIndexOrThrow(column); +// return cursor.getString(index); +// } +// } finally { +// if (cursor != null) +// cursor.close(); +// } +// return null; +// } +// +// +// /** +// * @param uri The Uri to check. +// * @return Whether the Uri authority is ExternalStorageProvider. +// */ +// public static boolean isExternalStorageDocument(Uri uri) { +// return "com.android.externalstorage.documents".equals(uri.getAuthority()); +// } +// +// /** +// * @param uri The Uri to check. +// * @return Whether the Uri authority is DownloadsProvider. +// */ +// public static boolean isDownloadsDocument(Uri uri) { +// return "com.android.providers.downloads.documents".equals(uri.getAuthority()); +// } +// +// /** +// * @param uri The Uri to check. +// * @return Whether the Uri authority is MediaProvider. +// */ +// public static boolean isMediaDocument(Uri uri) { +// return "com.android.providers.media.documents".equals(uri.getAuthority()); +// } +// +// /** +// * @param uri The Uri to check. +// * @return Whether the Uri authority is Google Photos. +// */ +// public static boolean isGooglePhotosUri(Uri uri) { +// return "com.google.android.apps.photos.content".equals(uri.getAuthority()); +// } + + private static String failReason; + + static String errorReason() { + return failReason; + } + + public static String getPath(final Context context, final Uri uri) { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + return getRealPathFromURI_BelowAPI19(context, uri); + } + return getRealPathFromURI_API19(context, uri); + } + + + @SuppressLint("NewApi") + public static String getRealPathFromURI_API19(final Context context, final Uri uri) { + + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + if (split.length > 1) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } else { + return Environment.getExternalStorageDirectory() + "/"; + } + } else { + return "storage" + "/" + docId.replace(":", "/"); + } + + } else if (isRawDownloadsDocument(uri)) { + String fileName = getFilePath(context, uri); + String subFolderName = getSubFolders(uri); + + if (fileName != null) { + return Environment.getExternalStorageDirectory().toString() + "/Download/" + subFolderName + fileName; + } + String id = DocumentsContract.getDocumentId(uri); + + final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + return getDataColumn(context, contentUri, null, null); + } else if (isDownloadsDocument(uri)) { + + System.out.println("downloadsDocument"); + String fileName = getFilePath(context, uri); + + if (fileName != null) { + return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName; + } + String id = DocumentsContract.getDocumentId(uri); + if (id.startsWith("raw:")) { + id = id.replaceFirst("raw:", ""); + File file = new File(id); + if (file.exists()) + return id; + } + if (id.startsWith("raw%3A%2F")) { + id = id.replaceFirst("raw%3A%2F", ""); + File file = new File(id); + if (file.exists()) + return id; + } + final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + return getDataColumn(context, contentUri, null, null); + } else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[]{ + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } else if ("content".equalsIgnoreCase(uri.getScheme())) { + if (isGooglePhotosUri(uri)) { + return uri.getLastPathSegment(); + } + if (getDataColumn(context, uri, null, null) == null) { + failReason = "dataReturnedNull"; + } + return getDataColumn(context, uri, null, null); + } else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + return null; + } + + private static String getSubFolders(Uri uri) { + String replaceChars = String.valueOf(uri).replace("%2F", "/").replace("%20", " ").replace("%3A", ":"); + String[] bits = replaceChars.split("/"); + String sub5 = bits[bits.length - 2]; + String sub4 = bits[bits.length - 3]; + String sub3 = bits[bits.length - 4]; + String sub2 = bits[bits.length - 5]; + String sub1 = bits[bits.length - 6]; + if (sub1.equals("Download")) { + return sub2 + "/" + sub3 + "/" + sub4 + "/" + sub5 + "/"; + } else if (sub2.equals("Download")) { + return sub3 + "/" + sub4 + "/" + sub5 + "/"; + } else if (sub3.equals("Download")) { + return sub4 + "/" + sub5 + "/"; + } else if (sub4.equals("Download")) { + return sub5 + "/"; + } else { + return ""; + } + } + + static String getRealPathFromURI_BelowAPI19(Context context, Uri contentUri) { + String[] proj = {MediaStore.Video.Media.DATA}; + CursorLoader loader = new CursorLoader(context, contentUri, proj, null, null, null); + Cursor cursor = loader.loadInBackground(); + assert cursor != null; + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA); + cursor.moveToFirst(); + String result = cursor.getString(column_index); + cursor.close(); + return result; + } + + @SuppressWarnings("TryFinallyCanBeTryWithResources") + private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + Cursor cursor = null; + final String column = "_data"; + final String[] projection = {column}; + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + final int index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(index); + } + } catch (Exception e) { + failReason = e.getMessage(); + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + + @SuppressWarnings("TryFinallyCanBeTryWithResources") + private static String getFilePath(Context context, Uri uri) { + Cursor cursor = null; + final String[] projection = {MediaStore.Files.FileColumns.DISPLAY_NAME}; + try { + cursor = context.getContentResolver().query(uri, projection, null, null, + null); + if (cursor != null && cursor.moveToFirst()) { + final int index = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME); + return cursor.getString(index); + } + } catch (Exception e) { + failReason = e.getMessage(); + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + + private static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + + private static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + private static boolean isRawDownloadsDocument(Uri uri) { + String uriToString = String.valueOf(uri); + return uriToString.contains("com.android.providers.downloads.documents/document/raw"); + } + + private static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + + private static boolean isGooglePhotosUri(Uri uri) { + return "com.google.android.apps.photos.content".equals(uri.getAuthority()); + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/DisplayUtils.java b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/DisplayUtils.java new file mode 100644 index 0000000..918b1d1 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/DisplayUtils.java @@ -0,0 +1,105 @@ +package cn.qjm253.quick_android_base.util; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Rect; +import android.util.TypedValue; +import android.view.WindowManager; + +/** + * Created by liufengkai on 15/11/8. + */ +public class DisplayUtils { + /** + * px to dip 尺寸不变 + * + * @param context + * @param pxValue + * @return + */ + public static int px2dip(Context context, float pxValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); + } + + + /** + * dip to px 尺寸不变 + * + * @param context + * @param dipValue + * @return + */ + public static int dip2px(Context context, float dipValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dipValue * scale + 0.5f); + } + + /** + * dp to px + * + * @param context + * @param dp + * @return + */ + public static int dp2px(Context context, int dp) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp, + context.getResources().getDisplayMetrics()); + } + + /** + * px to sp 文字不变 + * + * @param context + * @param pxValue + * @return + */ + public static int px2sp(Context context, float pxValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue / fontScale + 0.5f); + } + + /** + * sp to px 文字不变 + * + * @param context + * @param spValue + * @return + */ + public static int sp2px(Context context, float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } + + /** + * sp to px + * + * @param context + * @param px + * @return + */ + public static int sp2px(Context context, int px) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + px, + context.getResources().getDisplayMetrics()); + } + + public static int[] getScreenParams(Context context) { + + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + + int width = manager.getDefaultDisplay().getWidth(); + int height = manager.getDefaultDisplay().getHeight(); + + return new int[]{width, height}; + } + + public static int getStatusBarHeight(Activity context) { + Rect frame = new Rect(); + context.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); + return frame.top; + } +} diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/FileUtils.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/FileUtils.kt new file mode 100644 index 0000000..170123d --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/FileUtils.kt @@ -0,0 +1,118 @@ +package cn.qjm253.quick_android_base.util + +import android.os.Environment +import cn.qjm253.quick_android_base.QuickAndroid +import java.io.File + + +/** + * Created by tanshunwang on 2016/9/21 0021. + */ +object FileUtils { + + /** + * 获得应用的根目录 + * + * @return + */ + //判断sd卡是否存在 + //获取根目录 + val appPath: String + get() { + val sdCardExist = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED + val sdDir = if (sdCardExist) { + File(Environment.getExternalStorageDirectory().path + "/" + QuickAndroid.APP_NAME + "/") + } else { + File(Environment.getDataDirectory().toString() + "/" + QuickAndroid.APP_NAME + "/") + } + if (!sdDir.exists()) { + sdDir.mkdirs() + } + return sdDir.toString() + } + + val cachePath: String + get() { + val targetPath = "$appPath/Cache/" + val file = File(targetPath) + if (!file.exists()) + file.mkdirs() + return targetPath + } + + val recordPath: String + get() { + val targetPath = "$appPath/Record/" + val file = File(targetPath) + if (!file.exists()) + file.mkdirs() + return targetPath + } + + val picturePath: String + get() { + val targetPath = "$appPath/Picture/" + val file = File(targetPath) + if (!file.exists()) + file.mkdirs() + return targetPath + } + + val downloadPath: String + get() { + val targetPath = "$appPath/Download/" + val file = File(targetPath) + if (!file.exists()) + file.mkdirs() + return targetPath + } + + val wifiDirectPath: String + get() { + val path = "$appPath/WifiDirectFile/" + val file = File(path) + if (!file.exists()) { + file.mkdirs() + } + return path + } + + + /** + * 获得SDCard的根目录 + * + * @return + */ + //判断sd卡是否存在 + val sdPath: String? + get() { + val sdCardExist = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED + return if (sdCardExist) { + Environment.getExternalStorageDirectory().path + } else { + null + } + } + + + val path: String + get() { + val path = "$appPath/header/" + val file = File(path) + if (!file.exists()) { + file.mkdirs() + println("54555") + } + return path + } + + fun generateRecordFile(fileName: String): File { + return File(recordPath + File.separator + fileName) + } + + fun generatePictureFile(fileName: String): File { + return File(picturePath + File.separator + fileName) + } + + +} diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GenerateId.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GenerateId.kt new file mode 100644 index 0000000..b2ab782 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GenerateId.kt @@ -0,0 +1,30 @@ +package cn.qjm253.quick_android_base.util + +import java.util.concurrent.atomic.AtomicInteger + +/** + * @author SunnyQjm + * @date 19-7-14 下午8:16 + */ + +object GeneratedId { + private val sNextGeneratedId = AtomicInteger(20000) + + /** + * Generate a value suitable for use in setId + * This value will not collide with ID values generated at build time by aapt for R.id. + * + * @return a generated ID value + */ + fun generateViewId(): Int { + while (true) { + val result = sNextGeneratedId.get() + // aapt-generated IDs have the high byte nonzero; clamp to the range under that. + var newValue = result + 1 + if (newValue > 0x00FFFFFF) newValue = 1 // Roll over to 1, not 0. + if (sNextGeneratedId.compareAndSet(result, newValue)) { + return result + } + } + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GsonUtil.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GsonUtil.kt new file mode 100644 index 0000000..7ddbdb9 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/GsonUtil.kt @@ -0,0 +1,78 @@ +package cn.qjm253.quick_android_base.util + +import com.google.gson.Gson +import com.google.gson.JsonSyntaxException +import com.google.gson.reflect.TypeToken + +import java.util.ArrayList + +/** + * Created by Sunny on 2017/4/19 0019. + */ +object GsonUtil { + val instance: Gson = Gson() + + + fun json2Bean(json: String, beanClass: Class): T? { + var bean: T? = null + try { + bean = instance.fromJson(json, beanClass) + } catch (e: JsonSyntaxException) { + e.printStackTrace() + } + + return bean + } + + fun json2Bean(json: String): T? { + var bean: T? = null + val type = object : TypeToken>() { + + }.type + try { + bean = instance.fromJson(json, type) + } catch (e: JsonSyntaxException) { + e.printStackTrace() + } + + return bean + } + + // public static ArrayList json2TagList(String json) { + // Type type = new TypeToken>(){}.getType(); + // ArrayList bean = new ArrayList<>(); + // try { + // bean = getInstance().fromJson(json, type); + // } catch (JsonSyntaxException e) { + // e.printStackTrace(); + // } + // return bean; + // } + // + // public static ArrayList json2RecordList(String json) { + // Type type = new TypeToken>(){}.getType(); + // ArrayList bean = new ArrayList<>(); + // try { + // bean = getInstance().fromJson(json, type); + // } catch (JsonSyntaxException e) { + // e.printStackTrace(); + // } + // return bean; + // } + // + // public static ArrayList json2ImageList(String json) { + // Type type = new TypeToken>(){}.getType(); + // ArrayList bean = new ArrayList<>(); + // try { + // bean = getInstance().fromJson(json, type); + // } catch (JsonSyntaxException e) { + // e.printStackTrace(); + // } + // return bean; + // } + + + fun bean2Json(`object`: Any): String { + return instance.toJson(`object`) + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/RxSchedulersHelper.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/RxSchedulersHelper.kt new file mode 100644 index 0000000..976c8f4 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/RxSchedulersHelper.kt @@ -0,0 +1,41 @@ +package cn.qjm253.quick_android_base.util + +import io.reactivex.ObservableTransformer +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers + +/** + * 处理Rx线程转换 + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +object RxSchedulersHelper { + + fun io_main(): ObservableTransformer { + return ObservableTransformer { upstream -> + upstream + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + } + } + + fun io_io(): ObservableTransformer{ + return ObservableTransformer { upstream -> + upstream.subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + } + } + fun main_io(): ObservableTransformer { + return ObservableTransformer { upstream -> + upstream.subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(Schedulers.io()) + } + } + + fun comppute_main(): ObservableTransformer { + return ObservableTransformer { upstream -> + upstream.subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + } + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpUtils.java b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpUtils.java new file mode 100644 index 0000000..7272bca --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpUtils.java @@ -0,0 +1,303 @@ +package cn.qjm253.quick_android_base.util; + +import android.content.Context; +import android.content.SharedPreferences; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * 简化Sp存储的工具类 + * + * @author liufengkai + */ +public class SpUtils { + + public SpUtils() { + /* cannot be instantiated */ + throw new UnsupportedOperationException("cannot be instantiated"); + } + + /** + * Sp文件名 + */ + public static final String FILE_NAME = "share_data"; + + /** + * 保存数据的方法,添加具体数据类型 + * + * @param context + * @param key + * @param object + */ + public static void put(Context context, String key, Object object) { + + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + + // 判断数据类型 + if (object instanceof String) { + editor.putString(key, (String) object); + } else if (object instanceof Integer) { + editor.putInt(key, (Integer) object); + } else if (object instanceof Boolean) { + editor.putBoolean(key, (Boolean) object); + } else if (object instanceof Float) { + editor.putFloat(key, (Float) object); + } else if (object instanceof Long) { + editor.putLong(key, (Long) object); + } else { + editor.putString(key, object.toString()); + } + + SharedPreferencesCompat.apply(editor); + } + + public static void put(Context context, String key, String value) { + + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.putString(key, value); + SharedPreferencesCompat.apply(editor); + } + + public static void put(Context context, String key, int value) { + + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.putInt(key, value); + SharedPreferencesCompat.apply(editor); + } + + public static void put(Context context, String key, float value) { + + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.putFloat(key, value); + SharedPreferencesCompat.apply(editor); + } + + public static void put(Context context, String key, long value) { + + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.putLong(key, value); + SharedPreferencesCompat.apply(editor); + } + + public static String get(Context context, String key, String defaultValue) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getString(key, defaultValue); + } + + public static int get(Context context, String key, int defaultValue) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getInt(key, defaultValue); + } + + public static float get(Context context, String key, float defaultValue) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getFloat(key, defaultValue); + } + + public static long get(Context context, String key, long defaultValue) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getLong(key, defaultValue); + } + + public static boolean get(Context context, String key, boolean judge) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getBoolean(key, judge); + } + + /** + * 获取保存数据的方法,添加具体数据类型 + * + * @param context + * @param key + * @param defaultObject + * @return object + */ + public static Object get(Context context, String key, Object defaultObject) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + + if (defaultObject instanceof String) { + return sp.getString(key, (String) defaultObject); + } else if (defaultObject instanceof Integer) { + return sp.getInt(key, (Integer) defaultObject); + } else if (defaultObject instanceof Boolean) { + return sp.getBoolean(key, (Boolean) defaultObject); + } else if (defaultObject instanceof Float) { + return sp.getFloat(key, (Float) defaultObject); + } else if (defaultObject instanceof Long) { + return sp.getLong(key, (Long) defaultObject); + } + + return null; + } + + /** + * 存入哈希表 + * + * @param context + * @param map + * @param key + */ + public static void putMap(Context context, Map map, String key) { + JSONArray jsonArray = new JSONArray(); + Set set = map.entrySet(); + Iterator iterator = set.iterator(); + for (int i = 0; i < map.size(); i++) { + Map.Entry mapEntry = (Map.Entry) iterator.next(); + try { + JSONObject object = new JSONObject(); + object.put("key", mapEntry.getKey()); + object.put("value", mapEntry.getValue()); + jsonArray.put(object); + } catch (JSONException e) { + e.printStackTrace(); + } + } + put(context, key, jsonArray.toString()); + } + + /** + * 读取哈希表 + * + * @param context + * @param key + * @return map + */ + public static Map getMap(Context context, String key) { + Map map = new HashMap(); + try { + JSONArray jsonArray = new JSONArray((String) get(context, key, "")); + for (int i = 0; i < jsonArray.length(); i++) { + try { + JSONObject object = jsonArray.getJSONObject(i); + map.put(object.getString("key"), object.getString("value")); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + return map; + } + + /** + * 移除某个key值已经对应的值 + * + * @param context + * @param key + */ + public static void remove(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.remove(key); + SharedPreferencesCompat.apply(editor); + } + + /** + * 清除所有数据 + * + * @param context + */ + public static void clear(Context context) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + SharedPreferencesCompat.apply(editor); + } + + /** + * 查询某个key是否存在 + * + * @param context + * @param key + * @return + */ + public static boolean contains(Context context, String key) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.contains(key); + } + + /** + * 返回所有的键值对 + * + * @param context + * @return map + */ + public static Map getAll(Context context) { + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getAll(); + } + + /** + * 解决SharedPreferencesCompat.apply方法的兼容类 + * + * @author liufengkai + */ + private static class SharedPreferencesCompat { + + private static final Method sApplyMethod = findApplyMethod(); + + /** + * 反射查找apply的方法 + * + * @return method + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + private static Method findApplyMethod() { + try { + Class clz = SharedPreferences.Editor.class; + return clz.getMethod("apply"); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 如果找到则使用apply执行,否则使用commit + * + * @param editor + */ + public static void apply(SharedPreferences.Editor editor) { + try { + if (sApplyMethod != null) { + sApplyMethod.invoke(editor); + return; + } + } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + editor.commit(); + } + } + +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpannableUtil.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpannableUtil.kt new file mode 100644 index 0000000..f50c86c --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SpannableUtil.kt @@ -0,0 +1,85 @@ +package cn.qjm253.quick_android_base.util + +import android.graphics.Typeface +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.Spanned +import android.text.style.ForegroundColorSpan +import android.text.style.StyleSpan + + +/** + * SpannableText的工具类,可以设置文本的显示样式 + * Created by sunny on 18-1-27. + */ + +object SpannableUtil { + /** + * Returns a CharSequence that concatenates the specified array of CharSequence + * objects and then applies a list of zero or more tags to the entire range. + * + * @param content an array of character sequences to apply a style to + * @param tags the styled span objects to apply to the content + * such as android.text.style.StyleSpan + */ + private fun apply(content: Array, vararg tags: Any): CharSequence { + val text = SpannableStringBuilder() + openTags(text, tags) + for (item in content) { + text.append(item) + } + closeTags(text, tags) + return text + } + + /** + * Iterates over an array of tags and applies them to the beginning of the specified + * Spannable object so that future text appended to the text will have the styling + * applied to it. Do not call this method directly. + */ + private fun openTags(text: Spannable, tags: Array) { + for (tag in tags) { + text.setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK) + } + } + + /** + * "Closes" the specified tags on a Spannable by updating the spans to be + * endpoint-exclusive so that future text appended to the end will not take + * on the same styling. Do not call this method directly. + */ + private fun closeTags(text: Spannable, tags: Array) { + val len = text.length + for (tag in tags) { + if (len > 0) { + text.setSpan(tag, 0, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } else { + text.removeSpan(tag) + } + } + } + + /** + * Returns a CharSequence that applies boldface to the concatenation + * of the specified CharSequence objects. + */ + fun bold(vararg content: CharSequence): CharSequence { + return apply(content, StyleSpan(Typeface.BOLD)) + } + + /** + * Returns a CharSequence that applies italics to the concatenation + * of the specified CharSequence objects. + */ + fun italic(vararg content: CharSequence): CharSequence { + return apply(content, StyleSpan(Typeface.ITALIC)) + } + + /** + * Returns a CharSequence that applies a foreground color to the + * concatenation of the specified CharSequence objects. + */ + fun color(color: Int, vararg content: CharSequence): CharSequence { + return apply(content, ForegroundColorSpan(color)) + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SystemInfoHelper.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SystemInfoHelper.kt new file mode 100644 index 0000000..1f6fb81 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/SystemInfoHelper.kt @@ -0,0 +1,88 @@ +package cn.qjm253.quick_android_base.util + +import android.content.Context +import cn.qjm253.quick_android_base.model.SystemInfo +import java.util.* + +/** + * 获取系统信息的工具类 + * + * @author SunnyQjm + * @date 19-7-10 上午9:02 + */ + +object SystemInfoHelper { + + /** + * 获取系统状态栏的高度 + */ + fun getStatusBarHeight(context: Context): Int { + val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android") + return context.resources.getDimensionPixelSize(resourceId) + } + + /** + * 获取手机型号 + */ + fun getSystemModel(): String { + return android.os.Build.MODEL ?: "" + } + + /** + * 获取手机厂商 + */ + fun getDeviceBrand(): String { + return android.os.Build.BRAND ?: "" + } + + /** + * 获取手机的版本号 + */ + fun getSystemVersion(): String { + return android.os.Build.VERSION.RELEASE + } + + /** + * 获取当前手机的语言 + */ + fun getSystemLanguage(): String { + return Locale.getDefault().language ?: "" + } + + /** + * 获取当前系统上的语言列表 + */ + fun getSystemLanguageLists(): Array { + return Locale.getAvailableLocales() ?: arrayOf() + } + + /** + * 获取系统硬件信息 + */ + fun getSystemHardware(): String { + return android.os.Build.HARDWARE ?: "" + } + + /** + * 获取当前系统的SDK版本 + */ + fun getSdkInt(): Int { + return android.os.Build.VERSION.SDK_INT + } + + + /** + * 构建系统信息 + */ + fun buildSystemInfo(context: Context): SystemInfo { + return SystemInfo( + getDeviceBrand(), + getSystemModel(), + getSystemHardware(), + getSdkInt(), + getSystemVersion(), + getStatusBarHeight(context), + getSystemLanguage() + ) + } +} \ No newline at end of file diff --git a/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/notification/MyNotificationUtil.kt b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/notification/MyNotificationUtil.kt new file mode 100644 index 0000000..0617f93 --- /dev/null +++ b/quick_android_base/src/main/java/cn/qjm253/quick_android_base/util/notification/MyNotificationUtil.kt @@ -0,0 +1,162 @@ +package cn.qjm253.quick_android_base.util.notification + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.BitmapFactory +import android.graphics.Color +import android.os.Build +import androidx.annotation.DrawableRes +import androidx.core.app.NotificationCompat +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.R +import cn.qjm253.quick_android_base.params.IntentParam + +/** + * 通知显示工具类 + * Created by sunny on 18-1-30. + */ + +class MyNotificationUtil private constructor(val context: Context, channelId: String = QuickAndroid.APP_NAME) { + + private var notification: Notification? = null + private var notificationManager: NotificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + private var builder = NotificationCompat.Builder(context, channelId) + + companion object { + private var default_notifyId = 0 + fun newInstance(context: Context): MyNotificationUtil { + return MyNotificationUtil(context) + } + + @Synchronized + fun generateNotifyId(): Int { + default_notifyId = (default_notifyId + 1) % 100 + return default_notifyId + } + + fun createChannelForOreo(context: Context, channelId: String, channelName: String) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val channel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW) + } else { + TODO("VERSION.SDK_INT < O") + } + channel.enableLights(true) + channel.setShowBadge(true) + channel.lightColor = Color.GREEN + channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC + + notificationManager.createNotificationChannel(channel) + } + } + } + + fun notify(notification: Notification, notificationId: Int){ + notificationManager.notify(notificationId, notification) + } + + fun cancel(notificationId: Int){ + notificationManager.cancel(notificationId) + } + + + fun initProgress(progress: Int, progressMax: Int = 100, indeterminate: Boolean = true, + title: String = "", content: String = "", ticker: String = ""): MyNotificationUtil { + initNotification(progress = progress, progressMax = progressMax, indeterminate = indeterminate, + title = title, content = content, ticker = ticker, isProgress = true, isSound = false, + isVibrate = false, autoCancel = false) + return this + } + + + fun initNotification(@DrawableRes smallIcon: Int = R.drawable.logo, + @DrawableRes bigIcon: Int = R.drawable.logo, title: String = "", + content: String = "", ticker: String = "", time: Long = System.currentTimeMillis(), + /** + * 1.将AutoCancel设为true后,当你点击通知栏的notification后,它会自动被取消消失, + * 不设置的话点击消息后也不清除,但可以滑动删除 + * 2.将Ongoing设为true 那么notification将不能滑动删除 + */ + autoCancel: Boolean = true, onGoing: Boolean = false, + /** + * 从Android4.1开始,可以通过以下方法,设置notification的优先级, + * 优先级越高的,通知排的越靠前,优先级低的,不会在手机最顶部的状态栏显示图标 + */ + priority: Int = NotificationCompat.PRIORITY_DEFAULT, + /** + * Notification.DEFAULT_ALL:铃声、闪光、震动均系统默认。 + * Notification.DEFAULT_SOUND:系统默认铃声。 + * Notification.DEFAULT_VIBRATE:系统默认震动。 + * Notification.DEFAULT_LIGHTS:系统默认闪光。 + * notifyBuilder.setDefaults(Notification.DEFAULT_ALL); + */ + isSound: Boolean = true, isVibrate: Boolean = true, isLight: Boolean = true, + /** + * 下面是进度相关设置 + */ + progress: Int = 0, progressMax: Int = 100, indeterminate: Boolean = true, + /** + * 是否显示进度条 + */ + isProgress: Boolean = false, + /** + * 点击跳转相关设置 + * 注意事项: setContentIntent一定要在build之前调用,不然无效 + */ + requestCode: Int = 0, target: Class<*>? = null, + pendingIntentFlag: Int = PendingIntent.FLAG_UPDATE_CURRENT, + pendingIntentParam: IntentParam? = null, + + // 适配Android8.0+ 通知必须配置渠道,要不然无法在通知栏显示 + channelId: String = QuickAndroid.APP_NAME, + channelName: String = QuickAndroid.APP_NAME + ) + : MyNotificationUtil { + // 适配Android8.0+ 通知必须配置渠道,要不然无法在通知栏显示 + createChannelForOreo(context, channelId, channelName) + + builder.setAutoCancel(autoCancel) + builder.setSmallIcon(smallIcon) + val bitmap = BitmapFactory.decodeResource(context.resources, bigIcon) + builder.setLargeIcon(bitmap) + builder.setContentText(content) + builder.setContentTitle(title) + builder.setTicker(ticker) + builder.setWhen(time) + builder.priority = priority + builder.setOngoing(onGoing) + var defaults = 0 + if (isSound) { + defaults = defaults or Notification.DEFAULT_SOUND + } + if (isVibrate) { + defaults = defaults or Notification.DEFAULT_VIBRATE + } + if (isLight) { + defaults = defaults or Notification.DEFAULT_LIGHTS + } + + if (isProgress) + builder.setProgress(progressMax, progress, indeterminate) + if (target != null) { + val intent = Intent(context, target) + pendingIntentParam?.applyParam(intent) + builder.setContentIntent(PendingIntent.getActivity(context, requestCode, + intent, pendingIntentFlag)) + } + builder.setDefaults(defaults) + return this + } + + fun show(notificationId: Int = generateNotifyId()): Int { + notification = builder.build() + notificationManager.notify(notificationId, notification) + return notificationId + } +} diff --git a/quick_android_base/src/main/res/drawable/logo.png b/quick_android_base/src/main/res/drawable/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bdc6af1f316ea0238f7774f7059ed211ee3fcded GIT binary patch literal 2903 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 Bk?a5f literal 0 HcmV?d00001 diff --git a/quick_android_base/src/main/res/values/strings.xml b/quick_android_base/src/main/res/values/strings.xml new file mode 100644 index 0000000..5c77f4e --- /dev/null +++ b/quick_android_base/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + 本功能需要请求摄像头权限 + diff --git a/quick_android_base/src/test/java/cn/qjm253/quick_android_base/ExampleUnitTest.java b/quick_android_base/src/test/java/cn/qjm253/quick_android_base/ExampleUnitTest.java new file mode 100644 index 0000000..26d7a37 --- /dev/null +++ b/quick_android_base/src/test/java/cn/qjm253/quick_android_base/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_base; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/quick_android_custom_view/.gitignore b/quick_android_custom_view/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_custom_view/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_custom_view/build.gradle b/quick_android_custom_view/build.gradle new file mode 100644 index 0000000..136d981 --- /dev/null +++ b/quick_android_custom_view/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.library' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + implementation project(path: ':quick_android_base') + +} diff --git a/quick_android_custom_view/proguard-rules.pro b/quick_android_custom_view/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/quick_android_custom_view/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/quick_android_custom_view/src/androidTest/java/cn/qjm253/quick_android_custom_view/ExampleInstrumentedTest.java b/quick_android_custom_view/src/androidTest/java/cn/qjm253/quick_android_custom_view/ExampleInstrumentedTest.java new file mode 100644 index 0000000..00362ce --- /dev/null +++ b/quick_android_custom_view/src/androidTest/java/cn/qjm253/quick_android_custom_view/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package cn.qjm253.quick_android_custom_view; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_custom_view.test", appContext.getPackageName()); + } +} diff --git a/quick_android_custom_view/src/main/AndroidManifest.xml b/quick_android_custom_view/src/main/AndroidManifest.xml new file mode 100644 index 0000000..521a706 --- /dev/null +++ b/quick_android_custom_view/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableButton.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableButton.kt new file mode 100644 index 0000000..00858e4 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableButton.kt @@ -0,0 +1,102 @@ +package cn.qjm253.quick_android_custom_view.custom_drawable_size_view + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatButton +import cn.qjm253.quick_android_custom_view.R + +/** + * 这是一个Button的封装组件,支持自定义四个方向的drawable的大小 + * + * 1. 使用 'left_drawable', 'right_drawable', 'top_drawable', 'bottom_drawable' 属性来设置四个方向的drawable资源 + * + * 2. 使用 'drawable_width', 'drawable_height' 统一设置四个drawable的大小 + * + * 3. 使用 'left_drawable_width', 'left_drawable_height', 'right_drawable_width', 'right_drawable_height', + * 'top_drawable_width', 'top_drawable_height', 'bottom_drawable_width', 'bottom_drawable_height' + * 来定制指定方向drawable的大小 + * + * @author SunnyQjm + * @date 19-7-10 下午9:09 + */ + + +open class DrawableButton @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.buttonStyle +) : AppCompatButton(context, attrs, defStyleAttr) { + companion object { + const val DEFAULT_SIZE = 20 + } + + init { + val ta = context.obtainStyledAttributes(attrs, R.styleable.DrawableButton) + + val width = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_drawable_width, + DEFAULT_SIZE + ) + val height = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_drawable_height, + DEFAULT_SIZE + ) + + val sizeWrap = SizeWrap() + + val letfD = ta.getDrawable(R.styleable.DrawableButton_left_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_left_drawable_width, + DEFAULT_SIZE + ) + val lheight = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_left_drawable_height, + DEFAULT_SIZE + ) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val rightD = ta.getDrawable(R.styleable.DrawableButton_right_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_right_drawable_width, + DEFAULT_SIZE + ) + val lheight = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_right_drawable_height, + DEFAULT_SIZE + ) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val topD = ta.getDrawable(R.styleable.DrawableButton_top_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_top_drawable_width, + DEFAULT_SIZE + ) + val lheight = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_top_drawable_height, + DEFAULT_SIZE + ) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val bottomD = ta.getDrawable(R.styleable.DrawableButton_bottom_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_bottom_drawable_width, + DEFAULT_SIZE + ) + val lheight = ta.getDimensionPixelOffset( + R.styleable.DrawableButton_bottom_drawable_height, + DEFAULT_SIZE + ) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + + this.setCompoundDrawables(letfD, topD, rightD, bottomD) + + ta.recycle() + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableEditText.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableEditText.kt new file mode 100644 index 0000000..49fac98 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableEditText.kt @@ -0,0 +1,75 @@ +package cn.qjm253.quick_android_custom_view.custom_drawable_size_view + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatEditText +import cn.qjm253.quick_android_custom_view.R + +/** + * 这是一个EditText的封装组件,支持自定义四个方向的drawable的大小 + * + * 1. 使用 'left_drawable', 'right_drawable', 'top_drawable', 'bottom_drawable' 属性来设置四个方向的drawable资源 + * + * 2. 使用 'drawable_width', 'drawable_height' 统一设置四个drawable的大小 + * + * 3. 使用 'left_drawable_width', 'left_drawable_height', 'right_drawable_width', 'right_drawable_height', + * 'top_drawable_width', 'top_drawable_height', 'bottom_drawable_width', 'bottom_drawable_height' + * 来定制指定方向drawable的大小 + * + * @author SunnyQjm + * @date 19-7-10 下午9:04 + */ + +open class DrawableEditText @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.editTextStyle +) : AppCompatEditText(context, attrs, defStyleAttr) { + companion object { + const val DEFAULT_SIZE = 20 + } + + init { + val ta = context.obtainStyledAttributes(attrs, R.styleable.DrawableEditText) + + val width = ta.getDimensionPixelOffset(R.styleable.DrawableEditText_drawable_width, DEFAULT_SIZE) + val height = ta.getDimensionPixelOffset(R.styleable.DrawableEditText_drawable_height, DEFAULT_SIZE) + + val sizeWrap = SizeWrap() + + val letfD = ta.getDrawable(R.styleable.DrawableEditText_left_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableEditText_left_drawable_width, DEFAULT_SIZE) + val lheight = + ta.getDimensionPixelOffset(R.styleable.DrawableEditText_left_drawable_height, DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val rightD = ta.getDrawable(R.styleable.DrawableEditText_right_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableEditText_right_drawable_width, DEFAULT_SIZE) + val lheight = + ta.getDimensionPixelOffset(R.styleable.DrawableEditText_right_drawable_height, DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val topD = ta.getDrawable(R.styleable.DrawableEditText_top_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableEditText_top_drawable_width, DEFAULT_SIZE) + val lheight = ta.getDimensionPixelOffset(R.styleable.DrawableEditText_top_drawable_height, DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val bottomD = ta.getDrawable(R.styleable.DrawableEditText_bottom_drawable) + ?.apply { + val lwidth = + ta.getDimensionPixelOffset(R.styleable.DrawableEditText_bottom_drawable_width, DEFAULT_SIZE) + val lheight = + ta.getDimensionPixelOffset(R.styleable.DrawableEditText_bottom_drawable_height, DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + + this.setCompoundDrawables(letfD, topD, rightD, bottomD) + + ta.recycle() + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableTextView.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableTextView.kt new file mode 100644 index 0000000..a6045d5 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/DrawableTextView.kt @@ -0,0 +1,76 @@ +package cn.qjm253.quick_android_custom_view.custom_drawable_size_view + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatTextView +import cn.qjm253.quick_android_custom_view.R + +/** + * 这是一个TextView的封装组件,支持自定义四个方向的drawable的大小 + * + * 1. 使用 'left_drawable', 'right_drawable', 'top_drawable', 'bottom_drawable' 属性来设置四个方向的drawable资源 + * + * 2. 使用 'drawable_width', 'drawable_height' 统一设置四个drawable的大小 + * + * 3. 使用 'left_drawable_width', 'left_drawable_height', 'right_drawable_width', 'right_drawable_height', + * 'top_drawable_width', 'top_drawable_height', 'bottom_drawable_width', 'bottom_drawable_height' + * 来定制指定方向drawable的大小 + * + * @author SunnyQjm + * @date 19-7-10 下午8:48 + */ + +open class DrawableTextView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, + defStyleAttr: Int = android.R.attr.textViewStyle +) : AppCompatTextView(context, attrs, defStyleAttr) { + + companion object { + const val DRAWABLE_DEFAULT_SIZE = 20 + } + + init { + val ta = context.obtainStyledAttributes(attrs, R.styleable.DrawableTextView) + + val width = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_drawable_width, DRAWABLE_DEFAULT_SIZE) + val height = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_drawable_height, DRAWABLE_DEFAULT_SIZE) + + val sizeWrap = SizeWrap() + + val letfD = ta.getDrawable(R.styleable.DrawableTextView_left_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_left_drawable_width, DRAWABLE_DEFAULT_SIZE) + val lheight = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_left_drawable_height, DRAWABLE_DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val rightD = ta.getDrawable(R.styleable.DrawableTextView_right_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_right_drawable_width, DRAWABLE_DEFAULT_SIZE) + val lheight = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_right_drawable_height, DRAWABLE_DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val topD = ta.getDrawable(R.styleable.DrawableTextView_top_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_top_drawable_width, DRAWABLE_DEFAULT_SIZE) + val lheight = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_top_drawable_height, DRAWABLE_DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + val bottomD = ta.getDrawable(R.styleable.DrawableTextView_bottom_drawable) + ?.apply { + val lwidth = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_bottom_drawable_width, DRAWABLE_DEFAULT_SIZE) + val lheight = ta.getDimensionPixelOffset(R.styleable.DrawableTextView_bottom_drawable_height, DRAWABLE_DEFAULT_SIZE) + sizeWrap.checkSize(width, height, lwidth, lheight) + setBounds(0, 0, sizeWrap.width, sizeWrap.height) + } + + this.setCompoundDrawables(letfD, topD, rightD, bottomD) + + ta.recycle() + } + + + +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/SizeWrap.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/SizeWrap.kt new file mode 100644 index 0000000..2cdbd3e --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/custom_drawable_size_view/SizeWrap.kt @@ -0,0 +1,37 @@ +package cn.qjm253.quick_android_custom_view.custom_drawable_size_view + +/** + * 这是一个处理drawable自定义大小设置的工具类 + * + * 1. 四个方向的drawable都有一个默认大小 DRAWABLE_DEFAULT_SIZE; + * + * 2. 使用 'drawable_width' 和 'drawable_height' 来设置全局大小,则四个方向的drawable均被设置; + * + * 3. 如果使用 'left_drawable_width' 和 'left_drawable_height' 这种单独设置某个方向的drawable会覆盖默认大小和全局大小 + * + * @author SunnyQjm + * @date 19-7-10 下午9:00 + */ +class SizeWrap(var width: Int = -1, var height: Int = -1) { + + /** + * 检查用户是否自定义了drawable的size,按上述规则进行判断 + */ + fun checkSize(globalWidth: Int, globalHeight: Int, localWidth: Int, localHeight: Int) { + width = DrawableTextView.DRAWABLE_DEFAULT_SIZE + height = DrawableTextView.DRAWABLE_DEFAULT_SIZE + + // 对某一个具体方向图标大小的设置会覆盖对全局图标大小的设置 + if (localHeight > 0 && localWidth > 0) { + width = localWidth + height = localHeight + } + + + if (localHeight == DrawableTextView.DRAWABLE_DEFAULT_SIZE && localWidth == DrawableTextView.DRAWABLE_DEFAULT_SIZE + && globalHeight > 0 && globalWidth > 0) { + width = globalWidth + height = globalHeight + } + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/ClearAbleEditText.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/ClearAbleEditText.kt new file mode 100644 index 0000000..165d02a --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/ClearAbleEditText.kt @@ -0,0 +1,74 @@ +package cn.qjm253.quick_android_custom_view.other + +import android.content.Context +import android.graphics.drawable.Drawable +import android.text.Editable +import android.text.TextWatcher +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import cn.qjm253.quick_android_custom_view.tin_view.TinEditText + +/** + * 这是一个可以显示清空按钮的EditText组件,right_drawable一般设置成有清空含义的图标 + * + * @author SunnyQjm + * @date 19-7-14 下午8:01 + */ + +class ClearAbleEditText @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.editTextStyle +) : TinEditText(context, attrs, defStyleAttr) { + + + init { + changeDrawables(right = null) + addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + } + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + if (s?.length ?: 0 > 0) { + changeDrawables(right = mDrawables[2]) + } else { + changeDrawables(right = null) + } + } + + }) + } + + override fun onFocusChange(v: View?, hasFocus: Boolean) { + super.onFocusChange(v, hasFocus) + if (!hasFocus || text?.isEmpty() == true) + changeDrawables(right = null) + else + changeDrawables(right = mDrawables[2]) + } + + override fun onTouchEvent(event: MotionEvent?): Boolean { + if (event?.action == MotionEvent.ACTION_UP) { + //getTotalPaddingRight()图标左边缘至控件右边缘的距离 + //getWidth() - getTotalPaddingRight()表示从最左边到图标左边缘的位置 + //getWidth() - getPaddingRight()表示最左边到图标右边缘的位置 + val touchable = event.x > width - totalPaddingRight && event.x < width - paddingRight + + if (touchable) { + this.setText("") + } + } + return super.onTouchEvent(event) + } + + private fun changeDrawables( + left: Drawable? = mDrawables[0], + top: Drawable? = mDrawables[1], + right: Drawable? = mDrawables[2], + bottom: Drawable? = mDrawables[3] + ) { + setCompoundDrawables(left, top, right, bottom) + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenu.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenu.kt new file mode 100644 index 0000000..20e1ea5 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenu.kt @@ -0,0 +1,37 @@ +package cn.qjm253.quick_android_custom_view.other + +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.DrawableRes + + +/** + * @author SunnyQjm + * @date 19-7-14 下午8:13 + */ +interface LineMenu { + fun getLeft_icon(): ImageView? + + fun getRight_icon(): ImageView? + + fun getTv_title(): TextView? + + fun getTv_value(): TextView? + + fun setLeftIcon(@DrawableRes res: Int) + + fun setRightIcon(@DrawableRes res: Int) + + + fun setRightIconVisible(visible: Int) + + fun setLeftIconVisible(visible: Int) + + fun setTitleIconVisible(visible: Int) + + fun setValueIconVisible(visible: Int) + + fun setTitle(title: String) + + fun setValue(value: String) +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuItem.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuItem.kt new file mode 100644 index 0000000..312a091 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuItem.kt @@ -0,0 +1,271 @@ +package cn.qjm253.quick_android_custom_view.other + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import cn.qjm253.quick_android_base.util.GeneratedId +import cn.qjm253.quick_android_custom_view.R + +/** + * 菜单(可以设置图标) + * + * @author SunnyQjm + * @date 19-7-14 下午8:14 + */ + +class LineMenuItem @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, + defStyleAttr: Int = 0) : RelativeLayout(context, attrs, defStyleAttr), LineMenu { + + private var myContext: Context? = null + private var menuTitle: String? = null + private var menuValue: String? = null + private var menuTitleSize: Float = 0.toFloat() + @ColorInt + private var menuTitleColor: Int = 0 + private var menuValueSize: Float = 0.toFloat() + @ColorInt + private var menuValueColor: Int = 0 + @DrawableRes + private var leftResource: Int = 0 + private var rightResource: Int = 0 + + private var isRightIconVisible: Boolean = false + private var isLeftIconVisible: Boolean = false + + private var leftIconSize: Int = 0 + private var rightIconSize: Int = 0 + + private var leftMargin: Int = 0 + private var rightMargin: Int = 0 + private var leftIconTextSpan: Int = 0 + + private var leftIcon: ImageView? = null + private var rightIcon: ImageView? = null + private var tvTitle: TextView? = null + private var tvValue: TextView? = null + + init { + this.myContext = context + getAttr(context, attrs, defStyleAttr) + initView() + } + + private fun getAttr(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + val ta = context.obtainStyledAttributes(attrs, R.styleable.LineMenuItem) + menuTitle = ta.getString(R.styleable.LineMenuItem_menu_title) + menuValue = ta.getString(R.styleable.LineMenuItem_menu_value) + menuTitleSize = px2sp(context, + ta.getDimensionPixelSize(R.styleable.LineMenuItem_menu_title_size, + sp2px(context, DEFAULT_TEXT_SIZE.toFloat())).toFloat()).toFloat() + menuTitleColor = ta.getColor(R.styleable.LineMenuItem_menu_title_color, + resources.getColor(DEFAULT_TITLE_COLOR)) + menuValueSize = px2sp(context, + ta.getDimension(R.styleable.LineMenuItem_menu_value_size, + sp2px(context, DEFAULT_TEXT_SIZE.toFloat()).toFloat())).toFloat() + menuValueColor = ta.getColor(R.styleable.LineMenuItem_menu_value_color, + resources.getColor(DEFAULT_TITLE_COLOR)) + leftResource = ta.getResourceId(R.styleable.LineMenuItem_left_resource, DEFAULT_LEFT_RESOURCE) + rightResource = ta.getResourceId(R.styleable.LineMenuItem_right_resource, DEFAULT_RIGHT_RESOURCE) + leftIconSize = ta.getDimensionPixelSize(R.styleable.LineMenuItem_left_icon_size, + dip2px(context, DEFAULT_LEFT_ICON_SIZE.toFloat())) + rightIconSize = ta.getDimensionPixelSize(R.styleable.LineMenuItem_right_icon_size, + dip2px(context, DEFAULT_RIGHT_ICON_SIZE.toFloat())) + isRightIconVisible = ta + .getBoolean(R.styleable.LineMenuItem_is_right_icon_visible, true) + isLeftIconVisible = ta + .getBoolean(R.styleable.LineMenuItem_is_left_icon_visible, false) + leftMargin = ta.getDimensionPixelSize(R.styleable.LineMenuItem_left_margin, dip2px(context, DEFAULT_MARGIN)) + rightMargin = ta.getDimensionPixelOffset(R.styleable.LineMenuItem_right_margin, dip2px(context, DEFAULT_MARGIN)) + leftIconTextSpan = ta.getDimensionPixelOffset(R.styleable.LineMenuItem_left_icon_text_span, + dip2px(context, DEFAULT_MARGIN)) + ta.recycle() + } + + private fun initView() { + leftIcon = ImageView(myContext) + leftIcon!!.setImageResource(leftResource) + leftIcon!!.scaleType = ImageView.ScaleType.FIT_CENTER + leftIcon!!.setBackgroundResource(R.color.transparent) + val left_icon_param = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + left_icon_param.addRule(CENTER_VERTICAL) + left_icon_param.width = leftIconSize + left_icon_param.height = leftIconSize + left_icon_param.leftMargin = leftMargin + leftIcon!!.layoutParams = left_icon_param + addView(leftIcon, left_icon_param) + if (!isLeftIconVisible) { + leftIcon!!.visibility = View.GONE + } + val left_icon_id = GeneratedId.generateViewId() + leftIcon!!.id = left_icon_id + + tvTitle = TextView(myContext) + tvTitle!!.text = menuTitle + tvTitle!!.setTextColor(menuTitleColor) + tvTitle!!.textSize = menuTitleSize + tvTitle!!.setBackgroundResource(R.color.transparent) + val title_param = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + title_param.addRule(CENTER_VERTICAL) + title_param.leftMargin = leftIconTextSpan + title_param.addRule(RIGHT_OF, left_icon_id) + tvTitle!!.layoutParams = title_param + addView(tvTitle, title_param) + + + rightIcon = ImageView(myContext) + rightIcon!!.setImageResource(rightResource) + rightIcon!!.scaleType = ImageView.ScaleType.FIT_CENTER + rightIcon!!.setBackgroundResource(R.color.transparent) + val right_icon_param = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + right_icon_param.addRule(CENTER_VERTICAL) + right_icon_param.addRule(ALIGN_PARENT_RIGHT) + right_icon_param.width = rightIconSize + right_icon_param.height = rightIconSize + right_icon_param.rightMargin = rightMargin + rightIcon!!.layoutParams = right_icon_param + addView(rightIcon, right_icon_param) + val right_icon_id = GeneratedId.generateViewId() + rightIcon!!.id = right_icon_id + + tvValue = TextView(myContext) + tvValue!!.text = menuValue + tvValue!!.setTextColor(menuValueColor) + tvValue!!.textSize = menuValueSize + tvValue!!.setBackgroundResource(R.color.transparent) + val tv_value_param = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + tv_value_param.addRule(CENTER_VERTICAL) + if (isRightIconVisible) + tv_value_param.addRule(LEFT_OF, right_icon_id) + else + tv_value_param.addRule(ALIGN_PARENT_RIGHT) + tv_value_param.rightMargin = dip2px(myContext!!, DEFAULT_MARGIN) + tvValue!!.layoutParams = tv_value_param + addView(tvValue, tv_value_param) + + if (isRightIconVisible) + setRightIconVisible(View.VISIBLE) + else + setRightIconVisible(View.INVISIBLE) + } + + override fun getLeft_icon(): ImageView? { + return leftIcon + } + + override fun getRight_icon(): ImageView? { + return rightIcon + } + + override fun getTv_title(): TextView? { + return tvTitle + } + + override fun getTv_value(): TextView? { + return tvValue + } + + fun value(): String { + return getTv_value()?.text?.toString() ?: "" + } + + fun title(): String { + return getTv_title()?.text?.toString() ?: "" + } + + override fun setLeftIcon(@DrawableRes res: Int) { + this.post { + leftResource = res + leftIcon!!.setImageResource(leftResource) + } + } + + override fun setRightIcon(@DrawableRes res: Int) { + this.post { + rightResource = res + rightIcon!!.setImageResource(rightResource) + } + } + + override fun setRightIconVisible(visible: Int) { + if (rightIcon != null) + rightIcon!!.visibility = visible + } + + override fun setLeftIconVisible(visible: Int) { + if (leftIcon != null) + leftIcon!!.visibility = visible + } + + override fun setTitleIconVisible(visible: Int) { + if (tvTitle != null) + tvTitle!!.visibility = visible + } + + override fun setValueIconVisible(visible: Int) { + if (tvValue != null) + tvValue!!.visibility = visible + } + + override fun setTitle(title: String) { + if (tvTitle != null) + tvTitle!!.text = title + } + + override fun setValue(value: String) { + if (tvValue != null) + tvValue!!.text = value + } + + companion object { + + private val DEFAULT_TEXT_SIZE = 14 + private val DEFAULT_MARGIN = 13f + + private val DEFAULT_TITLE_COLOR = R.color.text_gray + private val DEFAULT_LEFT_RESOURCE = R.drawable.menu + private val DEFAULT_RIGHT_RESOURCE = R.drawable.icon_arrow + private val DEFAULT_LEFT_ICON_SIZE = 24 + private val DEFAULT_RIGHT_ICON_SIZE = 24 + } + + + /** + * 根据手机的分辨率从 dp 的单位 转成为 px(像素) + */ + fun dip2px(context: Context, dpValue: Float): Int { + val scale = context.resources.displayMetrics.density + return (dpValue * scale + 0.5f).toInt() + } + + /** + * 将px值转换为sp值,保证文字大小不变 + * + * @param pxValue (DisplayMetrics类中属性scaledDensity) + * @return + */ + fun px2sp(context: Context, pxValue: Float): Int { + val fontScale = context.resources.displayMetrics.scaledDensity + return (pxValue / fontScale + 0.5f).toInt() + } + + /** + * 将sp值转换为px值,保证文字大小不变 + * + * @param spValue (DisplayMetrics类中属性scaledDensity) + * @return + */ + fun sp2px(context: Context, spValue: Float): Int { + val fontScale = context.resources.displayMetrics.scaledDensity + return (spValue * fontScale + 0.5f).toInt() + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuSwitch.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuSwitch.kt new file mode 100644 index 0000000..46d6a85 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/LineMenuSwitch.kt @@ -0,0 +1,154 @@ +package cn.qjm253.quick_android_custom_view.other + +import android.widget.CompoundButton +import android.content.Context +import android.widget.RelativeLayout +import android.os.Build +import android.util.AttributeSet +import android.view.ViewGroup +import android.widget.Switch +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import cn.qjm253.quick_android_custom_view.R + + +/** + * @author SunnyQjm + * @date 19-7-14 下午8:30 + */ +class LineMenuSwitch @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr) { + private var menuTitle: String? = null + @ColorInt + private var menuTitleColor: Int = 0 + private var menuTitleSize: Float = 0.toFloat() + + @DrawableRes + private var switchThumb: Int = 0 + @DrawableRes + private var switchTrack: Int = 0 + + private var leftMargin: Int = 0 + private var rightMargin: Int = 0 + + private var tv_title: TextView? = null + private var aSwitch: Switch? = null + private var checked = false + private var onCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null + + init { + getAttr(context, attrs, defStyleAttr) + initView() + } + + private fun initView() { + tv_title = TextView(context) + tv_title!!.text = menuTitle + tv_title!!.setTextColor(menuTitleColor) + tv_title!!.textSize = menuTitleSize + tv_title!!.setBackgroundResource(R.color.transparent) + val title_param = LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + title_param.addRule(CENTER_VERTICAL) + title_param.leftMargin = leftMargin + tv_title!!.layoutParams = title_param + addView(tv_title, title_param) + + aSwitch = Switch(context) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + aSwitch!!.setThumbResource(switchThumb) + aSwitch!!.setTrackResource(switchTrack) + } + val switch_param = LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + switch_param.addRule(ALIGN_PARENT_END) + } + switch_param.addRule(ALIGN_PARENT_RIGHT) + switch_param.addRule(CENTER_VERTICAL) + switch_param.rightMargin = rightMargin + addView(aSwitch, switch_param) + aSwitch!!.isChecked = checked + aSwitch!!.setOnCheckedChangeListener(onCheckedChangeListener) + } + + private fun getAttr(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + val ta = context.obtainStyledAttributes(attrs, R.styleable.LineMenuSwitch) + menuTitle = ta.getString(R.styleable.LineMenuSwitch_menu_title) + menuTitleSize = ta.getFloat(R.styleable.LineMenuSwitch_menu_title_size, DEFAULT_TEXT_SIZE.toFloat()) + menuTitleColor = ta.getColor( + R.styleable.LineMenuSwitch_menu_title_color, + resources.getColor(DEFAULT_TITLE_COLOR) + ) + leftMargin = ta.getDimensionPixelSize( + R.styleable.LineMenuSwitch_left_margin, + dip2px(context, DEFAULT_MARGIN) + ) + rightMargin = ta.getDimensionPixelOffset( + R.styleable.LineMenuSwitch_right_margin, + dip2px(context, DEFAULT_MARGIN) + ) + switchThumb = ta.getResourceId(R.styleable.LineMenuSwitch_switch_thumb, R.drawable.switch_thumb) + switchTrack = ta.getResourceId(R.styleable.LineMenuSwitch_switch_track, R.drawable.switch_track) + ta.recycle() + } + + fun setChecked(checked: Boolean) { + this.checked = checked + if (aSwitch != null) + aSwitch!!.isChecked = checked + } + + fun setOnCheckedChangeListener(onCheckedChangeListener: CompoundButton.OnCheckedChangeListener) { + this.onCheckedChangeListener = onCheckedChangeListener + if (aSwitch != null) + aSwitch!!.setOnCheckedChangeListener(onCheckedChangeListener) + } + + companion object { + + private val DEFAULT_TEXT_SIZE = 14 + private val DEFAULT_MARGIN = 13f + + private val DEFAULT_TITLE_COLOR = R.color.text_gray + } + + + /** + * 根据手机的分辨率从 dp 的单位 转成为 px(像素) + */ + fun dip2px(context: Context, dpValue: Float): Int { + val scale = context.resources.displayMetrics.density + return (dpValue * scale + 0.5f).toInt() + } + + /** + * 将px值转换为sp值,保证文字大小不变 + * + * @param pxValue (DisplayMetrics类中属性scaledDensity) + * @return + */ + fun px2sp(context: Context, pxValue: Float): Int { + val fontScale = context.resources.displayMetrics.scaledDensity + return (pxValue / fontScale + 0.5f).toInt() + } + + /** + * 将sp值转换为px值,保证文字大小不变 + * + * @param spValue (DisplayMetrics类中属性scaledDensity) + * @return + */ + fun sp2px(context: Context, spValue: Float): Int { + val fontScale = context.resources.displayMetrics.scaledDensity + return (spValue * fontScale + 0.5f).toInt() + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/NoneScrollViewPager.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/NoneScrollViewPager.kt new file mode 100644 index 0000000..bfb8e69 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/other/NoneScrollViewPager.kt @@ -0,0 +1,58 @@ +package cn.qjm253.quick_android_custom_view.other + +import android.content.Context +import android.util.AttributeSet +import androidx.viewpager.widget.ViewPager +import android.view.MotionEvent + + + +/** + * @author SunnyQjm + * @date 19-7-14 下午7:52 + */ + +class NoneScrollViewPager(context: Context, attrs: AttributeSet? = null) : ViewPager(context, attrs) { + private var isScroll = false + init { + + } + + /** + * 是否拦截 + * 拦截:会走到自己的onTouchEvent方法里面来 + * 不拦截:事件传递给子孩子 + */ + override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { + // return false;//可行,不拦截事件, + // return true;//不行,孩子无法处理事件 + //return super.onInterceptTouchEvent(ev);//不行,会有细微移动 + return if (isScroll) { + super.onInterceptTouchEvent(ev) + } else { + false + } + } + + /** + * 是否消费事件 + * 消费:事件就结束 + * 不消费:往父控件传 + */ + override fun onTouchEvent(ev: MotionEvent): Boolean { + //return false;// 可行,不消费,传给父控件 + //return true;// 可行,消费,拦截事件 + //super.onTouchEvent(ev); //不行, + //虽然onInterceptTouchEvent中拦截了, + //但是如果viewpage里面子控件不是viewgroup,还是会调用这个方法. + return if (isScroll) { + super.onTouchEvent(ev) + } else { + true// 可行,消费,拦截事件 + } + } + + fun setScroll(scroll: Boolean) { + isScroll = scroll + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinButton.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinButton.kt new file mode 100644 index 0000000..dd1ef02 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinButton.kt @@ -0,0 +1,112 @@ +package cn.qjm253.quick_android_custom_view.tin_view + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.ColorRes +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import cn.qjm253.quick_android_custom_view.R +import cn.qjm253.quick_android_custom_view.custom_drawable_size_view.DrawableButton + +/** + * 这是一个 DrawableButton 的封装组件,在DrawableButton的基础上支持设置drawable的tinColor + * + * @see DrawableButton + * @author SunnyQjm + * @date 19-7-10 下午10:33 + */ +class TinButton @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.buttonStyle +): DrawableButton(context, attrs, defStyleAttr) { + companion object { + const val NONE = 0x0000 + const val LEFT = 0x0001 + const val TOP = 0x0002 + const val RIGHT = 0x0004 + const val BOTTOM = 0x0008 + const val ALL = 0x000f + } + + + private var tints: Int = TinTextView.NONE + private lateinit var mDrawables: Array + + init { + if (!isInEditMode) { + mDrawables = compoundDrawables + loadFromAttribute(context, attrs, defStyleAttr) + } + } + + /** + * 从布局文件中加载属性配置 + */ + private fun loadFromAttribute(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + attrs?.let { + val ta = context.obtainStyledAttributes(it, R.styleable.TinButton) + tints = ta.getInt(R.styleable.TinButton_tints, ALL) + ta.getColorStateList(R.styleable.TinButton_tinColor)?.let { tinColorStateList -> + updateDrawablesTinColor(tinColorStateList) + } + ta.recycle() + } + } + + /** + * 设置哪些方向的drawable需要设置tinColor + * + * @see TinButton.NONE -> 四个方向都不着色 + * @see TinButton.LEFT -> 左边drawable着色 + * @see TinButton.RIGHT -> 右边drawable着色 + * @see TinButton.TOP -> 顶部drawable着色 + * @see TinButton.BOTTOM -> 底部drawable着色 + * @see TinButton.ALL -> 四个方向都着色 + * + * 如果需要单独设置两个方向可以 => TinButton.LEFT or TinButton.RIGHT + * + */ + fun updateTints(tints: Int) { + if (tints < 0 || tints > 8) + return + this.tints = tints + } + + /** + * 设置tinColor的颜色 + */ + private fun updateDrawablesTinColor(colorStateList: ColorStateList) { + //设置icon + if (mDrawables[0] != null && (tints and TinTextView.LEFT) == TinTextView.LEFT) { + mDrawables[0] = DrawableCompat.wrap(mDrawables[0]!!.mutate()) + DrawableCompat.setTintList(mDrawables[0]!!, colorStateList) + } + + if (mDrawables[1] != null && (tints and TinTextView.TOP) == TinTextView.TOP) { + mDrawables[1] = DrawableCompat.wrap(mDrawables[1]!!.mutate()) + DrawableCompat.setTintList(mDrawables[1]!!, colorStateList) + } + + if (mDrawables[2] != null && (tints and TinTextView.RIGHT) == TinTextView.RIGHT) { + mDrawables[2] = DrawableCompat.wrap(mDrawables[2]!!.mutate()) + DrawableCompat.setTintList(mDrawables[2]!!, colorStateList) + } + + if (mDrawables[3] != null && (tints and TinTextView.BOTTOM) == TinTextView.BOTTOM) { + mDrawables[3] = DrawableCompat.wrap(mDrawables[3]!!.mutate()) + DrawableCompat.setTintList(mDrawables[3]!!, colorStateList) + } + setCompoundDrawables(mDrawables[0], mDrawables[1], mDrawables[2], mDrawables[3]) + } + + /** + * 设置tinColor的颜色 + */ + fun updateDrawablesTinColor(@ColorRes color: Int) { + ContextCompat.getColorStateList(context, color)?.let { + updateDrawablesTinColor(it) + } + } + +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinEditText.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinEditText.kt new file mode 100644 index 0000000..2fb7053 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinEditText.kt @@ -0,0 +1,146 @@ +package cn.qjm253.quick_android_custom_view.tin_view + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorRes +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import cn.qjm253.quick_android_custom_view.R +import cn.qjm253.quick_android_custom_view.custom_drawable_size_view.DrawableEditText + +/** + * 这是一个 DrawableEditText 的封装组件,在 DrawableEditText 的基础上支持设置drawable的tinColor + * + * @see DrawableEditText + * @author SunnyQjm + * @date 19-7-10 下午10:15 + */ + +open class TinEditText @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.editTextStyle +) : DrawableEditText(context, attrs, defStyleAttr), View.OnFocusChangeListener { + + + companion object { + const val NONE = 0x0000 + const val LEFT = 0x0001 + const val TOP = 0x0002 + const val RIGHT = 0x0004 + const val BOTTOM = 0x0008 + const val ALL = 0x000f + } + + + private var tints: Int = NONE + + private var tinColor: ColorStateList? = null + private var focusedTinColor: ColorStateList? = null + + protected lateinit var mDrawables: Array + + init { + + if (!isInEditMode) { + mDrawables = compoundDrawables + loadFromAttribute(context, attrs, defStyleAttr) + this.onFocusChangeListener = this + } + } + + /** + * 从布局文件中加载属性配置 + */ + private fun loadFromAttribute(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + attrs?.let { + val ta = context.obtainStyledAttributes(it, R.styleable.TinEditText) + tints = ta.getInt(R.styleable.TinEditText_tints, ALL) + tinColor = ta.getColorStateList(R.styleable.TinEditText_tinColor) + focusedTinColor = ta.getColorStateList(R.styleable.TinEditText_focusedTinColor) + ta.recycle() + } + + // 根绝当前是否聚焦,修改tinColor + onFocusChange(this, isFocused) + } + + /** + * 设置哪些方向的drawable需要设置tinColor + * + * @see TinEditText.NONE -> 四个方向都不着色 + * @see TinEditText.LEFT -> 左边drawable着色 + * @see TinEditText.RIGHT -> 右边drawable着色 + * @see TinEditText.TOP -> 顶部drawable着色 + * @see TinEditText.BOTTOM -> 底部drawable着色 + * @see TinEditText.ALL -> 四个方向都着色 + * + * 如果需要单独设置两个方向可以 => TinEditText.LEFT or TinEditText.RIGHT + * + */ + fun updateTints(tints: Int) { + if (tints < 0 || tints > 8) + return + this.tints = tints + } + + /** + * 设置tinColor的颜色 + */ + private fun updateDrawablesTinColor(colorStateList: ColorStateList?) { + colorStateList?.let { + //设置icon + if (mDrawables[0] != null && (tints and LEFT) == LEFT) { + mDrawables[0] = DrawableCompat.wrap(mDrawables[0]!!.mutate()) + DrawableCompat.setTintList(mDrawables[0]!!, colorStateList) + } + + if (mDrawables[1] != null && (tints and TinTextView.TOP) == TinTextView.TOP) { + mDrawables[1] = DrawableCompat.wrap(mDrawables[1]!!.mutate()) + DrawableCompat.setTintList(mDrawables[1]!!, colorStateList) + } + + if (mDrawables[2] != null && (tints and RIGHT) == RIGHT) { + mDrawables[2] = DrawableCompat.wrap(mDrawables[2]!!.mutate()) + DrawableCompat.setTintList(mDrawables[2]!!, colorStateList) + } + + if (mDrawables[3] != null && (tints and BOTTOM) == BOTTOM) { + mDrawables[3] = DrawableCompat.wrap(mDrawables[3]!!.mutate()) + DrawableCompat.setTintList(mDrawables[3]!!, colorStateList) + } + setCompoundDrawables(mDrawables[0], mDrawables[1], mDrawables[2], mDrawables[3]) + } + } + + + /** + * 设置tinColor的颜色 + */ + fun updateDrawablesTinColor(@ColorRes color: Int) { + this.tinColor = ContextCompat.getColorStateList(context, color) + onFocusChange(this, isFocused) + } + + + /** + * 更新聚焦状态下 drawable 的颜色 + */ + fun updateDrawablesFocusedTinColor(@ColorRes color: Int) { + this.focusedTinColor = ContextCompat.getColorStateList(context, color) + onFocusChange(this, isFocused) + } + + + /** + * 处理EditText焦点变化的时候修改 drawable 的 tinColor + */ + override fun onFocusChange(v: View?, hasFocus: Boolean) { + if (hasFocus) { + updateDrawablesTinColor(focusedTinColor) + } else { + updateDrawablesTinColor(tinColor) + } + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinImageView.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinImageView.kt new file mode 100644 index 0000000..6bd69b2 --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinImageView.kt @@ -0,0 +1,65 @@ +package cn.qjm253.quick_android_custom_view.tin_view + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.ColorRes +import androidx.appcompat.widget.AppCompatImageView +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import cn.qjm253.quick_android_custom_view.R + +/** + * 这是一个 DrawableButton 的封装组件,在AppCompatImageView的基础上支持设置drawable的tinColor + * + * @author SunnyQjm + * @date 19-7-11 下午4:46 + */ + +class TinImageView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : AppCompatImageView(context, attrs, defStyleAttr) { + + private var mDrawable: Drawable? = drawable + + init { + loadFromAttribute(context, attrs, defStyleAttr) + } + + /** + * 从布局文件中加载属性配置 + */ + private fun loadFromAttribute(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + attrs?.let { + val ta = context.obtainStyledAttributes(it, R.styleable.TinImageView) + ta.getColorStateList(R.styleable.TinImageView_tinColor)?.let { tinColorStateList -> + updateDrawablesTinColor(tinColorStateList) + } + ta.recycle() + } + } + + /** + * 设置tinColor的颜色 + */ + fun updateDrawablesTinColor(@ColorRes color: Int) { + updateDrawablesTinColor(ContextCompat.getColorStateList(context, color)) + } + + /** + * 设置tinColor的颜色 + */ + private fun updateDrawablesTinColor(colorStateList: ColorStateList?) { + if (mDrawable == null) { + mDrawable = drawable + } + colorStateList?.let { + mDrawable?.let { _mDrawable -> + mDrawable = DrawableCompat.wrap(_mDrawable.mutate()) + DrawableCompat.setTintList(mDrawable!!, colorStateList) + setImageDrawable(mDrawable) + } + } + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinTextView.kt b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinTextView.kt new file mode 100644 index 0000000..57fa80d --- /dev/null +++ b/quick_android_custom_view/src/main/java/cn/qjm253/quick_android_custom_view/tin_view/TinTextView.kt @@ -0,0 +1,114 @@ +package cn.qjm253.quick_android_custom_view.tin_view + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.ColorRes +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import cn.qjm253.quick_android_custom_view.R +import cn.qjm253.quick_android_custom_view.custom_drawable_size_view.DrawableTextView + +/** + * 这是一个 DrawableTextView 的封装组件,在DrawableTextView的基础上支持设置drawable的tinColor + * + * @see DrawableTextView + * @author SunnyQjm + * @date 19-7-10 下午9:12 + */ + +class TinTextView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.textViewStyle +) : DrawableTextView(context, attrs, defStyleAttr) { + companion object { + const val NONE = 0x0000 + const val LEFT = 0x0001 + const val TOP = 0x0002 + const val RIGHT = 0x0004 + const val BOTTOM = 0x0008 + const val ALL = 0x000f + } + + + private var tints: Int = NONE + private lateinit var mDrawables: Array + + init { + if (!isInEditMode) { + mDrawables = compoundDrawables + loadFromAttribute(context, attrs, defStyleAttr) + } + } + + /** + * 从布局文件中加载属性配置 + */ + private fun loadFromAttribute(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + attrs?.let { + val ta = context.obtainStyledAttributes(it, R.styleable.TinTextView) + tints = ta.getInt(R.styleable.TinTextView_tints, ALL) + ta.getColorStateList(R.styleable.TinTextView_tinColor)?.let { tinColorStateList -> + updateDrawablesTinColor(tinColorStateList) + } + ta.recycle() + } + } + + + /** + * 设置哪些方向的drawable需要设置tinColor + * + * @see TinTextView.NONE -> 四个方向都不着色 + * @see TinTextView.LEFT -> 左边drawable着色 + * @see TinTextView.RIGHT -> 右边drawable着色 + * @see TinTextView.TOP -> 顶部drawable着色 + * @see TinTextView.BOTTOM -> 底部drawable着色 + * @see TinTextView.ALL -> 四个方向都着色 + * + * 如果需要单独设置两个方向可以 => TinTextView.LEFT or TinTextView.RIGHT + * + */ + fun updateTints(tints: Int) { + if (tints < 0 || tints > 8) + return + this.tints = tints + } + + /** + * 设置tinColor的颜色 + */ + private fun updateDrawablesTinColor(colorStateList: ColorStateList) { + //设置icon + if (mDrawables[0] != null && (tints and LEFT) == LEFT) { + mDrawables[0] = DrawableCompat.wrap(mDrawables[0]!!.mutate()) + DrawableCompat.setTintList(mDrawables[0]!!, colorStateList) + } + + if (mDrawables[1] != null && (tints and TOP) == TOP) { + mDrawables[1] = DrawableCompat.wrap(mDrawables[1]!!.mutate()) + DrawableCompat.setTintList(mDrawables[1]!!, colorStateList) + } + + if (mDrawables[2] != null && (tints and RIGHT) == RIGHT) { + mDrawables[2] = DrawableCompat.wrap(mDrawables[2]!!.mutate()) + DrawableCompat.setTintList(mDrawables[2]!!, colorStateList) + } + + if (mDrawables[3] != null && (tints and BOTTOM) == BOTTOM) { + mDrawables[3] = DrawableCompat.wrap(mDrawables[3]!!.mutate()) + DrawableCompat.setTintList(mDrawables[3]!!, colorStateList) + } + setCompoundDrawables(mDrawables[0], mDrawables[1], mDrawables[2], mDrawables[3]) + } + + + /** + * 设置tinColor的颜色 + */ + fun updateDrawablesTinColor(@ColorRes color: Int) { + ContextCompat.getColorStateList(context, color)?.let { + updateDrawablesTinColor(it) + } + } +} \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/drawable/blue_thumb.xml b/quick_android_custom_view/src/main/res/drawable/blue_thumb.xml new file mode 100644 index 0000000..8a37987 --- /dev/null +++ b/quick_android_custom_view/src/main/res/drawable/blue_thumb.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/drawable/blue_track.xml b/quick_android_custom_view/src/main/res/drawable/blue_track.xml new file mode 100644 index 0000000..7111385 --- /dev/null +++ b/quick_android_custom_view/src/main/res/drawable/blue_track.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/drawable/gray_thumb.xml b/quick_android_custom_view/src/main/res/drawable/gray_thumb.xml new file mode 100644 index 0000000..872df99 --- /dev/null +++ b/quick_android_custom_view/src/main/res/drawable/gray_thumb.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/drawable/gray_track.xml b/quick_android_custom_view/src/main/res/drawable/gray_track.xml new file mode 100644 index 0000000..ade52a6 --- /dev/null +++ b/quick_android_custom_view/src/main/res/drawable/gray_track.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/drawable/icon_arrow.png b/quick_android_custom_view/src/main/res/drawable/icon_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..d6d292420ab7a61fb4fece7f7ab852fcf76263ac GIT binary patch literal 992 zcmV<610Vc}P)OZ{*zCLgEWWI@p7medW4R}9y7{{MjE19-I%5w{T z?I5QAO&7x8d&#nMB5fI7mL9hgzjPGWMd?Zy8D6(y9$u6=Z7t5?LzVWlE`^ay8^d2% zgXMT#%5xizbQju%=~@_(HX%K2y_DxmB5^w=y9@1nY7hnoC8K)fxk57T6n3eoJWG!i z|HVOU!n-&s<@uV*MvhuCtjB)oX=fzE?v{&Sj%478?m`Q-34^`ZEKdYOB5eqNNO^Yp zz+R&;*eBBF;Ta6da61?8>u|WOsfW#E58e=QlUOM|?P*-wRZz8NSdaZO++HouoXch8 zIE@eFawtme!r(i3#=HiP<6gWf7r}1Xu@$2qguz!*p1cP%30o+c)q58(iO)&~&@Vj<7T{S~YcG?X z*$!C+6{BB--Gt|4$+$vp#tC^<{UB_Kj1$ASLpB#%WuQG!I+)sf*Z`g|E$gV1 z;kXWDQFn$d!Shmv%cW;cOno|$MZLln<0=1c@SCST`#OxP%931!M@_G*kH}JSLg5B~ zA!^I80l5v=$ZdE`7Ka;EAd9+$4al4|gnOjHZyWVuq8kC;Z8y%{XMYqBh<6#*cR!Pr#TY6TNvgl6O zfQ$~qvOztD_hf>vRul=B(qM+=rD$F3dJxhloGZYkBO|aviKX<2R&;hrG!0* z`=tzbi>$sW!+%mr*kKX$x!j0f6gs!jXfzs)Mx)VaG#ZUYqtR$w27d#(_P-l+#@<2z O0000 zh;1;K*rYW{hY&xe0s^FRkwWdX+Yq;9aqOh3-2j!?XuC3OH(WBD_`K5z_2f1_=X|y^ zk*M}hf6se+&ij71_an~mAJ6dkQ6r$10cSV^wGueP6QDK;F8C6-@Yb;v4chc}A=)XZ z1M$I3ULJgFSKI6Jk-ZC=fYn<^J7}7NB=i!&KKp6De%s+)fqzv)L|Ftx$4_*KX?_DD zmyujjhT+JJ=#N|-FR`8;k z5kft~sv*IZfJi+3HIjdE3$BduxY6pnq!hlA;H%99R|2AmbU(mNWd!IBC07{%{q16) zTks+f5`P77h0~lM^jvXh=OypCJMkI9oq%}y6_A&!DpbLlMAwx8-~IwtC3pyKO?@%+ zc+=65CkWnTYe(c=Q}cAHlAu69=I%R67ZFcF}=Yn zhi%sRSuqi8OZA8UaEgu_#M9)D?RFwTfOsk$YQxjaJNfvz6411HWG9I&wl!TU_ySmg z1b}xZ`$7*aOah*1j5Hq^`47nYQVxnpPpZG|w~lj)MS?H(EQxQG#z`#M*EXkoi?N?u z25f!w@NthOv5JE)2=0)&rX#UuN|GQloxC7?7Ix6IBXU6!0I)aN7kWr#MZxCb`eyJs zkk`(gsBt{i7hbVAO91#qsxN%6lk=we^-7|5DFCmMs0`{g(i&x05$bb{rZA{cXV#u=a*=Z{C+1C9%eSO~>z( z{oy-`$JcHfUz(rES;yo~hZW?pRDbvuw=$}D4gh2T!Xr)w1o#1o3+?s+*8kRphu4#P zmEc$Hb;&@oFT4eyoD6=5M7x9Sy-6{zMgO|#>Iq0>tS#%;-4vBGu8DS8SFrJaH#%x0 z;E9}=ch*DO>lnPqi%H10Rf4yCcFllDBE6HK?PjH%z-O@{Q%n55b2`7wsbX0b5=4-7 z+BL!o{(|uJ*ufc9zg!8}H{8BlO|@7w7{&&Rx31dVP%%#LdiicHLS8}?t-e756?ak{>fB>b6Rlf&xp zTykaj#&T-@bX`grpcL%?0c0(CW@kEwKMi`#M6&8-DZK*9Mnn}=5l z_(K3*A*W1}gA)UxQMce!#>*yPd|bT8^OK>xW-9jumYt=KTzU~FRUEP~k%N=xa5{gn zNoXoE9#fmz5Nv!y1zT|mM8?vsF!5`U>j^ZJX)Ghe{pVBvT}umdcCyh#W}`rQ39cX%0HzHn7tYY22ox&sFV|NEugRK;@pi&G?94(z;>HP*rkQ;gfKOGaBaXb^2^Xg3ETfwqWE4e}U?Q044*FKBfE5U^`8t9T5Fa`k5d=}9wJqdT-2r{CB|8+KY!c>^ zbM%Nzfwayb4nL^}IQLFK@V*iBoi{%O#7j3u=A$n#n*oW*W)t~?r#mZxL)}52!!8hr zjD56%GJR|=dHA;x^qpHHK!E}G5~yWBtprLoM{9GyJTymZlVEKXs4atwVju7Zhz^A% zRUINU3dh!c2TrUq^X7!QunJO+8Lj@6DoB-mz#b6aR8gjkDS9OJN>Y}6n#(F*mZ;be z$ZOrLe%rQLu?|-PBJs?RNH{-KQ1PmO5jkK4{Vl~JkwoTA!m-s=js>fQahK7m|4K#3 zl>qAs>{vcKMndUyox>^dx~*Gob{ii;7Itd<%XM0V^10+0^+7QT5P3pQf1eZI$UMs5v3gE%G zoLz@(uTXl*X^vQDb5ize)cW0Cl|@D;S5uq$IlvoLNw6+h2pJYIf_l%RDvg(l2vBus zvEk;S<`!GXr}|qXU~zxH>b + + + + diff --git a/quick_android_custom_view/src/main/res/drawable/switch_track.xml b/quick_android_custom_view/src/main/res/drawable/switch_track.xml new file mode 100644 index 0000000..9453a17 --- /dev/null +++ b/quick_android_custom_view/src/main/res/drawable/switch_track.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/values/custom_drawable_size_view.xml b/quick_android_custom_view/src/main/res/values/custom_drawable_size_view.xml new file mode 100644 index 0000000..0e4145b --- /dev/null +++ b/quick_android_custom_view/src/main/res/values/custom_drawable_size_view.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/values/line_menu.xml b/quick_android_custom_view/src/main/res/values/line_menu.xml new file mode 100644 index 0000000..7e3db22 --- /dev/null +++ b/quick_android_custom_view/src/main/res/values/line_menu.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/values/quick_android_custom_view_color.xml b/quick_android_custom_view/src/main/res/values/quick_android_custom_view_color.xml new file mode 100644 index 0000000..f93779b --- /dev/null +++ b/quick_android_custom_view/src/main/res/values/quick_android_custom_view_color.xml @@ -0,0 +1,13 @@ + + + #161923 + #eee + #bbb + #fff + #00ffffff + #333333 + #000 + #f00 + + #dddddd + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/values/quick_android_custom_view_dimen.xml b/quick_android_custom_view/src/main/res/values/quick_android_custom_view_dimen.xml new file mode 100644 index 0000000..e73e92e --- /dev/null +++ b/quick_android_custom_view/src/main/res/values/quick_android_custom_view_dimen.xml @@ -0,0 +1,6 @@ + + + 26dp + 13dp + 35dp + \ No newline at end of file diff --git a/quick_android_custom_view/src/main/res/values/strings.xml b/quick_android_custom_view/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_custom_view/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_custom_view/src/main/res/values/tin_view.xml b/quick_android_custom_view/src/main/res/values/tin_view.xml new file mode 100644 index 0000000..82b4828 --- /dev/null +++ b/quick_android_custom_view/src/main/res/values/tin_view.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_custom_view/src/test/java/cn/qjm253/quick_android_custom_view/ExampleUnitTest.java b/quick_android_custom_view/src/test/java/cn/qjm253/quick_android_custom_view/ExampleUnitTest.java new file mode 100644 index 0000000..0f21fc1 --- /dev/null +++ b/quick_android_custom_view/src/test/java/cn/qjm253/quick_android_custom_view/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_custom_view; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/quick_android_easy_bar/.gitignore b/quick_android_easy_bar/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_easy_bar/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_easy_bar/build.gradle b/quick_android_easy_bar/build.gradle new file mode 100644 index 0000000..4c207f8 --- /dev/null +++ b/quick_android_easy_bar/build.gradle @@ -0,0 +1,38 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles 'consumer-rules.pro' + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "androidx.appcompat:appcompat:${appcompact_version}" + implementation "androidx.core:core-ktx:${core_ktx_version}" + testImplementation "junit:junit:${junit_version}" + + implementation project(path: ':quick_android_base') + implementation project(path: ':quick_android_custom_view') + + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/quick_android_easy_bar/consumer-rules.pro b/quick_android_easy_bar/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/quick_android_easy_bar/proguard-rules.pro b/quick_android_easy_bar/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/quick_android_easy_bar/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/quick_android_easy_bar/src/androidTest/java/cn/qjm253/quick_android_easy_bar/ExampleInstrumentedTest.kt b/quick_android_easy_bar/src/androidTest/java/cn/qjm253/quick_android_easy_bar/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..e54a232 --- /dev/null +++ b/quick_android_easy_bar/src/androidTest/java/cn/qjm253/quick_android_easy_bar/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package cn.qjm253.quick_android_easy_bar + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("cn.qjm253.quick_android_easy_bar.test", appContext.packageName) + } +} diff --git a/quick_android_easy_bar/src/main/AndroidManifest.xml b/quick_android_easy_bar/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6a731b4 --- /dev/null +++ b/quick_android_easy_bar/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBar.kt b/quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBar.kt new file mode 100644 index 0000000..4ea1087 --- /dev/null +++ b/quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBar.kt @@ -0,0 +1,354 @@ +package cn.qjm253.quick_android_easy_bar + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import android.os.Build +import android.text.TextUtils +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import cn.qjm253.quick_android_base.util.DisplayUtils +import cn.qjm253.quick_android_custom_view.tin_view.TinImageView + + +/** + * Created by Sunny on 2017/8/17 0017. + */ + +class EasyBar @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr) { + private var title: String? = null + @Dimension + private var titleSize: Int = 0 + @ColorInt + private var titleColor: Int = 0 + @DrawableRes + private var leftIcon: Int = 0 + @DrawableRes + private var rightIcon: Int = 0 + @Dimension + private var iconSize: Int = 0 + @Dimension + private var iconMargin: Int = 0 + + private var leftText: String = "" + private var rightText: String = "" + private var displayMode: Mode = Mode.TEXT + + + private lateinit var imgLeft: TinImageView + private lateinit var imgRight: TinImageView + private lateinit var tvTitle: TextView + private lateinit var tvLeftText: TextView + private lateinit var tvRightText: TextView + private var mListener: OnEasyBarClickListener? = null + + init { + initAttr(context, attrs) + initView(context) + } + + @SuppressLint("ObsoleteSdkInt") + private fun initView(context: Context) { + + //left icon + imgLeft = TinImageView(context) + imgLeft.setImageResource(leftIcon) + imgLeft.scaleType = ImageView.ScaleType.FIT_CENTER + val imgLeftParam = RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + imgLeftParam.addRule(RelativeLayout.CENTER_VERTICAL) + imgLeftParam.addRule(RelativeLayout.ALIGN_PARENT_LEFT) + imgLeftParam.width = iconSize + imgLeftParam.height = iconSize + imgLeft.layoutParams = imgLeftParam + imgLeft.setPadding(iconMargin, iconMargin, iconMargin, iconMargin) + addView(imgLeft, imgLeftParam) + + imgLeft.setOnClickListener { v -> + mListener?.onLeftIconClick(v) + } + + //center title + tvTitle = TextView(context) + tvTitle.ellipsize = TextUtils.TruncateAt.END + tvTitle.setSingleLine() + tvTitle.text = title + tvTitle.textSize = titleSize.toFloat() + tvTitle.setTextColor(titleColor) + val tvTitleParam = RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + val titleMargin = iconSize + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + tvTitleParam.marginStart = titleMargin + tvTitleParam.marginEnd = titleMargin + } else { + tvTitleParam.leftMargin = titleMargin + tvTitleParam.rightMargin = titleMargin + } + tvTitleParam.addRule(RelativeLayout.CENTER_IN_PARENT) + tvTitle.layoutParams = tvTitleParam + addView(tvTitle, tvTitleParam) + + //left text + tvLeftText = TextView(context) + tvLeftText.textSize = titleSize.toFloat() + tvLeftText.setTextColor(titleColor) + val tvLeftTextParam = RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + tvLeftTextParam.addRule(RelativeLayout.ALIGN_PARENT_LEFT) + tvLeftTextParam.addRule(RelativeLayout.CENTER_VERTICAL) + tvLeftTextParam.leftMargin = iconMargin + tvLeftText.layoutParams = tvLeftTextParam + addView(tvLeftText) + tvLeftText.text = leftText + tvLeftText.visibility = View.INVISIBLE + tvLeftText.setOnClickListener { v -> + mListener?.onLeftIconClick(v) + } + + + //right text + tvRightText = TextView(context) + tvRightText.textSize = titleSize.toFloat() + tvRightText.setTextColor(titleColor) + val tvRightTextParam = RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + tvRightTextParam.addRule(RelativeLayout.ALIGN_PARENT_RIGHT) + tvRightTextParam.addRule(RelativeLayout.CENTER_VERTICAL) + tvRightTextParam.rightMargin = iconMargin + tvRightText.layoutParams = tvRightTextParam + addView(tvRightText) + tvRightText.text = rightText + tvRightText.visibility = View.INVISIBLE + tvRightText.setOnClickListener { v -> + mListener?.onRightIconClick(v) + } + + //right icon + imgRight = TinImageView(context) + imgRight.setImageResource(rightIcon) + imgRight.scaleType = ImageView.ScaleType.FIT_CENTER + val imgRightParam = RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + imgRightParam.addRule(RelativeLayout.CENTER_VERTICAL) + imgRightParam.addRule(RelativeLayout.ALIGN_PARENT_RIGHT) + imgRightParam.width = iconSize + imgRightParam.height = iconSize + imgRight.layoutParams = imgRightParam + imgRight.setPadding(iconMargin, iconMargin, iconMargin, iconMargin) + addView(imgRight, imgRightParam) + + imgRight.visibility = View.INVISIBLE + imgRight.setOnClickListener { v -> + mListener?.onRightIconClick(v) + } + + setDisplayMode(displayMode) + } + + private fun initAttr(context: Context, attrs: AttributeSet?) { + val ta = context.obtainStyledAttributes(attrs, R.styleable.EasyBar) + title = ta.getString(R.styleable.EasyBar_title) + titleSize = DisplayUtils.px2sp( + context, + ta.getDimensionPixelSize( + R.styleable.EasyBar_title_size, + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + 14f, + resources.displayMetrics + ).toInt() + ).toFloat() + ) + titleColor = + ta.getColor(R.styleable.EasyBar_title_color, resources.getColor(R.color.text_gray)) + leftIcon = ta.getResourceId(R.styleable.EasyBar_left_icon, R.drawable.back) +// rightIcon = ta.getResourceId(R.styleable.EasyBar_right_icon, R.drawable.back) + iconSize = ta.getDimensionPixelSize( + R.styleable.EasyBar_icon_size, + DisplayUtils.dip2px(context, 24f) + ) + iconMargin = ta.getDimensionPixelOffset( + R.styleable.EasyBar_icon_margin, + DisplayUtils.dip2px(context, 12f) + ) + leftText = ta.getString(R.styleable.EasyBar_left_text).toString() + rightText = ta.getString(R.styleable.EasyBar_right_text).toString() + val mode = ta.getInt(R.styleable.EasyBar_displayMode, 0) + displayMode = when (mode) { + 0 -> Mode.ICON + 1 -> Mode.TEXT + else -> Mode.ICON + } + ta.recycle() + } + + fun setTitle(title: String) { + this.title = title + tvTitle.text = title + } + + fun setTitle(@StringRes titleRes: Int) { + this.title = context.getString(titleRes) + tvTitle.setText(titleRes) + } + + fun setLeftText(text: String) { + this.leftText = text + tvLeftText.text = text + } + + fun setRightText(text: String) { + this.rightText = text + tvRightText.text = text + } + + fun setOnEasyBarClickListener(listener: OnEasyBarClickListener) { + this.mListener = listener + } + + + fun setRightIcon(drawable: Drawable) { + imgRight.setImageDrawable(drawable) + } + + fun setRightIcon(bitmap: Bitmap) { + imgRight.setImageBitmap(bitmap) + } + + fun setRightIcon(@DrawableRes res: Int) { + imgRight.setImageResource(res) + } + + fun getRightIcon(): TinImageView? { + return imgRight + } + + fun getRightText(): String? { + return tvRightText.text.toString() + } + + fun setLeftIcon(drawable: Drawable) { + imgLeft.setImageDrawable(drawable) + } + + fun setLeftIcon(bitmap: Bitmap) { + imgLeft.setImageBitmap(bitmap) + } + + fun setLeftIcon(@DrawableRes res: Int) { + imgLeft.setImageResource(res) + println("drawable: ${imgLeft.drawable}") + println("drawable state: ${imgLeft.drawableState}") + println("drawing time: ${imgLeft.drawingTime}") + } + + fun getLeftIcon(): TinImageView? { + return imgLeft + } + + interface OnEasyBarClickListener { + /** + * 如果是图标模式,则响应左图标点击,否则响应左文字点击 + * + * @param view + */ + fun onLeftIconClick(view: View) + + /** + * 如果是图标模式,则响应右图标点击,否则响应右文字点击 + * + * @param view + */ + fun onRightIconClick(view: View) + } + + + enum class Mode { + ICON, TEXT, ICON_TEXT, TEXT_ICON, ICON_, TEXT_, _ICON, _TEXT, NONE + } + + fun setDisplayMode(mode: Mode?) { + when (mode) { + Mode.ICON -> { + tvLeftText.visibility = View.INVISIBLE + tvRightText.visibility = View.INVISIBLE + imgLeft.visibility = View.VISIBLE + imgRight.visibility = View.VISIBLE + + } + Mode.TEXT -> { + tvLeftText.visibility = View.VISIBLE + tvRightText.visibility = View.VISIBLE + imgLeft.visibility = View.INVISIBLE + imgRight.visibility = View.INVISIBLE + } + Mode.ICON_TEXT -> { + tvLeftText.visibility = View.INVISIBLE + tvRightText.visibility = View.VISIBLE + imgLeft.visibility = View.VISIBLE + imgRight.visibility = View.INVISIBLE + } + Mode.TEXT_ICON -> { + tvLeftText.visibility = View.VISIBLE + tvRightText.visibility = View.INVISIBLE + imgLeft.visibility = View.INVISIBLE + imgRight.visibility = View.VISIBLE + } + Mode.TEXT_ -> { + tvLeftText.visibility = View.VISIBLE + tvRightText.visibility = View.INVISIBLE + imgLeft.visibility = View.INVISIBLE + imgRight.visibility = View.INVISIBLE + } + Mode.ICON_ -> { + tvLeftText.visibility = View.INVISIBLE + tvRightText.visibility = View.INVISIBLE + imgLeft.visibility = View.VISIBLE + imgRight.visibility = View.INVISIBLE + } + Mode._ICON -> { + tvLeftText.visibility = View.INVISIBLE + tvRightText.visibility = View.INVISIBLE + imgLeft.visibility = View.INVISIBLE + imgRight.visibility = View.VISIBLE + } + Mode._TEXT -> { + tvLeftText.visibility = View.INVISIBLE + tvRightText.visibility = View.VISIBLE + imgLeft.visibility = View.INVISIBLE + imgRight.visibility = View.INVISIBLE + } + Mode.NONE -> { + tvLeftText.visibility = View.INVISIBLE + tvRightText.visibility = View.INVISIBLE + imgLeft.visibility = View.INVISIBLE + imgRight.visibility = View.INVISIBLE + } + } + } +} diff --git a/quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBarExtensions.kt b/quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBarExtensions.kt new file mode 100644 index 0000000..a1bd07a --- /dev/null +++ b/quick_android_easy_bar/src/main/java/cn/qjm253/quick_android_easy_bar/EasyBarExtensions.kt @@ -0,0 +1,89 @@ +package cn.qjm253.quick_android_easy_bar + + +import android.annotation.SuppressLint +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes + +/** + * Created by sunny on 18-1-25. + */ + +class EasyBarParams( + val mode: EasyBar.Mode = EasyBar.Mode.ICON_, + val title: String = "", + val leftCallback: (v: View) -> Unit = {}, + val rightCallback: (v: View) -> Unit = { + println("empty right") + }, @DrawableRes val leftRes: Int = R.drawable.back, + @DrawableRes val rightRes: Int = 0, + val leftText: String = "", + val rightText: String = "", @StringRes val titleRes: Int = -1, + val isCoverCallback: Boolean = true, + @ColorRes + val tinColor: Int = -1 +) { +} + +fun EasyBar.init(easyBarParams: EasyBarParams) { + init( + easyBarParams.mode, + easyBarParams.title, + easyBarParams.leftCallback, + easyBarParams.rightCallback, + easyBarParams.leftRes, + easyBarParams.rightRes, + easyBarParams.leftText, + easyBarParams.rightText, + easyBarParams.titleRes, + easyBarParams.isCoverCallback, + easyBarParams.tinColor + ) +} + +/** + * 标题栏初始化 + */ +@SuppressLint("ResourceType") +fun EasyBar.init( + mode: EasyBar.Mode = EasyBar.Mode.ICON_, + title: String = "", + leftCallback: (v: View) -> Unit = {}, + rightCallback: (v: View) -> Unit = { + println("empty right") + }, @DrawableRes leftRes: Int = R.drawable.back, + @DrawableRes rightRes: Int = 0, + leftText: String = "", + rightText: String = "", @StringRes titleRes: Int = -1, + isCoverCallback: Boolean = true, + @ColorRes tinColor: Int = -1 + +) { + this.setDisplayMode(mode) + if (titleRes > 0) + this.setTitle(titleRes) + else + this.setTitle(title) + this.setRightIcon(rightRes) + this.setLeftText(leftText) + this.setRightText(rightText) + this.setLeftIcon(leftRes) + if (tinColor > 0) { + this.getLeftIcon()?.updateDrawablesTinColor(tinColor) + this.getRightIcon()?.updateDrawablesTinColor(tinColor) + } + if (isCoverCallback) + this.setOnEasyBarClickListener(object : EasyBar.OnEasyBarClickListener { + override fun onLeftIconClick(view: View) { + leftCallback(view) + } + + override fun onRightIconClick(view: View) { + rightCallback.invoke(view) + } + + }) +} \ No newline at end of file diff --git a/quick_android_easy_bar/src/main/res/drawable/back.png b/quick_android_easy_bar/src/main/res/drawable/back.png new file mode 100644 index 0000000000000000000000000000000000000000..cab12e2c740bbe0ef5947e7408932e7cfe8222db GIT binary patch literal 752 zcmV z1*H^H%0kFOsgF*5r%q3g)ji*PzT@7zzvnsc*FE>nbI&tG#}9VAA3Z?70y-|x-vS+9 z0Q2J^C}|0R zq@4iHWTE%$%Kz|+4+9`+H-OVw=mU%Y<{2LXK+;|S`QP?O7XQ^dzB+)U2>>Uu&?grE zrH%Ni0FovF9LqwVTKwm>;;R8jItbuM7W&NMKeQQN1whha0Ee>B7Z(4%?f6;%X^Ahk z*jE<+u10(m06YhzimQ#zpOcrE~vmI8R0P3{)S(WaC2IKMc6qy+$Or%gf8i2JnxsVUO z9L@tE?ct}r{B*1)nKm@T9v%Q``KQ|;9s5Y03|sH9D?IQ^PI~cKLGo=>1dkOk0^mM? zWfnb4a!qFdQmCYr0PbedGbG0%A{1W%bCE;73Wr2+1F)4axcd_h!4+UWAh-iWM`#5g zGD2$rQ4v}Nh=|ZSKs1CZ0Fe-?0YpKl3J?LIIzVlN5CAn1!T{7l2nA3BAsj&42q6L5 zLX_<0W^NLIVszI7@O@rvMCLqy1aWG|5k$11K3hI9B*uz%xFL-2-?FM<2gm i0nx9J_xw7)0{#NZ(FaghNsuW30000 + + #333333 + \ No newline at end of file diff --git a/quick_android_easy_bar/src/main/res/values/quick_android_easy_bar_attrs.xml b/quick_android_easy_bar/src/main/res/values/quick_android_easy_bar_attrs.xml new file mode 100644 index 0000000..8268eda --- /dev/null +++ b/quick_android_easy_bar/src/main/res/values/quick_android_easy_bar_attrs.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_easy_bar/src/main/res/values/strings.xml b/quick_android_easy_bar/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_easy_bar/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_easy_bar/src/test/java/cn/qjm253/quick_android_easy_bar/ExampleUnitTest.kt b/quick_android_easy_bar/src/test/java/cn/qjm253/quick_android_easy_bar/ExampleUnitTest.kt new file mode 100644 index 0000000..3d28083 --- /dev/null +++ b/quick_android_easy_bar/src/test/java/cn/qjm253/quick_android_easy_bar/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_easy_bar + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/quick_android_file_picker/.gitignore b/quick_android_file_picker/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_file_picker/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_file_picker/README.md b/quick_android_file_picker/README.md new file mode 100644 index 0000000..332d2ff --- /dev/null +++ b/quick_android_file_picker/README.md @@ -0,0 +1,67 @@ +> ## quick_android_file_picker 模块说明文档 +> +> 本模块简单封装了打开系统的文件管理器选择文件的功能,并返回文件的原始Uri以及经过处理后文件的绝对路径。 +> +> 通过RxJava用简单的链式调用即可获得选择文件的结果 + +- 返回数据结构 + + ```kotlin + data class FilePickerResult ( + val path: String, // 文件的绝对路径 + val uri: Uri // 文件的Uri + ) + ``` + +- ### 使用示例 + + - 本接口需要读取文件的权限 => `READ_EXTERNAL_STORAGE`,权限的获取可以参考本库的另一个模块 [quick_android_rx_permission模块文档](https://github.com/SunnyQjm/quickandroid/tree/master/quick_android_rx_permission) + + - 包含权限请求的使用示例: + + ps: `checkMyPermission` 为 [quick_android_base模块文档](https://github.com/SunnyQjm/quickandroid/tree/master/quick_android_base) 模块提供的用于检查权限是否存在的 `Context` 类的扩展方法 + + ```kotlin + QuickAndroidFilePicker + .create(this) + .request( + arrayOf( + Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) + .subscribe { + if (it.granted) { + checkMyPermission(Manifest.permission.READ_EXTERNAL_STORAGE, { + QuickAndroid + .createFilePicker(this) + .pickerFile() + .subscribe { fpr -> + toast(fpr.path) + } + }) + } + } + + ////////////////////////////////////////////////////////////// + //// 使用 QuickAndroid 扩展的用法 + ////////////////////////////////////////////////////////////// + QuickAndroid + .createRxPermission(this) + .request( + arrayOf( + Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) + .subscribe { + if (it.granted) { + checkMyPermission(Manifest.permission.READ_EXTERNAL_STORAGE, { + QuickAndroid + .createFilePicker(this) + .pickerFile() + .subscribe { fpr -> + toast(fpr.path) + } + }) + } + } + ``` \ No newline at end of file diff --git a/quick_android_file_picker/build.gradle b/quick_android_file_picker/build.gradle new file mode 100644 index 0000000..ae1af08 --- /dev/null +++ b/quick_android_file_picker/build.gradle @@ -0,0 +1,45 @@ +apply plugin: 'com.android.library' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + implementation project(path: ':quick_android_base') +} diff --git a/quick_android_file_picker/consumer-rules.pro b/quick_android_file_picker/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/quick_android_file_picker/proguard-rules.pro b/quick_android_file_picker/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/quick_android_file_picker/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/quick_android_file_picker/src/androidTest/java/com/example/quick_android_file_picker/ExampleInstrumentedTest.kt b/quick_android_file_picker/src/androidTest/java/com/example/quick_android_file_picker/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..2bbecd9 --- /dev/null +++ b/quick_android_file_picker/src/androidTest/java/com/example/quick_android_file_picker/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.quick_android_file_picker + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.quick_android_file_picker.test", appContext.packageName) + } +} diff --git a/quick_android_file_picker/src/main/AndroidManifest.xml b/quick_android_file_picker/src/main/AndroidManifest.xml new file mode 100644 index 0000000..fac2a43 --- /dev/null +++ b/quick_android_file_picker/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePicker.kt b/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePicker.kt new file mode 100644 index 0000000..4a13da5 --- /dev/null +++ b/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePicker.kt @@ -0,0 +1,50 @@ +package com.example.quick_android_file_picker + +import androidx.annotation.RequiresPermission +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.FragmentManager +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.extensions.getLazySingleton +import com.example.quick_android_file_picker.model.FilePickerResult +import io.reactivex.Observable + +class QuickAndroidFilePicker(fragmentManager: FragmentManager) { + companion object { + const val TAG = "QuickAndroidFilePicker" + + fun create(activity: FragmentActivity): QuickAndroidFilePicker { + return QuickAndroidFilePicker(activity.supportFragmentManager) + } + + fun create(fragment: Fragment): QuickAndroidFilePicker { + return QuickAndroidFilePicker(fragment.childFragmentManager) + } + } + + private var mRxAndroidFilePickerFragment: Lazy + + init { + mRxAndroidFilePickerFragment = + fragmentManager.getLazySingleton(TAG, QuickAndroidFilePickerFragment::class.java) + } + + @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) + fun pickerFile(fileType: String = "*/*"): Observable { + return mRxAndroidFilePickerFragment + .value + .pickerFile(fileType) + } +} + +////////////////////////////////////////////////////////// +////////// QuickAndroid 扩展 +////////////////////////////////////////////////////////// + +fun QuickAndroid.createFilePicker(activity: FragmentActivity): QuickAndroidFilePicker { + return QuickAndroidFilePicker(activity.supportFragmentManager) +} + +fun QuickAndroid.createFilePicker(fragment: Fragment): QuickAndroidFilePicker { + return QuickAndroidFilePicker(fragment.childFragmentManager) +} \ No newline at end of file diff --git a/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePickerFragment.kt b/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePickerFragment.kt new file mode 100644 index 0000000..249fa12 --- /dev/null +++ b/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/QuickAndroidFilePickerFragment.kt @@ -0,0 +1,49 @@ +package com.example.quick_android_file_picker + +import android.content.Intent +import android.os.Bundle +import androidx.annotation.RequiresPermission +import androidx.fragment.app.Fragment +import cn.qjm253.quick_android_base.extensions.i +import cn.qjm253.quick_android_base.util.ContentUriUtil +import com.example.quick_android_file_picker.model.FilePickerResult +import io.reactivex.Observable +import io.reactivex.ObservableEmitter + +/** + * 这个fragment用于接收文件选择的结果 + */ +class QuickAndroidFilePickerFragment : Fragment() { + private var emitter: ObservableEmitter? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + retainInstance = true + } + + @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) + fun pickerFile(fileType: String = "*/*"): Observable { + return Observable.create { _emitter -> + this.emitter = _emitter + + // 调用系统的文件选择器 + Intent(Intent.ACTION_GET_CONTENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = fileType + this@QuickAndroidFilePickerFragment.startActivityForResult(this, 0) + } + } + + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + data?.data?.let { + it.path?.i() + val path = ContentUriUtil.getPath(context, it) + println(it.toString()) + emitter?.onNext(FilePickerResult(path, it)) + emitter?.onComplete() + } + } +} \ No newline at end of file diff --git a/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/model/FilePickerResult.kt b/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/model/FilePickerResult.kt new file mode 100644 index 0000000..352227f --- /dev/null +++ b/quick_android_file_picker/src/main/java/com/example/quick_android_file_picker/model/FilePickerResult.kt @@ -0,0 +1,8 @@ +package com.example.quick_android_file_picker.model + +import android.net.Uri + +data class FilePickerResult ( + val path: String, + val uri: Uri +) \ No newline at end of file diff --git a/quick_android_file_picker/src/main/res/values/strings.xml b/quick_android_file_picker/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_file_picker/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_file_picker/src/test/java/com/example/quick_android_file_picker/ExampleUnitTest.kt b/quick_android_file_picker/src/test/java/com/example/quick_android_file_picker/ExampleUnitTest.kt new file mode 100644 index 0000000..98c2794 --- /dev/null +++ b/quick_android_file_picker/src/test/java/com/example/quick_android_file_picker/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.example.quick_android_file_picker + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/quick_android_image_picker/.gitignore b/quick_android_image_picker/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_image_picker/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_image_picker/README.md b/quick_android_image_picker/README.md new file mode 100644 index 0000000..8a15efa --- /dev/null +++ b/quick_android_image_picker/README.md @@ -0,0 +1,85 @@ +> ## quick_android_image_picker 模块使用说明 +> +> 本模块基于[RxImagePicker](https://github.com/qingmei2/RxImagePicker)进行封装,并额外提供图片裁剪功能,提供简单的调用接口。关于`RxImagePicker`的更多使用说明,请参考[RxImagePicker](https://github.com/qingmei2/RxImagePicker) + +- ### 使用 + + - 简单使用 + + ```kotlin + + /** + * 打开知乎样式的图片选择器 + */ + QuickAndroidImagePicker + .openZhihuStyleGallery( + context, + ZhihuConfigurationBuilder( + MimeType.ofImage(), + false + ) + .maxSelectable(1) + .countable(true) + .spanCount(4) + .build() // ICustomPickerConfiguration 类型 + ) + .subscribe({ result -> + // 将结果传给图片裁剪界面进行图片裁剪 + QuickAndroidImagePicker.startClipImage(context, result.uri) + }) + + ``` + - 其他功能 + ```kotlin + /** + * 打开知乎样式的图片选择器 + */ + QuickAndroidImagePicker + .openWechatStyleGallery( + context, + WechatConfigrationBuilder( + MimeType.ofImage(), + false + ) + .maxSelectable(1) + .countable(true) + .spanCount(4) + .build() // ICustomPickerConfiguration 类型 + ) + .subscribe({ result -> + + }) + + /** + * 打开摄像头拍摄 + */ + QuickAndroidImagePicker + .openCamera(context) + .subscribe({ result -> + }) + + /** + * 跳转到裁剪页面裁剪图片 + * @param context + * @param uri Uri类型 + * @param multiple 裁剪后文件的压缩强度 + * 0.2 -> 50 ~ 100 KB + * 0.3 -> 100 ~ 200 KB + */ + QuickAndroidImagePicker + .startClipImage(context, uri, 0.3) + + /** + * 跳转到裁剪页面裁剪图片 + * @param context + * @param path 文件的绝对路径 + * @param multiple 裁剪后文件的压缩强度 + * 0.2 -> 50 ~ 100 KB + * 0.3 -> 100 ~ 200 KB + */ + QuickANdroidImagePicker + .startClipImage(context, path, 0.3) + + ``` + + 当然,上面的所有接口都有`QuickAndroid`对应的扩展,都可以用`QuickAndroid.xxx`来调用 diff --git a/quick_android_image_picker/build.gradle b/quick_android_image_picker/build.gradle new file mode 100644 index 0000000..75fb167 --- /dev/null +++ b/quick_android_image_picker/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + implementation "androidx.constraintlayout:constraintlayout:${constraintlayout_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + // RxImagePicker + api "com.github.qingmei2:rximagepicker:${rx_image_picker_version}" + api "com.github.qingmei2:rximagepicker_support:${rx_image_picker_version}" + // Zhihu picture selector + api "com.github.qingmei2:rximagepicker_support_zhihu:${rx_image_picker_version}" + // WeChat picture selector + api "com.github.qingmei2:rximagepicker_support_wechat:${rx_image_picker_version}" + + + implementation project(path: ':quick_android_base') + +} +repositories { + mavenCentral() +} diff --git a/quick_android_image_picker/proguard-rules.pro b/quick_android_image_picker/proguard-rules.pro new file mode 100644 index 0000000..af8464c --- /dev/null +++ b/quick_android_image_picker/proguard-rules.pro @@ -0,0 +1,26 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + + +##------------- Begin RxImagePicker-------------## +-keep class com.qingmei2.rximagepicker.**{*;} +##------------- Begin RxImagePicker-------------## diff --git a/quick_android_image_picker/src/androidTest/java/cn/qjm253/quick_android_image_picker/ExampleInstrumentedTest.java b/quick_android_image_picker/src/androidTest/java/cn/qjm253/quick_android_image_picker/ExampleInstrumentedTest.java new file mode 100644 index 0000000..54b7655 --- /dev/null +++ b/quick_android_image_picker/src/androidTest/java/cn/qjm253/quick_android_image_picker/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package cn.qjm253.quick_android_image_picker; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_image_picker.test", appContext.getPackageName()); + } +} diff --git a/quick_android_image_picker/src/main/AndroidManifest.xml b/quick_android_image_picker/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e2df19f --- /dev/null +++ b/quick_android_image_picker/src/main/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/MyImagePicker.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/MyImagePicker.kt new file mode 100644 index 0000000..1295aee --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/MyImagePicker.kt @@ -0,0 +1,35 @@ +package cn.qjm253.quick_android_image_picker + +import android.content.Context +import com.qingmei2.rximagepicker.entity.Result +import com.qingmei2.rximagepicker.entity.sources.Camera +import com.qingmei2.rximagepicker.entity.sources.Gallery +import com.qingmei2.rximagepicker.ui.ICustomPickerConfiguration +import com.qingmei2.rximagepicker_extension_wechat.ui.WechatImagePickerActivity +import com.qingmei2.rximagepicker_extension_zhihu.ui.ZhihuImagePickerActivity +import io.reactivex.Observable + +/** + * @author SunnyQjm + * @date 19-7-7 下午1:52 + */ + +interface MyImagePicker { + + /** + * 打开类知乎的图片选择器 + */ + @Gallery(componentClazz = ZhihuImagePickerActivity::class, openAsFragment = false) + fun openZhihuStyleGallery(context: Context, + config: ICustomPickerConfiguration): Observable + + /** + * 打开类微信的图片选择器 + */ + @Gallery(componentClazz = WechatImagePickerActivity::class, openAsFragment = false) + fun openWechatStyleGallery(context: Context, + config: ICustomPickerConfiguration): Observable + + @Camera + fun openCamera(context: Context): Observable +} \ No newline at end of file diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/QuickAndroidImagePicker.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/QuickAndroidImagePicker.kt new file mode 100644 index 0000000..130bd1a --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/QuickAndroidImagePicker.kt @@ -0,0 +1,174 @@ +package cn.qjm253.quick_android_image_picker + +import android.content.Context +import android.net.Uri +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.extensions.jumpTo +import cn.qjm253.quick_android_base.params.IntentParam +import cn.qjm253.quick_android_base.util.ContentUriUtil +import cn.qjm253.quick_android_image_picker.activity.QuickAndroidClipImageActivity +import com.qingmei2.rximagepicker.core.RxImagePicker +import com.qingmei2.rximagepicker.entity.Result +import com.qingmei2.rximagepicker.ui.ICustomPickerConfiguration +import com.qingmei2.rximagepicker_extension.MimeType +import com.qingmei2.rximagepicker_extension_wechat.WechatConfigrationBuilder +import com.qingmei2.rximagepicker_extension_zhihu.ZhihuConfigurationBuilder +import io.reactivex.Observable + +/** + * @author SunnyQjm + * @date 19-7-7 下午2:25 + */ +object QuickAndroidImagePicker { + + /** + * 打开知乎样式的图片选择器 + */ + fun openZhihuStyleGallery( + context: Context, + config: ICustomPickerConfiguration = ZhihuConfigurationBuilder(MimeType.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .theme(R.style.Zhihu_Normal) + .build() + ): Observable { + return RxImagePicker + .create(MyImagePicker::class.java) + .openZhihuStyleGallery(context, config) + } + + /** + * 打开微信样式的图片选择器 + */ + fun openWechatStyleGallery( + context: Context, + config: ICustomPickerConfiguration = WechatConfigrationBuilder(MimeType.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .build() + ): Observable { + return RxImagePicker + .create(MyImagePicker::class.java) + .openWechatStyleGallery(context, config) + } + + + /** + * 打开摄像头拍摄 + */ + fun openCamera(context: Context): Observable { + return RxImagePicker + .create() + .openCamera(context) + } + + /** + * 跳转到裁剪页面裁剪图片 + * @param context + * @param path 文件的绝对路径 + * @param multiple 裁剪后文件的压缩强度 + * 0.2 -> 50 ~ 100 KB + * 0.3 -> 100 ~ 200 KB + */ + fun startClipImage(context: Context, path: String, multiple: Float = 0.3f): QuickAndroidImagePicker { + context.jumpTo( + QuickAndroidClipImageActivity::class.java, IntentParam() + .add(QuickAndroidClipImageActivity.QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH, path) + .add(QuickAndroidClipImageActivity.QUICK_ANDROID_CLIP_IMAGE_MULTIPLE, multiple) + ) + return this + } + + /** + * 跳转到裁剪页面裁剪图片 + * @param context + * @param uri Uri类型 + * @param multiple 裁剪后文件的压缩强度 + * 0.2 -> 50 ~ 100 KB + * 0.3 -> 100 ~ 200 KB + */ + fun startClipImage(context: Context, uri: Uri, multiple: Float = 0.3f): QuickAndroidImagePicker { + startClipImage(context, ContentUriUtil.getPath(context, uri), multiple) + return this + } + +} + +////////////////////////////////////////////////////////// +////////// QuickAndroid 扩展 +////////////////////////////////////////////////////////// + +fun QuickAndroid.openZhihuStyleGallery( + context: Context, + config: ICustomPickerConfiguration = ZhihuConfigurationBuilder(MimeType.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .theme(R.style.Zhihu_Normal) + .build() +): Observable { + return QuickAndroidImagePicker.openZhihuStyleGallery(context, config) +} + +fun QuickAndroid.openWechatStyleGallery( + context: Context, + config: ICustomPickerConfiguration = WechatConfigrationBuilder(MimeType.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .build() +): Observable { + return QuickAndroidImagePicker.openWechatStyleGallery(context, config) +} + +fun QuickAndroid.openCamera(context: Context): Observable { + return QuickAndroidImagePicker.openCamera(context) +} + +fun QuickAndroid.startClipImage(context: Context, path: String, multiple: Float = 0.3f): QuickAndroidImagePicker { + return QuickAndroidImagePicker.startClipImage(context, path, multiple) +} + +fun QuickAndroid.startClipImage(context: Context, uri: Uri, multiple: Float = 0.3f): QuickAndroidImagePicker { + return QuickAndroidImagePicker.startClipImage(context, uri, multiple) +} + + +////////////////////////////////////////////////////////// +////////// Context 扩展 +////////////////////////////////////////////////////////// + +fun Context.openZhihuStyleGallery( + config: ICustomPickerConfiguration = ZhihuConfigurationBuilder(MimeType.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .theme(R.style.Zhihu_Normal) + .build() +): Observable { + return QuickAndroidImagePicker.openZhihuStyleGallery(this, config) +} + +fun Context.openWechatStyleGallery( + config: ICustomPickerConfiguration = WechatConfigrationBuilder(MimeType.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .build() +): Observable { + return QuickAndroidImagePicker.openWechatStyleGallery(this, config) +} + +fun Context.openCamera(): Observable { + return QuickAndroidImagePicker.openCamera(this) +} + +fun Context.startClipImage(path: String, multiple: Float = 0.3f): QuickAndroidImagePicker { + return QuickAndroidImagePicker.startClipImage(this, path, multiple) +} + +fun Context.startClipImage(uri: Uri, multiple: Float = 0.3f): QuickAndroidImagePicker { + return QuickAndroidImagePicker.startClipImage(this, uri, multiple) +} \ No newline at end of file diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/activity/QuickAndroidClipImageActivity.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/activity/QuickAndroidClipImageActivity.kt new file mode 100644 index 0000000..fde883e --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/activity/QuickAndroidClipImageActivity.kt @@ -0,0 +1,42 @@ +package cn.qjm253.quick_android_image_picker.activity + +import android.os.Bundle +import cn.qjm253.quick_android_base.base.activity.BaseQuickAndroidActivity +import cn.qjm253.quick_android_base.base.fragment.BaseQuickAndroidFragment +import cn.qjm253.quick_android_base.extensions.addFragmentToActivity +import cn.qjm253.quick_android_image_picker.R +import cn.qjm253.quick_android_image_picker.fragment.QuickAndroidClipImageFragment +import com.gyf.immersionbar.BarHide +import com.gyf.immersionbar.ImmersionBar +import kotlinx.android.synthetic.main.activity_quick_android_clip_image.* + +class QuickAndroidClipImageActivity : BaseQuickAndroidActivity(), BaseQuickAndroidFragment.OnFragmentInteractionListener { + + companion object { + const val QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH = QuickAndroidClipImageFragment.QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH + const val QUICK_ANDROID_CLIP_IMAGE_MULTIPLE = QuickAndroidClipImageFragment.QUICK_ANDROID_CLIP_IMAGE_MULTIPLE + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + ImmersionBar.with(this) + .fullScreen(true) + .hideBar(BarHide.FLAG_HIDE_NAVIGATION_BAR) + .init() + setContentView(R.layout.activity_quick_android_clip_image) + + // 如果有的话隐藏ActionBar + supportActionBar?.hide() + + val path = intent.getStringExtra(QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH) + val multiple = intent.getFloatExtra(QUICK_ANDROID_CLIP_IMAGE_MULTIPLE, QuickAndroidClipImageFragment.DEFAULT_MULTIPLE) + + val fragment = addFragmentToActivity(R.id.quickAndroidClipImageFragmentContainer) { + return@addFragmentToActivity QuickAndroidClipImageFragment.newInstance(path, multiple) + } + + tvFinish.setOnClickListener { + fragment.doClip() + } + } +} diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/fragment/QuickAndroidClipImageFragment.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/fragment/QuickAndroidClipImageFragment.kt new file mode 100644 index 0000000..e076da3 --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/fragment/QuickAndroidClipImageFragment.kt @@ -0,0 +1,118 @@ +package cn.qjm253.quick_android_image_picker.fragment + +import android.Manifest +import android.annotation.SuppressLint +import android.content.Intent +import android.graphics.Bitmap +import cn.qjm253.quick_android_base.base.fragment.BaseQuickAndroidFragment +import cn.qjm253.quick_android_base.extensions.e +import cn.qjm253.quick_android_base.extensions.i +import cn.qjm253.quick_android_base.params.IntentParam +import cn.qjm253.quick_android_base.util.FileUtils +import cn.qjm253.quick_android_base.util.RxSchedulersHelper +import cn.qjm253.quick_android_image_picker.R +import io.reactivex.Observable +import io.reactivex.ObservableEmitter +import kotlinx.android.synthetic.main.fragment_quick_android_clip_image.* +import java.io.File +import java.lang.Exception + +/** + * 图片裁剪Fragment + * + * @author SunnyQjm + * @date 19-7-7 下午3:58 + */ +class QuickAndroidClipImageFragment : BaseQuickAndroidFragment() { + + companion object { + // 需要裁剪的原图片路径 + const val QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH = "QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH" + + // 压缩强度 + const val QUICK_ANDROID_CLIP_IMAGE_MULTIPLE = "QUICK_ANDROID_CLIP_IMAGE_MULTIPLE" + + // 裁剪后的图片路径 + const val QUICK_ANDROID_CLIP_IMAGE_RESULT = "QUICK_ANDROID_CLIP_IMAGE_RESULT" + + const val QUICK_ANDROID_CLIP_IMAGE_RW_PERMISSION_REQUEST_CODE = 1 + + const val DEFAULT_MULTIPLE = 0.3f + fun newInstance(path: String, multiple: Float = 0.3f): QuickAndroidClipImageFragment { + return newInstance_( + QuickAndroidClipImageFragment::class.java, IntentParam() + .add(QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH, path) + .add(QUICK_ANDROID_CLIP_IMAGE_MULTIPLE, multiple) + ) + } + } + + + private var multiple: Float = DEFAULT_MULTIPLE + + override fun getRes(): Int = R.layout.fragment_quick_android_clip_image + + override fun initView() { + val imagePath = arguments?.getString(QUICK_ANDROID_CLIP_IMAGE_IMAGE_PATH) ?: "" + multiple = arguments?.getFloat(QUICK_ANDROID_CLIP_IMAGE_MULTIPLE, DEFAULT_MULTIPLE) ?: DEFAULT_MULTIPLE + + // 检查边界,限制在 0~1之间 + if (multiple < 0) { + multiple = 0.1f + } else if (multiple > 1f) { + multiple = 1f + } + clipImageLayout.setImagePath(imagePath) + } + + @SuppressLint("CheckResult") + private fun doCLip_() { + Observable.create { emitter: ObservableEmitter -> + try { + FileUtils.generatePictureFile("clip.png").apply { + if (!exists()) + createNewFile() + outputStream().use { + clipImageLayout.clip(multiple) + .compress(Bitmap.CompressFormat.PNG, 100, it) + } + emitter.onNext(this) + emitter.onComplete() + } + } catch (err: Exception) { + emitter.onError(err) + } + } + .compose(RxSchedulersHelper.io_main()) + .subscribe({ file -> + Intent().let { + it.putExtra(QUICK_ANDROID_CLIP_IMAGE_RESULT, file.absolutePath) + activity?.setResult(0, it) + activity?.finish() + } + "${file.absolutePath} 压缩成功 (${file.length()})".i() + }, { + it.e() + }) + } + + fun doClip() { + requestPermissions( + arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE), + R.string.clip_image_permission_tip, QUICK_ANDROID_CLIP_IMAGE_RW_PERMISSION_REQUEST_CODE + ) + } + + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + super.onPermissionsGranted(requestCode, perms) + when (requestCode) { + QUICK_ANDROID_CLIP_IMAGE_RW_PERMISSION_REQUEST_CODE -> { + doCLip_() + } + } + } + + override fun initialLoadData() { + } + +} \ No newline at end of file diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageBorderView.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageBorderView.kt new file mode 100644 index 0000000..a20d011 --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageBorderView.kt @@ -0,0 +1,107 @@ +package cn.qjm253.quick_android_image_picker.views + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Paint.Style +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View + +/** + * @author fucker + */ +class ClipImageBorderView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : + View(context, attrs, defStyle) { + /** + * 水平方向与View的边距 + */ + private var mHorizontalPadding: Int = 0 + /** + * 垂直方向与View的边距 + */ + private var mVerticalPadding: Int = 0 + /** + * 裁剪框的纵横比,mVerticalPadding通过该值计算 + * 默认是正方形,所以等于1 + */ + private var aspectRatio = 1f + /** + * 绘制的矩形的宽度 + */ + private var mWidth: Int = 0 + /** + * 边框的颜色,默认为白色 + */ + private val mBorderColor = Color.parseColor("#FFFFFF") + /** + * 边框的宽度单位dp + */ + private var mBorderWidth = 1 + + private val mPaint: Paint + + init { + + mBorderWidth = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, mBorderWidth.toFloat(), resources + .displayMetrics + ).toInt() + mPaint = Paint() + mPaint.isAntiAlias = true + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + // 计算矩形区域的宽度 + mWidth = width - 2 * mHorizontalPadding + // 计算距离屏幕垂直边界的边距 + mVerticalPadding = ((height - mWidth * aspectRatio) / 2).toInt() + mPaint.color = Color.parseColor("#000000") + mPaint.alpha = (255 * 0.48f).toInt() + mPaint.style = Style.FILL + // 绘制左边1 + canvas.drawRect(0f, 0f, mHorizontalPadding.toFloat(), height.toFloat(), mPaint) + // 绘制右边2 + canvas.drawRect( + (width - mHorizontalPadding).toFloat(), 0f, width.toFloat(), + height.toFloat(), mPaint + ) + // 绘制上边3 + canvas.drawRect( + mHorizontalPadding.toFloat(), 0f, (width - mHorizontalPadding).toFloat(), + mVerticalPadding.toFloat(), mPaint + ) + // 绘制下边4 + canvas.drawRect( + mHorizontalPadding.toFloat(), (height - mVerticalPadding).toFloat(), + (width - mHorizontalPadding).toFloat(), height.toFloat(), mPaint + ) + // 绘制外边距 + mPaint.color = mBorderColor + mPaint.strokeWidth = mBorderWidth.toFloat() + mPaint.style = Style.STROKE + canvas.drawRect( + mHorizontalPadding.toFloat(), + mVerticalPadding.toFloat(), + (width - mHorizontalPadding).toFloat(), + (height - mVerticalPadding).toFloat(), + mPaint + ) + + } + + fun setHorizontalPadding(mHorizontalPadding: Int) { + this.mHorizontalPadding = mHorizontalPadding + } + + /** + * 设置clip框的纵横比 + * + * @param aspectRatio + */ + fun setAspectRatio(aspectRatio: Float) { + this.aspectRatio = aspectRatio + } +} \ No newline at end of file diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageLayout.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageLayout.kt new file mode 100644 index 0000000..a1e92f4 --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipImageLayout.kt @@ -0,0 +1,104 @@ +package cn.qjm253.quick_android_image_picker.views + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.util.AttributeSet +import android.util.TypedValue +import android.widget.RelativeLayout +import cn.qjm253.quick_android_base.util.DisplayUtils +import kotlin.math.roundToInt + + +/** + * @author fucker + */ +class ClipImageLayout(context: Context, attrs: AttributeSet) : RelativeLayout(context, attrs) { + + private val mZoomImageView: ClipZoomImageView = ClipZoomImageView(context) + private val mClipImageView: ClipImageBorderView = ClipImageBorderView(context) + + private var mHorizontalPadding = 24 + private var aspectRatio = 1f + + init { + + val lp = LayoutParams( + android.view.ViewGroup.LayoutParams.MATCH_PARENT, + android.view.ViewGroup.LayoutParams.MATCH_PARENT + ) + + this.addView(mZoomImageView, lp) + this.addView(mClipImageView, lp) + + setHorizontalPadding(mHorizontalPadding) + setAspectRatio(aspectRatio) + } + + fun setImageBitmap(bm: Bitmap) { + mZoomImageView.setImageBitmap(bm) + } + + fun setImagePath(path: String) { + val screen = DisplayUtils.getScreenParams(context) + val width = screen[0] + val height = screen[1] + + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + BitmapFactory.decodeFile(path, options) + var scale = (if (options.outWidth * 1.0 / width < 1) + 1f + else + options.outWidth * 1.0f / width) + val scale2 = (if (options.outHeight * 1.0 / height < 1) + 1f + else + options.outHeight * 1.0f / height) + scale = if (scale < scale2) scale2 else scale//select a bigger scale number. + options.outHeight = (options.outHeight / scale).toInt() + options.outWidth = (options.outWidth / scale).toInt() + options.inSampleSize = scale.roundToInt() + options.inJustDecodeBounds = false + val bm = BitmapFactory.decodeFile(path, options) + setImageBitmap(bm) + } + + /** + * 设置左右边距的方法 + * + * @param mHorizontalPadding dp + */ + fun setHorizontalPadding(mHorizontalPadding: Int) { + var mHorizontalPadding = mHorizontalPadding + this.mHorizontalPadding = mHorizontalPadding + // 计算padding的px + mHorizontalPadding = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding.toFloat(), resources + .displayMetrics + ).toInt() + mZoomImageView.setHorizontalPadding(mHorizontalPadding) + mClipImageView.setHorizontalPadding(mHorizontalPadding) + } + + /** + * 设置裁剪图像的纵横比 + * + * @param aspectRatio = height / width + */ + fun setAspectRatio(aspectRatio: Float) { + this.aspectRatio = aspectRatio + mZoomImageView.setAspectRatio(aspectRatio) + mClipImageView.setAspectRatio(aspectRatio) + } + + /** + * 裁切图片,multiple 0~1.0f + * + * @return + */ + fun clip(multiple: Float): Bitmap { + return mZoomImageView.clip(multiple) + } + +} \ No newline at end of file diff --git a/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipZoomImageView.kt b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipZoomImageView.kt new file mode 100644 index 0000000..563b724 --- /dev/null +++ b/quick_android_image_picker/src/main/java/cn/qjm253/quick_android_image_picker/views/ClipZoomImageView.kt @@ -0,0 +1,361 @@ +package cn.qjm253.quick_android_image_picker.views + + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Matrix +import android.graphics.RectF +import android.util.AttributeSet +import android.view.* +import androidx.appcompat.widget.AppCompatImageView +import kotlin.math.sqrt + +/** + * @author fucker + */ +@SuppressLint("ClickableViewAccessibility") +class ClipZoomImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + AppCompatImageView(context, attrs), ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener, + ViewTreeObserver.OnGlobalLayoutListener { + + private var initScale = 0.5f + private var once = true + + private val matrixValues = FloatArray(9) + + private var mScaleGestureDetector: ScaleGestureDetector? = null + private val mScaleMatrix = Matrix() + + /** + */ + private val mGestureDetector: GestureDetector + private var isAutoScale: Boolean = false + + private val mTouchSlop: Int = 0 + + private var mLastX: Float = 0.toFloat() + private var mLastY: Float = 0.toFloat() + + private var isCanDrag: Boolean = false + private var lastPointerCount: Int = 0 + + private val matrixRectF: RectF + get() { + val matrix = mScaleMatrix + val rect = RectF() + val d = drawable + if (null != d) { + rect.set(0f, 0f, d.intrinsicWidth.toFloat(), d.intrinsicHeight.toFloat()) + matrix.mapRect(rect) + } + return rect + } + + val scale: Float + get() { + mScaleMatrix.getValues(matrixValues) + return matrixValues[Matrix.MSCALE_X] + } + + private var mHorizontalPadding: Int = 0 + private var mVerticalPadding: Int = 0 + /** + * 裁剪框的纵横比,mVerticalPadding通过该值计算 + * 默认是正方形,所以等于1 + */ + private var aspectRatio = 1f + + init { + + scaleType = ScaleType.MATRIX + mGestureDetector = GestureDetector(context, + object : GestureDetector.SimpleOnGestureListener() { + override fun onDoubleTap(e: MotionEvent): Boolean { + if (isAutoScale == true) + return true + + val x = e.x + val y = e.y + if (scale < SCALE_MID) { + this@ClipZoomImageView.postDelayed( + AutoScaleRunnable(SCALE_MID, x, y), 16 + ) + isAutoScale = true + } else { + this@ClipZoomImageView.postDelayed( + AutoScaleRunnable(initScale, x, y), 16 + ) + isAutoScale = true + } + + return true + } + }) + mScaleGestureDetector = ScaleGestureDetector(context, this) + this.setOnTouchListener(this) + } + + fun setInitScale(scale: Float) { + if (drawable != null) { + this.initScale = scale + } + } + + /** + * @author zhy + */ + private inner class AutoScaleRunnable + /** + * @param targetScale + */ + (private val mTargetScale: Float, private val x: Float, private val y: Float) : Runnable { + private var tmpScale: Float = 0.toFloat() + + init { + if (scale < mTargetScale) { + tmpScale = 1.07f + } else { + tmpScale = 0.93f + } + + } + + override fun run() { + mScaleMatrix.postScale(tmpScale, tmpScale, x, y) + checkBorder() + imageMatrix = mScaleMatrix + + val currentScale = scale + if (tmpScale > 1f && currentScale < mTargetScale || tmpScale < 1f && mTargetScale < currentScale) { + this@ClipZoomImageView.postDelayed(this, 16) + } else { + val deltaScale = mTargetScale / currentScale + mScaleMatrix.postScale(deltaScale, deltaScale, x, y) + checkBorder() + imageMatrix = mScaleMatrix + isAutoScale = false + } + + } + + } + + override fun onScale(detector: ScaleGestureDetector): Boolean { + val scale = scale + var scaleFactor = detector.scaleFactor + + if (drawable == null) + return true + + if (scale < SCALE_MAX && scaleFactor > 1.0f || scale > initScale && scaleFactor <= 1.0f) { + if (scaleFactor * scale < initScale) { + scaleFactor = initScale / scale + } + if (scaleFactor * scale > SCALE_MAX) { + scaleFactor = SCALE_MAX / scale + } + mScaleMatrix.postScale( + scaleFactor, scaleFactor, + detector.focusX, detector.focusY + ) + checkBorder() + imageMatrix = mScaleMatrix + } + return true + + } + + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + return true + } + + @SuppressLint("ClickableViewAccessibility") + override fun onScaleEnd(detector: ScaleGestureDetector) { + } + + override fun onTouch(v: View, event: MotionEvent): Boolean { + + if (mGestureDetector.onTouchEvent(event)) + return true + mScaleGestureDetector!!.onTouchEvent(event) + + var x = 0f + var y = 0f + val pointerCount = event.pointerCount + for (i in 0 until pointerCount) { + x += event.getX(i) + y += event.getY(i) + } + x /= pointerCount + y /= pointerCount + + if (pointerCount != lastPointerCount) { + isCanDrag = false + mLastX = x + mLastY = y + } + + lastPointerCount = pointerCount + when (event.action) { + MotionEvent.ACTION_MOVE -> { + var dx = x - mLastX + var dy = y - mLastY + + if (!isCanDrag) { + isCanDrag = isCanDrag(dx, dy) + } + if (isCanDrag) { + if (drawable != null) { + + val rectF = matrixRectF + + if (rectF.width() <= width - mHorizontalPadding * 2) { + dx = 0f + } + if (rectF.height() <= height - mVerticalPadding * 2) { + dy = 0f + } + mScaleMatrix.postTranslate(dx, dy) + checkBorder() + imageMatrix = mScaleMatrix + } + } + mLastX = x + mLastY = y + } + + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> lastPointerCount = 0 + } + + return true + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + viewTreeObserver.addOnGlobalLayoutListener(this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + viewTreeObserver.removeGlobalOnLayoutListener(this) + } + + override fun onGlobalLayout() { + if (once) { + val d = drawable ?: return + mVerticalPadding = ((height - aspectRatio * (width - 2 * mHorizontalPadding)) / 2).toInt() + + val width = width + val height = height + + val dw = d.intrinsicWidth + val dh = d.intrinsicHeight + var scale = 1.0f + if (dw < getWidth() - mHorizontalPadding * 2 && dh > getHeight() - mVerticalPadding * 2) { + scale = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw + } + + if (dh < getHeight() - mVerticalPadding * 2 && dw > getWidth() - mHorizontalPadding * 2) { + scale = (getHeight() * 1.0f - mVerticalPadding * 2) / dh + } + + if (dw < getWidth() - mHorizontalPadding * 2 && dh < getHeight() - mVerticalPadding * 2) { + val scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw + val scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh + scale = Math.max(scaleW, scaleH) + } + if (dw >= getWidth() - mHorizontalPadding * 2 && dh >= getHeight() - mVerticalPadding * 2) { + val scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw + val scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh + scale = Math.max(scaleW, scaleH) + } + + initScale = scale + SCALE_MID = initScale * 2 + SCALE_MAX = initScale * 4 + mScaleMatrix.postTranslate(((width - dw) / 2).toFloat(), ((height - dh) / 2).toFloat()) + mScaleMatrix.postScale( + scale, scale, (getWidth() / 2).toFloat(), + (getHeight() / 2).toFloat() + ) + + imageMatrix = mScaleMatrix + once = false + } + + } + + fun clip(multiple: Float): Bitmap { + var multiple = multiple + multiple = if (multiple <= 0) 1.0f else multiple + multiple = if (multiple > 1) 1.0f else multiple + val width = width + val height = height + val bitmap = Bitmap.createBitmap( + width, height, + Bitmap.Config.ARGB_8888 + ) + val canvas = Canvas(bitmap) + draw(canvas) + val matrix = Matrix() + matrix.postScale(multiple, multiple) + return Bitmap.createBitmap( + bitmap, mHorizontalPadding, + mVerticalPadding, width - 2 * mHorizontalPadding, height - 2 * mVerticalPadding, matrix, true + ) + } + + private fun checkBorder() { + + val rect = matrixRectF + var deltaX = 0f + var deltaY = 0f + + val width = width + val height = height + if (rect.width() + 0.01 >= width - 2 * mHorizontalPadding) { + if (rect.left > mHorizontalPadding) { + deltaX = -rect.left + mHorizontalPadding + } + if (rect.right < width - mHorizontalPadding) { + deltaX = width.toFloat() - mHorizontalPadding.toFloat() - rect.right + } + } + if (rect.height() + 0.01 >= height - 2 * mVerticalPadding) { + if (rect.top > mVerticalPadding) { + deltaY = -rect.top + mVerticalPadding + } + if (rect.bottom < height - mVerticalPadding) { + deltaY = height.toFloat() - mVerticalPadding.toFloat() - rect.bottom + } + } + mScaleMatrix.postTranslate(deltaX, deltaY) + + } + + private fun isCanDrag(dx: Float, dy: Float): Boolean { + return sqrt((dx * dx + dy * dy).toDouble()) >= mTouchSlop + } + + fun setHorizontalPadding(mHorizontalPadding: Int) { + this.mHorizontalPadding = mHorizontalPadding + } + + /** + * 设置clip框的纵横比 + * + * @param aspectRatio + */ + fun setAspectRatio(aspectRatio: Float) { + this.aspectRatio = aspectRatio + } + + companion object { + + var SCALE_MAX = 4.0f + private var SCALE_MID = 2.0f + } + +} \ No newline at end of file diff --git a/quick_android_image_picker/src/main/res/layout/activity_quick_android_clip_image.xml b/quick_android_image_picker/src/main/res/layout/activity_quick_android_clip_image.xml new file mode 100644 index 0000000..7f8f6b6 --- /dev/null +++ b/quick_android_image_picker/src/main/res/layout/activity_quick_android_clip_image.xml @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file diff --git a/quick_android_image_picker/src/main/res/layout/fragment_quick_android_clip_image.xml b/quick_android_image_picker/src/main/res/layout/fragment_quick_android_clip_image.xml new file mode 100644 index 0000000..3fede61 --- /dev/null +++ b/quick_android_image_picker/src/main/res/layout/fragment_quick_android_clip_image.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/quick_android_image_picker/src/main/res/values/strings.xml b/quick_android_image_picker/src/main/res/values/strings.xml new file mode 100644 index 0000000..1a2ada8 --- /dev/null +++ b/quick_android_image_picker/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + 裁剪图片需要获取读写文件的权限 + diff --git a/quick_android_image_picker/src/test/java/cn/qjm253/quick_android_image_picker/ExampleUnitTest.java b/quick_android_image_picker/src/test/java/cn/qjm253/quick_android_image_picker/ExampleUnitTest.java new file mode 100644 index 0000000..aea8878 --- /dev/null +++ b/quick_android_image_picker/src/test/java/cn/qjm253/quick_android_image_picker/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_image_picker; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/quick_android_mvp/.gitignore b/quick_android_mvp/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_mvp/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_mvp/README.md b/quick_android_mvp/README.md new file mode 100644 index 0000000..1b700d8 --- /dev/null +++ b/quick_android_mvp/README.md @@ -0,0 +1,172 @@ +> ## quick_android_mvp模块 +> +> 本模块提供了一个快速实现MVP架构的框架,并且封装了网络请求(Retrofit + RxJava) + +- ### 说明 + + 本模块提供提供了一系列MVP模式实现代码的封装,并且使用[retrofit](https://github.com/square/retrofit) + [RxJava2](https://github.com/ReactiveX/RxJava) + 实现了网络请求。默认使用[AutoDispose](https://github.com/uber/AutoDispose)来实现订阅对象随Activity的销毁而自动取消,防止内存泄漏 + +- ### 使用 + + - 初始化 + + ```kotlin + /** + * QuickAndroidMVP 模块初始化操作 + * + * @param context Application 对象 + * @param baseUrl 网络请求的前缀, eg.: https://example.cn/ + * @param enablePersistentCookieJar 是否开启Cookie的自动持久化和发送 + */ + QuickAndroidMVP + .init( + context, baseUrl, enablePersistentCookieJar + ) + + // 当然,如果使用Kotlin开发也可以使用下面的统一扩展接口,参数说明同上 + QuickAndroid.initMVP( + context, baseUrl, enablePersistentCookieJar + ) + ``` + + 具体MVP架构的使用方式参考本项目的[demo](https://github.com/SunnyQjm/quickandroid/tree/master/app/src/main/java/cn/qjm253/quick_android/mvp_demo) + +- ### 如何使用网络请求? + + - 首先定义网络请求的Service接口(具体定义规则参看[Retrofit 官网](https://square.github.io/retrofit/)) + + ```kotlin + interface TestServices { + + @GET("api") + fun getWeather( + @Query("city") city: String = "成都", + @Query("version") version: String = "v1" + ): Observable + } + ``` + + - 使用 + + ```kotlin + QuickAndroidMVPAPIManager.getService(TestServices::class.java) + .getWeather("成都") + .compose(RxScheduler.io_main()) + .subscribe({ // onNext + + }, { // onError + + }, { // onComplete + + }) + + ``` + + 轻松两步便可实现网络请求 + +- ### 如何对每一个网络请求添加监听? + + 下面的所有接口都有对应 `QuickAndroid` 的扩展,如果使用`kotlin`开发的话,也可以使用`QuickAndroid.xxx`的方式来调用。**所有的网络请求,只有使用`qaSubscribe`扩展进行订阅的才会调用下面的回调** + + - 添加一个可以监听所有网络请求的onComplete事件的监听器 + + ```kotlin + /** + * 添加一个网络请求 onComplete 的拦截监听 + * 每一个使用 Observable.qaSubscribe 进行订阅的网络请求的onComplete执行的时候都会触发 + * + * @see cn.qjm253.quick_android_mvp.model.inernet.rx.qaSubscribe + */ + QuickAndroidMVP.addOnAPICompleteListener(onComplete) + + // 可以通过下面的方法清空所有对onComplete事件的监听器 + QuickAndroidMVP.clearOnAPICompleteListeners() + ``` + + - 添加一个可以监听所有网络请求的onNext事件的监听器 + + ```kotlin + /** + * 添加一个网络请求 onNext 的拦截监听 + * 每一个使用 Observable.qaSubscribe 进行订阅的网络请求的onNext执行的之前都会触发 + * + * @see cn.qjm253.quick_android_mvp.model.inernet.rx.qaSubscribe + */ + QuickAndroidMVP.addOnAPICompleteListener(onBeforeNextListener) + + QuickAndroidMVP.clearOnAPIBeforeNextListeners() + ``` + + - 添加一个可以监听所有网络请求的onError事件的监听器 + + ```kotlin + /** + * 添加一个网络请求 onError 的拦截监听 + * 每一个使用 Observable.qaSubscribe 进行订阅的网络请求的onError执行的时候都会触发 + * + * @see cn.qjm253.quick_android_mvp.model.inernet.rx.qaSubscribe + */ + QuickAndroidMVP.addOnAPIErrorListener(onErrorListener) + + // 可以通过下面的方法清空所有对onError事件的监听器 + QuickAndroidMVP.clearOnAPIErrorListeners() + ``` + +- ### 如何对网络请求的结果进行统一的处理 + + - 使用要求 + + - 所有的网络请求都必须使用`qaHandleResult()`扩展 + + ```kotlin + Observable.just(BaseQuickAndroidResponseBody(-2)) + .qaHandleResult() + .qaSubscribe(mView, { + + }) + ``` + + - 网络请求的Model数据类需要继承自[BaseQuickAndroidResponseBody](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/response/BaseQuickAndroidResponseBody.kt),里面包含一个`code`属性标识网络请求的状态码 + + - 使用 + + 网络请求成功的情况下,通常返回的结果中会包含状态码(状态码一般又分为请求正常、请求错误等等),如果需要对网络请求的结果进行统一处理,便可以使用如下的方式 + + ```kotlin + QuickAndroidMVP + .registerAPIResultDeal(object : QuickAndroidMVPResultDeal( + // 包含所有网络请求失败的code + arrayOf( + -1 to "网络请求失败" + ), + + // 包含所有请求成功的code + arrayOf( + 0 to "网络请求成功" + ), + + // token 失效,需要重新获取token之后重新发起请求的code + arrayOf( + -2 to "Token失效" + ) + ) { + override fun dealRetry(t: Throwable): Observable { + t.e("dealRetry") + return Observable.error(t) + } + + override fun normalDeal(code: Int, description: String) { + "normalDeal => code: $code, description: $description".i() + } + + override fun errorDeal(code: Int, description: String) { + "errorDeal => code: $code, description: $description".e() + } + + }) + ``` + + + + \ No newline at end of file diff --git a/quick_android_mvp/build.gradle b/quick_android_mvp/build.gradle new file mode 100644 index 0000000..4dcc7d8 --- /dev/null +++ b/quick_android_mvp/build.gradle @@ -0,0 +1,59 @@ +apply plugin: 'com.android.library' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +def AUTO_DISPOSE_VERSION = "1.3.0" + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + // AutoDispose + implementation "com.uber.autodispose:autodispose:${AUTO_DISPOSE_VERSION}" + implementation "com.uber.autodispose:autodispose-android:${AUTO_DISPOSE_VERSION}" + implementation "com.uber.autodispose:autodispose-lifecycle:${AUTO_DISPOSE_VERSION}" + implementation "com.uber.autodispose:autodispose-android-archcomponents:${AUTO_DISPOSE_VERSION}" + + + + // PersistentCookieJar + implementation "com.github.franmontiel:PersistentCookieJar:${persistent_cookie_jar_version}" + + + implementation project(path: ':quick_android_base') +} diff --git a/quick_android_mvp/proguard-rules.pro b/quick_android_mvp/proguard-rules.pro new file mode 100644 index 0000000..1eb290a --- /dev/null +++ b/quick_android_mvp/proguard-rules.pro @@ -0,0 +1,34 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +##---------------Begin: AndroidX---------------## +-keep class com.google.android.material.** {*;} +-keep class androidx.** {*;} +-keep public class * extends androidx.** +-keep interface androidx.** {*;} +-dontwarn com.google.android.material.** +-dontnote com.google.android.material.** +-dontwarn androidx.** +##---------------End: AndroidX---------------## + + + diff --git a/quick_android_mvp/src/androidTest/java/cn/qjm253/quick_android_mvp/ExampleInstrumentedTest.java b/quick_android_mvp/src/androidTest/java/cn/qjm253/quick_android_mvp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..904e2dd --- /dev/null +++ b/quick_android_mvp/src/androidTest/java/cn/qjm253/quick_android_mvp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package cn.qjm253.quick_android_mvp; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_mvp.test", appContext.getPackageName()); + } +} diff --git a/quick_android_mvp/src/main/AndroidManifest.xml b/quick_android_mvp/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6415375 --- /dev/null +++ b/quick_android_mvp/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/QuickAndroidMVP.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/QuickAndroidMVP.kt new file mode 100644 index 0000000..64525f1 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/QuickAndroidMVP.kt @@ -0,0 +1,196 @@ +package cn.qjm253.quick_android_mvp + +import android.app.Application +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_mvp.model.inernet.QuickAndroidMVPAPIManager +import cn.qjm253.quick_android_mvp.model.inernet.rx.QuickAndroidMVPResultDeal +import com.github.anzewei.parallaxbacklayout.ParallaxHelper + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +object QuickAndroidMVP { + + ////////////////////////////////////////// + /////// 初始化操作 + ////////////////////////////////////////// + + /** + * QuickAndroidMVP 模块初始化操作 + * + * @param context Application 对象 + * @param baseUrl 网络请求的前缀, eg.: https://example.cn/ + * @param enablePersistentCookieJar 是否开启Cookie的自动持久化和发送 + */ + fun init( + context: Application, + baseUrl: String = "", + enablePersistentCookieJar: Boolean = true + ): QuickAndroidMVP { + QuickAndroidMVPAPIManager.init(context, enablePersistentCookieJar, baseUrl) + return this + } + + + + + + //////////////////////////////////////////// + //////// 网络请求统一处理 + //////////////////////////////////////////// + val onCompleteListeners = mutableListOf<() -> Unit>() + + + /** + * 添加一个网络请求 onComplete 的拦截监听 + * 每一个使用 Observable.qaSubscribe 进行订阅的网络请求的onComplete执行的时候都会触发 + * + * @see cn.qjm253.quick_android_mvp.model.inernet.rx.qaSubscribe + */ + fun addOnAPICompleteListener(onComplete: () -> Unit): QuickAndroidMVP { + onCompleteListeners.add(onComplete) + return this + } + + + + fun clearOnAPICompleteListeners(): QuickAndroidMVP { + onCompleteListeners.clear() + return this + } + + + val onBeforeNextListeners = mutableListOf<() -> Unit>() + + /** + * 添加一个网络请求 onNext 的拦截监听 + * 每一个使用 Observable.qaSubscribe 进行订阅的网络请求的onNext执行的之前都会触发 + * + * @see cn.qjm253.quick_android_mvp.model.inernet.rx.qaSubscribe + */ + fun addOnAPIBeforeNextListener(onBeforeNextListener: () -> Unit): QuickAndroidMVP { + onBeforeNextListeners.add(onBeforeNextListener) + return this + } + + fun clearOnAPIBeforeNextListeners(): QuickAndroidMVP { + onBeforeNextListeners.clear() + return this + } + + val onErrorListeners = mutableListOf<(Throwable) -> Unit>() + + /** + * 添加一个网络请求 onError 的拦截监听 + * 每一个使用 Observable.qaSubscribe 进行订阅的网络请求的onError执行的时候都会触发 + * + * @see cn.qjm253.quick_android_mvp.model.inernet.rx.qaSubscribe + */ + fun addOnAPIErrorListener(onErrorListener: (Throwable) -> Unit): QuickAndroidMVP { + onErrorListeners.add(onErrorListener) + return this + } + + fun clearOnAPIErrorListeners() { + onErrorListeners.clear() + } + + + ///////////////////////////////////////////////////// + /////////// 网络请求结果统一处理 + ///////////////////////////////////////////////////// + + + var quickAndroidMVPResultDeal: QuickAndroidMVPResultDeal? = null + + /** + * 注册App网络请求结果的统一处理 + * + * @see QuickAndroidMVPResultDeal + */ + fun registerAPIResultDeal(quickAndroidMVPResultDeal: QuickAndroidMVPResultDeal): QuickAndroidMVP { + this.quickAndroidMVPResultDeal = quickAndroidMVPResultDeal + return this + } + +} + + + +/******************************************************* + * 给 QuickAndroid 添加的扩展 + * + * @see cn.qjm253.quick_android_base.QuickAndroid + * + ******************************************************/ + + +/** + * @see QuickAndroidMVP.init + */ +fun QuickAndroid.initMVP( + context: Application, + baseUrl: String = "", + enablePersistentCookieJar: Boolean = true +): QuickAndroid { + QuickAndroidMVP.init(context, baseUrl, enablePersistentCookieJar) + return this +} + +/** + * @see QuickAndroidMVP.addOnAPICompleteListener + */ +fun QuickAndroid.addOnAPICompleteListener(onComplete: () -> Unit): QuickAndroid { + QuickAndroidMVP.addOnAPICompleteListener(onComplete) + return this +} + + +/** + * @see QuickAndroidMVP.clearOnAPICompleteListeners + */ +fun QuickAndroid.clearOnAPICompleteListeners(): QuickAndroid { + QuickAndroidMVP.clearOnAPICompleteListeners() + return this +} + +/** + * @see QuickAndroidMVP.addOnAPIBeforeNextListener + */ +fun QuickAndroid.addOnAPIBeforeNextListener(onBeforeNextListener: () -> Unit): QuickAndroid { + QuickAndroidMVP.addOnAPIBeforeNextListener(onBeforeNextListener) + return this +} + +/** + * @see QuickAndroidMVP.clearOnAPIBeforeNextListeners + */ +fun QuickAndroid.clearOnAPIBeforeNextListeners(): QuickAndroid { + QuickAndroidMVP.clearOnAPIBeforeNextListeners() + return this +} + +/** + * @see QuickAndroidMVP.addOnAPIErrorListener + */ +fun QuickAndroid.addOnAPIErrorListener(onErrorListener: (Throwable) -> Unit): QuickAndroid { + QuickAndroidMVP.addOnAPIErrorListener(onErrorListener) + return this +} + +/** + * @see QuickAndroidMVP.clearOnAPIErrorListeners + */ +fun QuickAndroid.clearOnAPIErrorListeners(): QuickAndroid { + QuickAndroidMVP.clearOnAPIErrorListeners() + return this +} + +/** + * @see QuickAndroidMVP.registerAPIResultDeal + */ +fun QuickAndroid.registerAPIResultDeal(quickAndroidMVPResultDeal: QuickAndroidMVPResultDeal): QuickAndroid { + QuickAndroidMVP.registerAPIResultDeal(quickAndroidMVPResultDeal) + return this +} diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/activity/BaseQuickAndroidMVPActivity.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/activity/BaseQuickAndroidMVPActivity.kt new file mode 100644 index 0000000..93cc1fc --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/activity/BaseQuickAndroidMVPActivity.kt @@ -0,0 +1,69 @@ +package cn.qjm253.quick_android_mvp.base.activity + +import android.os.Bundle +import androidx.lifecycle.Lifecycle +import cn.qjm253.quick_android_base.base.activity.BaseQuickAndroidActivity +import cn.qjm253.quick_android_base.extensions.toast +import cn.qjm253.quick_android_mvp.base.mvp.BasePresenter +import cn.qjm253.quick_android_mvp.base.mvp.BaseView +import com.orhanobut.logger.Logger +//import com.uber.autodispose.AutoDispose +//import com.uber.autodispose.AutoDisposeConverter +//import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider + +/** + * MVP 模式的Activity基类 + * + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +abstract class BaseQuickAndroidMVPActivity

> : BaseQuickAndroidActivity(), BaseView { + + protected lateinit var mPresenter: P + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mPresenter = onCreatePresenter() + } + + + override fun doToast(res: Int, duration: Int) { + toast(res, duration) + } + + override fun doToast(message: String, duration: Int) { + toast(message, duration) + } + + + override fun onError(e: Throwable) { + // 打印错误 + Logger.e(e, e.message ?: "") + } + + + override fun showLoading() { + } + + override fun hideLoading() { + } + + + /** + * RxJava订阅绑定到Activity的生命周期中,触发onDestroy生命周期函数的时候自动取消订阅 +// */ +// override fun bindAutoDispose(): AutoDisposeConverter { +// return AutoDispose.autoDisposable( +// AndroidLifecycleScopeProvider +// .from(this, Lifecycle.Event.ON_DESTROY) +// ) +// } + + + /** + * 创建Presenter的接口,每个实现本类的Activity应该都要实现本方法,返回对应的Presenter + */ + abstract fun onCreatePresenter(): P + + +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/fragment/BaseQuickAndroidMVPFragment.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/fragment/BaseQuickAndroidMVPFragment.kt new file mode 100644 index 0000000..4212dfc --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/fragment/BaseQuickAndroidMVPFragment.kt @@ -0,0 +1,63 @@ +package cn.qjm253.quick_android_mvp.base.fragment + +import android.os.Bundle +import androidx.lifecycle.Lifecycle +import cn.qjm253.quick_android_base.base.fragment.BaseQuickAndroidFragment +import cn.qjm253.quick_android_base.extensions.toast +import cn.qjm253.quick_android_mvp.base.mvp.BasePresenter +import cn.qjm253.quick_android_mvp.base.mvp.BaseView +import com.orhanobut.logger.Logger +//import com.uber.autodispose.AutoDispose +//import com.uber.autodispose.AutoDisposeConverter +//import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider + +/** + * MVP 模式的Fragment基类 + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +abstract class BaseQuickAndroidMVPFragment> + : BaseQuickAndroidFragment(), BaseView { + + + + protected lateinit var mPresenter: P + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mPresenter = onCreatePresenter() + } + + /** + * 创建Presenter的接口,每个实现本类的Activity应该都要实现本方法,返回对应的Presenter + */ + abstract fun onCreatePresenter(): P + + + + + override fun onError(e: Throwable) { + Logger.e(e, e.message ?: "") + } + + override fun doToast(message: String, duration: Int) { + context?.toast(message, duration) + } + + override fun doToast(res: Int, duration: Int) { + context?.toast(res, duration) + } + + override fun showLoading() { + } + + override fun hideLoading() { + } + +// override fun bindAutoDispose(): AutoDisposeConverter { +// return AutoDispose.autoDisposable( +// AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY) +// ) +// } +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseModel.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseModel.kt new file mode 100644 index 0000000..e3df554 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseModel.kt @@ -0,0 +1,7 @@ +package cn.qjm253.quick_android_mvp.base.mvp + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +interface BaseModel \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BasePresenter.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BasePresenter.kt new file mode 100644 index 0000000..a2d9acd --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BasePresenter.kt @@ -0,0 +1,10 @@ +package cn.qjm253.quick_android_mvp.base.mvp + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +abstract class BasePresenter { + protected lateinit var mView: V + protected lateinit var mModel: M +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseView.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseView.kt new file mode 100644 index 0000000..28f6875 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/base/mvp/BaseView.kt @@ -0,0 +1,43 @@ +package cn.qjm253.quick_android_mvp.base.mvp + +import android.widget.Toast +import androidx.annotation.StringRes +import cn.qjm253.quick_android_mvp.exceptions.MVPExceptionWrapper +//import com.uber.autodispose.AutoDisposeConverter + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +interface BaseView { + + /** + * 通用的错误回调,应在Activity或者Fragment中实现 + */ + fun onError(e: Throwable) + + /** + * 显示吐司弹窗 + */ + fun doToast(message: String, duration: Int = Toast.LENGTH_SHORT) + fun doToast(@StringRes res: Int, duration: Int = Toast.LENGTH_SHORT) + + + /** + * 现在正在加载状态 + */ + fun showLoading() + + /** + * 取消正在加载状态 + */ + fun hideLoading() + + /** + * 绑定Android生命周期 防止RxJava内存泄漏 + * + * @param + * @return + */ +// fun bindAutoDispose(): AutoDisposeConverter +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealException.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealException.kt new file mode 100644 index 0000000..a4b765f --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealException.kt @@ -0,0 +1,9 @@ +package cn.qjm253.quick_android_mvp.exceptions + +import java.lang.Exception + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +class MVPAPIResultDealException(msg: String) : Exception(msg) \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealNeedRetryException.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealNeedRetryException.kt new file mode 100644 index 0000000..6150329 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPAPIResultDealNeedRetryException.kt @@ -0,0 +1,9 @@ +package cn.qjm253.quick_android_mvp.exceptions + +import java.lang.Exception + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +class MVPAPIResultDealNeedRetryException(msg: String) : Exception(msg) \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPExceptionWrapper.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPExceptionWrapper.kt new file mode 100644 index 0000000..f1aa0eb --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/exceptions/MVPExceptionWrapper.kt @@ -0,0 +1,16 @@ +package cn.qjm253.quick_android_mvp.exceptions + +import cn.qjm253.quick_android_base.util.GsonUtil +import java.lang.Exception + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +class MVPExceptionWrapper( + val originException: Exception +) + +fun test() { + +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/QuickAndroidMVPAPIManager.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/QuickAndroidMVPAPIManager.kt new file mode 100644 index 0000000..89977f7 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/QuickAndroidMVPAPIManager.kt @@ -0,0 +1,84 @@ +package cn.qjm253.quick_android_mvp.model.inernet + +import android.app.Application +import com.franmontiel.persistentcookiejar.PersistentCookieJar +import com.franmontiel.persistentcookiejar.cache.SetCookieCache +import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor +import okhttp3.OkHttpClient +import retrofit2.Converter +import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import java.nio.charset.Charset +import java.util.concurrent.TimeUnit + + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +object QuickAndroidMVPAPIManager { + + val UTF8 = Charset.forName("UTF-8") + val DEFAULT_CACHE_SIZE = 20 * 1024 * 1024 + val DEFAULT_TIME_OUT = 10L + val services = mutableListOf() + lateinit var client: OkHttpClient + lateinit var baseUrl: String + + + /** + * 网络请求工具类初始化 + */ + fun init( + application: Application, + enablePersistentCookieJar: Boolean = true, // 是否开启自动cookie保存和提交 + baseUrl: String = "" + ) { + val okhttpBuilder = OkHttpClient.Builder() + .connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS) + .writeTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS) + .readTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS) + + if (enablePersistentCookieJar) { + okhttpBuilder.cookieJar(PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(application))) + } + + this.baseUrl = baseUrl + client = okhttpBuilder + .build() + } + + /** + * 注册一个服务,支持Json解析 + */ + fun registerService(serviceClass: Class): T { + val newService = createService(serviceClass, GsonConverterFactory.create()) + services.add(newService!!) + return newService + } + + fun getService(serviceClass: Class): T { + var result: T? = null + services.forEach { + if(it as? T != null ) { + result = it + } + } + return result ?: registerService(serviceClass) + } + + fun createService(serviceClass: Class, vararg factory: Converter.Factory): T { + val build = Retrofit.Builder() + .baseUrl(baseUrl) + .client(client) + for (aFactory in factory) { + build.addConverterFactory(aFactory) + } + + val retrofit = build + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build() + return retrofit.create(serviceClass) + } +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPObserver.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPObserver.kt new file mode 100644 index 0000000..e0152d4 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPObserver.kt @@ -0,0 +1,43 @@ +package cn.qjm253.quick_android_mvp.model.inernet.rx + +import androidx.annotation.CallSuper +import cn.qjm253.quick_android_mvp.QuickAndroidMVP +import cn.qjm253.quick_android_mvp.base.mvp.BaseView +import io.reactivex.Observer +import io.reactivex.disposables.Disposable + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +abstract class QuickAndroidMVPObserver(private val mView: BaseView) : Observer { + + @CallSuper + override fun onComplete() { + QuickAndroidMVP.onCompleteListeners.forEach { + it() + } + } + + @CallSuper + override fun onNext(t: T) { + QuickAndroidMVP.onBeforeNextListeners.forEach { + it() + } + + } + + @CallSuper + override fun onError(e: Throwable) { + QuickAndroidMVP.onErrorListeners.forEach { + it(e) + } + mView.onError(e) + } + + @CallSuper + override fun onSubscribe(d: Disposable) { + } + +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPResultDeal.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPResultDeal.kt new file mode 100644 index 0000000..f4e2661 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/QuickAndroidMVPResultDeal.kt @@ -0,0 +1,69 @@ +package cn.qjm253.quick_android_mvp.model.inernet.rx + +import io.reactivex.Observable + + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +abstract class QuickAndroidMVPResultDeal ( + exceptionCodes: Array>, // 错误的状态码对应表 + normalCodes: Array>, // 除错误以外的状态码 + needRetryCodes: Array> // 需要重试的状态码 +) { + + enum class Type { + TYPE_NORMAL, TYPE_ERROR, TYPE_ERROR_NEED_RETRY + } + + class QuickAndroidMVPResultDealItem( + val code: Int, + val description: String, + val type: Type + ) + + + private val exceptionCodeMap: MutableMap = mutableMapOf(*exceptionCodes) + private val normalCodeMap: MutableMap = mutableMapOf(*normalCodes) + private val needRetryCodeMap: MutableMap = mutableMapOf(*needRetryCodes) + + + fun getQuickAndroidMVPResultDealItem(code: Int): QuickAndroidMVPResultDealItem? { + var item: QuickAndroidMVPResultDealItem? = null + when { + exceptionCodeMap.keys.contains(code) -> { + item = QuickAndroidMVPResultDealItem(code, exceptionCodeMap[code] ?: "", Type.TYPE_ERROR) + } + normalCodeMap.keys.contains(code) -> { + item = QuickAndroidMVPResultDealItem(code, normalCodeMap[code] ?: "", Type.TYPE_NORMAL) + } + needRetryCodeMap.keys.contains(code) -> { + item = QuickAndroidMVPResultDealItem(code, needRetryCodeMap[code] ?: "", Type.TYPE_ERROR_NEED_RETRY) + } + } + return item + } + + + /** + * 正常状态码下的统一处理回调 + */ + abstract fun normalDeal(code: Int, description: String) + + + /** + * 错误状态码下的统一处理回调 + */ + abstract fun errorDeal(code: Int, description: String) + + /** + * 处理后重试 + * + * eg.: 应用场景 => Token失效之后重新获取Token,新的Token获取成功后重新发起原先失败的请求 + * @return 返回的Observable触发onComplete 或者 onError, 则不会重新订阅原Observable + * 返回的Observable触发onNext,则会重新订阅原Observable + */ + abstract fun dealRetry(t: Throwable): Observable +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/RxExtensions.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/RxExtensions.kt new file mode 100644 index 0000000..709dd75 --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/inernet/rx/RxExtensions.kt @@ -0,0 +1,82 @@ +package cn.qjm253.quick_android_mvp.model.inernet.rx + +import cn.qjm253.quick_android_mvp.QuickAndroidMVP +import cn.qjm253.quick_android_mvp.base.mvp.BaseView +import cn.qjm253.quick_android_mvp.exceptions.MVPAPIResultDealException +import cn.qjm253.quick_android_mvp.exceptions.MVPAPIResultDealNeedRetryException +import cn.qjm253.quick_android_mvp.model.response.BaseQuickAndroidResponseBody +import io.reactivex.Observable +import io.reactivex.disposables.Disposable + + +/** + * 网络请求结果统一处理 + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +fun Observable.qaHandleResult(): Observable { + return this.compose { upstream -> + upstream.flatMap { + val code = it.code + + val item = QuickAndroidMVP.quickAndroidMVPResultDeal?.getQuickAndroidMVPResultDealItem(code) + when (item?.type) { + QuickAndroidMVPResultDeal.Type.TYPE_NORMAL -> { + QuickAndroidMVP.quickAndroidMVPResultDeal?.normalDeal(item.code, item.description) + return@flatMap Observable.just(it) + } + QuickAndroidMVPResultDeal.Type.TYPE_ERROR -> { + QuickAndroidMVP.quickAndroidMVPResultDeal?.errorDeal(item.code, item.description) + return@flatMap Observable.error(MVPAPIResultDealException(item.description)) + } + QuickAndroidMVPResultDeal.Type.TYPE_ERROR_NEED_RETRY -> { + return@flatMap Observable.error(MVPAPIResultDealNeedRetryException(item.description)) + } + } + return@flatMap Observable.just(it) + }.retryWhen { t: Observable -> + t.flatMap { + if(QuickAndroidMVP.quickAndroidMVPResultDeal != null && + it is MVPAPIResultDealNeedRetryException) { + return@flatMap QuickAndroidMVP.quickAndroidMVPResultDeal?.dealRetry(it) + } + return@flatMap Observable.error(it) + } + + } + } +} + + +/** + * 网络请求订阅封装 + */ +fun Observable.qaSubscribe( + mView: BaseView, + onNext_: (T) -> Unit, + onError_: (Throwable) -> Unit = {}, + onComplete_: () -> Unit = {}, + onSubscribe_: (Disposable) -> Unit = {} +) { + this.subscribe(object : QuickAndroidMVPObserver(mView) { + override fun onNext(t: T) { + super.onNext(t) + onNext_(t) + } + + override fun onError(e: Throwable) { + super.onError(e) + onError_(e) + } + + override fun onComplete() { + super.onComplete() + onComplete_() + } + + override fun onSubscribe(d: Disposable) { + super.onSubscribe(d) + onSubscribe_(d) + } + }) +} \ No newline at end of file diff --git a/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/response/BaseQuickAndroidResponseBody.kt b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/response/BaseQuickAndroidResponseBody.kt new file mode 100644 index 0000000..db6f0bb --- /dev/null +++ b/quick_android_mvp/src/main/java/cn/qjm253/quick_android_mvp/model/response/BaseQuickAndroidResponseBody.kt @@ -0,0 +1,9 @@ +package cn.qjm253.quick_android_mvp.model.response + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ +open class BaseQuickAndroidResponseBody( + val code: Int +) \ No newline at end of file diff --git a/quick_android_mvp/src/main/res/values/strings.xml b/quick_android_mvp/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_mvp/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_mvp/src/test/java/cn/qjm253/quick_android_mvp/ExampleUnitTest.java b/quick_android_mvp/src/test/java/cn/qjm253/quick_android_mvp/ExampleUnitTest.java new file mode 100644 index 0000000..a8a9b64 --- /dev/null +++ b/quick_android_mvp/src/test/java/cn/qjm253/quick_android_mvp/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_mvp; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/quick_android_qrcode/.gitignore b/quick_android_qrcode/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_qrcode/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_qrcode/README.md b/quick_android_qrcode/README.md new file mode 100644 index 0000000..3f01e17 --- /dev/null +++ b/quick_android_qrcode/README.md @@ -0,0 +1,51 @@ +> ## quick_android_qrcode 模块说明文档 +> +> 本模块基于[**BGAQRCode-Android**](https://github.com/bingoogolapple/BGAQRCode-Android)进行进一步的封装,支持使用RxJava链式调用的方式进行扫码并获得扫码的结果(不用复写`onActivityResult`来手动获取结果) + + + +- ### 基本使用 + +```kotlin +QuickAndroidQrCode + .create(context) // context 可以是Activity或者Fragment + .scanQrCode() + .subscribe({qrCodeResult-> // 扫码成功 + + }, { err-> // 扫码失败(权限被拒绝,摄像头打开失败等) + + }) + +// 当然,如果使用Kotlin开发也可以使用下面的统一扩展接口 +QuickAndroid + .scanQrCode(context) + .subscribe({qrCodeResult-> // 扫码成功 + + }, { err-> // 扫码失败(权限被拒绝,摄像头打开失败等) + + }) +``` + +- ### 进阶 + - **修改返回按钮的样式** + ```kotlin + QuickAndroidQrCode + .create(context) // context 可以是Activity或者Fragment + .setBackIconRes(R.drawable.back) // 设置返回按钮的资源 + .setBackIconSize(30f) // 设置返回按钮的大小 + .setBackIconMargin(top, right, bottom, left) // 设置返回按钮的边距 + .scanQrCode() + .subscribe({qrCodeResult-> // 扫码成功 + + }, { err-> // 扫码失败(权限被拒绝,摄像头打开失败等) + + }) + ``` + + + +- ### 模块说明 + + - 本模块提供了一个简单的[QuickAndroidQrCodeActivity](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/activity/QuickAndroidQrCodeActivity.kt)实现扫码界面,可以直接使用 + - 如果希望自定义扫码界面,也可以参考[QuickAndroidQrCodeActivity](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/activity/QuickAndroidQrCodeActivity.kt)复用本模块提供的[QuickAndroidQrCodeFragment](https://github.com/SunnyQjm/quickandroid/blob/master/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeFragment.kt)来实现自定义的界面 + diff --git a/quick_android_qrcode/build.gradle b/quick_android_qrcode/build.gradle new file mode 100644 index 0000000..cc041a3 --- /dev/null +++ b/quick_android_qrcode/build.gradle @@ -0,0 +1,42 @@ +apply plugin: 'com.android.library' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + implementation project(path: ':quick_android_base') + + // zxing 二维码识别和生成 + implementation "cn.bingoogolapple:bga-qrcode-zxing:${bag_qrcode_zxing_version}" +} diff --git a/quick_android_qrcode/proguard-rules.pro b/quick_android_qrcode/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/quick_android_qrcode/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/quick_android_qrcode/src/androidTest/java/cn/qjm253/quick_android_qrcode/ExampleInstrumentedTest.java b/quick_android_qrcode/src/androidTest/java/cn/qjm253/quick_android_qrcode/ExampleInstrumentedTest.java new file mode 100644 index 0000000..c7240b6 --- /dev/null +++ b/quick_android_qrcode/src/androidTest/java/cn/qjm253/quick_android_qrcode/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package cn.qjm253.quick_android_qrcode; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_qrcode.test", appContext.getPackageName()); + } +} diff --git a/quick_android_qrcode/src/main/AndroidManifest.xml b/quick_android_qrcode/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c3c81da --- /dev/null +++ b/quick_android_qrcode/src/main/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/QuickAndroidQrCode.kt b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/QuickAndroidQrCode.kt new file mode 100644 index 0000000..fa2f510 --- /dev/null +++ b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/QuickAndroidQrCode.kt @@ -0,0 +1,131 @@ +package cn.qjm253.quick_android_qrcode + +import androidx.annotation.DrawableRes +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.extensions.getLazySingleton +import cn.qjm253.quick_android_base.util.RxSchedulersHelper +import cn.qjm253.quick_android_qrcode.activity.QuickAndroidQrCodeActivity +import cn.qjm253.quick_android_qrcode.fragment.QuickAndroidQrCodeTransFragment +import cn.qjm253.quick_android_qrcode.model.QrCodeResult +import io.reactivex.Observable + +/** + * @author SunnyQjm + * @date 19-7-7 下午10:11 + */ + +class QuickAndroidQrCode { + + private var mQrCodeTransFragment: Lazy + private var backIconRes: Int = R.drawable.quick_android_qr_code_default_back + private var backIconSize: Float = 30f + private var backIconTopMargin: Float = 15f + private var backIconRightMargin: Float = 0f + private var backIconBottomMargin: Float = 0f + private var backIconLeftMargin: Float = 15f + + companion object { + const val TAG = "QuickAndroidQrCode" + + fun create(activity: FragmentActivity): QuickAndroidQrCode { + return QuickAndroidQrCode(activity) + } + + fun create(fragment: Fragment): QuickAndroidQrCode { + return QuickAndroidQrCode(fragment) + } + } + + constructor(activity: FragmentActivity) { + mQrCodeTransFragment = activity.supportFragmentManager + .getLazySingleton(TAG, QuickAndroidQrCodeTransFragment::class.java) + } + + constructor(fragment: Fragment) { + mQrCodeTransFragment = fragment.childFragmentManager + .getLazySingleton(TAG, QuickAndroidQrCodeTransFragment::class.java) + } + + /** + * 设置返回按钮的资源 + */ + fun setBackIconRes(@DrawableRes icon: Int): QuickAndroidQrCode { + backIconRes = icon + return this + } + + /** + * 设置返回按钮的大小 + * ps: 单位为dp + */ + fun setBackIconSize(size: Float): QuickAndroidQrCode { + backIconSize = size + return this + } + + /** + * 设置返回按钮的边距 + * 1. 单位为dp + * 2. 代码中已经自动去掉了状态栏的高度,不用考虑状态栏 + */ + fun setBackIconMargin(top: Float, right: Float, bottom: Float, left: Float): QuickAndroidQrCode { + backIconTopMargin = top + backIconRightMargin = right + backIconBottomMargin = bottom + backIconLeftMargin = left + return this + } + + /** + * 跳转到扫码界面,并返回一个Observable对象用于接收扫码结果 + */ + fun scanQrCode(): Observable { + return mQrCodeTransFragment.value + .setBackIconRes(backIconRes) + .setBackIconSize(backIconSize) + .setBackIconMargin( + backIconTopMargin, + backIconRightMargin, + backIconBottomMargin, + backIconLeftMargin + ) + .scanCode(QuickAndroidQrCodeActivity::class.java) + .compose(RxSchedulersHelper.io_main()) + } +} + + +////////////////////////////////////////////////////////// +////////// QuickAndroid 扩展 +////////////////////////////////////////////////////////// + +fun QuickAndroid.scanQrCode(activity: FragmentActivity): Observable { + return QuickAndroidQrCode.create(activity) + .scanQrCode() +} + +fun QuickAndroid.scanQrCode(fragment: Fragment): Observable { + return QuickAndroidQrCode.create(fragment) + .scanQrCode() +} + + +////////////////////////////////////////////////////////// +////////// FragmentActivity 扩展 +////////////////////////////////////////////////////////// + +fun FragmentActivity.scanCode(): Observable { + return QuickAndroidQrCode.create(this) + .scanQrCode() +} + +////////////////////////////////////////////////////////// +////////// Fragment 扩展 +////////////////////////////////////////////////////////// + +fun Fragment.scanCode(): Observable { + return QuickAndroidQrCode.create(this) + .scanQrCode() +} \ No newline at end of file diff --git a/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/activity/QuickAndroidQrCodeActivity.kt b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/activity/QuickAndroidQrCodeActivity.kt new file mode 100644 index 0000000..68c0632 --- /dev/null +++ b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/activity/QuickAndroidQrCodeActivity.kt @@ -0,0 +1,32 @@ +package cn.qjm253.quick_android_qrcode.activity + +import android.os.Bundle +import cn.qjm253.quick_android_base.base.activity.BaseQuickAndroidActivity +import cn.qjm253.quick_android_base.extensions.addFragmentToActivity +import cn.qjm253.quick_android_qrcode.R +import cn.qjm253.quick_android_qrcode.fragment.QuickAndroidQrCodeFragment +import com.gyf.immersionbar.BarHide +import com.gyf.immersionbar.ImmersionBar + +class QuickAndroidQrCodeActivity : BaseQuickAndroidActivity() { + + companion object { + const val QR_CODE_RESULT = QuickAndroidQrCodeFragment.QR_CODE_RESULT + const val QR_CODE_ERROR = QuickAndroidQrCodeFragment.QR_CODE_ERROR + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + ImmersionBar.with(this) + .fullScreen(true) + .hideBar(BarHide.FLAG_HIDE_NAVIGATION_BAR) + .init() + setContentView(R.layout.activity_quick_android_qr_code) + + // 如果有的话隐藏ActionBar + supportActionBar?.hide() + addFragmentToActivity(R.id.quickAndroidQrCodeContainer) { + return@addFragmentToActivity QuickAndroidQrCodeFragment.newInstance() + } + } +} diff --git a/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeFragment.kt b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeFragment.kt new file mode 100644 index 0000000..6366496 --- /dev/null +++ b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeFragment.kt @@ -0,0 +1,132 @@ +package cn.qjm253.quick_android_qrcode.fragment + +import android.content.Intent +import android.widget.RelativeLayout +import cn.bingoogolapple.qrcode.core.QRCodeView +import cn.qjm253.quick_android_base.base.fragment.BaseQuickAndroidFragment +import cn.qjm253.quick_android_base.extensions.e +import cn.qjm253.quick_android_base.extensions.i +import cn.qjm253.quick_android_base.extensions.vibrator +import cn.qjm253.quick_android_base.params.IntentParam +import cn.qjm253.quick_android_base.util.DisplayUtils +import cn.qjm253.quick_android_qrcode.R +import com.gyf.immersionbar.ImmersionBar +import kotlinx.android.synthetic.main.fragment_quick_android_qrcode.* + + +/** + * @author SunnyQjm + * @date 19-7-7 上午8:43 + */ + +class QuickAndroidQrCodeFragment : BaseQuickAndroidFragment() { + + companion object { + const val QR_CODE_RESULT = "QR_CODE_RESULT" + const val QR_CODE_ERROR = "QR_CODE_ERROR" + const val QR_CODE_BACK_ICON_RES = "QR_CODE_BACK_ICON_RES" + const val QR_CODE_BACK_ICON_SIZE = "QR_CODE_BACK_ICON_SIZE" + const val QR_CODE_BAKC_ICON_MARGIN = "QR_CODE_BAKC_ICON_MARGIN" + + fun newInstance(intentParam: IntentParam? = null): QuickAndroidQrCodeFragment { + return newInstance_(QuickAndroidQrCodeFragment::class.java, intentParam) + } + } + + override fun getRes(): Int = R.layout.fragment_quick_android_qrcode + + override fun initView() { + zxingview.setDelegate(object : QRCodeView.Delegate { + override fun onScanQRCodeSuccess(result: String?) { + // 识别成功,震动 + activity?.vibrator() + + Intent() + .putExtra(QR_CODE_RESULT, result).let { + activity?.setResult(0, it) + activity?.finish() + } + + } + + override fun onCameraAmbientBrightnessChanged(isDark: Boolean) { +// "onCameraAmbientBrightnessChanged => isDark: $isDark".i() + } + + override fun onScanQRCodeOpenCameraError() { + Intent() + .putExtra(QR_CODE_RESULT, "打开相机失败").let { + activity?.setResult(0, it) + activity?.finish() + } + "打开相机失败".e() + } + + }) + + val statusBarHeight = ImmersionBar.getStatusBarHeight(this); + + activity?.intent?.let { + val backIconRes = + it.getIntExtra(QR_CODE_BACK_ICON_RES, R.drawable.quick_android_qr_code_default_back) + val backIconSize = it.getFloatExtra(QR_CODE_BACK_ICON_SIZE, 30f) + val backIconMargin: FloatArray = + it.getFloatArrayExtra(QR_CODE_BAKC_ICON_MARGIN) ?: floatArrayOf(15f, 0f, 0f, 15f) + RelativeLayout.LayoutParams(imgBack.layoutParams).let { lp -> + lp.setMargins( + DisplayUtils.dip2px(context, backIconMargin[3]), + DisplayUtils.dip2px(context, backIconMargin[0]) + statusBarHeight, + DisplayUtils.dip2px(context, backIconMargin[1]), + DisplayUtils.dip2px(context, backIconMargin[2]) + ) + lp.width = DisplayUtils.dip2px(context, backIconSize) + lp.height = DisplayUtils.dip2px(context, backIconSize) + imgBack.layoutParams = lp + } + imgBack.setImageResource(backIconRes) + } + + imgBack.setOnClickListener { + activity?.onBackPressed() + } + + requestCamera() + } + + + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + super.onPermissionsGranted(requestCode, perms) + + // 打开后摄像头开始预览,但是并没有开始识别 + zxingview.startCamera() + + // 显示扫描框,并开始识别 + zxingview.startSpotAndShowRect() + } + + + override fun onPermissionsDenied(requestCode: Int, perms: MutableList) { + super.onPermissionsDenied(requestCode, perms) + Intent() + .putExtra(QR_CODE_RESULT, "获取相机权限失败").let { + activity?.setResult(0, it) + activity?.finish() + } + } + + override fun onStop() { + super.onStop() + zxingview.stopCamera() + } + + override fun onDestroy() { + zxingview?.onDestroy() + super.onDestroy() + } + + + override fun initialLoadData() { + } + + +} \ No newline at end of file diff --git a/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeTransFragment.kt b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeTransFragment.kt new file mode 100644 index 0000000..0ec7e3c --- /dev/null +++ b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/fragment/QuickAndroidQrCodeTransFragment.kt @@ -0,0 +1,114 @@ +package cn.qjm253.quick_android_qrcode.fragment + +import android.content.Intent +import android.os.Bundle +import androidx.annotation.DrawableRes +import androidx.fragment.app.Fragment +import cn.qjm253.quick_android_base.base.activity.BaseQuickAndroidActivity +import cn.qjm253.quick_android_base.extensions.e +import cn.qjm253.quick_android_base.extensions.i +import cn.qjm253.quick_android_base.extensions.jumpForResult +import cn.qjm253.quick_android_base.extensions.toJson +import cn.qjm253.quick_android_base.params.IntentParam +import cn.qjm253.quick_android_qrcode.R +import cn.qjm253.quick_android_qrcode.model.QrCodeResult +import io.reactivex.Observable +import io.reactivex.ObservableEmitter + +/** + * 这个Fragment用于跳转到扫码界面,并接收其返回的结果,然后使用RxJava进行封装,便于链式调用 + * + * @author SunnyQjm + * @date 19-7-8 下午3:22 + */ +class QuickAndroidQrCodeTransFragment : Fragment() { + + private var emitter: ObservableEmitter? = null + + private var backIconRes: Int = R.drawable.quick_android_qr_code_default_back + private var backIconSize: Float = 30f + private var backIconTopMargin: Float = 15f + private var backIconRightMargin: Float = 0f + private var backIconBottomMargin: Float = 0f + private var backIconLeftMargin: Float = 15f + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + retainInstance = true + } + + /** + * 设置返回按钮的资源 + */ + fun setBackIconRes(@DrawableRes icon: Int): QuickAndroidQrCodeTransFragment { + backIconRes = icon + return this + } + + /** + * 设置返回按钮的大小 + * ps: 单位为dp + */ + fun setBackIconSize(size: Float): QuickAndroidQrCodeTransFragment { + backIconSize = size + return this + } + + /** + * 设置返回按钮的边距 + * 1. 单位为dp + * 2. 代码中已经自动去掉了状态栏的高度,不用考虑状态栏 + */ + fun setBackIconMargin( + top: Float, + right: Float, + bottom: Float, + left: Float + ): QuickAndroidQrCodeTransFragment { + backIconTopMargin = top + backIconRightMargin = right + backIconBottomMargin = bottom + backIconLeftMargin = left + return this + } + + fun scanCode(clazz: Class): Observable { + return Observable.create { emitter -> + // 保存事件发送器 + this.emitter = emitter + jumpForResult( + clazz, 0, IntentParam() + .add(QuickAndroidQrCodeFragment.QR_CODE_BACK_ICON_RES, backIconRes) + .add(QuickAndroidQrCodeFragment.QR_CODE_BACK_ICON_SIZE, backIconSize) + .add( + QuickAndroidQrCodeFragment.QR_CODE_BAKC_ICON_MARGIN, floatArrayOf( + backIconTopMargin, backIconRightMargin, + backIconBottomMargin, backIconLeftMargin + ) + ) + ) + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + when (requestCode) { + 0 -> { // 扫码结果处理 + data?.let { + val qrCodeResult = it.getStringExtra(QuickAndroidQrCodeFragment.QR_CODE_RESULT) + val qrCodeError = it.getStringExtra(QuickAndroidQrCodeFragment.QR_CODE_ERROR) + qrCodeResult?.i() + qrCodeError?.e() + when { + qrCodeResult != null -> this.emitter?.onNext(QrCodeResult(qrCodeResult)) + qrCodeError != null -> this.emitter?.onError(Throwable(qrCodeError)) + else -> { + + } + } + this.emitter?.onComplete() + } + } + } + } +} \ No newline at end of file diff --git a/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/model/QrCodeResult.kt b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/model/QrCodeResult.kt new file mode 100644 index 0000000..87853a0 --- /dev/null +++ b/quick_android_qrcode/src/main/java/cn/qjm253/quick_android_qrcode/model/QrCodeResult.kt @@ -0,0 +1,9 @@ +package cn.qjm253.quick_android_qrcode.model + +/** + * @author SunnyQjm + * @date 19-7-8 下午3:32 + */ +class QrCodeResult ( + val content: String +) \ No newline at end of file diff --git a/quick_android_qrcode/src/main/res/drawable/quick_android_qr_code_default_back.png b/quick_android_qrcode/src/main/res/drawable/quick_android_qr_code_default_back.png new file mode 100644 index 0000000000000000000000000000000000000000..cab12e2c740bbe0ef5947e7408932e7cfe8222db GIT binary patch literal 752 zcmV z1*H^H%0kFOsgF*5r%q3g)ji*PzT@7zzvnsc*FE>nbI&tG#}9VAA3Z?70y-|x-vS+9 z0Q2J^C}|0R zq@4iHWTE%$%Kz|+4+9`+H-OVw=mU%Y<{2LXK+;|S`QP?O7XQ^dzB+)U2>>Uu&?grE zrH%Ni0FovF9LqwVTKwm>;;R8jItbuM7W&NMKeQQN1whha0Ee>B7Z(4%?f6;%X^Ahk z*jE<+u10(m06YhzimQ#zpOcrE~vmI8R0P3{)S(WaC2IKMc6qy+$Or%gf8i2JnxsVUO z9L@tE?ct}r{B*1)nKm@T9v%Q``KQ|;9s5Y03|sH9D?IQ^PI~cKLGo=>1dkOk0^mM? zWfnb4a!qFdQmCYr0PbedGbG0%A{1W%bCE;73Wr2+1F)4axcd_h!4+UWAh-iWM`#5g zGD2$rQ4v}Nh=|ZSKs1CZ0Fe-?0YpKl3J?LIIzVlN5CAn1!T{7l2nA3BAsj&42q6L5 zLX_<0W^NLIVszI7@O@rvMCLqy1aWG|5k$11K3hI9B*uz%xFL-2-?FM<2gm i0nx9J_xw7)0{#NZ(FaghNsuW30000 + + + + + + \ No newline at end of file diff --git a/quick_android_qrcode/src/main/res/layout/fragment_quick_android_qrcode.xml b/quick_android_qrcode/src/main/res/layout/fragment_quick_android_qrcode.xml new file mode 100644 index 0000000..e444d95 --- /dev/null +++ b/quick_android_qrcode/src/main/res/layout/fragment_quick_android_qrcode.xml @@ -0,0 +1,38 @@ + + + + + + + + + + \ No newline at end of file diff --git a/quick_android_qrcode/src/main/res/values/strings.xml b/quick_android_qrcode/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_qrcode/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_qrcode/src/test/java/cn/qjm253/quick_android_qrcode/ExampleUnitTest.java b/quick_android_qrcode/src/test/java/cn/qjm253/quick_android_qrcode/ExampleUnitTest.java new file mode 100644 index 0000000..5486f0f --- /dev/null +++ b/quick_android_qrcode/src/test/java/cn/qjm253/quick_android_qrcode/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_qrcode; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/quick_android_rx_permission/.gitignore b/quick_android_rx_permission/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_rx_permission/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_rx_permission/README.md b/quick_android_rx_permission/README.md new file mode 100644 index 0000000..510bc39 --- /dev/null +++ b/quick_android_rx_permission/README.md @@ -0,0 +1,37 @@ +> ## quick_android_rx_permission 模块说明文档 +> +> 本模块基于[easypermissions](https://github.com/googlesamples/easypermissions)进行封装,实现了RxJava链式调用进行动态权限请求,不需要显示的复写权限请求回调,请求逻辑和请求结果可以在同一代码段,不用分开编写。(封装实现时参考了[RxPermissions](https://github.com/tbruyelle/RxPermissions)项目) + + + +- ### 使用示例 + +```kotlin +QuickAndroidRxPermission + .create(context) // 这个context可以是Activity,也可以是Fragment + .request( + arrayof(Manifest.android.CAMERA) + ) + .subscribe { + if(it.granted) { // 权限请求通过 + + } else { // 权限请求拒绝 + + } + } + +// 当然,如果使用Kotlin开发也可以使用下面的统一扩展接口 +QuickAndroid + .createRxPermission(context) + .request( + arrayof(Manifest.android.CAMERA) + ) + .subscribe { + if(it.granted) { // 权限请求通过 + + } else { // 权限请求拒绝 + + } + } +``` + diff --git a/quick_android_rx_permission/build.gradle b/quick_android_rx_permission/build.gradle new file mode 100644 index 0000000..be7d677 --- /dev/null +++ b/quick_android_rx_permission/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + implementation project(path: ':quick_android_base') +} diff --git a/quick_android_rx_permission/proguard-rules.pro b/quick_android_rx_permission/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/quick_android_rx_permission/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/quick_android_rx_permission/src/androidTest/java/cn/qjm253/quick_android_rx_permission/ExampleInstrumentedTest.java b/quick_android_rx_permission/src/androidTest/java/cn/qjm253/quick_android_rx_permission/ExampleInstrumentedTest.java new file mode 100644 index 0000000..36cd7a1 --- /dev/null +++ b/quick_android_rx_permission/src/androidTest/java/cn/qjm253/quick_android_rx_permission/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package cn.qjm253.quick_android_rx_permission; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_rx_permission.test", appContext.getPackageName()); + } +} diff --git a/quick_android_rx_permission/src/main/AndroidManifest.xml b/quick_android_rx_permission/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3d9ae9b --- /dev/null +++ b/quick_android_rx_permission/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermission.kt b/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermission.kt new file mode 100644 index 0000000..139bbbd --- /dev/null +++ b/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermission.kt @@ -0,0 +1,65 @@ +package cn.qjm253.quick_android_rx_permission + +import androidx.annotation.StringRes +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import cn.qjm253.quick_android_base.QuickAndroid +import cn.qjm253.quick_android_base.extensions.getLazySingleton +import cn.qjm253.quick_android_base.util.RxSchedulersHelper +import io.reactivex.Observable + +/** + * @author SunnyQjm + * @date 19-7-8 上午9:03 + */ + +class QuickAndroidRxPermission { + companion object { + const val TAG = "QuickAndroidRxPermission" + + fun create(activity: FragmentActivity): QuickAndroidRxPermission { + return QuickAndroidRxPermission(activity) + } + + fun create(fragment: Fragment): QuickAndroidRxPermission { + return QuickAndroidRxPermission(fragment) + } + } + + private var mRxPermissionFragment: Lazy + private var requestCode = 0 + + constructor(activity: FragmentActivity) { + mRxPermissionFragment = activity.supportFragmentManager + .getLazySingleton(TAG, QuickAndroidRxPermissionFragment::class.java) + } + + constructor(fragment: Fragment) { + mRxPermissionFragment = fragment.childFragmentManager + .getLazySingleton(TAG, QuickAndroidRxPermissionFragment::class.java) + } + + + fun request(permissions: Array, @StringRes tip: Int): Observable { + requestCode++ + return mRxPermissionFragment.value.requestPermissions(permissions, tip, requestCode) + .compose(RxSchedulersHelper.io_main()) + } + + fun request(permissions: Array, tip: String = "请求权限"): Observable { + requestCode++ + return mRxPermissionFragment.value.requestPermissions(permissions, tip, requestCode) + .compose(RxSchedulersHelper.io_main()) + } +} + +////////////////////////////////////////////////////////// +////////// QuickAndroid 扩展 +////////////////////////////////////////////////////////// +fun QuickAndroid.createRxPermission(activity: FragmentActivity): QuickAndroidRxPermission { + return QuickAndroidRxPermission.create(activity) +} + +fun QuickAndroid.createRxPermission(fragment: Fragment): QuickAndroidRxPermission { + return QuickAndroidRxPermission.create(fragment) +} \ No newline at end of file diff --git a/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionFragment.kt b/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionFragment.kt new file mode 100644 index 0000000..e4b5033 --- /dev/null +++ b/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionFragment.kt @@ -0,0 +1,77 @@ +package cn.qjm253.quick_android_rx_permission + +import android.os.Bundle +import androidx.annotation.StringRes +import androidx.fragment.app.Fragment +import io.reactivex.Observable +import io.reactivex.ObservableEmitter +import pub.devrel.easypermissions.EasyPermissions + +/** + * @author SunnyQjm + * @date 19-7-8 上午9:13 + */ + +class QuickAndroidRxPermissionFragment : Fragment(), EasyPermissions.PermissionCallbacks { + + private val permissionsMap = + mutableMapOf>() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + retainInstance = true + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + /** + * 授权成功 + */ + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + permissionsMap[requestCode]?.let { + it.onNext(QuickAndroidRxPermissionItem(true, requestCode, perms)) + it.onComplete() + permissionsMap.remove(requestCode) + } + } + + /** + * 授权失败 + */ + override fun onPermissionsDenied(requestCode: Int, perms: MutableList) { + permissionsMap[requestCode]?.let { + it.onNext(QuickAndroidRxPermissionItem(false, requestCode, perms)) + it.onComplete() + permissionsMap.remove(requestCode) + } + } + + + /** + * 请求权限 + */ + fun requestPermissions(permissions: Array, @StringRes tip: Int, requestCode: Int) + : Observable { + return requestPermissions(permissions, getString(tip), requestCode) + } + + + fun requestPermissions(permissions: Array, tip: String, requestCode: Int) + : Observable { + return Observable.create { emitter -> + permissionsMap[requestCode] = emitter + activity?.let { + if (EasyPermissions.hasPermissions(it, *permissions)) { + onPermissionsGranted(requestCode, permissions.toMutableList()) + } else { + EasyPermissions.requestPermissions(this, tip, requestCode, *permissions) + } + } + } + } + +} \ No newline at end of file diff --git a/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionItem.kt b/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionItem.kt new file mode 100644 index 0000000..eaa55e9 --- /dev/null +++ b/quick_android_rx_permission/src/main/java/cn/qjm253/quick_android_rx_permission/QuickAndroidRxPermissionItem.kt @@ -0,0 +1,12 @@ +package cn.qjm253.quick_android_rx_permission + +/** + * @author SunnyQjm + * @date 19-7-8 上午9:34 + */ + +class QuickAndroidRxPermissionItem( + val granted: Boolean, + val requestCode: Int, + val perms: MutableList +) \ No newline at end of file diff --git a/quick_android_rx_permission/src/main/res/values/strings.xml b/quick_android_rx_permission/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_rx_permission/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_rx_permission/src/test/java/cn/qjm253/quick_android_rx_permission/ExampleUnitTest.java b/quick_android_rx_permission/src/test/java/cn/qjm253/quick_android_rx_permission/ExampleUnitTest.java new file mode 100644 index 0000000..7bb747a --- /dev/null +++ b/quick_android_rx_permission/src/test/java/cn/qjm253/quick_android_rx_permission/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_rx_permission; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/quick_android_webview/.gitignore b/quick_android_webview/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/quick_android_webview/.gitignore @@ -0,0 +1 @@ +/build diff --git a/quick_android_webview/README.md b/quick_android_webview/README.md new file mode 100644 index 0000000..41ed848 --- /dev/null +++ b/quick_android_webview/README.md @@ -0,0 +1,117 @@ +> ## quick_android_webview 模块说明文档 +> +> 本模块提供一个简单的**H5容器**实现方案。 +> +> - 接入腾讯的[X5浏览器](https://x5.tencent.com/)内核,比原生的更安全且对js的新特性有更好的支持,兼容性问题较少,同时支持和QQ、微信等共享内核,可以大大减少APP包的体积。 +> - 本模块实现一个简单的 `Android Webview Bridge` **QuickAndroidWebBridge**,可以实现js调用原生的扫码、图片选择、获取设备信息等功能 + + + +- ### 使用说明 + + - 首先在你的作为H5容器的Acivity中使用 `QuickAndroidWebview` 替代原生的Webview进行布局 + + ```xml + + + + ``` + + - 接着在Activity中使用 + + ```kotlin + // 初始化操作,绑定通信桥 + QuickAndroidWV + .init(this, quickAndroidWebview) + + // 加载URL + quickAndroidWebview.loadUrl("file:///android_asset/www/test.html") + ``` + + - 完成上面两步,基本上H5容器就可以使用了,H5端搭配使用[quick_android_web_bridge](https://github.com/SunnyQjm/quick_android_web_bridge) 这一JS库便可进行原生功能的调用 + +- ### 提供的原生调用能力如下: + + > H5端具体如何接入,参考[quick_android_web_bridge](https://github.com/SunnyQjm/quick_android_web_bridge) + + - #### toast(吐司弹窗) + + H5端可以使用[quick_android_web_bridge](https://github.com/SunnyQjm/quick_android_web_bridge)调用原生的toast + + ```javascript + /** + * 调用Android原生的toast接口 + * + * @param msg 要显示的信息 + */ + function toast(msg: string) + + // 使用示例 + QuickAndroidWebBridge.scanCode() + ``` + + - #### scanCode(扫码) + + H5端可以使用[quick_android_web_bridge](https://github.com/SunnyQjm/quick_android_web_bridge)调用原生的扫码功能,并得到扫码的结果 + + ```javascript + /** + * 调用原生 的扫码功能,并得到扫码的结果 + * + * @return 返回一个Promise对象,可以异步的得到扫码结果 + */ + function scanCode(): Promise + + + + // 使用示例 + QuickAndroidWebBridge.scanCode() + .then(result => { // 扫码成功,在此处理扫码的结果 + + }) + .catch(err => { // 发生错误,在此处理错误 + + }) + ``` + + - #### getSystemInfo(获取Android设备的信息) + + H5端可以使用[quick_android_web_bridge](https://github.com/SunnyQjm/quick_android_web_bridge)获取到当前Android手机的设备信息 + + ```javascript + /** + * 获取当前手机系统的信息 + * + * @return 返回一个Promise对象,可以异步得到扫码结果 + */ + function getSystemInfo(): Promise + + // 使用示例 + QuickAndroidWebBridge.getSystemInfo() + .then(result => { // 获取系统信息成功,在此处理结果 + + }) + .catch(err => { // 发生错误,在此处理错误 + + }) + ``` + + + + - 获取到的信息如下所示: + + | 属性名 | 属性类型 | 属性说明 | + | :-------------: | :------: | :------------------------: | + | brand | string | 手机品牌 | + | model | string | 手机型号 | + | hardware | string | 手机硬件信息 | + | sdkInt | number | Android SDK 版本 | + | release | string | 手机系统版本号 | + | statusBarHeight | number | 手机系统状态栏的高度(px) | + | systemLanguage | string | 当前手机上使用的语言 | + + + diff --git a/quick_android_webview/build.gradle b/quick_android_webview/build.gradle new file mode 100644 index 0000000..440f20f --- /dev/null +++ b/quick_android_webview/build.gradle @@ -0,0 +1,53 @@ +apply plugin: 'com.android.library' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' +android { + compileSdkVersion compile_sdk_version + + defaultConfig { + minSdkVersion min_sdk_version + targetSdkVersion target_sdk_version + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation "androidx.appcompat:appcompat:${appcompact_version}" + testImplementation "junit:junit:${junit_version}" + androidTestImplementation "androidx.test:runner:${test_runner_version}" + androidTestImplementation "androidx.test.espresso:espresso-core:${espresso_core_version}" + + implementation project(path: ':quick_android_base') + implementation project(path: ':quick_android_rx_permission') + implementation project(path: ':quick_android_image_picker') + implementation project(path: ':quick_android_qrcode') + api files('libs/tbs_sdk.jar') + implementation "org.jetbrains.anko:anko-commons:${anko_version}" + +} diff --git a/quick_android_webview/libs/armeabi/liblbs.so b/quick_android_webview/libs/armeabi/liblbs.so new file mode 100644 index 0000000000000000000000000000000000000000..b558c45172432db5a3ce760e7c052b4787173b10 GIT binary patch literal 15456 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

F&c2msYzLz4={-=8@%la*Rv0Unge|9V9=619* zuqR3P6kx?qly6`M2Rpzw3Fl3u4m{~R=E0X_7$k=KDKfBidn^JbiT zQg2iO=0rSeydnk-FLwq7`@swjc}cK8Hd6%cr`Sh)k{B+LI*mVtZZCj`QLGMQ4nBvg zhMv{wr-yhjQl8 zULu{i!Gq`c!H#o+vxC6f{LY{F@&K3vd;?mpvVR3M6_y>^v z*vor@46&f`;e9>lc;91jKH>(24}&axU5RtI1IN`}krMcVVvBUY6S`MSv1h$v&z6V{ za>*WQ)ANG?zP+9N*)E4}1<=|Wtq%t&Ht=)7emaNf93kFj_%KlDJG%*U_tnMkh7Wt> z5YDX&dpGgWfm~;kQv<>^Wx;_nzbGD)7wI5hlAoL%f+D*c04`oL%C<9S?Kq zPJ(BLQHlw~Zx3QSOF92kxgz9Ri+pGCQ`&{CEpfT4Q73sMONnp8%%H#yW*E31+^EDi z^e0(}>*!Y4TLOC8FSIWiFazGEo)wEkAI7^!O4!2lvDB^+7CbtVo!s>SJtJl(`xGpx zZE2!Cr1lRgnCHem;Aa4`0fm4SfDHgA-~qsHKsVqR;1u9xz%U>L_-IV!5d;rFHlPr& z0XH403QVv9^CH0=Ug}77~oXkbFzWkEu#-`3~)+T`dARQ zegioM{!4+~0`7!|kWXzvJWt}Rpn2D#dFij9Ir-nwSpDJq{yQ4UAAaYH$@-Y3AzJSc z<>(~DNTP@~o{0j;MbMWMaGr7Eig2R%3hvhj&nB>r5d-!jtv4r?BK~@!X6cnEn?rl6 zBPylD-#^ej>-49w3xor}-vGw`i_pD=AM`8F%kO%BmriS{?* zHT_N0Q*8b)o%{4$VS)@g%b3j{eH=2VPGj^uL1Wba4EpKr@pJgVCyHU@)-2ME?N-i9 z9J+f+kyMnEbW@{FG-VpB(aunacC@F8KQ|$W6Py-4P~Qy&W{? zSFquqbvoI=gK}Idd{4P;41UUhoX^pI9ySzCk5z9C)dPK3MPB)Jz-CPa3nPh4ax*I^%v5 znFHESp$G9NAEw%%qtr?79wJG3dzAR1^+ynozNWJ&89d3JF}z0;B|Ou>F3cbOPtf2% zQ{?h0jb=0HW>n=3K_2O6Qsu$UxGcyuTII;I$Q=}GurZ15cp~=b*u(KXx)x`e0ezG& zQt)n$M?MfFJd404+Sil|&CrLQW2WJ~Tsrj7_N}$BsCd!hB}+?gUr}0CzOn)zBB~#D z=B?e1j}C8Z!gn^e#k=m9cW)_j56eG|tQ>IQ3c=V@O8q$;Mff|PTdwxM@rT&1z=;H( z^hd%ezULJ@-M1+i+r>S@`jM4ajZ|z61T?1dnc4dAX+lBLH*MdLC z=h+l|+}8zsLOktT@JYPCT*1eE1Hk)0|NLiheT2(#etJBRddjy5{e)|Pp9OyHi+DSR zLTg7@``Z+1Q=z|Qpzo8(&d(9dgcGsZ2+vUQEMVkd)&ML5Q$b!)zJtddh#{sa;VXY9 zVFAXoBohE{0}%Uc00$pfGc!6-WzFD&JE+3T0Q^E_{O>8+QAdtY{?3ZNk@8_vVPCUM zVEkilKstcr;ZrB2;C|XdJpbAModWm(xW zDX((<=6TYhf<^Qx%h&2zkq2JNH=B&ZQZeJ=O)FV~VCE9JG$DhV$=ztk1Qf?aM=?)wiLL-Zys1x%xz|wF z3egcDMkeTJuM&J9p;IkHLj})23LVKgxhM{WG@urZZUx#Tm*|3^BbcMo5Yp)IoI-S- zJ=BLdCKy16<{FLeE{szyARp4-!O%V+`?Nx`sMG^e0YpcCKlME5C@*M5qiaD2)rpSw z%^>Ks97D7k@9(2dz9Tx?!}NEqBWfFH!q0nA*Z5Ihd0}b%Z)=E#3fV!hA3(f`AASEf x2bU_nT&;cpX04g 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%0Dw{d{pu#9FVj8RCE(d}NN6(R71WkUL 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 !3-Brg*_9PwKGi>G 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

q?D7Z1YI49Xs|&?HKZv8!gWZuS+L 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�B5EcL0Y$0ngtElTRsuuDl#}FJ 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

2?ieM=@4G}h9$o{jz_-ynBXk^{Ky;#?+GZ+?l% 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 documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("cn.qjm253.quick_android_webview.test", appContext.getPackageName()); + } +} diff --git a/quick_android_webview/src/main/AndroidManifest.xml b/quick_android_webview/src/main/AndroidManifest.xml new file mode 100644 index 0000000..bc94372 --- /dev/null +++ b/quick_android_webview/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/QuickAndroidWebview.kt b/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/QuickAndroidWebview.kt new file mode 100644 index 0000000..fd88df2 --- /dev/null +++ b/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/QuickAndroidWebview.kt @@ -0,0 +1,18 @@ +package cn.qjm253.quick_android_webview + +import androidx.fragment.app.FragmentActivity +import cn.qjm253.quick_android_webview.views.QuickAndroidWebview +import cn.qjm253.quick_android_webview.web_bridge.QuickAndroidWebBridge + +/** + * @author SunnyQjm + * @date 19-7-10 下午5:29 + */ +object QuickAndroidWV{ + + fun init(context: FragmentActivity, quickAndroidWebview: QuickAndroidWebview): QuickAndroidWV { + QuickAndroidWebBridge(context) + .bindWebView(quickAndroidWebview) + return this + } +} \ No newline at end of file diff --git a/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/views/QuickAndroidWebview.kt b/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/views/QuickAndroidWebview.kt new file mode 100644 index 0000000..f46485d --- /dev/null +++ b/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/views/QuickAndroidWebview.kt @@ -0,0 +1,180 @@ +package cn.qjm253.quick_android_webview.views + +/** + * @author SunnyQjm + * @date 19-7-7 下午11:24 + */ + +import android.Manifest +import android.annotation.SuppressLint +import android.content.Context +import android.net.Uri +import android.util.AttributeSet +import androidx.fragment.app.FragmentActivity +import cn.qjm253.quick_android_image_picker.MyImagePicker +import cn.qjm253.quick_android_rx_permission.QuickAndroidRxPermission +import com.qingmei2.rximagepicker.core.RxImagePicker +import com.qingmei2.rximagepicker_extension.MimeType +import com.qingmei2.rximagepicker_extension_wechat.WechatConfigrationBuilder +import com.tencent.smtt.export.external.interfaces.WebResourceError +import com.tencent.smtt.export.external.interfaces.WebResourceRequest +import com.tencent.smtt.sdk.* +import org.jetbrains.anko.selector + +/** + * 腾讯X5浏览器内核封装 + * 1. 支持图片选择 + */ +class QuickAndroidWebview(context: Context, attributeSet: AttributeSet) : + WebView(context, attributeSet) { + + var onWebViewLoadListener: OnWebViewLoadListener? = null + + init { + + val rxPermission = QuickAndroidRxPermission(context as FragmentActivity) + + this.webViewClient = object : WebViewClient() { + + /** + * 防止加载网页时调起系统浏览器 + */ + override fun shouldOverrideUrlLoading(p0: WebView?, p1: String?): Boolean { + p0?.loadUrl(p1 ?: "") + return true + } + + override fun onReceivedError(p0: WebView?, p1: WebResourceRequest?, p2: WebResourceError?) { + super.onReceivedError(p0, p1, p2) + p2?.let { + onWebViewLoadListener?.onLoadFail(p2) + } + } + + override fun onPageFinished(p0: WebView?, p1: String?) { + super.onPageFinished(p0, p1) + onWebViewLoadListener?.onLoadSuccess() + } + } + this.webChromeClient = object : WebChromeClient() { + override fun onProgressChanged(p0: WebView?, p1: Int) { + super.onProgressChanged(p0, p1) + onWebViewLoadListener?.onProgress(p1) + } + + @SuppressLint("CheckResult") + override fun openFileChooser(p0: ValueCallback?, p1: String?, p2: String?) { + rxPermission + .request(arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE)) + .subscribe { + if (it.granted) { + openImageChooserActivity(context, p0) + } + } + } + + @SuppressLint("CheckResult") + override fun onShowFileChooser( + p0: WebView?, + p1: ValueCallback>?, + p2: FileChooserParams? + ): Boolean { + rxPermission + .request(arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE)) + .subscribe { + if (it.granted) { + openImageChooserActivity(context, null, p1) + } + } + return true + } + } + initWebViewSettings() + } + + /** + * 打开图片选择 + */ + private fun openImageChooserActivity( + context: Context, valueCallback: ValueCallback? = null, + valueCallback2: ValueCallback>? = null + ) { + context.selector("选择获取图片方式", listOf("拍照", "相册")) { _, i -> + when (i) { + 0 -> { // 拍照 + // 使用摄像头拍摄 + RxImagePicker.create() + .openCamera(context) + .subscribe { result -> + valueCallback?.onReceiveValue(result.uri) + valueCallback2?.onReceiveValue(arrayOf(result.uri)) + } + } + 1 -> { // 相册选择 + val result = mutableListOf() + // 打开相册选择 + RxImagePicker.create(MyImagePicker::class.java) + .openZhihuStyleGallery( + context, + WechatConfigrationBuilder(MimeType.INSTANCE.ofImage(), false) + .maxSelectable(9) + .countable(true) + .spanCount(4) + .countable(false) + .build() + ) + .subscribe({ res -> + // onNext + result.add(res.uri) + }, { + // onError + + }, { + // onComplete + if (result.size <= 0) { + valueCallback2?.onReceiveValue(null) + } else { + valueCallback2?.onReceiveValue(result.toTypedArray()) + } + }) + + } + } + } + } + + @SuppressLint("SetJavaScriptEnabled") + private fun initWebViewSettings() { + val webSetting = this.settings + webSetting.javaScriptEnabled = true + webSetting.javaScriptCanOpenWindowsAutomatically = true + webSetting.allowFileAccess = true + webSetting.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS + webSetting.setSupportZoom(true) + webSetting.builtInZoomControls = true + webSetting.useWideViewPort = true + webSetting.setSupportMultipleWindows(true) + // webSetting.setLoadWithOverviewMode(true); + webSetting.setAppCacheEnabled(true) + // webSetting.setDatabaseEnabled(true); + webSetting.domStorageEnabled = true + webSetting.setGeolocationEnabled(true) + webSetting.setAppCacheMaxSize(java.lang.Long.MAX_VALUE) + // webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY); + webSetting.pluginState = WebSettings.PluginState.ON_DEMAND + // webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH); + webSetting.cacheMode = WebSettings.LOAD_NORMAL + + webSetting.setAllowUniversalAccessFromFileURLs(true) + + // this.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension + // settings 的设计 + } + + + interface OnWebViewLoadListener { + fun onLoadSuccess() + fun onLoadFail(error: WebResourceError) + fun onProgress(progress: Int) + } +} \ No newline at end of file diff --git a/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/web_bridge/QuickAndroidWebBridge.kt b/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/web_bridge/QuickAndroidWebBridge.kt new file mode 100644 index 0000000..98ac1c1 --- /dev/null +++ b/quick_android_webview/src/main/java/cn/qjm253/quick_android_webview/web_bridge/QuickAndroidWebBridge.kt @@ -0,0 +1,109 @@ +package cn.qjm253.quick_android_webview.web_bridge + +import android.annotation.SuppressLint +import android.webkit.JavascriptInterface +import androidx.fragment.app.FragmentActivity +import cn.qjm253.quick_android_base.extensions.toJson +import cn.qjm253.quick_android_base.extensions.toast +import cn.qjm253.quick_android_base.util.SystemInfoHelper +import cn.qjm253.quick_android_qrcode.QuickAndroidQrCode +import cn.qjm253.quick_android_webview.views.QuickAndroidWebview +import com.tencent.smtt.sdk.ValueCallback +import java.lang.Exception + +/** + * 与WebView中的Js相互通信的工具类 + * + * @author SunnyQjm + * @date 19-7-8 下午2:48 + */ + +class QuickAndroidWebBridge( + private val context: FragmentActivity +) { + companion object { + const val JS_CALLER_NAME = "QuickAndroidJsCallEr" + + + ////////////////////////////////////////////// + /////// 回调名称定义 + ////////////////////////////////////////////// + const val CALLBACK_BASE_NAME = "Quick_Android_Js_Callback_" + + /** + * 扫码相关回调 + */ + const val CALLBACK_SCAN_CODE_SUCCESS = "${CALLBACK_BASE_NAME}scan_code_success" // 扫码成功回调名 + const val CALLBACK_SCAN_CODE_FAIL = "${CALLBACK_BASE_NAME}scan_code_fail" // 扫码失败回调名 + const val CALLBACK_GET_SYSTEM_INFO_SUCCESS = "${CALLBACK_BASE_NAME}get_system_info_success" // 获取系统信息成功 + const val CALLBACK_GET_SYSTEM_INFO_FAIL = "${CALLBACK_BASE_NAME}get_system_info_fail" // 获取系统信息失败 + } + + private var webView: QuickAndroidWebview? = null + + /** + * 绑定到WebView上 + */ + fun bindWebView(webview: QuickAndroidWebview) { + this.webView = webview + webview.addJavascriptInterface(this, JS_CALLER_NAME) + } + + /** + * 提供给Js调用的显示toast接口 + */ + @JavascriptInterface + fun toast(msg: String) { + context.toast(msg) + } + + + /** + * 提供给Js调用的扫码接口 + */ + @SuppressLint("CheckResult") + @JavascriptInterface + fun scanCode() { + // 调用原生的扫码接口 + webView?.post { + // 需要在主线程中执行 + QuickAndroidQrCode.create(context) + .scanQrCode() + .subscribe({ + // 扫码结果 + callJs(CALLBACK_SCAN_CODE_SUCCESS, it.content) + }, { + // 扫码出错 + callJs(CALLBACK_SCAN_CODE_FAIL, it.message ?: "扫码出错") + }) + } + + } + + /** + * 提供给Js调用,得到系统的信息 + */ + @JavascriptInterface + fun getSystemInfo() { + try { + val systemInfo = SystemInfoHelper + .buildSystemInfo(context) + callJs(CALLBACK_GET_SYSTEM_INFO_SUCCESS, systemInfo.toJson()) + } catch (e: Exception) { + callJs(CALLBACK_GET_SYSTEM_INFO_FAIL, e.message ?: "获取系统信息失败") + } + } + + /** + * 调用Js的回调函数,并且支持传递一个字符串参数 + */ + fun callJs(callbackName: String, param: String = "", callback: ValueCallback = ValueCallback {}) { + webView?.post { + // 执行JS的代码,需要在主线程中进行 + webView?.evaluateJavascript("javascript:$callbackName('$param')", callback) + } + + } +} + + diff --git a/quick_android_webview/src/main/res/values/strings.xml b/quick_android_webview/src/main/res/values/strings.xml new file mode 100644 index 0000000..8542005 --- /dev/null +++ b/quick_android_webview/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/quick_android_webview/src/test/java/cn/qjm253/quick_android_webview/ExampleUnitTest.java b/quick_android_webview/src/test/java/cn/qjm253/quick_android_webview/ExampleUnitTest.java new file mode 100644 index 0000000..862f1a3 --- /dev/null +++ b/quick_android_webview/src/test/java/cn/qjm253/quick_android_webview/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package cn.qjm253.quick_android_webview; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 38427ab..2e38dff 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,11 @@ rootProject.name = "MIN-VPN-Client_V2" include ':app' +include ':quick_android_base' +include ':quick_android_custom_view' +include ':quick_android_easy_bar' +include ':quick_android_file_picker' +include ':quick_android_image_picker' +include ':quick_android_mvp' +include ':quick_android_qrcode' +include ':quick_android_rx_permission' +include ':quick_android_webview'