kotlin转化
This commit is contained in:
parent
89164dbd44
commit
90200b5348
@ -11,6 +11,7 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
<option value="$PROJECT_DIR$/mylibrary" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
|
|||||||
@ -25,6 +25,12 @@
|
|||||||
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_details_all.xml" value="0.2171875" />
|
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_details_all.xml" value="0.2171875" />
|
||||||
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_details_loading_all.xml" value="0.2171875" />
|
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_details_loading_all.xml" value="0.2171875" />
|
||||||
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_item.xml" value="0.2682291666666667" />
|
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_item.xml" value="0.2682291666666667" />
|
||||||
|
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_address_switch.xml" value="0.18125" />
|
||||||
|
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_choice_address.xml" value="0.25" />
|
||||||
|
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_dis_car.xml" value="0.19947916666666668" />
|
||||||
|
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_search_address.xml" value="0.159375" />
|
||||||
|
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/item_cargo.xml" value="0.36614583333333334" />
|
||||||
|
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/my.xml" value="0.33" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@ -83,40 +83,20 @@ dependencies {
|
|||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
implementation 'org.jetbrains:annotations:15.0'
|
// implementation 'org.jetbrains:annotations:15.0'
|
||||||
//implementation files('libs\\AMap2DMap_6.0.0_AMapSearch_7.9.0_20210331.jar')
|
|
||||||
// implementation files('libs\\AMap_Location_V5.3.1_20210331.jar')
|
|
||||||
//implementation files('libs\\Android_Lite3DMap_SDK_V1.2.0_20210412.jar')
|
|
||||||
// implementation files('libs\\AMap2DMap_6.0.0_AMapSearch_7.9.0_20210331.jar')
|
|
||||||
//implementation files('libs\\android-support-v4.jar')
|
|
||||||
testImplementation 'junit:junit:4.+'
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
|
||||||
//图片
|
|
||||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
|
||||||
implementation 'top.zibin:Luban:1.1.3'
|
implementation 'top.zibin:Luban:1.1.3'
|
||||||
//okhttp
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.2.0'
|
|
||||||
//gson
|
|
||||||
implementation 'com.google.code.gson:gson:2.8.5'
|
|
||||||
//角标文字
|
//角标文字
|
||||||
implementation 'com.haozhang.libary:android-slanted-textview:1.2'
|
implementation 'com.haozhang.libary:android-slanted-textview:1.2'
|
||||||
//加载
|
//加载
|
||||||
implementation 'com.scwang.smart:refresh-layout-kernel:2.0.1'
|
implementation 'com.scwang.smart:refresh-layout-kernel:2.0.1'
|
||||||
implementation 'com.scwang.smart:refresh-header-material:2.0.1'
|
implementation 'com.scwang.smart:refresh-header-material:2.0.1'
|
||||||
implementation 'com.scwang.smart:refresh-footer-ball:2.0.1' //球脉冲加载
|
|
||||||
implementation 'com.scwang.smart:refresh-footer-classics:2.0.1' //经典加载
|
|
||||||
implementation 'com.alibaba:fastjson:1.2.61'
|
implementation 'com.alibaba:fastjson:1.2.61'
|
||||||
//弹框
|
|
||||||
//
|
|
||||||
implementation 'com.lxj:xpopup:2.2.8'
|
|
||||||
//更新版本
|
//更新版本
|
||||||
implementation 'com.github.jenly1314.AppUpdater:app-updater:1.1.0'
|
implementation 'com.github.jenly1314.AppUpdater:app-updater:1.1.0'
|
||||||
implementation 'com.github.jenly1314.AppUpdater:app-dialog:1.1.0'
|
implementation 'com.github.jenly1314.AppUpdater:app-dialog:1.1.0'
|
||||||
//轮播插件
|
//轮播插件
|
||||||
implementation 'com.github.zhpanvip:BannerViewPager:3.5.4'
|
implementation 'com.github.zhpanvip:BannerViewPager:3.5.4'
|
||||||
//选择器
|
//选择器
|
||||||
//implementation 'com.github.gzu-liyujiang:AndroidPicker:Tag'
|
|
||||||
implementation 'com.github.gzu-liyujiang.AndroidPicker:WheelPicker:3.1.1'
|
implementation 'com.github.gzu-liyujiang.AndroidPicker:WheelPicker:3.1.1'
|
||||||
implementation 'com.github.gzu-liyujiang.AndroidPicker:AddressPicker:3.1.1'
|
implementation 'com.github.gzu-liyujiang.AndroidPicker:AddressPicker:3.1.1'
|
||||||
//EventBus
|
//EventBus
|
||||||
@ -125,13 +105,6 @@ dependencies {
|
|||||||
//工具类
|
//工具类
|
||||||
implementation 'cn.hutool:hutool-all:5.7.11'
|
implementation 'cn.hutool:hutool-all:5.7.11'
|
||||||
//UI库
|
//UI库
|
||||||
implementation 'com.github.tamsiree.RxTool:RxUI:2.6.2'
|
|
||||||
//相机库
|
|
||||||
implementation 'com.github.tamsiree.RxTool:RxCamera:2.6.2'
|
|
||||||
//功能库(Zxing扫描与生成二维码条形码)
|
|
||||||
implementation 'com.github.tamsiree.RxTool:RxFeature:2.6.2'
|
|
||||||
//ArcGis For Android工具库(API:100.1以上版本)
|
|
||||||
implementation 'com.github.tamsiree.RxTool:RxArcGisKit:2.6.2'
|
|
||||||
//友盟
|
//友盟
|
||||||
// 下面各SDK根据宿主App是否使用相关业务按需引入。
|
// 下面各SDK根据宿主App是否使用相关业务按需引入。
|
||||||
// 友盟统计SDK
|
// 友盟统计SDK
|
||||||
@ -142,21 +115,10 @@ dependencies {
|
|||||||
//xui
|
//xui
|
||||||
implementation 'com.github.xuexiangjys:XUI:1.1.8'
|
implementation 'com.github.xuexiangjys:XUI:1.1.8'
|
||||||
|
|
||||||
implementation "io.reactivex.rxjava3:rxjava:3.1.4"
|
|
||||||
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
|
|
||||||
// implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
|
|
||||||
|
|
||||||
implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.2.9'
|
|
||||||
|
|
||||||
// implementation 'io.github.lucksiege:pictureselector:v3.0.9'
|
|
||||||
|
|
||||||
implementation 'com.github.getActivity:XToast:8.2'
|
implementation 'com.github.getActivity:XToast:8.2'
|
||||||
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
|
|
||||||
|
|
||||||
implementation 'com.github.tbruyelle:rxpermissions:0.12'
|
implementation 'com.github.tbruyelle:rxpermissions:0.12'
|
||||||
|
|
||||||
|
|
||||||
implementation 'com.amap.api:3dmap:8.0.0'
|
implementation project(path: ':mylibrary')
|
||||||
implementation 'com.amap.api:location:5.4.0'
|
|
||||||
implementation 'com.amap.api:search:7.9.0'
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
@ -12,7 +12,7 @@
|
|||||||
"filters": [],
|
"filters": [],
|
||||||
"versionCode": 27,
|
"versionCode": 27,
|
||||||
"versionName": "3.0.7",
|
"versionName": "3.0.7",
|
||||||
"outputFile": "dhhy-cargo-0718_16-12-3.0.7.apk"
|
"outputFile": "dhhy-cargo-0830_17-18-3.0.7.apk"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@
|
|||||||
android:layout_width="@dimen/dp_22"
|
android:layout_width="@dimen/dp_22"
|
||||||
android:layout_height="@dimen/dp_22"
|
android:layout_height="@dimen/dp_22"
|
||||||
android:layout_marginLeft="@dimen/dp_4"
|
android:layout_marginLeft="@dimen/dp_4"
|
||||||
android:background="@drawable/selector_location"></ImageView>
|
></ImageView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.oneclouds.cargo.util.view.BaseRecyclerView
|
<com.oneclouds.cargo.util.view.BaseRecyclerView
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginLeft="@dimen/dp_6"
|
android:layout_marginLeft="@dimen/dp_6"
|
||||||
android:background="@color/transparent"
|
android:background="#00000000"
|
||||||
android:hint="请输入车牌号/手机号进行搜索"
|
android:hint="请输入车牌号/手机号进行搜索"
|
||||||
android:inputType="text|textAutoComplete"
|
android:inputType="text|textAutoComplete"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
|||||||
@ -39,7 +39,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginLeft="@dimen/dp_6"
|
android:layout_marginLeft="@dimen/dp_6"
|
||||||
android:background="@color/transparent"
|
android:background="#00000000"
|
||||||
android:hint="请输入关键字"
|
android:hint="请输入关键字"
|
||||||
android:inputType="text|textAutoComplete"
|
android:inputType="text|textAutoComplete"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
|||||||
@ -31,4 +31,5 @@
|
|||||||
<color name="tab_select">@color/color_theme</color>
|
<color name="tab_select">@color/color_theme</color>
|
||||||
<color name="tab_select_no">#C9C9C9</color>
|
<color name="tab_select_no">#C9C9C9</color>
|
||||||
<color name="gray">#999999</color>
|
<color name="gray">#999999</color>
|
||||||
|
<color name="red">#FF0000</color>
|
||||||
</resources>
|
</resources>
|
||||||
@ -1,5 +1,8 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
apply from: "compile.gradle"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
|
ext.kotlin_version = "1.5.0"
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
// jcenter() // 这个
|
// jcenter() // 这个
|
||||||
@ -18,6 +21,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "com.android.tools.build:gradle:4.2.0"
|
classpath "com.android.tools.build:gradle:4.2.0"
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
|
|||||||
92
compile.gradle
Normal file
92
compile.gradle
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
def SupportVersion = '28.0.0'
|
||||||
|
def ButterKnifeVersion = '10.0.0'
|
||||||
|
def CrashActivityVersion = '2.2.0'
|
||||||
|
def StatusBarVersion = '2.3.3'
|
||||||
|
def GsonVersion = '2.8.6'
|
||||||
|
def PhotoPickerVersion = 'v2.6.1'
|
||||||
|
//def PhotoPickerVersion = 'v2.7.2'
|
||||||
|
def GlideVersion = '4.12.0'
|
||||||
|
def AgentWebVersion = 'v4.1.9-androidx'
|
||||||
|
def NiceDialogVersion = '1.1.9'
|
||||||
|
def AndPermissionVersion = '2.0.3'
|
||||||
|
def BannerVersion = '1.4.10'
|
||||||
|
def SmartRefreshLayoutVersion = '1.1.0-alpha-12'
|
||||||
|
def MultideXVersion = '2.0.1'
|
||||||
|
def RXJavaVersion = '3.0.12'
|
||||||
|
def RXAndroidVersion = '3.0.0'
|
||||||
|
def RetrofitVersion = '2.9.0'
|
||||||
|
def OkHttpVersion = '4.9.1'
|
||||||
|
def AutoSizeVersion = '1.1.2'
|
||||||
|
def FlycoTabLayoutVersion = '2.1.2@aar'
|
||||||
|
def ZxingVersion = '1.3.8'
|
||||||
|
def BaseRecyclerViewAdapterHelper = '3.0.6'
|
||||||
|
def MagicIndicator = '1.7.0'
|
||||||
|
def PickerView = '4.1.9'
|
||||||
|
def NiceSpinner = '1.4.4'
|
||||||
|
def Countdownview = '2.1.6'
|
||||||
|
def Xpopup = '2.2.8'
|
||||||
|
def CheckVersionLib = '2.4.1_androidx'
|
||||||
|
def GooglePlayVersion = '15.0.1'
|
||||||
|
def Streamsupport = '1.7.3'
|
||||||
|
def NewbieGuideVersion = 'v2.4.0'
|
||||||
|
def CountdownviewVersion = '2.1.6'
|
||||||
|
def JpushVersion = '3.1.8'
|
||||||
|
def JcoreVersion = '1.2.7'
|
||||||
|
def BuglyVersion = 'latest.release'
|
||||||
|
project.ext {
|
||||||
|
android = [
|
||||||
|
compileSdkVersion: 30,
|
||||||
|
buildToolsVersion: "30.0.3",
|
||||||
|
applicationId : "com.dahe.examine",
|
||||||
|
minSdkVersion : 21,
|
||||||
|
targetSdkVersion : 30,
|
||||||
|
versionCode : 5,
|
||||||
|
versionName : "1.0.5",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"appcompat-v7" : "com.android.support:appcompat-v7:${SupportVersion}",
|
||||||
|
"support-v4" : "com.android.support:support-v4:${SupportVersion}",
|
||||||
|
"support-design" : "com.android.support:design:${SupportVersion}",
|
||||||
|
"recyclerview" : "com.android.support:recyclerview-v7:${SupportVersion}",
|
||||||
|
"butterknife" : "com.jakewharton:butterknife:${ButterKnifeVersion}",
|
||||||
|
"butterknife-compiler" : "com.jakewharton:butterknife-compiler:${ButterKnifeVersion}",
|
||||||
|
"customactivityoncrash": "cat.ereza:customactivityoncrash:${CrashActivityVersion}",
|
||||||
|
"gson" : "com.google.code.gson:gson:${GsonVersion}",
|
||||||
|
"PhotoPicker" : "com.github.LuckSiege.PictureSelector:picture_library:${PhotoPickerVersion}",
|
||||||
|
"PhotoPicker" : "io.github.lucksiege:pictureselector:${PhotoPickerVersion}",
|
||||||
|
"agentweb" : "com.github.Justson.AgentWeb:agentweb-core:${AgentWebVersion}",
|
||||||
|
"statusbaruitl" : "com.github.niorgai:StatusBarCompat:${StatusBarVersion}",
|
||||||
|
"glide" : "com.github.bumptech.glide:glide:${GlideVersion}",
|
||||||
|
"glide-compiler" : "com.github.bumptech.glide:compiler:${GlideVersion}",
|
||||||
|
"glide-okhttps" : "com.github.bumptech.glide:okhttp3-integration:${GlideVersion}",
|
||||||
|
"NiceDialog" : "com.github.Othershe:NiceDialog:${NiceDialogVersion}",
|
||||||
|
"Banner" : "com.youth.banner:banner:${BannerVersion}",
|
||||||
|
"RefreshLayout" : "com.scwang.smartrefresh:SmartRefreshLayout:${SmartRefreshLayoutVersion}",
|
||||||
|
"Multidex" : "androidx.multidex:multidex:${MultideXVersion}",
|
||||||
|
"rxjava" : "io.reactivex.rxjava3:rxjava:${RXJavaVersion}",
|
||||||
|
"rxandroid" : "io.reactivex.rxjava3:rxandroid:${RXAndroidVersion}",
|
||||||
|
"retrofit" : "com.squareup.retrofit2:retrofit:${RetrofitVersion}",
|
||||||
|
"converter-gson" : "com.squareup.retrofit2:converter-gson:${RetrofitVersion}",
|
||||||
|
"adapter-rxjava2" : "com.squareup.retrofit2:adapter-rxjava3:${RetrofitVersion}",
|
||||||
|
"okhttp" : "com.squareup.okhttp3:okhttp:${OkHttpVersion}",
|
||||||
|
"logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:${OkHttpVersion}",
|
||||||
|
"AutoSize" : "me.jessyan:autosize:${AutoSizeVersion}",
|
||||||
|
"FlycoTabLayout" : "com.flyco.tablayout:FlycoTabLayout_Lib:${FlycoTabLayoutVersion}",
|
||||||
|
"AndPermission" : "com.yanzhenjie:permission:${AndPermissionVersion}",
|
||||||
|
// "Zxing" : "cn.bingoogolapple:bga-qrcode-zxing:${ZxingVersion}",
|
||||||
|
"Zxing" : "com.github.bingoogolapple.BGAQRCode-Android:zxing:${ZxingVersion}",
|
||||||
|
"BaseRecyclerViewAdapterHelper" :"com.github.CymChad:BaseRecyclerViewAdapterHelper:${BaseRecyclerViewAdapterHelper}",
|
||||||
|
"MagicIndicator" :"com.github.hackware1993:MagicIndicator:${MagicIndicator}",
|
||||||
|
"NiceSpinner" :"com.github.arcadefire:nice-spinner:${NiceSpinner}",
|
||||||
|
"Countdownview" :"com.github.iwgang:countdownview:${Countdownview}",
|
||||||
|
"Xpopup" :"com.lxj:xpopup:${Xpopup}",
|
||||||
|
"CheckVersionLib" :"com.github.AlexLiuSheng:CheckVersionLib:${CheckVersionLib}",
|
||||||
|
"Bugly" :"com.tencent.bugly:crashreport:${BuglyVersion}",
|
||||||
|
"Streamsupport" :"net.sourceforge.streamsupport:streamsupport:${Streamsupport}",
|
||||||
|
"PickerView" :"com.contrarywind:Android-PickerView:${PickerView}",
|
||||||
|
"Permissionx" :'com.guolindev.permissionx:permissionx:1.6.4',
|
||||||
|
"3Dmap" :'com.amap.api:3dmap:8.0.0',
|
||||||
|
"Location" :'com.amap.api:location:5.4.0',
|
||||||
|
"Search" :'com.amap.api:search:7.9.0'
|
||||||
|
]
|
||||||
|
}
|
||||||
1
mylibrary/.gitignore
vendored
Normal file
1
mylibrary/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
||||||
78
mylibrary/build.gradle
Normal file
78
mylibrary/build.gradle
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'kotlin-android'
|
||||||
|
// id 'com.jakewharton.butterknife'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 30
|
||||||
|
buildToolsVersion "30.0.3"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 30
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
implementation 'androidx.core:core-ktx:1.3.1'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
|
testImplementation 'junit:junit:4.+'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
|
|
||||||
|
api rootProject.ext.dependencies["gson"]
|
||||||
|
api rootProject.ext.dependencies["glide"]
|
||||||
|
annotationProcessor rootProject.ext.dependencies["glide-compiler"]
|
||||||
|
api rootProject.ext.dependencies["agentweb"]
|
||||||
|
// api rootProject.ext.dependencies["Banner"]
|
||||||
|
api rootProject.ext.dependencies["RefreshLayout"]
|
||||||
|
api rootProject.ext.dependencies["rxjava"]
|
||||||
|
api rootProject.ext.dependencies["rxandroid"]
|
||||||
|
api rootProject.ext.dependencies["retrofit"]
|
||||||
|
api rootProject.ext.dependencies["converter-gson"]
|
||||||
|
api rootProject.ext.dependencies["adapter-rxjava2"]
|
||||||
|
api rootProject.ext.dependencies["okhttp"]
|
||||||
|
api rootProject.ext.dependencies["logging-interceptor"]
|
||||||
|
api rootProject.ext.dependencies["recyclerview"]
|
||||||
|
// api rootProject.ext.dependencies["AutoSize"]
|
||||||
|
api rootProject.ext.dependencies["statusbaruitl"]
|
||||||
|
api rootProject.ext.dependencies["BaseRecyclerViewAdapterHelper"]
|
||||||
|
api rootProject.ext.dependencies["PhotoPicker"]
|
||||||
|
// api rootProject.ext.dependencies["PickerView"]
|
||||||
|
api rootProject.ext.dependencies["Xpopup"]
|
||||||
|
// api rootProject.ext.dependencies["Countdownview"]
|
||||||
|
api rootProject.ext.dependencies["Multidex"]
|
||||||
|
api rootProject.ext.dependencies["NiceDialog"]
|
||||||
|
api rootProject.ext.dependencies["glide-okhttps"]
|
||||||
|
// api rootProject.ext.dependencies["Permissionx"]
|
||||||
|
api rootProject.ext.dependencies["3Dmap"]
|
||||||
|
api rootProject.ext.dependencies["Location"]
|
||||||
|
api rootProject.ext.dependencies["Search"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
0
mylibrary/consumer-rules.pro
Normal file
0
mylibrary/consumer-rules.pro
Normal file
21
mylibrary/proguard-rules.pro
vendored
Normal file
21
mylibrary/proguard-rules.pro
vendored
Normal file
@ -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
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.dahe.mylibrary
|
||||||
|
|
||||||
|
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.dahe.mylibrary.test", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
28
mylibrary/src/main/AndroidManifest.xml
Normal file
28
mylibrary/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.dahe.mylibrary">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:supportsRtl="true">
|
||||||
|
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="design_width_in_dp"
|
||||||
|
android:value="360" />
|
||||||
|
<meta-data
|
||||||
|
android:name="design_height_in_dp"
|
||||||
|
android:value="640" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.dahe.mylibrary.glide.AppGlideModule"
|
||||||
|
android:value="AppGlideModule"/>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
@ -0,0 +1,137 @@
|
|||||||
|
package com.dahe.mylibrary;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||||
|
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
|
||||||
|
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
|
||||||
|
import com.scwang.smartrefresh.layout.api.RefreshFooter;
|
||||||
|
import com.scwang.smartrefresh.layout.api.RefreshHeader;
|
||||||
|
import com.scwang.smartrefresh.layout.api.RefreshLayout;
|
||||||
|
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
|
||||||
|
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2018/7/15 0015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CommonBaseLibrary {
|
||||||
|
public volatile static CommonBaseLibrary mInstance = null;
|
||||||
|
private static Application mApplication = null;
|
||||||
|
public static WeakReference<Activity> topActivity;
|
||||||
|
public static List<Activity> activityList = new LinkedList<>();
|
||||||
|
private static Retrofit mRetrofit;
|
||||||
|
|
||||||
|
static {
|
||||||
|
SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
|
||||||
|
@Override
|
||||||
|
public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
|
||||||
|
return new ClassicsHeader(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
|
||||||
|
@Override
|
||||||
|
public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
|
||||||
|
return new ClassicsFooter(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonBaseLibrary() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonBaseLibrary getInstance() {
|
||||||
|
if (null == mInstance) {
|
||||||
|
synchronized (CommonBaseLibrary.class) {
|
||||||
|
if (null == mInstance) {
|
||||||
|
mInstance = new CommonBaseLibrary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonBaseLibrary init(Application application, String baseUrl) {
|
||||||
|
mApplication = application;
|
||||||
|
application.registerActivityLifecycleCallbacks(mCallbacks);
|
||||||
|
Gson gson = new GsonBuilder().setDateFormat("yyy-MM-dd HH:mm:ss").create();
|
||||||
|
mRetrofit = new Retrofit.Builder()
|
||||||
|
.baseUrl(baseUrl)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
|
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// .addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Application getApplication() {
|
||||||
|
return mApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Retrofit getRetrofit() {
|
||||||
|
if (null == mRetrofit)
|
||||||
|
throw new NullPointerException("please call CommonBaseLibrary.getInstance().init() first in application!");
|
||||||
|
return mRetrofit;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Application.ActivityLifecycleCallbacks mCallbacks = new Application.ActivityLifecycleCallbacks() {
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Activity activity, Bundle bundle) {
|
||||||
|
activityList.add(activity);
|
||||||
|
setTopActivityWeakRef(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStarted(Activity activity) {
|
||||||
|
setTopActivityWeakRef(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResumed(Activity activity) {
|
||||||
|
setTopActivityWeakRef(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityPaused(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStopped(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityDestroyed(Activity activity) {
|
||||||
|
activityList.remove(activity);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static void setTopActivityWeakRef(Activity activity) {
|
||||||
|
if (topActivity == null || !activity.equals(topActivity.get())) {
|
||||||
|
topActivity = new WeakReference<>(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.dahe.mylibrary.adapter;
|
||||||
|
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.bean.CarBean;
|
||||||
|
import com.dahe.mylibrary.bean.NodeBean;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CarAdapter extends BaseQuickAdapter<CarBean, BaseViewHolder> {
|
||||||
|
|
||||||
|
public CarAdapter(int layoutResId, @Nullable List<CarBean> data) {
|
||||||
|
super(R.layout.item_car_select, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void convert(@NotNull BaseViewHolder helper, CarBean item) {
|
||||||
|
helper.setText(R.id.tv_title, item.getVehicle())
|
||||||
|
.setText(R.id.tv_lxr, "司机信息:"+item.getDriverName() + " " + item.getDriverPhone())
|
||||||
|
.setText(R.id.tv_zz, "载重(Kg):"+item.getApprovedLoad())
|
||||||
|
.setText(R.id.tv_ckg, "长宽高(毫米):"+item.getOutlineLong()+"*"+item.getOutlineWide()+"*"+item.getOutlineHigh());
|
||||||
|
CheckBox cb = helper.getView(R.id.cb);
|
||||||
|
cb.setChecked(item.isSelect());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.dahe.mylibrary.adapter;
|
||||||
|
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.bean.StateBean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CenterSimAdapter extends BaseQuickAdapter<StateBean, BaseViewHolder> {
|
||||||
|
private StateBean selectString=null;
|
||||||
|
|
||||||
|
|
||||||
|
public CenterSimAdapter(int layoutResId, @Nullable List<StateBean> data, StateBean selectString) {
|
||||||
|
super(R.layout.item_select, data);
|
||||||
|
this.selectString = selectString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void convert(BaseViewHolder helper, StateBean item) {
|
||||||
|
helper.setText(R.id.tv_content,item.getDictLabel());
|
||||||
|
TextView tv = helper.getView(R.id.tv_content);
|
||||||
|
if (selectString!=null&&item.getDictValue()!=null){
|
||||||
|
if (item.getDictValue().equals(selectString.getDictValue())){
|
||||||
|
tv.setSelected(true);
|
||||||
|
}else{
|
||||||
|
tv.setSelected(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelect(StateBean selectString){
|
||||||
|
this.selectString = selectString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,272 @@
|
|||||||
|
package com.dahe.mylibrary.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.callback.OnItemLongClickListener;
|
||||||
|
import com.luck.picture.lib.config.PictureMimeType;
|
||||||
|
import com.luck.picture.lib.entity.LocalMedia;
|
||||||
|
import com.luck.picture.lib.listener.OnItemClickListener;
|
||||||
|
import com.luck.picture.lib.tools.DateUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author:luck
|
||||||
|
* @date:2016-7-27 23:02
|
||||||
|
* @describe:GridImageAdapter
|
||||||
|
*/
|
||||||
|
public class GridImageAdapter extends
|
||||||
|
RecyclerView.Adapter<GridImageAdapter.ViewHolder> {
|
||||||
|
public static final String TAG = "PictureSelector";
|
||||||
|
public static final int TYPE_CAMERA = 1;
|
||||||
|
public static final int TYPE_PICTURE = 2;
|
||||||
|
public boolean IS_ONLY_SHOW = false;
|
||||||
|
private final Context ctx;
|
||||||
|
private LayoutInflater mInflater;
|
||||||
|
private List<LocalMedia> list = new ArrayList<>();
|
||||||
|
private int selectMax = 9;
|
||||||
|
/**
|
||||||
|
* 点击添加图片跳转
|
||||||
|
*/
|
||||||
|
private onAddPicClickListener mOnAddPicClickListener;
|
||||||
|
|
||||||
|
public interface onAddPicClickListener {
|
||||||
|
void onAddPicClick();
|
||||||
|
void onDelPicClick(int postion,LocalMedia localMedia);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
public void delete(int position) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (position != RecyclerView.NO_POSITION && list.size() > position) {
|
||||||
|
list.remove(position);
|
||||||
|
notifyItemRemoved(position);
|
||||||
|
notifyItemRangeChanged(position, list.size());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GridImageAdapter(Context context, onAddPicClickListener mOnAddPicClickListener) {
|
||||||
|
this.ctx = context;
|
||||||
|
this.mInflater = LayoutInflater.from(context);
|
||||||
|
this.mOnAddPicClickListener = mOnAddPicClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectMax(int selectMax) {
|
||||||
|
this.selectMax = selectMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<LocalMedia> list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListNotif(List<LocalMedia> list) {
|
||||||
|
if (null!=list&&list.size()>0){
|
||||||
|
this.list = list;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LocalMedia> getData() {
|
||||||
|
return list == null ? new ArrayList<>() : list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(int position) {
|
||||||
|
if (list != null && position < list.size()) {
|
||||||
|
list.remove(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
ImageView mImg;
|
||||||
|
ImageView mIvDel;
|
||||||
|
TextView tvDuration;
|
||||||
|
|
||||||
|
public ViewHolder(View view) {
|
||||||
|
super(view);
|
||||||
|
mImg = view.findViewById(R.id.fiv);
|
||||||
|
mIvDel = view.findViewById(R.id.iv_del);
|
||||||
|
tvDuration = view.findViewById(R.id.tv_duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
if (list.size() < selectMax&&!IS_ONLY_SHOW) {
|
||||||
|
return list.size() + 1;
|
||||||
|
} else {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (isShowAddItem(position)) {
|
||||||
|
return TYPE_CAMERA;
|
||||||
|
} else {
|
||||||
|
return TYPE_PICTURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建ViewHolder
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
||||||
|
View view = mInflater.inflate(R.layout.gv_filter_image, viewGroup, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isShowAddItem(int position) {
|
||||||
|
if (IS_ONLY_SHOW){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int size = list.size();
|
||||||
|
return position == size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsOnlyShow(boolean b){
|
||||||
|
this.IS_ONLY_SHOW = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
|
||||||
|
//少于8张,显示继续添加的图标
|
||||||
|
if (getItemViewType(position) == TYPE_CAMERA) {
|
||||||
|
viewHolder.mImg.setImageResource(R.drawable.id_select_z);
|
||||||
|
// viewHolder.mImg.setImageResource(R.drawable.ic_add_image);
|
||||||
|
viewHolder.mImg.setOnClickListener(v -> mOnAddPicClickListener.onAddPicClick());
|
||||||
|
viewHolder.mIvDel.setVisibility(View.INVISIBLE);
|
||||||
|
} else {
|
||||||
|
viewHolder.mIvDel.setVisibility(IS_ONLY_SHOW?View.GONE:View.VISIBLE);
|
||||||
|
viewHolder.mIvDel.setOnClickListener(view -> {
|
||||||
|
int index = viewHolder.getAbsoluteAdapterPosition();
|
||||||
|
|
||||||
|
// 这里有时会返回-1造成数据下标越界,具体可参考getAdapterPosition()源码,
|
||||||
|
// 通过源码分析应该是bindViewHolder()暂未绘制完成导致,知道原因的也可联系我~感谢
|
||||||
|
if (index != RecyclerView.NO_POSITION && list.size() > index) {
|
||||||
|
mOnAddPicClickListener.onDelPicClick(index, list.get(index));
|
||||||
|
// list.remove(index);
|
||||||
|
// notifyItemRemoved(index);
|
||||||
|
// notifyItemRangeChanged(index, list.size());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
LocalMedia media = list.get(position);
|
||||||
|
if (media == null
|
||||||
|
|| TextUtils.isEmpty(media.getPath())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int chooseModel = media.getChooseModel();
|
||||||
|
String path;
|
||||||
|
if (media.isCut() && !media.isCompressed()) {
|
||||||
|
// 裁剪过
|
||||||
|
path = media.getCutPath();
|
||||||
|
} else if (media.isCompressed() || (media.isCut() && media.isCompressed())) {
|
||||||
|
// 压缩过,或者裁剪同时压缩过,以最终压缩过图片为准
|
||||||
|
path = media.getCompressPath();
|
||||||
|
} else {
|
||||||
|
// 原图
|
||||||
|
path = media.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "原图地址::" + media.getPath());
|
||||||
|
|
||||||
|
if (media.isCut()) {
|
||||||
|
Log.i(TAG, "裁剪地址::" + media.getCutPath());
|
||||||
|
}
|
||||||
|
if (media.isCompressed()) {
|
||||||
|
Log.i(TAG, "压缩地址::" + media.getCompressPath());
|
||||||
|
Log.i(TAG, "压缩后文件大小::" + new File(media.getCompressPath()).length() / 1024 + "k");
|
||||||
|
}
|
||||||
|
if (!TextUtils.isEmpty(media.getAndroidQToPath())) {
|
||||||
|
Log.i(TAG, "Android Q特有地址::" + media.getAndroidQToPath());
|
||||||
|
}
|
||||||
|
if (media.isOriginal()) {
|
||||||
|
Log.i(TAG, "是否开启原图功能::" + true);
|
||||||
|
Log.i(TAG, "开启原图功能后地址::" + media.getOriginalPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
long duration = media.getDuration();
|
||||||
|
viewHolder.tvDuration.setVisibility(PictureMimeType.isHasVideo(media.getMimeType())
|
||||||
|
? View.VISIBLE : View.GONE);
|
||||||
|
if (chooseModel == PictureMimeType.ofAudio()) {
|
||||||
|
viewHolder.tvDuration.setVisibility(View.VISIBLE);
|
||||||
|
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
|
||||||
|
(R.drawable.picture_icon_audio, 0, 0, 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
|
||||||
|
(R.drawable.picture_icon_video, 0, 0, 0);
|
||||||
|
}
|
||||||
|
viewHolder.tvDuration.setText(DateUtils.formatDurationTime(duration));
|
||||||
|
if (chooseModel == PictureMimeType.ofAudio()) {
|
||||||
|
viewHolder.mImg.setImageResource(R.drawable.picture_audio_placeholder);
|
||||||
|
} else {
|
||||||
|
RequestOptions requestOptions = RequestOptions.fitCenterTransform().transform(new CenterCrop(), new RoundedCorners(5));
|
||||||
|
Glide.with(ctx)
|
||||||
|
.load(PictureMimeType.isContent(path) && !media.isCut() && !media.isCompressed() ? Uri.parse(path)
|
||||||
|
: path)
|
||||||
|
.centerCrop()
|
||||||
|
.apply(requestOptions)//圆角半径
|
||||||
|
.placeholder(R.drawable.id_select_loading)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
|
.into(viewHolder.mImg);
|
||||||
|
}
|
||||||
|
//itemView 的点击事件
|
||||||
|
if (mItemClickListener != null) {
|
||||||
|
viewHolder.itemView.setOnClickListener(v -> {
|
||||||
|
int adapterPosition = viewHolder.getAdapterPosition();
|
||||||
|
mItemClickListener.onItemClick(v, adapterPosition);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mItemLongClickListener != null) {
|
||||||
|
viewHolder.itemView.setOnLongClickListener(v -> {
|
||||||
|
int adapterPosition = viewHolder.getAdapterPosition();
|
||||||
|
mItemLongClickListener.onItemLongClick(viewHolder, adapterPosition, v);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnItemClickListener mItemClickListener;
|
||||||
|
|
||||||
|
public void setOnItemClickListener(OnItemClickListener l) {
|
||||||
|
this.mItemClickListener = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnItemLongClickListener mItemLongClickListener;
|
||||||
|
|
||||||
|
public void setItemLongClickListener(OnItemLongClickListener l) {
|
||||||
|
this.mItemLongClickListener = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.dahe.mylibrary.adapter;
|
||||||
|
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.bean.NodeBean;
|
||||||
|
import com.dahe.mylibrary.utils.StringUtils;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NodeAdapter extends BaseQuickAdapter<NodeBean, BaseViewHolder> {
|
||||||
|
|
||||||
|
public NodeAdapter(int layoutResId, @Nullable List<NodeBean> data) {
|
||||||
|
super(R.layout.item_node_select, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void convert(@NotNull BaseViewHolder helper, NodeBean item) {
|
||||||
|
helper.setText(R.id.tv_title, item.getNode())
|
||||||
|
.setText(R.id.tv_lxr, StringUtils.isEmpty(item.getDocking())?"":item.getDocking() + " " + (StringUtils.isEmpty(item.getDockingPhone())?"":item.getDockingPhone()))
|
||||||
|
.setText(R.id.tv_addres, item.getFreighter());
|
||||||
|
CheckBox cb = helper.getView(R.id.cb);
|
||||||
|
cb.setChecked("1".equals(item.isSelect())?true:false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package com.dahe.mylibrary.adapter;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.bean.DictBean;
|
||||||
|
import com.dahe.mylibrary.bean.StateBean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class SelectDicAdapter extends BaseQuickAdapter<StateBean, BaseViewHolder> {
|
||||||
|
private int selectPos = -1;
|
||||||
|
|
||||||
|
|
||||||
|
public SelectDicAdapter(int layoutResId, @Nullable List<StateBean> data, int selectPos) {
|
||||||
|
super(R.layout.item_dic_select, data);
|
||||||
|
this.selectPos = selectPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void convert(BaseViewHolder helper, StateBean item) {
|
||||||
|
helper.setText(R.id.tv_content,item.getDictLabel());
|
||||||
|
// TextView tv = helper.getView(R.id.tv_content);
|
||||||
|
// if (item.equals(selectString)){
|
||||||
|
// tv.setSelected(true);
|
||||||
|
// }else{
|
||||||
|
// tv.setSelected(false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelect(int selectString){
|
||||||
|
this.selectPos = selectString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,250 @@
|
|||||||
|
package com.dahe.mylibrary.base;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorRes;
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.callback.RefreshCallBack;
|
||||||
|
import com.dahe.mylibrary.utils.BarUtils;
|
||||||
|
import com.dahe.mylibrary.utils.ConvertUtils;
|
||||||
|
import com.dahe.mylibrary.utils.StatusBar;
|
||||||
|
import com.dahe.mylibrary.utils.ToastUtils;
|
||||||
|
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||||
|
import com.scwang.smartrefresh.layout.api.RefreshLayout;
|
||||||
|
import com.scwang.smartrefresh.layout.constant.RefreshState;
|
||||||
|
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
|
||||||
|
|
||||||
|
import qiu.niorgai.StatusBarCompat;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class BaseActivity extends AppCompatActivity {
|
||||||
|
protected Context mContext;
|
||||||
|
protected final int DEFAULT_STATUS_BAR_ALPHA = 0;
|
||||||
|
private static final String TAG = "BaseActivity";
|
||||||
|
protected Toolbar mToolbar;
|
||||||
|
protected int mRefreshPage = 1;
|
||||||
|
protected int mRefreshCount = 15;
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(getLayout());
|
||||||
|
mContext = this;
|
||||||
|
setStatusBarColor(R.color.colorPrimaryDark);
|
||||||
|
initView(savedInstanceState);
|
||||||
|
initDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题栏的颜色 文字白色
|
||||||
|
*/
|
||||||
|
public void setStatusBarCancelLightColor() {
|
||||||
|
StatusBar.cancelLightStatusBar(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置沉浸式标题栏 标题栏的颜色
|
||||||
|
*/
|
||||||
|
public void setStatusBarColor(int color) {
|
||||||
|
StatusBarCompat.setStatusBarColor(this, ContextCompat.getColor(mContext, color), DEFAULT_STATUS_BAR_ALPHA);
|
||||||
|
StatusBar.changeToLightStatusBar(this); //黑色 下边白色
|
||||||
|
// StatusBar.cancelLightStatusBar(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置沉浸式标题栏 标题栏的颜色
|
||||||
|
*/
|
||||||
|
public void setStatusBarColor() {
|
||||||
|
// StatusBarCompat.setStatusBarColor(this, ContextCompat.getColor(mContext, color), DEFAULT_STATUS_BAR_ALPHA);
|
||||||
|
// StatusBar.changeToLightStatusBar(this); //黑色 下边白色
|
||||||
|
StatusBar.cancelLightStatusBar(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置沉浸式标题栏 里面是Fragment
|
||||||
|
*/
|
||||||
|
public void setStatusBarColorInFragment() {
|
||||||
|
StatusBarCompat.translucentStatusBar(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置透明沉浸式标题栏
|
||||||
|
*/
|
||||||
|
public void setStatusBarColorToLight() {
|
||||||
|
StatusBar.translucentStatusBar(this, false);
|
||||||
|
StatusBar.changeToLightStatusBar(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
protected void setTitleBar(String title, View.OnClickListener listener) {
|
||||||
|
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title))
|
||||||
|
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
mToolbar.setNavigationIcon(R.drawable.left);
|
||||||
|
mToolbar.setNavigationOnClickListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setTitleBar(String title) {
|
||||||
|
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title))
|
||||||
|
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示右边标题
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* @param listener
|
||||||
|
* @param isVisible
|
||||||
|
* @param right
|
||||||
|
*/
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
protected void setTitleBar(String title, View.OnClickListener listener, boolean isVisible, String right, View.OnClickListener rightListener) {
|
||||||
|
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title))
|
||||||
|
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
TextView mTextRight = (TextView) findViewById(R.id.common_toolBar_text_right);
|
||||||
|
if (isVisible) {
|
||||||
|
mTextRight.setVisibility(View.VISIBLE);
|
||||||
|
mTextRight.setText(right);
|
||||||
|
mTextRight.setOnClickListener(rightListener);
|
||||||
|
}
|
||||||
|
mToolbar.setNavigationIcon(R.drawable.left);
|
||||||
|
mToolbar.setNavigationOnClickListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置距离顶部距离
|
||||||
|
*/
|
||||||
|
protected void setStatusHeightParams(View llContent) {
|
||||||
|
RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
closeLayoutParams.topMargin = ConvertUtils.dp2px(8) + BarUtils.getStatusBarHeight();
|
||||||
|
// closeLayoutParams.topMargin = BarUtils.getStatusBarHeight();
|
||||||
|
llContent.setLayoutParams(closeLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int getLayout();
|
||||||
|
|
||||||
|
protected abstract void initView(Bundle savedInstanceState);
|
||||||
|
|
||||||
|
protected abstract void initDate();
|
||||||
|
|
||||||
|
protected void showToast(Object message) {
|
||||||
|
ToastUtils.showToast(this, message instanceof String ? message + "" : getResources().getString((int) message));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void canCelToast(){
|
||||||
|
ToastUtils.cancelToast();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// protected void showToast(Object message,int time) {
|
||||||
|
// ToastUtils.showToast(this, message instanceof String ? message + "" : getResources().getString((int) message),time);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置刷新控件
|
||||||
|
*
|
||||||
|
* @param refreshLayout
|
||||||
|
* @param callBack 访问网络回调
|
||||||
|
*/
|
||||||
|
protected void setRefresh(final SmartRefreshLayout refreshLayout, final RefreshCallBack callBack) {
|
||||||
|
refreshLayout.setEnableOverScrollDrag(true)
|
||||||
|
.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
|
||||||
|
@Override
|
||||||
|
public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
|
||||||
|
mRefreshPage++;
|
||||||
|
callBack.getRefreshDate(2, mRefreshPage, mRefreshCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
|
||||||
|
mRefreshPage = 1;
|
||||||
|
callBack.getRefreshDate(1, mRefreshPage, mRefreshCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络访问完成 刷新控件
|
||||||
|
*
|
||||||
|
* @param refreshLayout
|
||||||
|
* @param isLoadMore false禁用下拉加载更多
|
||||||
|
*/
|
||||||
|
protected void setFinishRefresh(final SmartRefreshLayout refreshLayout, boolean isLoadMore) {
|
||||||
|
if (refreshLayout != null && refreshLayout.getState() == RefreshState.Refreshing)
|
||||||
|
refreshLayout.finishRefresh();
|
||||||
|
else if (refreshLayout != null && refreshLayout.getState() == RefreshState.Loading)
|
||||||
|
refreshLayout.finishLoadMore();
|
||||||
|
if (!isLoadMore){
|
||||||
|
refreshLayout.finishLoadMore(); //加载完成
|
||||||
|
refreshLayout.finishLoadMoreWithNoMoreData(); //全部加载完成,没有数据了调用此方法
|
||||||
|
}
|
||||||
|
// refreshLayout.setEnableLoadMore(isLoadMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View view){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Drawable
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Drawable getDrawableV4(@DrawableRes int id) {
|
||||||
|
return ContextCompat.getDrawable(this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Color
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected int getColorV4(@ColorRes int id) {
|
||||||
|
return ContextCompat.getColor(this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,321 @@
|
|||||||
|
package com.dahe.mylibrary.base;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.callback.RefreshCallBack;
|
||||||
|
import com.dahe.mylibrary.utils.StatusBar;
|
||||||
|
import com.dahe.mylibrary.utils.ToastUtils;
|
||||||
|
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||||
|
import com.scwang.smartrefresh.layout.api.RefreshLayout;
|
||||||
|
import com.scwang.smartrefresh.layout.constant.RefreshState;
|
||||||
|
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
|
||||||
|
|
||||||
|
import qiu.niorgai.StatusBarCompat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Fragment基类,封装了懒加载的实现
|
||||||
|
* <p>
|
||||||
|
* 1、Viewpager + Fragment情况下,fragment的生命周期因Viewpager的缓存机制而失去了具体意义
|
||||||
|
* 该抽象类自定义一个新的回调方法,当fragment可见状态改变时会触发的回调方法
|
||||||
|
*
|
||||||
|
* @see #onFragmentVisibleChange(boolean)
|
||||||
|
* @see #onFragmentFirstVisible()
|
||||||
|
*/
|
||||||
|
public abstract class BaseFragment extends Fragment {
|
||||||
|
private boolean isFragmentVisible;
|
||||||
|
private boolean isReuseView;
|
||||||
|
private boolean isFirstVisible;
|
||||||
|
private boolean isPause;
|
||||||
|
private View rootView;
|
||||||
|
private static final String TAG = "BaseFragment";
|
||||||
|
protected Context mContext;
|
||||||
|
protected int mRefreshPage = 1;
|
||||||
|
protected int mRefreshCount = 20;
|
||||||
|
protected Toolbar mToolbar;
|
||||||
|
protected final int DEFAULT_STATUS_BAR_ALPHA = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
Log.i(TAG, "onViewCreated: " + (rootView == null) + "---getUserVisibleHint()" + getUserVisibleHint() + "---isFirstVisible" + isFirstVisible);
|
||||||
|
//如果setUserVisibleHint()在rootView创建前调用时,那么
|
||||||
|
//就等到rootView创建完后才回调onFragmentVisibleChange(true)
|
||||||
|
//保证onFragmentVisibleChange()的回调发生在rootView创建完成之后,以便支持ui操作
|
||||||
|
if (rootView == null) {
|
||||||
|
rootView = view;
|
||||||
|
if (getUserVisibleHint()) {
|
||||||
|
if (isFirstVisible) {
|
||||||
|
onFragmentFirstVisible();
|
||||||
|
isFirstVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFragmentVisibleChange(isFirstVisible);
|
||||||
|
isFragmentVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onViewCreated(isReuseView && rootView != null ? rootView : view, savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
if (getContentViewLayoutID() != 0) {
|
||||||
|
mContext = getActivity();
|
||||||
|
return inflater.inflate(getContentViewLayoutID(), container, false);
|
||||||
|
} else {
|
||||||
|
return super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract int getContentViewLayoutID();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题栏的颜色 文字白色
|
||||||
|
*/
|
||||||
|
public void setStatusBarCancelLightColor() {
|
||||||
|
StatusBar.cancelLightStatusBar(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置沉浸式标题栏 标题栏的颜色
|
||||||
|
*/
|
||||||
|
public void setStatusBarColor(int color) {
|
||||||
|
StatusBarCompat.setStatusBarColor(getActivity(), ContextCompat.getColor(mContext, color), DEFAULT_STATUS_BAR_ALPHA);
|
||||||
|
StatusBar.changeToLightStatusBar(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置沉浸式标题栏 里面是Fragment
|
||||||
|
*/
|
||||||
|
public void setStatusBarColorInFragment() {
|
||||||
|
StatusBarCompat.translucentStatusBar(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatusBarColorToLight() {
|
||||||
|
StatusBar.translucentStatusBar(getActivity(), true);
|
||||||
|
StatusBar.changeToLightStatusBar(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
initVariable();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void showToast(Object message) {
|
||||||
|
ToastUtils.showToast(mContext, message instanceof String ? message + "" : getResources().getString((int) message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置刷新控件
|
||||||
|
*
|
||||||
|
* @param refreshLayout
|
||||||
|
* @param callBack 访问网络回调
|
||||||
|
*/
|
||||||
|
protected void setRefresh(final SmartRefreshLayout refreshLayout, final RefreshCallBack callBack) {
|
||||||
|
refreshLayout.setEnableOverScrollDrag(true)
|
||||||
|
.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
|
||||||
|
@Override
|
||||||
|
public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
|
||||||
|
mRefreshPage++;
|
||||||
|
callBack.getRefreshDate(2, mRefreshPage, mRefreshCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
|
||||||
|
mRefreshPage = 1;
|
||||||
|
callBack.getRefreshDate(1, mRefreshPage, mRefreshCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络访问完成 刷新控件
|
||||||
|
*
|
||||||
|
* @param refreshLayout
|
||||||
|
* @param isLoadMore false禁用下拉加载更多
|
||||||
|
*/
|
||||||
|
protected void setFinishRefresh(final SmartRefreshLayout refreshLayout, boolean isLoadMore) {
|
||||||
|
if (refreshLayout.getState() == RefreshState.Refreshing)
|
||||||
|
refreshLayout.finishRefresh();
|
||||||
|
else if (refreshLayout.getState() == RefreshState.Loading)
|
||||||
|
refreshLayout.finishLoadMore();
|
||||||
|
if (!isLoadMore){
|
||||||
|
refreshLayout.finishLoadMore(); //加载完成
|
||||||
|
refreshLayout.finishLoadMoreWithNoMoreData(); //全部加载完成,没有数据了调用此方法
|
||||||
|
}
|
||||||
|
// refreshLayout.setEnableLoadMore(isLoadMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setTitleBar(String title, View.OnClickListener listener) {
|
||||||
|
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title))
|
||||||
|
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
mToolbar.setNavigationIcon(R.drawable.black_back);
|
||||||
|
mToolbar.setNavigationOnClickListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setTitleBar(String title) {
|
||||||
|
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title))
|
||||||
|
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setTitleBar(String title, boolean isRight, View.OnClickListener listener) {
|
||||||
|
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title)) {
|
||||||
|
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
((RelativeLayout) rootView.findViewById(R.id.rlMessage)).setVisibility(isRight ? View.VISIBLE : View.GONE);
|
||||||
|
(rootView.findViewById(R.id.rlMessage)).setOnClickListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setTitleBar(String title, boolean isRight,String message, View.OnClickListener listener) {
|
||||||
|
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
|
||||||
|
if (!TextUtils.isEmpty(title)) {
|
||||||
|
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
|
||||||
|
((RelativeLayout) rootView.findViewById(R.id.rlMessage)).setVisibility(isRight ? View.VISIBLE : View.GONE);
|
||||||
|
((TextView) rootView.findViewById(R.id.tvMessage)).setText(message);
|
||||||
|
(rootView.findViewById(R.id.rlMessage)).setOnClickListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setBadView(boolean isRight) {
|
||||||
|
if (null != ((TextView) rootView.findViewById(R.id.tvCount))) {
|
||||||
|
((TextView) rootView.findViewById(R.id.tvCount)).setVisibility(isRight ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setCount(int count) {
|
||||||
|
if (count > 100) {
|
||||||
|
((TextView) rootView.findViewById(R.id.tvCount)).setText("99··");
|
||||||
|
} else {
|
||||||
|
((TextView) rootView.findViewById(R.id.tvCount)).setText(count + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//setUserVisibleHint()在Fragment创建时会先被调用一次,传入isVisibleToUser = false
|
||||||
|
//如果当前Fragment可见,那么setUserVisibleHint()会再次被调用一次,传入isVisibleToUser = true
|
||||||
|
//如果Fragment从可见->不可见,那么setUserVisibleHint()也会被调用,传入isVisibleToUser = false
|
||||||
|
//总结:setUserVisibleHint()除了Fragment的可见状态发生变化时会被回调外,在new Fragment()时也会被回调
|
||||||
|
@Override
|
||||||
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
|
Log.i(TAG, "isFirstVisible: " + isFirstVisible + "--isVisibleToUser" + isVisibleToUser + "--rootView == null" + (rootView == null));
|
||||||
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
|
//setUserVisibleHint()有可能在fragment的生命周期外被调用
|
||||||
|
if (rootView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isFirstVisible && isVisibleToUser) {
|
||||||
|
onFragmentFirstVisible();
|
||||||
|
isFirstVisible = false;
|
||||||
|
isFragmentVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isVisibleToUser) {
|
||||||
|
onFragmentVisibleChange(true);
|
||||||
|
isFragmentVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isFragmentVisible) {
|
||||||
|
isFragmentVisible = false;
|
||||||
|
onFragmentVisibleChange(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
initVariable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initVariable() {
|
||||||
|
isFirstVisible = true;
|
||||||
|
isFragmentVisible = false;
|
||||||
|
isPause = false;
|
||||||
|
rootView = null;
|
||||||
|
isReuseView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
isPause = true;
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
if (isPause && getUserVisibleHint())
|
||||||
|
onFragmentVisibleChange(true);
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param isReuse
|
||||||
|
*/
|
||||||
|
protected void reuseView(boolean isReuse) {
|
||||||
|
isReuseView = isReuse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去除setUserVisibleHint()多余的回调场景,保证只有当fragment可见状态发生变化时才回调
|
||||||
|
* 回调时机在view创建完后,所以支持ui操作,解决在setUserVisibleHint()里进行ui操作有可能报null异常的问题
|
||||||
|
* <p>
|
||||||
|
* 可在该回调方法里进行一些ui显示与隐藏
|
||||||
|
*
|
||||||
|
* @param isVisible true 不可见 -> 可见
|
||||||
|
* false 可见 -> 不可见
|
||||||
|
*/
|
||||||
|
protected abstract void onFragmentVisibleChange(boolean isVisible);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在fragment首次可见时回调,可用于加载数据,防止每次进入都重复加载数据
|
||||||
|
*/
|
||||||
|
protected abstract void onFragmentFirstVisible();
|
||||||
|
|
||||||
|
protected boolean isFragmentVisible() {
|
||||||
|
return isFragmentVisible;
|
||||||
|
}
|
||||||
|
}
|
||||||
100
mylibrary/src/main/java/com/dahe/mylibrary/bean/CarBean.java
Normal file
100
mylibrary/src/main/java/com/dahe/mylibrary/bean/CarBean.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package com.dahe.mylibrary.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class CarBean implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
// private String approved_load;
|
||||||
|
// private String driver_name;
|
||||||
|
// private String current_load;
|
||||||
|
// private String car_number;
|
||||||
|
// private String outline_wide;
|
||||||
|
// private String outline_long;
|
||||||
|
// private String driver_phone;
|
||||||
|
// private Integer car_id;
|
||||||
|
// private String outline_high;
|
||||||
|
private boolean isSelect;
|
||||||
|
|
||||||
|
private String vehicle;
|
||||||
|
private String carId;
|
||||||
|
private String outlineWide;
|
||||||
|
private String outlineHigh;
|
||||||
|
private String outlineLong;
|
||||||
|
private String approvedLoad;
|
||||||
|
private String driverName;
|
||||||
|
private String driverPhone;
|
||||||
|
|
||||||
|
public String getVehicle() {
|
||||||
|
return vehicle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVehicle(String vehicle) {
|
||||||
|
this.vehicle = vehicle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCarId() {
|
||||||
|
return carId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCarId(String carId) {
|
||||||
|
this.carId = carId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutlineWide() {
|
||||||
|
return outlineWide;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutlineWide(String outlineWide) {
|
||||||
|
this.outlineWide = outlineWide;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutlineHigh() {
|
||||||
|
return outlineHigh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutlineHigh(String outlineHigh) {
|
||||||
|
this.outlineHigh = outlineHigh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutlineLong() {
|
||||||
|
return outlineLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutlineLong(String outlineLong) {
|
||||||
|
this.outlineLong = outlineLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApprovedLoad() {
|
||||||
|
return approvedLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApprovedLoad(String approvedLoad) {
|
||||||
|
this.approvedLoad = approvedLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDriverName() {
|
||||||
|
return driverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriverName(String driverName) {
|
||||||
|
this.driverName = driverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDriverPhone() {
|
||||||
|
return driverPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriverPhone(String driverPhone) {
|
||||||
|
this.driverPhone = driverPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelect() {
|
||||||
|
return isSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelect(boolean select) {
|
||||||
|
isSelect = select;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
154
mylibrary/src/main/java/com/dahe/mylibrary/bean/DictBean.java
Normal file
154
mylibrary/src/main/java/com/dahe/mylibrary/bean/DictBean.java
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package com.dahe.mylibrary.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class DictBean implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private String searchValue;
|
||||||
|
private String createBy;
|
||||||
|
private String createTime;
|
||||||
|
private String updateBy;
|
||||||
|
private String updateTime;
|
||||||
|
private String remark;
|
||||||
|
private String dictCode;
|
||||||
|
private String dictSort;
|
||||||
|
private String dictLabel;
|
||||||
|
private String dictValue;
|
||||||
|
private String dictType;
|
||||||
|
private String cssClass;
|
||||||
|
private String listClass;
|
||||||
|
private String isDefault;
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
public DictBean() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DictBean(String dictValue, String dictLabel) {
|
||||||
|
this.dictValue = dictValue;
|
||||||
|
this.dictLabel = dictLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSearchValue() {
|
||||||
|
return searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchValue(String searchValue) {
|
||||||
|
this.searchValue = searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateBy() {
|
||||||
|
return createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateBy(String createBy) {
|
||||||
|
this.createBy = createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTime(String createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateBy() {
|
||||||
|
return updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateBy(String updateBy) {
|
||||||
|
this.updateBy = updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateTime() {
|
||||||
|
return updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateTime(String updateTime) {
|
||||||
|
this.updateTime = updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark() {
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark) {
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getDictCode() {
|
||||||
|
return dictCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictCode(String dictCode) {
|
||||||
|
this.dictCode = dictCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictSort() {
|
||||||
|
return dictSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictSort(String dictSort) {
|
||||||
|
this.dictSort = dictSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictLabel() {
|
||||||
|
return dictLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictLabel(String dictLabel) {
|
||||||
|
this.dictLabel = dictLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictValue() {
|
||||||
|
return dictValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictValue(String dictValue) {
|
||||||
|
this.dictValue = dictValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictType() {
|
||||||
|
return dictType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictType(String dictType) {
|
||||||
|
this.dictType = dictType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCssClass() {
|
||||||
|
return cssClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCssClass(String cssClass) {
|
||||||
|
this.cssClass = cssClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getListClass() {
|
||||||
|
return listClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListClass(String listClass) {
|
||||||
|
this.listClass = listClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsDefault() {
|
||||||
|
return isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsDefault(String isDefault) {
|
||||||
|
this.isDefault = isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
354
mylibrary/src/main/java/com/dahe/mylibrary/bean/NodeBean.java
Normal file
354
mylibrary/src/main/java/com/dahe/mylibrary/bean/NodeBean.java
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
package com.dahe.mylibrary.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class NodeBean implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private String searchValue;
|
||||||
|
private String createBy;
|
||||||
|
private String createTime;
|
||||||
|
private String updateBy;
|
||||||
|
private String updateTime;
|
||||||
|
private String remark;
|
||||||
|
private String planId;
|
||||||
|
private String nodeId;
|
||||||
|
private String nodeType;
|
||||||
|
private String orderId;
|
||||||
|
private String nodeName;
|
||||||
|
private String address;
|
||||||
|
private String contacts;
|
||||||
|
private String contactsPhone;
|
||||||
|
private String contacts_phone;
|
||||||
|
private String provinceId;
|
||||||
|
private String provinceName;
|
||||||
|
private String cityId;
|
||||||
|
private String cityName;
|
||||||
|
private String countyId;
|
||||||
|
private String countyName;
|
||||||
|
private String planIndex;
|
||||||
|
private String remarks;
|
||||||
|
private String node_name;
|
||||||
|
private String warehouseId;
|
||||||
|
private String warehouseName;
|
||||||
|
private String isSelect;
|
||||||
|
private String w_child_id;
|
||||||
|
private String firstNameCode;
|
||||||
|
|
||||||
|
|
||||||
|
private String wChildId;
|
||||||
|
private String waybillId;
|
||||||
|
private String freighter;
|
||||||
|
private String freighterId;
|
||||||
|
private String node;
|
||||||
|
private String state;
|
||||||
|
private String isSelectOld;
|
||||||
|
private String dockingPhone;
|
||||||
|
private String docking;
|
||||||
|
|
||||||
|
public String getwChildId() {
|
||||||
|
return wChildId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setwChildId(String wChildId) {
|
||||||
|
this.wChildId = wChildId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWaybillId() {
|
||||||
|
return waybillId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWaybillId(String waybillId) {
|
||||||
|
this.waybillId = waybillId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFreighter() {
|
||||||
|
return freighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFreighter(String freighter) {
|
||||||
|
this.freighter = freighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFreighterId() {
|
||||||
|
return freighterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFreighterId(String freighterId) {
|
||||||
|
this.freighterId = freighterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNode() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNode(String node) {
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(String state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsSelectOld() {
|
||||||
|
return isSelectOld;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsSelectOld(String isSelectOld) {
|
||||||
|
this.isSelectOld = isSelectOld;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDockingPhone() {
|
||||||
|
return dockingPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDockingPhone(String dockingPhone) {
|
||||||
|
this.dockingPhone = dockingPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDocking() {
|
||||||
|
return docking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDocking(String docking) {
|
||||||
|
this.docking = docking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWarehouseId() {
|
||||||
|
return warehouseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWarehouseId(String warehouseId) {
|
||||||
|
this.warehouseId = warehouseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWarehouseName() {
|
||||||
|
return warehouseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWarehouseName(String warehouseName) {
|
||||||
|
this.warehouseName = warehouseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstNameCode() {
|
||||||
|
return firstNameCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstNameCode(String firstNameCode) {
|
||||||
|
this.firstNameCode = firstNameCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getW_child_id() {
|
||||||
|
return w_child_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setW_child_id(String w_child_id) {
|
||||||
|
this.w_child_id = w_child_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String isSelect() {
|
||||||
|
return isSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelect(String select) {
|
||||||
|
isSelect = select;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNode_name() {
|
||||||
|
return node_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNode_name(String node_name) {
|
||||||
|
this.node_name = node_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContacts_phone() {
|
||||||
|
return contacts_phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContacts_phone(String contacts_phone) {
|
||||||
|
this.contacts_phone = contacts_phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSearchValue() {
|
||||||
|
return searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchValue(String searchValue) {
|
||||||
|
this.searchValue = searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateBy() {
|
||||||
|
return createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateBy(String createBy) {
|
||||||
|
this.createBy = createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTime(String createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateBy() {
|
||||||
|
return updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateBy(String updateBy) {
|
||||||
|
this.updateBy = updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateTime() {
|
||||||
|
return updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateTime(String updateTime) {
|
||||||
|
this.updateTime = updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark() {
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark) {
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getPlanId() {
|
||||||
|
return planId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlanId(String planId) {
|
||||||
|
this.planId = planId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeId() {
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeId(String nodeId) {
|
||||||
|
this.nodeId = nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeType() {
|
||||||
|
return nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeType(String nodeType) {
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderId(String orderId) {
|
||||||
|
this.orderId = orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeName() {
|
||||||
|
return nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeName(String nodeName) {
|
||||||
|
this.nodeName = nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContacts() {
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContacts(String contacts) {
|
||||||
|
this.contacts = contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContactsPhone() {
|
||||||
|
return contactsPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactsPhone(String contactsPhone) {
|
||||||
|
this.contactsPhone = contactsPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvinceId() {
|
||||||
|
return provinceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProvinceId(String provinceId) {
|
||||||
|
this.provinceId = provinceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvinceName() {
|
||||||
|
return provinceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProvinceName(String provinceName) {
|
||||||
|
this.provinceName = provinceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCityId() {
|
||||||
|
return cityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCityId(String cityId) {
|
||||||
|
this.cityId = cityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCityName() {
|
||||||
|
return cityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCityName(String cityName) {
|
||||||
|
this.cityName = cityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountyId() {
|
||||||
|
return countyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountyId(String countyId) {
|
||||||
|
this.countyId = countyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountyName() {
|
||||||
|
return countyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountyName(String countyName) {
|
||||||
|
this.countyName = countyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlanIndex() {
|
||||||
|
return planIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlanIndex(String planIndex) {
|
||||||
|
this.planIndex = planIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemarks() {
|
||||||
|
return remarks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemarks(String remarks) {
|
||||||
|
this.remarks = remarks;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
151
mylibrary/src/main/java/com/dahe/mylibrary/bean/StateBean.java
Normal file
151
mylibrary/src/main/java/com/dahe/mylibrary/bean/StateBean.java
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package com.dahe.mylibrary.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class StateBean implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private String searchValue;
|
||||||
|
private String createBy;
|
||||||
|
private String createTime;
|
||||||
|
private String updateBy;
|
||||||
|
private String updateTime;
|
||||||
|
private String remark;
|
||||||
|
private String dictCode;
|
||||||
|
private String dictSort;
|
||||||
|
private String dictLabel;
|
||||||
|
private String dictValue;
|
||||||
|
private String dictType;
|
||||||
|
private String cssClass;
|
||||||
|
private String listClass;
|
||||||
|
private String isDefault;
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
public StateBean(String dictLabel, String dictValue) {
|
||||||
|
this.dictLabel = dictLabel;
|
||||||
|
this.dictValue = dictValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSearchValue() {
|
||||||
|
return searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchValue(String searchValue) {
|
||||||
|
this.searchValue = searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateBy() {
|
||||||
|
return createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateBy(String createBy) {
|
||||||
|
this.createBy = createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTime(String createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateBy() {
|
||||||
|
return updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateBy(String updateBy) {
|
||||||
|
this.updateBy = updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateTime() {
|
||||||
|
return updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateTime(String updateTime) {
|
||||||
|
this.updateTime = updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark() {
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark) {
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictCode() {
|
||||||
|
return dictCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictCode(String dictCode) {
|
||||||
|
this.dictCode = dictCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictSort() {
|
||||||
|
return dictSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictSort(String dictSort) {
|
||||||
|
this.dictSort = dictSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictLabel() {
|
||||||
|
return dictLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictLabel(String dictLabel) {
|
||||||
|
this.dictLabel = dictLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictValue() {
|
||||||
|
return dictValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictValue(String dictValue) {
|
||||||
|
this.dictValue = dictValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDictType() {
|
||||||
|
return dictType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictType(String dictType) {
|
||||||
|
this.dictType = dictType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCssClass() {
|
||||||
|
return cssClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCssClass(String cssClass) {
|
||||||
|
this.cssClass = cssClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getListClass() {
|
||||||
|
return listClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListClass(String listClass) {
|
||||||
|
this.listClass = listClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsDefault() {
|
||||||
|
return isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsDefault(String isDefault) {
|
||||||
|
this.isDefault = isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ParamsDTO {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.dahe.mylibrary.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class TipsBean implements Serializable {
|
||||||
|
private String title;
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
public TipsBean(String title, String content) {
|
||||||
|
this.title = title;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.dahe.mylibrary.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class VersionBean implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private ParamsDao data;
|
||||||
|
|
||||||
|
public ParamsDao getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(ParamsDao data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ParamsDao implements Serializable{
|
||||||
|
private int versionId;
|
||||||
|
private int version;
|
||||||
|
private String versionName;
|
||||||
|
private String introduce;
|
||||||
|
private String updateType;
|
||||||
|
private String createTime;
|
||||||
|
private String remark;
|
||||||
|
private String apkUrl;
|
||||||
|
|
||||||
|
public String getApkUrl() {
|
||||||
|
return apkUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApkUrl(String apkUrl) {
|
||||||
|
this.apkUrl = apkUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersionId() {
|
||||||
|
return versionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersionId(int versionId) {
|
||||||
|
this.versionId = versionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(int version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersionName() {
|
||||||
|
return versionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersionName(String versionName) {
|
||||||
|
this.versionName = versionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIntroduce() {
|
||||||
|
return introduce;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntroduce(String introduce) {
|
||||||
|
this.introduce = introduce;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateType() {
|
||||||
|
return updateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateType(String updateType) {
|
||||||
|
this.updateType = updateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTime(String createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark() {
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark) {
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.dahe.mylibrary.callback;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author:luck
|
||||||
|
* @date:2020-01-13 17:58
|
||||||
|
* @describe:长按事件
|
||||||
|
*/
|
||||||
|
public interface OnItemLongClickListener {
|
||||||
|
void onItemLongClick(RecyclerView.ViewHolder holder, int position, View v);
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.dahe.mylibrary.callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新的回调
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface RefreshCallBack {
|
||||||
|
/**
|
||||||
|
* @param stat 1刷新 2加载更多
|
||||||
|
* @param page 当前页数
|
||||||
|
* @param count 当前count
|
||||||
|
*/
|
||||||
|
void getRefreshDate(int stat, int page, int count);
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
package com.dahe.mylibrary.cuspop;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.listener.OnItemClickListener;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.adapter.CarAdapter;
|
||||||
|
import com.dahe.mylibrary.bean.CarBean;
|
||||||
|
import com.dahe.mylibrary.net.JsonUtils;
|
||||||
|
import com.lxj.xpopup.core.CenterPopupView;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CarSelPopupView extends CenterPopupView {
|
||||||
|
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private List<CarBean> data;
|
||||||
|
public CarSelPopupView(Context context, String data) {
|
||||||
|
super(context);
|
||||||
|
this.context = context;
|
||||||
|
ArrayList<CarBean> nodeBeans = JsonUtils.getInstance().jsonToList(data, CarBean.class);
|
||||||
|
this.data = nodeBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getImplLayoutId() {
|
||||||
|
return R.layout.view_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
TextView tvTitle = (TextView) findViewById(R.id.tvTitle);
|
||||||
|
ImageView ivCha = (ImageView) findViewById(R.id.ivCha);
|
||||||
|
LinearLayout llCha = (LinearLayout) findViewById(R.id.llCha);
|
||||||
|
Button btnOK = (Button) findViewById(R.id.btnOK);
|
||||||
|
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(context,RecyclerView.VERTICAL,false));
|
||||||
|
recyclerView.setHasFixedSize(true);
|
||||||
|
CarAdapter nodeAdapter = new CarAdapter(-1,data);
|
||||||
|
recyclerView.setAdapter(nodeAdapter);
|
||||||
|
|
||||||
|
tvTitle.setText("关联司机");
|
||||||
|
nodeAdapter.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(@NonNull @NotNull BaseQuickAdapter<?, ?> adapter, @NonNull @NotNull View view, int position) {
|
||||||
|
CarBean nodeSelectBean = data.get(position);
|
||||||
|
nodeSelectBean.setSelect(!nodeSelectBean.isSelect());
|
||||||
|
nodeAdapter.notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btnOK.setOnClickListener(v -> {
|
||||||
|
if (listener!=null){
|
||||||
|
// ArrayList<CarBean> temp = new ArrayList<>();
|
||||||
|
// for (int i = 0; i < data.size(); i++) {
|
||||||
|
// CarBean nodeSelectBean = data.get(i);
|
||||||
|
// if ("1".equals(nodeSelectBean.isSelect())){
|
||||||
|
// temp.add(nodeSelectBean);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// if (temp.size()<=0){
|
||||||
|
// ToastUtils.showToast(context,"至少存在一个节点");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
listener.okClick(JsonUtils.getInstance().toJson(nodeAdapter.getData()));
|
||||||
|
// temp = null;
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
llCha.setOnClickListener(v -> {
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private OnOkListener listener;
|
||||||
|
|
||||||
|
public CarSelPopupView setOnOkListener(OnOkListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnOkListener {
|
||||||
|
void okClick(String data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
package com.dahe.mylibrary.cuspop;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.listener.OnItemClickListener;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.adapter.CenterSimAdapter;
|
||||||
|
import com.dahe.mylibrary.bean.StateBean;
|
||||||
|
import com.luck.picture.lib.decoration.GridSpacingItemDecoration;
|
||||||
|
import com.lxj.xpopup.impl.PartShadowPopupView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 自定义局部阴影弹窗
|
||||||
|
* Create by dance, at 2018/12/21
|
||||||
|
*/
|
||||||
|
public class CenterPopupView extends PartShadowPopupView {
|
||||||
|
private Context ctx;
|
||||||
|
private RecyclerView recyclerView;
|
||||||
|
private List<StateBean> wordList;
|
||||||
|
private CenterSimAdapter adapter;
|
||||||
|
private StateBean selectString;
|
||||||
|
|
||||||
|
public CenterPopupView(@NonNull Activity context, List<StateBean> wordList, StateBean selectString) {
|
||||||
|
super(context);
|
||||||
|
this.wordList= wordList;
|
||||||
|
this.selectString = selectString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getImplLayoutId() {
|
||||||
|
return R.layout.custom_part_shadow_popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
recyclerView = findViewById(R.id.recyclerView);
|
||||||
|
GridLayoutManager gridLayoutManager = new GridLayoutManager(ctx, 4);
|
||||||
|
recyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 20, false));
|
||||||
|
recyclerView.setLayoutManager(gridLayoutManager);
|
||||||
|
adapter = new CenterSimAdapter(-1, wordList,selectString);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
adapter.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) {
|
||||||
|
if (listener!=null){
|
||||||
|
listener.selectChange(wordList.get(position),position);
|
||||||
|
}
|
||||||
|
((CenterSimAdapter)adapter).setSelect(wordList.get(position));
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onShow() {
|
||||||
|
super.onShow();
|
||||||
|
Log.e("tag", "CustomPartShadowPopupView onShow");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDismiss() {
|
||||||
|
super.onDismiss();
|
||||||
|
Log.e("tag", "CustomPartShadowPopupView onDismiss");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private OnSelectChangeListener listener;
|
||||||
|
public CenterPopupView setOnSelectChangeListener(OnSelectChangeListener listener){
|
||||||
|
this.listener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public interface OnSelectChangeListener{
|
||||||
|
void selectChange(StateBean item ,int postion);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
package com.dahe.mylibrary.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头像选择 dialog
|
||||||
|
*
|
||||||
|
* @Description:
|
||||||
|
* @Author: tao
|
||||||
|
* @CreateDate: 2018/7/26 10:34
|
||||||
|
*/
|
||||||
|
public class DialogPhotoSelect extends MyBaseDialog {
|
||||||
|
|
||||||
|
private TextView take_photo;
|
||||||
|
private TextView select_photo;
|
||||||
|
private TextView do_cancel;
|
||||||
|
|
||||||
|
private onSelectClickListener onSelectClickListener;
|
||||||
|
|
||||||
|
public void setOnSelectClickListener(onSelectClickListener onSelectClickListener) {
|
||||||
|
this.onSelectClickListener = onSelectClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogPhotoSelect(@NonNull Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.dialog_photo_select);
|
||||||
|
|
||||||
|
initView();
|
||||||
|
initListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initView() {
|
||||||
|
take_photo = findViewById( R.id.take_photo);
|
||||||
|
select_photo = findViewById(R.id.select_photo);
|
||||||
|
do_cancel = findViewById(R.id.do_cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListener() {
|
||||||
|
|
||||||
|
//拍照
|
||||||
|
take_photo.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
dismiss();
|
||||||
|
onSelectClickListener.onTakePhoto();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//相册选择
|
||||||
|
select_photo.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
dismiss();
|
||||||
|
onSelectClickListener.onSelectPhoto();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
do_cancel.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(@NonNull Context context) {
|
||||||
|
Window window = getWindow();
|
||||||
|
window.setWindowAnimations(R.style.BottomAnim);
|
||||||
|
window.setGravity( Gravity.BOTTOM);
|
||||||
|
//默认的Dialog只有5/6左右的宽度,改为全屏宽度,由dialog的布局自己来决定实际显示宽度
|
||||||
|
window.getDecorView().setPadding(0, 0, 0, 0);
|
||||||
|
WindowManager.LayoutParams lp = window.getAttributes();
|
||||||
|
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||||
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
window.setAttributes(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelAble() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface onSelectClickListener {
|
||||||
|
|
||||||
|
void onTakePhoto();
|
||||||
|
|
||||||
|
void onSelectPhoto();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.dahe.mylibrary.dialog;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog 基类 基类 基类
|
||||||
|
* <p>
|
||||||
|
* 以后再写Dialog,都要继承这个
|
||||||
|
*
|
||||||
|
* @Description:
|
||||||
|
* @Author: tao
|
||||||
|
* @CreateDate: 2018/7/26 10:29
|
||||||
|
*/
|
||||||
|
public class MyBaseDialog extends Dialog {
|
||||||
|
|
||||||
|
|
||||||
|
public MyBaseDialog(@NonNull Context context) {
|
||||||
|
super(context, R.style.MyBaseDialog);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(@NonNull Context context) {
|
||||||
|
Window window = getWindow();
|
||||||
|
window.setWindowAnimations(R.style.BottomAnim);
|
||||||
|
window.setGravity(Gravity.CENTER);
|
||||||
|
//默认的Dialog只有5/6左右的宽度,改为全屏宽度,由dialog的布局自己来决定实际显示宽度
|
||||||
|
window.getDecorView().setPadding(0, 0, 0, 0);
|
||||||
|
WindowManager.LayoutParams lp = window.getAttributes();
|
||||||
|
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||||
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
window.setAttributes(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setCancelable(isCancelAble());
|
||||||
|
setCanceledOnTouchOutside(isCancelAble());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCancelAble() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.dahe.mylibrary.dialog;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Allen Liu on 2017/2/23.
|
||||||
|
*/
|
||||||
|
public class VersionDialog extends Dialog {
|
||||||
|
private int res;
|
||||||
|
|
||||||
|
public VersionDialog(Context context, int theme, int res) {
|
||||||
|
super(context, theme);
|
||||||
|
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||||
|
// TODO 自动生成的构造函数存根
|
||||||
|
setContentView(res);
|
||||||
|
this.res = res;
|
||||||
|
setCanceledOnTouchOutside(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.dahe.mylibrary.glide;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.Registry;
|
||||||
|
import com.bumptech.glide.annotation.GlideModule;
|
||||||
|
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
|
||||||
|
import com.bumptech.glide.load.model.GlideUrl;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AppGlideModule
|
||||||
|
* @Author 用户
|
||||||
|
* @Date 2021/10/11 10:13
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
@GlideModule
|
||||||
|
public class AppGlideModule extends com.bumptech.glide.module.AppGlideModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerComponents(@NonNull @NotNull Context context, @NonNull @NotNull Glide glide, @NonNull @NotNull Registry registry) {
|
||||||
|
super.registerComponents(context, glide, registry);
|
||||||
|
OkHttpClient client = UnsafeOkHttpClient.getUnsafeOkHttpClient();
|
||||||
|
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package com.dahe.mylibrary.glide;
|
||||||
|
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName UnsafeOkHttpClient
|
||||||
|
* @Author 用户
|
||||||
|
* @Date 2021/10/11 10:16
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
public class UnsafeOkHttpClient {
|
||||||
|
public static OkHttpClient getUnsafeOkHttpClient() {
|
||||||
|
try {
|
||||||
|
// Create a trust manager that does not validate certificate chains
|
||||||
|
final TrustManager[] trustAllCerts = new TrustManager[]{
|
||||||
|
new X509TrustManager() {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new java.security.cert.X509Certificate[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Install the all-trusting trust manager
|
||||||
|
final SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||||
|
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||||
|
|
||||||
|
// Create an ssl socket factory with our all-trusting manager
|
||||||
|
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||||
|
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
|
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
|
||||||
|
builder.hostnameVerifier(new HostnameVerifier() {
|
||||||
|
@Override
|
||||||
|
public boolean verify(String hostname, SSLSession session) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.connectTimeout(20, TimeUnit.SECONDS);
|
||||||
|
builder.readTimeout(20,TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
OkHttpClient okHttpClient = builder.build();
|
||||||
|
return okHttpClient;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回通用的实体类
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CommonResponseBean<T> implements Serializable {
|
||||||
|
private T data;
|
||||||
|
private int code;
|
||||||
|
private String info;
|
||||||
|
private String msg;
|
||||||
|
private String url;
|
||||||
|
private String fileName;
|
||||||
|
private boolean success;
|
||||||
|
|
||||||
|
public T getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(T data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfo(String info) {
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSuccess(boolean success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
public class ErrorResponse {
|
||||||
|
private int code;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import okio.Buffer;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传Interceptor
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FileInterceptor implements Interceptor {
|
||||||
|
private static final String TAG = "FileInterceptor";
|
||||||
|
private File mFile;
|
||||||
|
|
||||||
|
public FileInterceptor(File mFile) {
|
||||||
|
this.mFile = mFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
Request request = chain.request();
|
||||||
|
request = request.newBuilder()
|
||||||
|
.post(RequestBody.create(MediaType.parse("application/file; charset=utf-8"), mFile))
|
||||||
|
.build();
|
||||||
|
Response response = chain.proceed(request);
|
||||||
|
Log.i(TAG, "url= " + request.body());
|
||||||
|
Log.i(TAG, "method= " + request.method());
|
||||||
|
ResponseBody responseBody = response.body();
|
||||||
|
//为了不消耗buffer,我们这里使用source先获得buffer对象,然后clone()后使用
|
||||||
|
BufferedSource source = responseBody.source();
|
||||||
|
source.request(Long.MAX_VALUE); // Buffer the entire body.
|
||||||
|
//获得返回的数据
|
||||||
|
Buffer buffer = source.buffer();
|
||||||
|
//使用前clone()下,避免直接消耗
|
||||||
|
String responseBodyStr = buffer.clone().readString(Charset.forName("UTF-8"));
|
||||||
|
Log.i(TAG, "result-body= " + responseBodyStr);
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = new JSONObject(responseBodyStr);
|
||||||
|
responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.getString("response"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
response = response.newBuilder().body(responseBody).build();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import okio.Buffer;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
import retrofit2.Converter;
|
||||||
|
|
||||||
|
|
||||||
|
public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
|
||||||
|
private final Gson gson;
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
|
||||||
|
public GsonResponseBodyConverter(Gson gson, Type type) {
|
||||||
|
this.gson = gson;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T convert(ResponseBody value) throws IOException {
|
||||||
|
|
||||||
|
//为了不消耗buffer,我们这里使用source先获得buffer对象,然后clone()后使用
|
||||||
|
BufferedSource source = value.source();
|
||||||
|
source.request(Long.MAX_VALUE); // Buffer the entire body.
|
||||||
|
//获得返回的数据
|
||||||
|
Buffer buffer = source.buffer();
|
||||||
|
//使用前clone()下,避免直接消耗
|
||||||
|
String responseBodyStr = buffer.clone().readString(Charset.forName("UTF-8"));
|
||||||
|
try {
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject(responseBodyStr);
|
||||||
|
int code = jsonObject.optInt("code");
|
||||||
|
if (-1 == code) {
|
||||||
|
jsonObject.put("data", new JSONObject());
|
||||||
|
// ErrorResponse errorResponse = gson.fromJson(response, ErrorResponse.class);
|
||||||
|
//抛一个自定义ResultException 传入失败时候的状态码,和信息
|
||||||
|
|
||||||
|
throw new ResultException(-1, "errorResponse.getMsg()");
|
||||||
|
|
||||||
|
// return gson.fromJson(responseBodyStr,type);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return gson.fromJson(responseBodyStr, type);
|
||||||
|
|
||||||
|
|
||||||
|
// String response = value.string();
|
||||||
|
// //先将返回的json数据解析到Response中,如果code==200,则解析到我们的实体基类中,否则抛异常
|
||||||
|
// Response httpResult = gson.fromJson(response, Response.class);
|
||||||
|
// if (httpResult.code()==200){
|
||||||
|
// //200的时候就直接解析,不可能出现解析异常。因为我们实体基类中传入的泛型,就是数据成功时候的格式
|
||||||
|
// return gson.fromJson(response,type);
|
||||||
|
// }else {
|
||||||
|
// ErrorResponse errorResponse = gson.fromJson(response,ErrorResponse.class);
|
||||||
|
// //抛一个自定义ResultException 传入失败时候的状态码,和信息
|
||||||
|
// try {
|
||||||
|
// throw new ResultException(errorResponse.getCode(),errorResponse.getMsg());
|
||||||
|
// } catch (ResultException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import okio.Buffer;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* json的Interceptor
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class JsonInterceptor implements Interceptor {
|
||||||
|
private static final String TAG = "JsonInterceptor";
|
||||||
|
|
||||||
|
public JsonInterceptor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
Request request = chain.request();
|
||||||
|
Response response = chain.proceed(request);
|
||||||
|
ResponseBody responseBody = response.body();
|
||||||
|
//为了不消耗buffer,我们这里使用source先获得buffer对象,然后clone()后使用
|
||||||
|
BufferedSource source = responseBody.source();
|
||||||
|
source.request(Long.MAX_VALUE); // Buffer the entire body.
|
||||||
|
//获得返回的数据
|
||||||
|
Buffer buffer = source.buffer();
|
||||||
|
//使用前clone()下,避免直接消耗
|
||||||
|
String responseBodyStr = buffer.clone().readString(Charset.forName("UTF-8"));
|
||||||
|
Log.i(TAG, "result-body= " + responseBodyStr);
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = new JSONObject(responseBodyStr);
|
||||||
|
String str = jsonObject.optString("data");
|
||||||
|
int code = jsonObject.optInt("code");
|
||||||
|
if (-1 == code) {
|
||||||
|
jsonObject.put("data", new JSONObject());
|
||||||
|
throw new ResultException();
|
||||||
|
} else {
|
||||||
|
if (TextUtils.isEmpty(str)) {
|
||||||
|
jsonObject.put("data", new JSONObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String data = jsonObject.toString();
|
||||||
|
responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), data);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
response = response.newBuilder().body(responseBody).build();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonIOException;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 利用Gson反射对象类型,将json转化为对象
|
||||||
|
*/
|
||||||
|
public class JsonUtils {
|
||||||
|
private Gson mGson = null;
|
||||||
|
private static JsonUtils mUtils;
|
||||||
|
|
||||||
|
public static JsonUtils getInstance() {
|
||||||
|
if (mUtils == null) {
|
||||||
|
return new JsonUtils();
|
||||||
|
} else {
|
||||||
|
return mUtils;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gson getGson() {
|
||||||
|
if (null == mGson) {
|
||||||
|
mGson = new GsonBuilder().serializeNulls().create();
|
||||||
|
}
|
||||||
|
return mGson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJson(Object o){
|
||||||
|
return getGson().toJson(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将json数组转化为List
|
||||||
|
*
|
||||||
|
* @param json json字符串
|
||||||
|
* @param classOfT 对应实体类型
|
||||||
|
* @return 实体列表
|
||||||
|
*/
|
||||||
|
public <T> ArrayList<T> jsonToList(String json, Class<T> classOfT) {
|
||||||
|
try {
|
||||||
|
if (mGson == null) {
|
||||||
|
// 不要直接new Gson是为了避免放回结果为null的这种情况
|
||||||
|
mGson = new GsonBuilder().serializeNulls().create();
|
||||||
|
}
|
||||||
|
Type type = new TypeToken<ArrayList<JsonObject>>() {
|
||||||
|
}.getType();
|
||||||
|
ArrayList<JsonObject> jsonObjs = mGson.fromJson(json, type);
|
||||||
|
|
||||||
|
ArrayList<T> listOfT = new ArrayList<T>();
|
||||||
|
for (JsonObject jsonObj : jsonObjs) {
|
||||||
|
listOfT.add(mGson.fromJson(jsonObj, classOfT));
|
||||||
|
}
|
||||||
|
return listOfT;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T fromJson(String json, Class<T> type) throws JsonIOException, JsonSyntaxException {
|
||||||
|
try {
|
||||||
|
JSONObject object = new JSONObject(json);
|
||||||
|
json = object.getString("response");
|
||||||
|
Log.i("fromJson: ", json);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return getGson().fromJson(json, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T fromJson(String json, Type type) {
|
||||||
|
return getGson().fromJson(json, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||||
|
return getGson().fromJson(reader, typeOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2018\8\26 0026.
|
||||||
|
*/
|
||||||
|
public class PagerBean<T> {
|
||||||
|
private int total;
|
||||||
|
private int count;
|
||||||
|
private int more;
|
||||||
|
|
||||||
|
private ArrayList<T> rows;
|
||||||
|
|
||||||
|
public ArrayList<T> getRows() {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRows(ArrayList<T> rows) {
|
||||||
|
this.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(int total) {
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(int count) {
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMore() {
|
||||||
|
return more;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMore(int more) {
|
||||||
|
this.more = more;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回通用的实体类
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PagingBean<T> implements Serializable {
|
||||||
|
private T data;
|
||||||
|
private int code;
|
||||||
|
private String count;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
public T getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(T data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(String count) {
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import retrofit2.Converter;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
|
public class ResponseConverterFactory extends Converter.Factory {
|
||||||
|
|
||||||
|
public static ResponseConverterFactory create() {
|
||||||
|
return create(new Gson());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ResponseConverterFactory create(Gson gson) {
|
||||||
|
return new ResponseConverterFactory(gson);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Gson gson;
|
||||||
|
|
||||||
|
private ResponseConverterFactory(Gson gson) {
|
||||||
|
if (gson == null) throw new NullPointerException("gson == null");
|
||||||
|
this.gson = gson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
|
||||||
|
//返回我们自定义的Gson响应体变换器
|
||||||
|
return new GsonResponseBodyConverter<>(gson, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Converter<?, RequestBody> requestBodyConverter(Type type,
|
||||||
|
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
|
||||||
|
//返回我们自定义的Gson响应体变换器
|
||||||
|
return new GsonResponseBodyConverter<>(gson,type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.dahe.mylibrary.net;
|
||||||
|
|
||||||
|
public class ResultException extends Exception {
|
||||||
|
|
||||||
|
public ResultException() {
|
||||||
|
super();
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultException(int code, String msg) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.dahe.mylibrary.recycleviewswipe;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
|
||||||
|
|
||||||
|
private int spanCount; //列数
|
||||||
|
private int spacing; //间隔
|
||||||
|
private boolean includeEdge; //是否包含边缘
|
||||||
|
|
||||||
|
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
|
||||||
|
this.spanCount = spanCount;
|
||||||
|
this.spacing = spacing;
|
||||||
|
this.includeEdge = includeEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
|
||||||
|
//这里是关键,需要根据你有几列来判断
|
||||||
|
int position = parent.getChildAdapterPosition(view); // item position
|
||||||
|
int column = position % spanCount; // item column
|
||||||
|
|
||||||
|
if (includeEdge) {
|
||||||
|
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
|
||||||
|
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
|
||||||
|
|
||||||
|
if (position < spanCount) { // top edge
|
||||||
|
outRect.top = spacing;
|
||||||
|
}
|
||||||
|
outRect.bottom = spacing; // item bottom
|
||||||
|
} else {
|
||||||
|
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
|
||||||
|
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
|
||||||
|
if (position >= spanCount) {
|
||||||
|
outRect.top = spacing; // item top
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
package com.dahe.mylibrary.recycleviewswipe;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
|
||||||
|
public class MyDecoration extends RecyclerView.ItemDecoration{
|
||||||
|
|
||||||
|
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
|
||||||
|
|
||||||
|
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
|
||||||
|
|
||||||
|
private Drawable mDivider;
|
||||||
|
|
||||||
|
private int mOrientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分割线缩进值
|
||||||
|
*/
|
||||||
|
private int inset;
|
||||||
|
|
||||||
|
private Paint paint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @param orientation layout的方向
|
||||||
|
* @param drawable 引入的drawable的ID
|
||||||
|
* @param inset 分割线缩进值
|
||||||
|
*/
|
||||||
|
public MyDecoration(Context context, int orientation, int drawable, int inset) {
|
||||||
|
mDivider = context.getResources().getDrawable(drawable);
|
||||||
|
this.inset = inset;
|
||||||
|
paint = new Paint();
|
||||||
|
paint.setColor(context.getResources().getColor(R.color.white));
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
setOrientation(orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(int orientation) {
|
||||||
|
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
|
||||||
|
throw new IllegalArgumentException("invalid orientation");
|
||||||
|
}
|
||||||
|
mOrientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas c, RecyclerView parent) {
|
||||||
|
if (mOrientation == VERTICAL_LIST) {
|
||||||
|
drawVertical(c, parent);
|
||||||
|
} else {
|
||||||
|
drawHorizontal(c, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawVertical(Canvas c, RecyclerView parent) {
|
||||||
|
final int left = parent.getPaddingLeft();
|
||||||
|
final int right = parent.getWidth() - parent.getPaddingRight();
|
||||||
|
|
||||||
|
final int childCount = parent.getChildCount();
|
||||||
|
//最后一个item不画分割线
|
||||||
|
for (int i = 0; i < childCount - 1; i++) {
|
||||||
|
final View child = parent.getChildAt(i);
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||||
|
final int top = child.getBottom() + params.bottomMargin;
|
||||||
|
final int bottom = top + mDivider.getIntrinsicHeight();
|
||||||
|
if (inset > 0) {
|
||||||
|
c.drawRect(left, top, right, bottom, paint);
|
||||||
|
mDivider.setBounds(left + inset, top, right - inset, bottom);
|
||||||
|
} else {
|
||||||
|
mDivider.setBounds(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
mDivider.draw(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawHorizontal(Canvas c, RecyclerView parent) {
|
||||||
|
final int top = parent.getPaddingTop();
|
||||||
|
final int bottom = parent.getHeight() - parent.getPaddingBottom();
|
||||||
|
|
||||||
|
final int childCount = parent.getChildCount();
|
||||||
|
for (int i = 0; i < childCount - 1; i++) {
|
||||||
|
final View child = parent.getChildAt(i);
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||||
|
final int left = child.getRight() + params.rightMargin;
|
||||||
|
final int right = left + mDivider.getIntrinsicHeight();
|
||||||
|
mDivider.setBounds(left, top, right, bottom);
|
||||||
|
mDivider.draw(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//由于Divider也有宽高,每一个Item需要向下或者向右偏移
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
|
||||||
|
if (mOrientation == VERTICAL_LIST) {
|
||||||
|
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
|
||||||
|
} else {
|
||||||
|
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
package com.dahe.mylibrary.recycleviewswipe;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class RecycleViewDivider extends RecyclerView.ItemDecoration {
|
||||||
|
|
||||||
|
private Paint mPaint;
|
||||||
|
//分割线
|
||||||
|
private Drawable mDivider;
|
||||||
|
//分割线高度,默认是1px
|
||||||
|
private int mDividerHeight = 1;
|
||||||
|
//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
|
||||||
|
private int mOrientation;
|
||||||
|
|
||||||
|
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 默认分割线:高度为2px,颜色为灰色
|
||||||
|
* 获取属性值,
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param orientation 列表方向
|
||||||
|
*/
|
||||||
|
|
||||||
|
public RecycleViewDivider(Context context, int orientation){
|
||||||
|
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
|
||||||
|
throw new IllegalArgumentException("请输入正确的参数!");
|
||||||
|
}
|
||||||
|
mOrientation = orientation;
|
||||||
|
final TypedArray array = context.obtainStyledAttributes(ATTRS);
|
||||||
|
mDivider = array.getDrawable(0);
|
||||||
|
array.recycle();
|
||||||
|
mDividerHeight = mDivider.getIntrinsicHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义分割线
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param orientation 列表方向
|
||||||
|
* @param drawableId 分割线图片
|
||||||
|
*/
|
||||||
|
public RecycleViewDivider(Context context, int orientation, int drawableId) {
|
||||||
|
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
|
||||||
|
throw new IllegalArgumentException("请输入正确的参数!");
|
||||||
|
}
|
||||||
|
mOrientation = orientation;
|
||||||
|
|
||||||
|
mDivider = ContextCompat.getDrawable(context, drawableId);
|
||||||
|
mDividerHeight = mDivider.getIntrinsicHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义分割线
|
||||||
|
*
|
||||||
|
* @param orientation 列表方向
|
||||||
|
* @param dividerHeight 分割线高度
|
||||||
|
* @param dividerColor 分割线颜色
|
||||||
|
*/
|
||||||
|
public RecycleViewDivider(int orientation, int dividerHeight, int dividerColor) {
|
||||||
|
|
||||||
|
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
|
||||||
|
throw new IllegalArgumentException("请输入正确的参数!");
|
||||||
|
}
|
||||||
|
mOrientation = orientation;
|
||||||
|
|
||||||
|
mDividerHeight = dividerHeight;
|
||||||
|
|
||||||
|
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
mPaint.setColor(dividerColor);
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取分割线尺寸
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
|
||||||
|
if (mOrientation == LinearLayoutManager.VERTICAL) {
|
||||||
|
outRect.set(0, 0, 0, mDividerHeight);
|
||||||
|
} else {
|
||||||
|
outRect.set(0, 0, mDividerHeight, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
super.onDraw(c, parent, state);
|
||||||
|
if(mOrientation==LinearLayoutManager.VERTICAL){
|
||||||
|
drawVerticalLine(c,parent);
|
||||||
|
}else{
|
||||||
|
drawHorizontalLine(c,parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//为横方向item, 画分割线
|
||||||
|
private void drawHorizontalLine(Canvas canvas, RecyclerView parent) {
|
||||||
|
|
||||||
|
final int top = parent.getPaddingTop();
|
||||||
|
final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
|
||||||
|
final int childSize = parent.getChildCount();
|
||||||
|
for (int i = 0; i < childSize - 1; i++) {
|
||||||
|
if ((i+1) % 3 != 0) {
|
||||||
|
final View child = parent.getChildAt(i);
|
||||||
|
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||||
|
final int left = child.getRight() + layoutParams.rightMargin;
|
||||||
|
final int right = left + mDividerHeight;
|
||||||
|
if (mDivider != null) {
|
||||||
|
mDivider.setBounds(left, top, right, bottom);
|
||||||
|
mDivider.draw(canvas);
|
||||||
|
}
|
||||||
|
if (mPaint != null) {
|
||||||
|
canvas.drawRect(left, top, right, bottom, mPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//为竖方向item, 画分割线
|
||||||
|
private void drawVerticalLine(Canvas canvas, RecyclerView parent) {
|
||||||
|
|
||||||
|
final int left = parent.getPaddingLeft();
|
||||||
|
final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
|
||||||
|
final int childSize = parent.getChildCount();
|
||||||
|
for (int i = 0; i < childSize; i++) {
|
||||||
|
if (i < childSize -1) {
|
||||||
|
final View child = parent.getChildAt(i);
|
||||||
|
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||||
|
final int top = child.getBottom() + layoutParams.bottomMargin;
|
||||||
|
final int bottom = top + mDividerHeight;
|
||||||
|
|
||||||
|
if (mDivider != null) {
|
||||||
|
mDivider.setBounds(left, top, right, bottom);
|
||||||
|
mDivider.draw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPaint != null) {
|
||||||
|
canvas.drawRect(left, top, right, bottom, mPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,330 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.CommonBaseLibrary;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* author: Blankj
|
||||||
|
* blog : http://blankj.com
|
||||||
|
* time : 2016/09/23
|
||||||
|
* desc : Activity相关工具类
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class ActivityUtils {
|
||||||
|
|
||||||
|
public ActivityUtils() {
|
||||||
|
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动Activity
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param clz
|
||||||
|
* @param bundle
|
||||||
|
*/
|
||||||
|
public static void startActivity(@NonNull Context context, @NonNull Class<?> clz, Bundle bundle) {
|
||||||
|
Intent intent = new Intent(context, clz);
|
||||||
|
if (null != bundle) intent.putExtras(bundle);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动Activity
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param clz
|
||||||
|
* @param bundle
|
||||||
|
*/
|
||||||
|
public static void startPushActivity(@NonNull Context context, @NonNull Class<?> clz, Bundle bundle) {
|
||||||
|
Intent intent = new Intent(context, clz);
|
||||||
|
if (null != bundle){
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent.putExtras(bundle);
|
||||||
|
}
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动Activity
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param clz
|
||||||
|
*/
|
||||||
|
public static void startActivity(@NonNull Context context, @NonNull Class<?> clz) {
|
||||||
|
startActivity(context, clz, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动Activity
|
||||||
|
*
|
||||||
|
* @param activity
|
||||||
|
* @param clz
|
||||||
|
* @param bundle
|
||||||
|
*/
|
||||||
|
public static void startActivityForResult(@NonNull Activity activity, @NonNull Class<?> clz, Bundle bundle, int requestCode) {
|
||||||
|
Intent intent = new Intent(activity, clz);
|
||||||
|
if (null != bundle) intent.putExtras(bundle);
|
||||||
|
activity.startActivityForResult(intent, requestCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动Activity
|
||||||
|
*
|
||||||
|
* @param activity
|
||||||
|
* @param clz
|
||||||
|
*/
|
||||||
|
public static void startActivityForResult(@NonNull Activity activity, @NonNull Class<?> clz, int requestCode) {
|
||||||
|
startActivityForResult(activity, clz, null, requestCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 跳转登录界面
|
||||||
|
// *
|
||||||
|
// * @param context
|
||||||
|
// * @param finishOthers 是否结束其他的activity true结束 false 不结束
|
||||||
|
// */
|
||||||
|
// public static void openLoginActivity(@NonNull Context context, boolean finishOthers) {
|
||||||
|
// Intent intent = new Intent(context, LoginMainActivity.class);
|
||||||
|
// Bundle bundle = new Bundle();
|
||||||
|
// bundle.putBoolean("finishOthers", finishOthers);
|
||||||
|
// intent.putExtras(bundle);
|
||||||
|
// context.startActivity(intent);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 启动前必须登录Activity
|
||||||
|
// *
|
||||||
|
// * @param context
|
||||||
|
// * @param clz
|
||||||
|
// */
|
||||||
|
// public static void startActivityByLogin(@NonNull Context context, @NonNull Class<?> clz) {
|
||||||
|
// startActivityByLogin(context, clz, null);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回到桌面
|
||||||
|
*/
|
||||||
|
public static void startHomeActivity(Context context) {
|
||||||
|
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
|
||||||
|
homeIntent.addCategory(Intent.CATEGORY_HOME);
|
||||||
|
context.startActivity(homeIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Activity栈链表
|
||||||
|
*
|
||||||
|
* @return Activity栈链表
|
||||||
|
*/
|
||||||
|
public static List<Activity> getActivityList() {
|
||||||
|
return CommonBaseLibrary.activityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取启动项Activity
|
||||||
|
*
|
||||||
|
* @param packageName 包名
|
||||||
|
* @return 启动项Activity
|
||||||
|
*/
|
||||||
|
public static String getLauncherActivity(@NonNull final String packageName) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_MAIN, null);
|
||||||
|
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
PackageManager pm = CommonBaseLibrary.getApplication().getPackageManager();
|
||||||
|
List<ResolveInfo> info = pm.queryIntentActivities(intent, 0);
|
||||||
|
for (ResolveInfo aInfo : info) {
|
||||||
|
if (aInfo.activityInfo.packageName.equals(packageName)) {
|
||||||
|
return aInfo.activityInfo.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "no " + packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取栈顶Activity
|
||||||
|
*
|
||||||
|
* @return 栈顶Activity
|
||||||
|
*/
|
||||||
|
public static Activity getTopActivity() {
|
||||||
|
if (CommonBaseLibrary.topActivity != null) {
|
||||||
|
Activity activity = CommonBaseLibrary.topActivity.get();
|
||||||
|
if (activity != null) {
|
||||||
|
return activity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
int size = activities.size();
|
||||||
|
return size > 0 ? activities.get(size - 1) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断Activity是否存在栈中
|
||||||
|
*
|
||||||
|
* @param activity activity
|
||||||
|
* @return {@code true}: 存在<br>{@code false}: 不存在
|
||||||
|
*/
|
||||||
|
public static boolean isActivityExistsInStack(@NonNull final Activity activity) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
for (Activity aActivity : activities) {
|
||||||
|
if (aActivity.equals(activity)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断Activity是否存在栈中
|
||||||
|
*
|
||||||
|
* @param clz activity类
|
||||||
|
* @return {@code true}: 存在<br>{@code false}: 不存在
|
||||||
|
*/
|
||||||
|
public static boolean isActivityExistsInStack(@NonNull final Class<?> clz) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
for (Activity aActivity : activities) {
|
||||||
|
if (aActivity.getClass().equals(clz)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束Activity
|
||||||
|
*
|
||||||
|
* @param activity activity
|
||||||
|
*/
|
||||||
|
public static void finishActivity(@NonNull final Activity activity) {
|
||||||
|
activity.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束Activity
|
||||||
|
*
|
||||||
|
* @param clz activity类
|
||||||
|
*/
|
||||||
|
public static void finishActivity(@NonNull final Class<?> clz) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
for (Activity activity : activities) {
|
||||||
|
if (activity.getClass().equals(clz)) {
|
||||||
|
activity.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束到指定Activity
|
||||||
|
*
|
||||||
|
* @param activity activity
|
||||||
|
* @param isIncludeSelf 是否结束该activity自己
|
||||||
|
*/
|
||||||
|
public static boolean finishToActivity(@NonNull final Activity activity,
|
||||||
|
final boolean isIncludeSelf) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
for (int i = activities.size() - 1; i >= 0; --i) {
|
||||||
|
Activity aActivity = activities.get(i);
|
||||||
|
if (aActivity.equals(activity)) {
|
||||||
|
if (isIncludeSelf) {
|
||||||
|
finishActivity(aActivity);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
finishActivity(aActivity);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束到指定Activity
|
||||||
|
*
|
||||||
|
* @param isIncludeSelf 是否结束该activity自己
|
||||||
|
*/
|
||||||
|
public static boolean finishToActivity(@NonNull final Class<?> clz,
|
||||||
|
final boolean isIncludeSelf) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
for (int i = activities.size() - 1; i >= 0; --i) {
|
||||||
|
Activity aActivity = activities.get(i);
|
||||||
|
if (aActivity.getClass().equals(clz)) {
|
||||||
|
if (isIncludeSelf) {
|
||||||
|
finishActivity(aActivity);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
finishActivity(aActivity);
|
||||||
|
}
|
||||||
|
// finishActivity(aActivity);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束除最新之外的同类型Activity
|
||||||
|
* <p>也就是让栈中最多只剩下一种类型的Activity</p>
|
||||||
|
*
|
||||||
|
* @param clz activity类
|
||||||
|
*/
|
||||||
|
public static void finishOtherActivitiesExceptNewest(@NonNull final Class<?> clz) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
boolean flag = false;
|
||||||
|
for (int i = activities.size() - 1; i >= 0; i--) {
|
||||||
|
Activity activity = activities.get(i);
|
||||||
|
if (activity.getClass().equals(clz)) {
|
||||||
|
if (flag) {
|
||||||
|
finishActivity(activity);
|
||||||
|
} else {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finishActivity(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除除本activity之外所有的activity
|
||||||
|
*
|
||||||
|
* @param clz 本activity的类名
|
||||||
|
*/
|
||||||
|
public static void finishOtherActivities(@NonNull final Class<?> clz) {
|
||||||
|
List<Activity> activities = CommonBaseLibrary.activityList;
|
||||||
|
for (Activity activity : activities) {
|
||||||
|
if (!activity.getClass().equals(clz)) {
|
||||||
|
finishActivity(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束所有activity
|
||||||
|
*/
|
||||||
|
public static void finishAllActivities() {
|
||||||
|
List<Activity> activityList = CommonBaseLibrary.activityList;
|
||||||
|
for (int i = activityList.size() - 1; i >= 0; --i) {// 从栈顶开始移除
|
||||||
|
Activity activity = activityList.get(i);
|
||||||
|
activity.finish();// 在onActivityDestroyed发生remove
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Context getActivityOrApp() {
|
||||||
|
Activity topActivity = getTopActivity();
|
||||||
|
return topActivity == null ? CommonBaseLibrary.getApplication() : topActivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
1062
mylibrary/src/main/java/com/dahe/mylibrary/utils/AppUtils.java
Normal file
1062
mylibrary/src/main/java/com/dahe/mylibrary/utils/AppUtils.java
Normal file
File diff suppressed because it is too large
Load Diff
678
mylibrary/src/main/java/com/dahe/mylibrary/utils/BarUtils.java
Normal file
678
mylibrary/src/main/java/com/dahe/mylibrary/utils/BarUtils.java
Normal file
@ -0,0 +1,678 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.KeyCharacterMap;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewGroup.MarginLayoutParams;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.annotation.RequiresPermission;
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.CommonBaseLibrary;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.EXPAND_STATUS_BAR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getStatusBarHeight : 获取状态栏高度(px)
|
||||||
|
* setStatusBarVisibility : 设置状态栏是否可见
|
||||||
|
* isStatusBarVisible : 判断状态栏是否可见
|
||||||
|
* setStatusBarLightMode : 设置状态栏是否为浅色模式
|
||||||
|
* addMarginTopEqualStatusBarHeight : 为 view 增加 MarginTop 为状态栏高度
|
||||||
|
* subtractMarginTopEqualStatusBarHeight: 为 view 减少 MarginTop 为状态栏高度
|
||||||
|
* setStatusBarColor : 设置状态栏颜色
|
||||||
|
* setStatusBarColor4Drawer : 为 DrawerLayout 设置状态栏颜色
|
||||||
|
* getActionBarHeight : 获取 ActionBar 高度
|
||||||
|
* setNotificationBarVisibility : 设置通知栏是否可见
|
||||||
|
* getNavBarHeight : 获取导航栏高度
|
||||||
|
* setNavBarVisibility : 设置导航栏是否可见
|
||||||
|
* isNavBarVisible : 判断导航栏是否可见
|
||||||
|
* setNavBarColor : 设置导航栏颜色
|
||||||
|
* getNavBarColor : 获取导航栏颜色
|
||||||
|
* isSupportNavBar : 判断是否支持导航栏
|
||||||
|
*/
|
||||||
|
public final class BarUtils {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// status bar
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private static final String TAG_STATUS_BAR = "TAG_STATUS_BAR";
|
||||||
|
private static final String TAG_OFFSET = "TAG_OFFSET";
|
||||||
|
private static final int KEY_OFFSET = -123;
|
||||||
|
|
||||||
|
private BarUtils() {
|
||||||
|
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the status bar's height.
|
||||||
|
*
|
||||||
|
* @return the status bar's height
|
||||||
|
*/
|
||||||
|
public static int getStatusBarHeight() {
|
||||||
|
Resources resources = Resources.getSystem();
|
||||||
|
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
|
||||||
|
return resources.getDimensionPixelSize(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's visibility.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @param isVisible True to set status bar visible, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarVisibility(@NonNull final Activity activity,
|
||||||
|
final boolean isVisible) {
|
||||||
|
setStatusBarVisibility(activity.getWindow(), isVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's visibility.
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @param isVisible True to set status bar visible, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarVisibility(@NonNull final Window window,
|
||||||
|
final boolean isVisible) {
|
||||||
|
if (isVisible) {
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||||
|
showStatusBarView(window);
|
||||||
|
addMarginTopEqualStatusBarHeight(window);
|
||||||
|
} else {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||||
|
hideStatusBarView(window);
|
||||||
|
subtractMarginTopEqualStatusBarHeight(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the status bar is visible.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @return {@code true}: yes<br>{@code false}: no
|
||||||
|
*/
|
||||||
|
public static boolean isStatusBarVisible(@NonNull final Activity activity) {
|
||||||
|
int flags = activity.getWindow().getAttributes().flags;
|
||||||
|
return (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's light mode.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @param isLightMode True to set status bar light mode, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarLightMode(@NonNull final Activity activity,
|
||||||
|
final boolean isLightMode) {
|
||||||
|
setStatusBarLightMode(activity.getWindow(), isLightMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's light mode.
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @param isLightMode True to set status bar light mode, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarLightMode(@NonNull final Window window,
|
||||||
|
final boolean isLightMode) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
View decorView = window.getDecorView();
|
||||||
|
if (decorView != null) {
|
||||||
|
int vis = decorView.getSystemUiVisibility();
|
||||||
|
if (isLightMode) {
|
||||||
|
vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
|
||||||
|
} else {
|
||||||
|
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
|
||||||
|
}
|
||||||
|
decorView.setSystemUiVisibility(vis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the status bar light mode.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @return {@code true}: yes<br>{@code false}: no
|
||||||
|
*/
|
||||||
|
public static boolean isStatusBarLightMode(@NonNull final Activity activity) {
|
||||||
|
return isStatusBarLightMode(activity.getWindow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the status bar light mode.
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @return {@code true}: yes<br>{@code false}: no
|
||||||
|
*/
|
||||||
|
public static boolean isStatusBarLightMode(@NonNull final Window window) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
View decorView = window.getDecorView();
|
||||||
|
if (decorView != null) {
|
||||||
|
int vis = decorView.getSystemUiVisibility();
|
||||||
|
return (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the top margin size equals status bar's height for view.
|
||||||
|
*
|
||||||
|
* @param view The view.
|
||||||
|
*/
|
||||||
|
public static void addMarginTopEqualStatusBarHeight(@NonNull View view) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
view.setTag(TAG_OFFSET);
|
||||||
|
Object haveSetOffset = view.getTag(KEY_OFFSET);
|
||||||
|
if (haveSetOffset != null && (Boolean) haveSetOffset) return;
|
||||||
|
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
|
||||||
|
layoutParams.setMargins(layoutParams.leftMargin,
|
||||||
|
layoutParams.topMargin + getStatusBarHeight(),
|
||||||
|
layoutParams.rightMargin,
|
||||||
|
layoutParams.bottomMargin);
|
||||||
|
view.setTag(KEY_OFFSET, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract the top margin size equals status bar's height for view.
|
||||||
|
*
|
||||||
|
* @param view The view.
|
||||||
|
*/
|
||||||
|
public static void subtractMarginTopEqualStatusBarHeight(@NonNull View view) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
Object haveSetOffset = view.getTag(KEY_OFFSET);
|
||||||
|
if (haveSetOffset == null || !(Boolean) haveSetOffset) return;
|
||||||
|
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
|
||||||
|
layoutParams.setMargins(layoutParams.leftMargin,
|
||||||
|
layoutParams.topMargin - getStatusBarHeight(),
|
||||||
|
layoutParams.rightMargin,
|
||||||
|
layoutParams.bottomMargin);
|
||||||
|
view.setTag(KEY_OFFSET, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addMarginTopEqualStatusBarHeight(final Window window) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
View withTag = window.getDecorView().findViewWithTag(TAG_OFFSET);
|
||||||
|
if (withTag == null) return;
|
||||||
|
addMarginTopEqualStatusBarHeight(withTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void subtractMarginTopEqualStatusBarHeight(final Window window) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
View withTag = window.getDecorView().findViewWithTag(TAG_OFFSET);
|
||||||
|
if (withTag == null) return;
|
||||||
|
subtractMarginTopEqualStatusBarHeight(withTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's color.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @param color The status bar's color.
|
||||||
|
*/
|
||||||
|
public static View setStatusBarColor(@NonNull final Activity activity,
|
||||||
|
@ColorInt final int color) {
|
||||||
|
return setStatusBarColor(activity, color, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's color.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @param color The status bar's color.
|
||||||
|
* @param isDecor True to add fake status bar in DecorView,
|
||||||
|
* false to add fake status bar in ContentView.
|
||||||
|
*/
|
||||||
|
public static View setStatusBarColor(@NonNull final Activity activity,
|
||||||
|
@ColorInt final int color,
|
||||||
|
final boolean isDecor) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null;
|
||||||
|
transparentStatusBar(activity);
|
||||||
|
return applyStatusBarColor(activity, color, isDecor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's color.
|
||||||
|
*
|
||||||
|
* @param fakeStatusBar The fake status bar view.
|
||||||
|
* @param color The status bar's color.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarColor(@NonNull final View fakeStatusBar,
|
||||||
|
@ColorInt final int color) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
Activity activity = getActivityByView(fakeStatusBar);
|
||||||
|
if (activity == null) return;
|
||||||
|
transparentStatusBar(activity);
|
||||||
|
fakeStatusBar.setVisibility(View.VISIBLE);
|
||||||
|
ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
|
||||||
|
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
|
layoutParams.height = getStatusBarHeight();
|
||||||
|
fakeStatusBar.setBackgroundColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the custom status bar.
|
||||||
|
*
|
||||||
|
* @param fakeStatusBar The fake status bar view.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarCustom(@NonNull final View fakeStatusBar) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
Activity activity = getActivityByView(fakeStatusBar);
|
||||||
|
if (activity == null) return;
|
||||||
|
transparentStatusBar(activity);
|
||||||
|
fakeStatusBar.setVisibility(View.VISIBLE);
|
||||||
|
ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
|
||||||
|
if (layoutParams == null) {
|
||||||
|
layoutParams = new ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
getStatusBarHeight()
|
||||||
|
);
|
||||||
|
fakeStatusBar.setLayoutParams(layoutParams);
|
||||||
|
} else {
|
||||||
|
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
|
layoutParams.height = getStatusBarHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's color for DrawerLayout.
|
||||||
|
* <p>DrawLayout must add {@code android:fitsSystemWindows="true"}</p>
|
||||||
|
*
|
||||||
|
* @param drawer The DrawLayout.
|
||||||
|
* @param fakeStatusBar The fake status bar view.
|
||||||
|
* @param color The status bar's color.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer,
|
||||||
|
@NonNull final View fakeStatusBar,
|
||||||
|
@ColorInt final int color) {
|
||||||
|
setStatusBarColor4Drawer(drawer, fakeStatusBar, color, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status bar's color for DrawerLayout.
|
||||||
|
* <p>DrawLayout must add {@code android:fitsSystemWindows="true"}</p>
|
||||||
|
*
|
||||||
|
* @param drawer The DrawLayout.
|
||||||
|
* @param fakeStatusBar The fake status bar view.
|
||||||
|
* @param color The status bar's color.
|
||||||
|
* @param isTop True to set DrawerLayout at the top layer, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer,
|
||||||
|
@NonNull final View fakeStatusBar,
|
||||||
|
@ColorInt final int color,
|
||||||
|
final boolean isTop) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
Activity activity = getActivityByView(fakeStatusBar);
|
||||||
|
if (activity == null) return;
|
||||||
|
transparentStatusBar(activity);
|
||||||
|
drawer.setFitsSystemWindows(false);
|
||||||
|
setStatusBarColor(fakeStatusBar, color);
|
||||||
|
for (int i = 0, count = drawer.getChildCount(); i < count; i++) {
|
||||||
|
drawer.getChildAt(i).setFitsSystemWindows(false);
|
||||||
|
}
|
||||||
|
if (isTop) {
|
||||||
|
hideStatusBarView(activity);
|
||||||
|
} else {
|
||||||
|
setStatusBarColor(activity, color, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static View applyStatusBarColor(final Activity activity,
|
||||||
|
final int color,
|
||||||
|
boolean isDecor) {
|
||||||
|
ViewGroup parent = isDecor ?
|
||||||
|
(ViewGroup) activity.getWindow().getDecorView() :
|
||||||
|
(ViewGroup) activity.findViewById(android.R.id.content);
|
||||||
|
View fakeStatusBarView = parent.findViewWithTag(TAG_STATUS_BAR);
|
||||||
|
if (fakeStatusBarView != null) {
|
||||||
|
if (fakeStatusBarView.getVisibility() == View.GONE) {
|
||||||
|
fakeStatusBarView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
fakeStatusBarView.setBackgroundColor(color);
|
||||||
|
} else {
|
||||||
|
fakeStatusBarView = createStatusBarView(activity, color);
|
||||||
|
parent.addView(fakeStatusBarView);
|
||||||
|
}
|
||||||
|
return fakeStatusBarView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void hideStatusBarView(final Activity activity) {
|
||||||
|
hideStatusBarView(activity.getWindow());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void hideStatusBarView(final Window window) {
|
||||||
|
ViewGroup decorView = (ViewGroup) window.getDecorView();
|
||||||
|
View fakeStatusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
|
||||||
|
if (fakeStatusBarView == null) return;
|
||||||
|
fakeStatusBarView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showStatusBarView(final Window window) {
|
||||||
|
ViewGroup decorView = (ViewGroup) window.getDecorView();
|
||||||
|
View fakeStatusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
|
||||||
|
if (fakeStatusBarView == null) return;
|
||||||
|
fakeStatusBarView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static View createStatusBarView(final Activity activity,
|
||||||
|
final int color) {
|
||||||
|
View statusBarView = new View(activity);
|
||||||
|
statusBarView.setLayoutParams(new ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()));
|
||||||
|
statusBarView.setBackgroundColor(color);
|
||||||
|
statusBarView.setTag(TAG_STATUS_BAR);
|
||||||
|
return statusBarView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void transparentStatusBar(final Activity activity) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
int option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
|
||||||
|
window.getDecorView().setSystemUiVisibility(option);
|
||||||
|
window.setStatusBarColor(Color.TRANSPARENT);
|
||||||
|
} else {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// action bar
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the action bar's height.
|
||||||
|
*
|
||||||
|
* @return the action bar's height
|
||||||
|
*/
|
||||||
|
public static int getActionBarHeight() {
|
||||||
|
TypedValue tv = new TypedValue();
|
||||||
|
if (CommonBaseLibrary.getApplication().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
|
||||||
|
return TypedValue.complexToDimensionPixelSize(
|
||||||
|
tv.data, CommonBaseLibrary.getApplication().getResources().getDisplayMetrics()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// notification bar
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the notification bar's visibility.
|
||||||
|
* <p>Must hold {@code <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />}</p>
|
||||||
|
*
|
||||||
|
* @param isVisible True to set notification bar visible, false otherwise.
|
||||||
|
*/
|
||||||
|
@RequiresPermission(EXPAND_STATUS_BAR)
|
||||||
|
public static void setNotificationBarVisibility(final boolean isVisible) {
|
||||||
|
String methodName;
|
||||||
|
if (isVisible) {
|
||||||
|
methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";
|
||||||
|
} else {
|
||||||
|
methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels";
|
||||||
|
}
|
||||||
|
invokePanels(methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void invokePanels(final String methodName) {
|
||||||
|
try {
|
||||||
|
@SuppressLint("WrongConstant")
|
||||||
|
Object service = CommonBaseLibrary.getApplication().getSystemService("statusbar");
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
|
Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
|
||||||
|
Method expand = statusBarManager.getMethod(methodName);
|
||||||
|
expand.invoke(service);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// navigation bar
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the navigation bar's height.
|
||||||
|
*
|
||||||
|
* @return the navigation bar's height
|
||||||
|
*/
|
||||||
|
public static int getNavBarHeight() {
|
||||||
|
Resources res = Resources.getSystem();
|
||||||
|
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||||
|
if (resourceId != 0) {
|
||||||
|
return res.getDimensionPixelSize(resourceId);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the navigation bar's visibility.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @param isVisible True to set navigation bar visible, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setNavBarVisibility(@NonNull final Activity activity, boolean isVisible) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
setNavBarVisibility(activity.getWindow(), isVisible);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the navigation bar's visibility.
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @param isVisible True to set navigation bar visible, false otherwise.
|
||||||
|
*/
|
||||||
|
public static void setNavBarVisibility(@NonNull final Window window, boolean isVisible) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
|
||||||
|
final ViewGroup decorView = (ViewGroup) window.getDecorView();
|
||||||
|
for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
|
||||||
|
final View child = decorView.getChildAt(i);
|
||||||
|
final int id = child.getId();
|
||||||
|
if (id != View.NO_ID) {
|
||||||
|
String resourceEntryName = CommonBaseLibrary.getApplication()
|
||||||
|
.getResources()
|
||||||
|
.getResourceEntryName(id);
|
||||||
|
if ("navigationBarBackground".equals(resourceEntryName)) {
|
||||||
|
child.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
|
if (isVisible) {
|
||||||
|
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() & ~uiOptions);
|
||||||
|
} else {
|
||||||
|
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | uiOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the navigation bar visible.
|
||||||
|
* <p>Call it in onWindowFocusChanged will get right result.</p>
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @return {@code true}: yes<br>{@code false}: no
|
||||||
|
*/
|
||||||
|
public static boolean isNavBarVisible(@NonNull final Activity activity) {
|
||||||
|
return isNavBarVisible(activity.getWindow());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否显示了导航栏
|
||||||
|
* (说明这里的context 一定要是activity的context 否则类型转换失败)
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
// public static boolean isShowNavBar(Context context) {
|
||||||
|
// if (null == context) {
|
||||||
|
// node_return false;
|
||||||
|
// }
|
||||||
|
// /**
|
||||||
|
// * 获取应用区域高度
|
||||||
|
// */
|
||||||
|
// Rect outRect1 = new Rect();
|
||||||
|
// try {
|
||||||
|
// ((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);
|
||||||
|
// } catch (ClassCastException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// node_return false;
|
||||||
|
// }
|
||||||
|
// int activityHeight = outRect1.height();
|
||||||
|
// /**
|
||||||
|
// * 获取状态栏高度
|
||||||
|
// */
|
||||||
|
// int statuBarHeight = WindowDispaly.getStatusBarHeight();
|
||||||
|
// /**
|
||||||
|
// * 屏幕物理高度 减去 状态栏高度
|
||||||
|
// */
|
||||||
|
// int remainHeight = WindowDispaly.getRealHeight() - statuBarHeight;
|
||||||
|
// /**
|
||||||
|
// * 剩余高度跟应用区域高度相等 说明导航栏没有显示 否则相反
|
||||||
|
// */
|
||||||
|
// if (activityHeight == remainHeight) {
|
||||||
|
// node_return false;
|
||||||
|
// } else {
|
||||||
|
// node_return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the navigation bar visible.
|
||||||
|
* <p>Call it in onWindowFocusChanged will get right result.</p>
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @return {@code true}: yes<br>{@code false}: no
|
||||||
|
*/
|
||||||
|
public static boolean isNavBarVisible(@NonNull final Window window) {
|
||||||
|
boolean isVisible = false;
|
||||||
|
ViewGroup decorView = (ViewGroup) window.getDecorView();
|
||||||
|
for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
|
||||||
|
final View child = decorView.getChildAt(i);
|
||||||
|
final int id = child.getId();
|
||||||
|
if (id != View.NO_ID) {
|
||||||
|
String resourceEntryName = CommonBaseLibrary.getApplication()
|
||||||
|
.getResources()
|
||||||
|
.getResourceEntryName(id);
|
||||||
|
if ("navigationBarBackground".equals(resourceEntryName)
|
||||||
|
&& child.getVisibility() == View.VISIBLE) {
|
||||||
|
isVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isVisible) {
|
||||||
|
int visibility = decorView.getSystemUiVisibility();
|
||||||
|
isVisible = (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
|
||||||
|
}
|
||||||
|
return isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the navigation bar's color.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @param color The navigation bar's color.
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
public static void setNavBarColor(@NonNull final Activity activity, @ColorInt final int color) {
|
||||||
|
setNavBarColor(activity.getWindow(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the navigation bar's color.
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @param color The navigation bar's color.
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
public static void setNavBarColor(@NonNull final Window window, @ColorInt final int color) {
|
||||||
|
window.setNavigationBarColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the color of navigation bar.
|
||||||
|
*
|
||||||
|
* @param activity The activity.
|
||||||
|
* @return the color of navigation bar
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
public static int getNavBarColor(@NonNull final Activity activity) {
|
||||||
|
return getNavBarColor(activity.getWindow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the color of navigation bar.
|
||||||
|
*
|
||||||
|
* @param window The window.
|
||||||
|
* @return the color of navigation bar
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
public static int getNavBarColor(@NonNull final Window window) {
|
||||||
|
return window.getNavigationBarColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the navigation bar visible.
|
||||||
|
*
|
||||||
|
* @return {@code true}: yes<br>{@code false}: no
|
||||||
|
*/
|
||||||
|
public static boolean isSupportNavBar() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
|
WindowManager wm = (WindowManager) CommonBaseLibrary.getApplication().getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
if (wm == null) return false;
|
||||||
|
Display display = wm.getDefaultDisplay();
|
||||||
|
Point size = new Point();
|
||||||
|
Point realSize = new Point();
|
||||||
|
display.getSize(size);
|
||||||
|
display.getRealSize(realSize);
|
||||||
|
return realSize.y != size.y || realSize.x != size.x;
|
||||||
|
}
|
||||||
|
boolean menu = ViewConfiguration.get(CommonBaseLibrary.getApplication()).hasPermanentMenuKey();
|
||||||
|
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
|
||||||
|
return !menu && !back;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Activity getActivityByView(@NonNull final View view) {
|
||||||
|
Context context = view.getContext();
|
||||||
|
while (context instanceof ContextWrapper) {
|
||||||
|
if (context instanceof Activity) {
|
||||||
|
return (Activity) context;
|
||||||
|
}
|
||||||
|
context = ((ContextWrapper) context).getBaseContext();
|
||||||
|
}
|
||||||
|
Log.e("BarUtils", "the view's Context is not an Activity.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.util.Base64;
|
||||||
|
|
||||||
|
public class Base64Utils {
|
||||||
|
|
||||||
|
public static Bitmap asdf(String imageBase64){
|
||||||
|
byte[] decodedString = Base64.decode(imageBase64, Base64.DEFAULT);
|
||||||
|
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 轻量级数据存储工具类
|
||||||
|
*
|
||||||
|
* @author Administrator
|
||||||
|
*/
|
||||||
|
public class BaseSPUtils {
|
||||||
|
/**
|
||||||
|
* 保存在手机里面的文件名
|
||||||
|
*/
|
||||||
|
public static final String FILE_NAME = "sp_data";
|
||||||
|
public static final String USER_INFO_KEY = "user_info_key";
|
||||||
|
public static final String NET_SERVICE_TEST = "net_service_test";
|
||||||
|
public static final String SEARRH_CACHE = "search_cache";
|
||||||
|
public static final String NAVI_PH_EDIT_CACHE = "navi_ph_edit_cache";
|
||||||
|
public static final String FIRST_OPEN = "first_open";
|
||||||
|
public static final String KEY_PRIVACY_AGREEMENT = "privacy_agreement";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param key
|
||||||
|
* @param defaultObject
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除某个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
|
||||||
|
*/
|
||||||
|
public static Map<String, ?> getAll(Context context) {
|
||||||
|
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
|
||||||
|
return sp.getAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
|
||||||
|
*
|
||||||
|
* @author zhy
|
||||||
|
*/
|
||||||
|
private static class SharedPreferencesCompat {
|
||||||
|
private static final Method sApplyMethod = findApplyMethod();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反射查找apply的方法
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@SuppressWarnings(
|
||||||
|
{"unchecked", "rawtypes"})
|
||||||
|
private static Method findApplyMethod() {
|
||||||
|
try {
|
||||||
|
Class clz = SharedPreferences.Editor.class;
|
||||||
|
return clz.getMethod("apply");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果找到则使用apply执行,否则使用commit
|
||||||
|
*
|
||||||
|
* @param editor
|
||||||
|
*/
|
||||||
|
public static void apply(SharedPreferences.Editor editor) {
|
||||||
|
try {
|
||||||
|
if (sApplyMethod != null) {
|
||||||
|
sApplyMethod.invoke(editor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
}
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****---------------------------------------------***/
|
||||||
|
/**
|
||||||
|
* 是否含有用户信息
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean hasUserInfo(Context context) {
|
||||||
|
return contains(context, USER_INFO_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除用户信息
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static void cleanUserInfo(Context context) {
|
||||||
|
remove(context, USER_INFO_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
243
mylibrary/src/main/java/com/dahe/mylibrary/utils/BaseUtils.java
Normal file
243
mylibrary/src/main/java/com/dahe/mylibrary/utils/BaseUtils.java
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.shehuan.nicedialog.BaseNiceDialog;
|
||||||
|
import com.shehuan.nicedialog.NiceDialog;
|
||||||
|
import com.shehuan.nicedialog.ViewConvertListener;
|
||||||
|
import com.shehuan.nicedialog.ViewHolder;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class BaseUtils {
|
||||||
|
/**
|
||||||
|
* 验证手机格式
|
||||||
|
*/
|
||||||
|
public static boolean isMobileNO(String mobiles) {
|
||||||
|
String telRegex = "[1][3456789]\\d{9}";
|
||||||
|
// "[1]"代表第1位为数字1,"[358]"代表第二位可以为3、5、8中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
|
||||||
|
if (TextUtils.isEmpty(mobiles)) return false;
|
||||||
|
else return mobiles.matches(telRegex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取语言
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int getLanguage(Context context) {
|
||||||
|
Locale curLocale = getLocale(context);
|
||||||
|
String language = curLocale.getLanguage();
|
||||||
|
String country = curLocale.getCountry();
|
||||||
|
if (language.equals(Locale.CHINA.getLanguage())) {
|
||||||
|
//0是简体中文,1是繁体中文
|
||||||
|
return country.equals(Locale.SIMPLIFIED_CHINESE.getCountry()) ? 0 : 1;
|
||||||
|
} else if (language.equals(Locale.ENGLISH.getLanguage())) {
|
||||||
|
//英语
|
||||||
|
return 2;
|
||||||
|
} else if (language.equals("th")) {
|
||||||
|
//泰文
|
||||||
|
return 3;
|
||||||
|
} else if (language.equals(Locale.KOREAN.getLanguage())) {
|
||||||
|
//韩文
|
||||||
|
return 4;
|
||||||
|
} else if (language.equals("vi")) {
|
||||||
|
//越南语
|
||||||
|
return 5;
|
||||||
|
} else if (language.equals(Locale.JAPAN.getLanguage())) {
|
||||||
|
//日语
|
||||||
|
return 6;
|
||||||
|
} else if (language.equals("in")) {
|
||||||
|
//印尼语
|
||||||
|
return 7;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取Locale
|
||||||
|
private static Locale getLocale(Context context) {
|
||||||
|
Locale locale;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
locale = context.getResources().getConfiguration().getLocales().get(0);
|
||||||
|
} else {
|
||||||
|
locale = context.getResources().getConfiguration().locale;
|
||||||
|
}
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拨打电话(直接拨打电话)
|
||||||
|
* @param phoneNum 电话号码
|
||||||
|
*/
|
||||||
|
public static void callPhone(AppCompatActivity context , String phoneNum){
|
||||||
|
|
||||||
|
NiceDialog.init()
|
||||||
|
.setLayoutId(R.layout.dialog_phone)
|
||||||
|
.setConvertListener(new ViewConvertListener() {
|
||||||
|
@Override
|
||||||
|
protected void convertView(ViewHolder viewHolder, BaseNiceDialog baseNiceDialog) {
|
||||||
|
viewHolder.setText(R.id.message, phoneNum);
|
||||||
|
viewHolder.setOnClickListener(R.id.ok, new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_CALL);
|
||||||
|
Uri data = Uri.parse("tel:" + phoneNum);
|
||||||
|
intent.setData(data);
|
||||||
|
context.startActivity(intent);
|
||||||
|
baseNiceDialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
viewHolder.setOnClickListener(R.id.cancel, new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
baseNiceDialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setWidth(260).show(context.getSupportFragmentManager());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取VersionCode
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String geVersionCode(Context context) {
|
||||||
|
try {
|
||||||
|
PackageInfo packageInfo = context.getPackageManager()
|
||||||
|
.getPackageInfo(context.getPackageName(), 0);
|
||||||
|
return packageInfo.versionName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "1.0.0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转qq
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String goToQQ(Context context, String qqNumber) {
|
||||||
|
try {
|
||||||
|
context.getPackageManager().getApplicationInfo("com.tencent.mobileqq",
|
||||||
|
PackageManager.GET_UNINSTALLED_PACKAGES);
|
||||||
|
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("mqqwpa://im/chat?chat_type=wpa&uin=" + qqNumber + "&version=1")));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return "客服为qq在线,联系客服请先安装qq";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转手机通讯录 选择联系人 并返回联系人信息
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param uri
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String[] getPhoneContacts(Context context, Uri uri) {
|
||||||
|
String[] contact = new String[2];
|
||||||
|
ContentResolver cr = context.getContentResolver();
|
||||||
|
Cursor cursor = cr.query(uri, null, null, null, null);
|
||||||
|
if (cursor != null && cursor.getCount() != 0) {
|
||||||
|
cursor.moveToFirst();
|
||||||
|
int nameFieldColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
|
||||||
|
contact[0] = cursor.getString(nameFieldColumnIndex);
|
||||||
|
String ContactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
|
||||||
|
Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
|
||||||
|
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + ContactId, null, null);
|
||||||
|
if (phone != null && phone.getCount() != 0) {
|
||||||
|
phone.moveToFirst();
|
||||||
|
contact[1] = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).trim().replace(" ", "").toString();
|
||||||
|
} else {
|
||||||
|
contact[1] = "";
|
||||||
|
}
|
||||||
|
phone.close();
|
||||||
|
cursor.close();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
|
||||||
|
*/
|
||||||
|
public static int dip2px(Context context, float dpValue) {
|
||||||
|
final float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
return (int) (dpValue * scale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
|
||||||
|
*/
|
||||||
|
public static int px2dip(Context context, float pxValue) {
|
||||||
|
final float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
return (int) (pxValue / scale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将sp值转换为px值,保证文字大小不变
|
||||||
|
*
|
||||||
|
* @param spValue
|
||||||
|
* @param spValue (DisplayMetrics类中属性scaledDensity)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int sp2px(Context context, float spValue) {
|
||||||
|
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||||
|
return (int) (spValue * fontScale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制隐藏输入法键盘
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param view EditText
|
||||||
|
*/
|
||||||
|
public static void hideInput(Context context, View view) {
|
||||||
|
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏软键盘(只适用于Activity,不适用于Fragment)
|
||||||
|
*/
|
||||||
|
public static void hideSoftKeyboard(Activity activity) {
|
||||||
|
View view = activity.getCurrentFocus();
|
||||||
|
if (view != null) {
|
||||||
|
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||||
|
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//view为接受软键盘输入的视图,SHOW_FORCED表示强制显示
|
||||||
|
public static void hideSoftKeyboard(Activity activity, View view) {
|
||||||
|
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
|
||||||
|
imm.hideSoftInputFromWindow(view.getWindowToken(), 0); //强制隐藏键盘
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
public class CNPinyinIndex {
|
||||||
|
|
||||||
|
|
||||||
|
//自动获取汉子的首字母
|
||||||
|
static final int GB_SP_DIFF = 160;
|
||||||
|
// 存放国标一级汉字不同读音的起始区位码
|
||||||
|
static final int[] secPosValueList = {1601, 1637, 1833, 2078, 2274, 2302,
|
||||||
|
2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027,
|
||||||
|
4086, 4390, 4558, 4684, 4925, 5249, 5600};
|
||||||
|
// 存放国标一级汉字不同读音的起始区位码对应读音
|
||||||
|
static final char[] firstLetter = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
|
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x',
|
||||||
|
'y', 'z'};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static String getSpells(String characters) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
for (int i = 0; i < characters.length(); i++) {
|
||||||
|
|
||||||
|
char ch = characters.charAt(i);
|
||||||
|
if ((ch >> 7) == 0) {
|
||||||
|
// 判断是否为汉字,如果左移7为为0就不是汉字,否则是汉字
|
||||||
|
} else {
|
||||||
|
char spell = getFirstLetter(ch);
|
||||||
|
buffer.append(String.valueOf(spell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取一个汉字的首字母
|
||||||
|
public static Character getFirstLetter(char ch) {
|
||||||
|
|
||||||
|
byte[] uniCode = null;
|
||||||
|
try {
|
||||||
|
uniCode = String.valueOf(ch).getBytes("GBK");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (uniCode[0] < 128 && uniCode[0] > 0) { // 非汉字
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return convert(uniCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一个汉字的拼音首字母。 GB码两个字节分别减去160,转换成10进制码组合就可以得到区位码
|
||||||
|
* 例如汉字“你”的GB码是0xC4/0xE3,分别减去0xA0(160)就是0x24/0x43
|
||||||
|
* 0x24转成10进制就是36,0x43是67,那么它的区位码就是3667,在对照表中读音为‘n’
|
||||||
|
*/
|
||||||
|
static char convert(byte[] bytes) {
|
||||||
|
char result = '-';
|
||||||
|
int secPosValue = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < bytes.length; i++) {
|
||||||
|
bytes[i] -= GB_SP_DIFF;
|
||||||
|
}
|
||||||
|
secPosValue = bytes[0] * 100 + bytes[1];
|
||||||
|
for (i = 0; i < 23; i++) {
|
||||||
|
if (secPosValue >= secPosValueList[i]
|
||||||
|
&& secPosValue < secPosValueList[i + 1]) {
|
||||||
|
result = firstLetter[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,645 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.CommonBaseLibrary;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bytes2Bits, bits2Bytes : bytes 与 bits 互转
|
||||||
|
* bytes2Chars, chars2Bytes : bytes 与 chars 互转
|
||||||
|
* bytes2HexString, hexString2Bytes : bytes 与 hexString 互转
|
||||||
|
* memorySize2Byte, byte2MemorySize : 以 unit 为单位的内存大小与字节数互转
|
||||||
|
* byte2FitMemorySize : 字节数转合适内存大小
|
||||||
|
* timeSpan2Millis, millis2TimeSpan : 以 unit 为单位的时间长度与毫秒时间戳互转
|
||||||
|
* millis2FitTimeSpan : 毫秒时间戳转合适时间长度
|
||||||
|
* input2OutputStream, output2InputStream : inputStream 与 outputStream 互转
|
||||||
|
* inputStream2Bytes, bytes2InputStream : inputStream 与 bytes 互转
|
||||||
|
* outputStream2Bytes, bytes2OutputStream : outputStream 与 bytes 互转
|
||||||
|
* inputStream2String, string2InputStream : inputStream 与 string 按编码互转
|
||||||
|
* outputStream2String, string2OutputStream: outputStream 与 string 按编码互转
|
||||||
|
* bitmap2Bytes, bytes2Bitmap : bitmap 与 bytes 互转
|
||||||
|
* drawable2Bitmap, bitmap2Drawable : drawable 与 bitmap 互转
|
||||||
|
* drawable2Bytes, bytes2Drawable : drawable 与 bytes 互转
|
||||||
|
* view2Bitmap : view 转 Bitmap
|
||||||
|
* dp2px, px2dp : dp 与 px 互转
|
||||||
|
* sp2px, px2sp : sp 与 px 互转
|
||||||
|
*/
|
||||||
|
public final class ConvertUtils {
|
||||||
|
|
||||||
|
private ConvertUtils() {
|
||||||
|
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final char hexDigits[] =
|
||||||
|
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to bits.
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return bits
|
||||||
|
*/
|
||||||
|
public static String bytes2Bits(final byte[] bytes) {
|
||||||
|
if (bytes == null || bytes.length == 0) return "";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte aByte : bytes) {
|
||||||
|
for (int j = 7; j >= 0; --j) {
|
||||||
|
sb.append(((aByte >> j) & 0x01) == 0 ? '0' : '1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bits to bytes.
|
||||||
|
*
|
||||||
|
* @param bits The bits.
|
||||||
|
* @return bytes
|
||||||
|
*/
|
||||||
|
public static byte[] bits2Bytes(String bits) {
|
||||||
|
int lenMod = bits.length() % 8;
|
||||||
|
int byteLen = bits.length() / 8;
|
||||||
|
// add "0" until length to 8 times
|
||||||
|
if (lenMod != 0) {
|
||||||
|
for (int i = lenMod; i < 8; i++) {
|
||||||
|
bits = "0" + bits;
|
||||||
|
}
|
||||||
|
byteLen++;
|
||||||
|
}
|
||||||
|
byte[] bytes = new byte[byteLen];
|
||||||
|
for (int i = 0; i < byteLen; ++i) {
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
bytes[i] <<= 1;
|
||||||
|
bytes[i] |= bits.charAt(i * 8 + j) - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to chars.
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return chars
|
||||||
|
*/
|
||||||
|
public static char[] bytes2Chars(final byte[] bytes) {
|
||||||
|
if (bytes == null) return null;
|
||||||
|
int len = bytes.length;
|
||||||
|
if (len <= 0) return null;
|
||||||
|
char[] chars = new char[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
chars[i] = (char) (bytes[i] & 0xff);
|
||||||
|
}
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chars to bytes.
|
||||||
|
*
|
||||||
|
* @param chars The chars.
|
||||||
|
* @return bytes
|
||||||
|
*/
|
||||||
|
public static byte[] chars2Bytes(final char[] chars) {
|
||||||
|
if (chars == null || chars.length <= 0) return null;
|
||||||
|
int len = chars.length;
|
||||||
|
byte[] bytes = new byte[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
bytes[i] = (byte) (chars[i]);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to hex string.
|
||||||
|
* <p>e.g. bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns "00A8"</p>
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return hex string
|
||||||
|
*/
|
||||||
|
public static String bytes2HexString(final byte[] bytes) {
|
||||||
|
if (bytes == null) return "";
|
||||||
|
int len = bytes.length;
|
||||||
|
if (len <= 0) return "";
|
||||||
|
char[] ret = new char[len << 1];
|
||||||
|
for (int i = 0, j = 0; i < len; i++) {
|
||||||
|
ret[j++] = hexDigits[bytes[i] >> 4 & 0x0f];
|
||||||
|
ret[j++] = hexDigits[bytes[i] & 0x0f];
|
||||||
|
}
|
||||||
|
return new String(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hex string to bytes.
|
||||||
|
* <p>e.g. hexString2Bytes("00A8") returns { 0, (byte) 0xA8 }</p>
|
||||||
|
*
|
||||||
|
* @param hexString The hex string.
|
||||||
|
* @return the bytes
|
||||||
|
*/
|
||||||
|
public static byte[] hexString2Bytes(String hexString) {
|
||||||
|
if (isSpace(hexString)) return null;
|
||||||
|
int len = hexString.length();
|
||||||
|
if (len % 2 != 0) {
|
||||||
|
hexString = "0" + hexString;
|
||||||
|
len = len + 1;
|
||||||
|
}
|
||||||
|
char[] hexBytes = hexString.toUpperCase().toCharArray();
|
||||||
|
byte[] ret = new byte[len >> 1];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
ret[i >> 1] = (byte) (hex2Int(hexBytes[i]) << 4 | hex2Int(hexBytes[i + 1]));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int hex2Int(final char hexChar) {
|
||||||
|
if (hexChar >= '0' && hexChar <= '9') {
|
||||||
|
return hexChar - '0';
|
||||||
|
} else if (hexChar >= 'A' && hexChar <= 'F') {
|
||||||
|
return hexChar - 'A' + 10;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of memory in unit to size of byte.
|
||||||
|
*
|
||||||
|
* @param memorySize Size of memory.
|
||||||
|
* @param unit The unit of memory size.
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link MemoryConstants#BYTE}</li>
|
||||||
|
* <li>{@link MemoryConstants#KB}</li>
|
||||||
|
* <li>{@link MemoryConstants#MB}</li>
|
||||||
|
* <li>{@link MemoryConstants#GB}</li>
|
||||||
|
* </ul>
|
||||||
|
* @return size of byte
|
||||||
|
*/
|
||||||
|
public static long memorySize2Byte(final long memorySize,
|
||||||
|
@MemoryConstants.Unit final int unit) {
|
||||||
|
if (memorySize < 0) return -1;
|
||||||
|
return memorySize * unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of byte to size of memory in unit.
|
||||||
|
*
|
||||||
|
* @param byteSize Size of byte.
|
||||||
|
* @param unit The unit of memory size.
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link MemoryConstants#BYTE}</li>
|
||||||
|
* <li>{@link MemoryConstants#KB}</li>
|
||||||
|
* <li>{@link MemoryConstants#MB}</li>
|
||||||
|
* <li>{@link MemoryConstants#GB}</li>
|
||||||
|
* </ul>
|
||||||
|
* @return size of memory in unit
|
||||||
|
*/
|
||||||
|
public static double byte2MemorySize(final long byteSize,
|
||||||
|
@MemoryConstants.Unit final int unit) {
|
||||||
|
if (byteSize < 0) return -1;
|
||||||
|
return (double) byteSize / unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of byte to fit size of memory.
|
||||||
|
* <p>to three decimal places</p>
|
||||||
|
*
|
||||||
|
* @param byteSize Size of byte.
|
||||||
|
* @return fit size of memory
|
||||||
|
*/
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
public static String byte2FitMemorySize(final long byteSize) {
|
||||||
|
if (byteSize < 0) {
|
||||||
|
return "shouldn't be less than zero!";
|
||||||
|
} else if (byteSize < MemoryConstants.KB) {
|
||||||
|
return String.format("%.3fB", (double) byteSize);
|
||||||
|
} else if (byteSize < MemoryConstants.MB) {
|
||||||
|
return String.format("%.3fKB", (double) byteSize / MemoryConstants.KB);
|
||||||
|
} else if (byteSize < MemoryConstants.GB) {
|
||||||
|
return String.format("%.3fMB", (double) byteSize / MemoryConstants.MB);
|
||||||
|
} else {
|
||||||
|
return String.format("%.3fGB", (double) byteSize / MemoryConstants.GB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time span in unit to milliseconds.
|
||||||
|
*
|
||||||
|
* @param timeSpan The time span.
|
||||||
|
* @param unit The unit of time span.
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link TimeConstants#MSEC}</li>
|
||||||
|
* <li>{@link TimeConstants#SEC }</li>
|
||||||
|
* <li>{@link TimeConstants#MIN }</li>
|
||||||
|
* <li>{@link TimeConstants#HOUR}</li>
|
||||||
|
* <li>{@link TimeConstants#DAY }</li>
|
||||||
|
* </ul>
|
||||||
|
* @return milliseconds
|
||||||
|
*/
|
||||||
|
public static long timeSpan2Millis(final long timeSpan, @TimeConstants.Unit final int unit) {
|
||||||
|
return timeSpan * unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Milliseconds to time span in unit.
|
||||||
|
*
|
||||||
|
* @param millis The milliseconds.
|
||||||
|
* @param unit The unit of time span.
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link TimeConstants#MSEC}</li>
|
||||||
|
* <li>{@link TimeConstants#SEC }</li>
|
||||||
|
* <li>{@link TimeConstants#MIN }</li>
|
||||||
|
* <li>{@link TimeConstants#HOUR}</li>
|
||||||
|
* <li>{@link TimeConstants#DAY }</li>
|
||||||
|
* </ul>
|
||||||
|
* @return time span in unit
|
||||||
|
*/
|
||||||
|
public static long millis2TimeSpan(final long millis, @TimeConstants.Unit final int unit) {
|
||||||
|
return millis / unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Milliseconds to fit time span.
|
||||||
|
*
|
||||||
|
* @param millis The milliseconds.
|
||||||
|
* <p>millis <= 0, node_return null</p>
|
||||||
|
* @param precision The precision of time span.
|
||||||
|
* <ul>
|
||||||
|
* <li>precision = 0, node_return null</li>
|
||||||
|
* <li>precision = 1, node_return 天</li>
|
||||||
|
* <li>precision = 2, node_return 天, 小时</li>
|
||||||
|
* <li>precision = 3, node_return 天, 小时, 分钟</li>
|
||||||
|
* <li>precision = 4, node_return 天, 小时, 分钟, 秒</li>
|
||||||
|
* <li>precision >= 5,node_return 天, 小时, 分钟, 秒, 毫秒</li>
|
||||||
|
* </ul>
|
||||||
|
* @return fit time span
|
||||||
|
*/
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
public static String millis2FitTimeSpan(long millis, int precision) {
|
||||||
|
if (millis <= 0 || precision <= 0) return null;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String[] units = {"天", "小时", "分钟", "秒", "毫秒"};
|
||||||
|
int[] unitLen = {86400000, 3600000, 60000, 1000, 1};
|
||||||
|
precision = Math.min(precision, 5);
|
||||||
|
for (int i = 0; i < precision; i++) {
|
||||||
|
if (millis >= unitLen[i]) {
|
||||||
|
long mode = millis / unitLen[i];
|
||||||
|
millis -= mode * unitLen[i];
|
||||||
|
sb.append(mode).append(units[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input stream to output stream.
|
||||||
|
*
|
||||||
|
* @param is The input stream.
|
||||||
|
* @return output stream
|
||||||
|
*/
|
||||||
|
public static ByteArrayOutputStream input2OutputStream(final InputStream is) {
|
||||||
|
if (is == null) return null;
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
byte[] b = new byte[MemoryConstants.KB];
|
||||||
|
int len;
|
||||||
|
while ((len = is.read(b, 0, MemoryConstants.KB)) != -1) {
|
||||||
|
os.write(b, 0, len);
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output stream to input stream.
|
||||||
|
*
|
||||||
|
* @param out The output stream.
|
||||||
|
* @return input stream
|
||||||
|
*/
|
||||||
|
public ByteArrayInputStream output2InputStream(final OutputStream out) {
|
||||||
|
if (out == null) return null;
|
||||||
|
return new ByteArrayInputStream(((ByteArrayOutputStream) out).toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input stream to bytes.
|
||||||
|
*
|
||||||
|
* @param is The input stream.
|
||||||
|
* @return bytes
|
||||||
|
*/
|
||||||
|
public static byte[] inputStream2Bytes(final InputStream is) {
|
||||||
|
if (is == null) return null;
|
||||||
|
return input2OutputStream(is).toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to input stream.
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return input stream
|
||||||
|
*/
|
||||||
|
public static InputStream bytes2InputStream(final byte[] bytes) {
|
||||||
|
if (bytes == null || bytes.length <= 0) return null;
|
||||||
|
return new ByteArrayInputStream(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output stream to bytes.
|
||||||
|
*
|
||||||
|
* @param out The output stream.
|
||||||
|
* @return bytes
|
||||||
|
*/
|
||||||
|
public static byte[] outputStream2Bytes(final OutputStream out) {
|
||||||
|
if (out == null) return null;
|
||||||
|
return ((ByteArrayOutputStream) out).toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to output stream.
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return output stream
|
||||||
|
*/
|
||||||
|
public static OutputStream bytes2OutputStream(final byte[] bytes) {
|
||||||
|
if (bytes == null || bytes.length <= 0) return null;
|
||||||
|
ByteArrayOutputStream os = null;
|
||||||
|
try {
|
||||||
|
os = new ByteArrayOutputStream();
|
||||||
|
os.write(bytes);
|
||||||
|
return os;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (os != null) {
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input stream to string.
|
||||||
|
*
|
||||||
|
* @param is The input stream.
|
||||||
|
* @param charsetName The name of charset.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static String inputStream2String(final InputStream is, final String charsetName) {
|
||||||
|
if (is == null || isSpace(charsetName)) return "";
|
||||||
|
try {
|
||||||
|
return new String(inputStream2Bytes(is), charsetName);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String to input stream.
|
||||||
|
*
|
||||||
|
* @param string The string.
|
||||||
|
* @param charsetName The name of charset.
|
||||||
|
* @return input stream
|
||||||
|
*/
|
||||||
|
public static InputStream string2InputStream(final String string, final String charsetName) {
|
||||||
|
if (string == null || isSpace(charsetName)) return null;
|
||||||
|
try {
|
||||||
|
return new ByteArrayInputStream(string.getBytes(charsetName));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output stream to string.
|
||||||
|
*
|
||||||
|
* @param out The output stream.
|
||||||
|
* @param charsetName The name of charset.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static String outputStream2String(final OutputStream out, final String charsetName) {
|
||||||
|
if (out == null || isSpace(charsetName)) return "";
|
||||||
|
try {
|
||||||
|
return new String(outputStream2Bytes(out), charsetName);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String to output stream.
|
||||||
|
*
|
||||||
|
* @param string The string.
|
||||||
|
* @param charsetName The name of charset.
|
||||||
|
* @return output stream
|
||||||
|
*/
|
||||||
|
public static OutputStream string2OutputStream(final String string, final String charsetName) {
|
||||||
|
if (string == null || isSpace(charsetName)) return null;
|
||||||
|
try {
|
||||||
|
return bytes2OutputStream(string.getBytes(charsetName));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap to bytes.
|
||||||
|
*
|
||||||
|
* @param bitmap The bitmap.
|
||||||
|
* @param format The format of bitmap.
|
||||||
|
* @return bytes
|
||||||
|
*/
|
||||||
|
public static byte[] bitmap2Bytes(final Bitmap bitmap, final Bitmap.CompressFormat format) {
|
||||||
|
if (bitmap == null) return null;
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
bitmap.compress(format, 100, baos);
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to bitmap.
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return bitmap
|
||||||
|
*/
|
||||||
|
public static Bitmap bytes2Bitmap(final byte[] bytes) {
|
||||||
|
return (bytes == null || bytes.length == 0)
|
||||||
|
? null
|
||||||
|
: BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawable to bitmap.
|
||||||
|
*
|
||||||
|
* @param drawable The drawable.
|
||||||
|
* @return bitmap
|
||||||
|
*/
|
||||||
|
public static Bitmap drawable2Bitmap(final Drawable drawable) {
|
||||||
|
if (drawable instanceof BitmapDrawable) {
|
||||||
|
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||||
|
if (bitmapDrawable.getBitmap() != null) {
|
||||||
|
return bitmapDrawable.getBitmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bitmap bitmap;
|
||||||
|
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
|
||||||
|
bitmap = Bitmap.createBitmap(1, 1,
|
||||||
|
drawable.getOpacity() != PixelFormat.OPAQUE
|
||||||
|
? Bitmap.Config.ARGB_8888
|
||||||
|
: Bitmap.Config.RGB_565);
|
||||||
|
} else {
|
||||||
|
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
|
||||||
|
drawable.getIntrinsicHeight(),
|
||||||
|
drawable.getOpacity() != PixelFormat.OPAQUE
|
||||||
|
? Bitmap.Config.ARGB_8888
|
||||||
|
: Bitmap.Config.RGB_565);
|
||||||
|
}
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
drawable.draw(canvas);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap to drawable.
|
||||||
|
*
|
||||||
|
* @param bitmap The bitmap.
|
||||||
|
* @return drawable
|
||||||
|
*/
|
||||||
|
public static Drawable bitmap2Drawable(final Bitmap bitmap) {
|
||||||
|
return bitmap == null ? null : new BitmapDrawable(CommonBaseLibrary.getApplication().getResources(), bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawable to bytes.
|
||||||
|
*
|
||||||
|
* @param drawable The drawable.
|
||||||
|
* @param format The format of bitmap.
|
||||||
|
* @return bytes
|
||||||
|
*/
|
||||||
|
public static byte[] drawable2Bytes(final Drawable drawable,
|
||||||
|
final Bitmap.CompressFormat format) {
|
||||||
|
return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes to drawable.
|
||||||
|
*
|
||||||
|
* @param bytes The bytes.
|
||||||
|
* @return drawable
|
||||||
|
*/
|
||||||
|
public static Drawable bytes2Drawable(final byte[] bytes) {
|
||||||
|
return bytes == null ? null : bitmap2Drawable(bytes2Bitmap(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View to bitmap.
|
||||||
|
*
|
||||||
|
* @param view The view.
|
||||||
|
* @return bitmap
|
||||||
|
*/
|
||||||
|
public static Bitmap view2Bitmap(final View view) {
|
||||||
|
if (view == null) return null;
|
||||||
|
Bitmap ret =
|
||||||
|
Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(ret);
|
||||||
|
Drawable bgDrawable = view.getBackground();
|
||||||
|
if (bgDrawable != null) {
|
||||||
|
bgDrawable.draw(canvas);
|
||||||
|
} else {
|
||||||
|
canvas.drawColor(Color.WHITE);
|
||||||
|
}
|
||||||
|
view.draw(canvas);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of dp to value of px.
|
||||||
|
*
|
||||||
|
* @param dpValue The value of dp.
|
||||||
|
* @return value of px
|
||||||
|
*/
|
||||||
|
public static int dp2px(final float dpValue) {
|
||||||
|
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||||
|
return (int) (dpValue * scale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of px to value of dp.
|
||||||
|
*
|
||||||
|
* @param pxValue The value of px.
|
||||||
|
* @return value of dp
|
||||||
|
*/
|
||||||
|
public static int px2dp(final float pxValue) {
|
||||||
|
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||||
|
return (int) (pxValue / scale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of sp to value of px.
|
||||||
|
*
|
||||||
|
* @param spValue The value of sp.
|
||||||
|
* @return value of px
|
||||||
|
*/
|
||||||
|
public static int sp2px(final float spValue) {
|
||||||
|
final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
|
||||||
|
return (int) (spValue * fontScale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of px to value of sp.
|
||||||
|
*
|
||||||
|
* @param pxValue The value of px.
|
||||||
|
* @return value of sp
|
||||||
|
*/
|
||||||
|
public static int px2sp(final float pxValue) {
|
||||||
|
final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
|
||||||
|
return (int) (pxValue / fontScale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// other utils methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private static boolean isSpace(final String s) {
|
||||||
|
if (s == null) return true;
|
||||||
|
for (int i = 0, len = s.length(); i < len; ++i) {
|
||||||
|
if (!Character.isWhitespace(s.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class CountDownTimerUtils extends CountDownTimer {
|
||||||
|
|
||||||
|
private TextView mTextView;
|
||||||
|
/**
|
||||||
|
* @param millisInFuture The number of millis in the future from the call
|
||||||
|
* to {@link #start()} until the countdown is done and {@link #onFinish()}
|
||||||
|
* is called.
|
||||||
|
* @param countDownInterval The interval along the way to receive
|
||||||
|
* {@link #onTick(long)} callbacks.
|
||||||
|
*/
|
||||||
|
public CountDownTimerUtils(TextView textView, long millisInFuture, long countDownInterval) {
|
||||||
|
super(millisInFuture, countDownInterval);
|
||||||
|
this.mTextView = textView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTick(long millisUntilFinished) {
|
||||||
|
mTextView.setClickable(false); //设置不可点击
|
||||||
|
mTextView.setText(millisUntilFinished / 1000 + "秒后重新发送"); //设置倒计时时间
|
||||||
|
// mTextView.setBackgroundResource(R.drawable.bg_identify_code_press); //设置按钮为灰色,这时是不能点击的
|
||||||
|
// SpannableString spannableString = new SpannableString(mTextView.getText().toString()); //获取按钮上的文字
|
||||||
|
// ForegroundColorSpan span = new ForegroundColorSpan(Color.RED);
|
||||||
|
// spannableString.setSpan(span, 0, 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);//将倒计时的时间设置为红色
|
||||||
|
// mTextView.setText(spannableString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
mTextView.setText("获取验证码");
|
||||||
|
mTextView.setClickable(true);//重新获得点击
|
||||||
|
// mTextView.setBackgroundResource(R.drawable.bg_identify_code_normal); //还原背景色
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,243 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static android.os.Environment.DIRECTORY_ALARMS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <h3>全局捕获异常</h3>
|
||||||
|
* <br>
|
||||||
|
* 当程序发生Uncaught异常的时候,有该类来接管程序,并记录错误日志
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@SuppressLint("SimpleDateFormat")
|
||||||
|
public class CrashHandler implements Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
public static String TAG = "MyCrash";
|
||||||
|
// 系统默认的UncaughtException处理类
|
||||||
|
private Thread.UncaughtExceptionHandler mDefaultHandler;
|
||||||
|
|
||||||
|
private static CrashHandler instance = new CrashHandler();
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
// 用来存储设备信息和异常信息
|
||||||
|
private Map<String, String> infos = new HashMap<String, String>();
|
||||||
|
|
||||||
|
// 用于格式化日期,作为日志文件名的一部分
|
||||||
|
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
/** 保证只有一个CrashHandler实例 */
|
||||||
|
private CrashHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取CrashHandler实例 ,单例模式 */
|
||||||
|
public static CrashHandler getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
public void init(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
// 获取系统默认的UncaughtException处理器
|
||||||
|
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
// 设置该CrashHandler为程序的默认处理器
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||||
|
FileUtil.removeFileByTime(getGlobalpath());
|
||||||
|
// autoClear(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当UncaughtException发生时会转入该函数来处理
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread thread, Throwable ex) {
|
||||||
|
if (!handleException(ex) && mDefaultHandler != null) {
|
||||||
|
// 如果用户没有处理则让系统默认的异常处理器来处理
|
||||||
|
mDefaultHandler.uncaughtException(thread, ex);
|
||||||
|
} else {
|
||||||
|
SystemClock.sleep(3000);
|
||||||
|
// 退出程序
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
|
||||||
|
*
|
||||||
|
* @param ex
|
||||||
|
* @return true:如果处理了该异常信息; 否则返回false.
|
||||||
|
*/
|
||||||
|
private boolean handleException(Throwable ex) {
|
||||||
|
if (ex == null)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
// 使用Toast来显示异常信息
|
||||||
|
new Thread() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Looper.prepare();
|
||||||
|
Toast.makeText(mContext, "很抱歉,程序出现异常,即将重启.",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
Looper.loop();
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
// 收集设备参数信息
|
||||||
|
collectDeviceInfo(mContext);
|
||||||
|
// 保存日志文件
|
||||||
|
saveCrashInfoFile(ex);
|
||||||
|
SystemClock.sleep(3000);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收集设备参数信息
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
*/
|
||||||
|
public void collectDeviceInfo(Context ctx) {
|
||||||
|
try {
|
||||||
|
PackageManager pm = ctx.getPackageManager();
|
||||||
|
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
|
||||||
|
PackageManager.GET_ACTIVITIES);
|
||||||
|
if (pi != null) {
|
||||||
|
String versionName = pi.versionName + "";
|
||||||
|
String versionCode = pi.versionCode + "";
|
||||||
|
infos.put("versionName", versionName);
|
||||||
|
infos.put("versionCode", versionCode);
|
||||||
|
}
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "an error occured when collect package info", e);
|
||||||
|
}
|
||||||
|
Field[] fields = Build.class.getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
try {
|
||||||
|
field.setAccessible(true);
|
||||||
|
infos.put(field.getName(), field.get(null).toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "an error occured when collect crash info", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存错误信息到文件中
|
||||||
|
* @param ex
|
||||||
|
* @return 返回文件名称,便于将文件传送到服务器
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private String saveCrashInfoFile(Throwable ex) throws Exception {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
try {
|
||||||
|
SimpleDateFormat sDateFormat = new SimpleDateFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss");
|
||||||
|
String date = sDateFormat.format(new java.util.Date());
|
||||||
|
sb.append("\r\n" + date + "\n");
|
||||||
|
for (Map.Entry<String, String> entry : infos.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue();
|
||||||
|
sb.append(key + "=" + value + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer writer = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(writer);
|
||||||
|
ex.printStackTrace(printWriter);
|
||||||
|
Throwable cause = ex.getCause();
|
||||||
|
while (cause != null) {
|
||||||
|
cause.printStackTrace(printWriter);
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
printWriter.flush();
|
||||||
|
printWriter.close();
|
||||||
|
String result = writer.toString();
|
||||||
|
sb.append(result);
|
||||||
|
|
||||||
|
String fileName = writeFile(sb.toString());
|
||||||
|
return fileName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "an error occured while writing file...", e);
|
||||||
|
sb.append("an error occured while writing file...\r\n");
|
||||||
|
writeFile(sb.toString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String writeFile(String sb) throws Exception {
|
||||||
|
String time = formatter.format(new Date());
|
||||||
|
String fileName = "crash-" + time + ".log";
|
||||||
|
// if (FileUtil.hasSdcard()) {
|
||||||
|
String path = getGlobalpath();
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists())
|
||||||
|
dir.mkdirs();
|
||||||
|
|
||||||
|
String filePath = path + fileName;
|
||||||
|
File txtFile = new File(filePath);
|
||||||
|
if (!txtFile.exists())
|
||||||
|
txtFile.createNewFile();
|
||||||
|
|
||||||
|
FileOutputStream fos = new FileOutputStream(txtFile, true);
|
||||||
|
fos.write(sb.getBytes());
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
// }
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getGlobalpath() {
|
||||||
|
return Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||||
|
+ File.separator + "crash" + File.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTag(String tag) {
|
||||||
|
TAG = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件删除
|
||||||
|
* @param day 文件保存天数
|
||||||
|
*/
|
||||||
|
// public void autoClear(final int autoClearDay) {
|
||||||
|
// FileUtil.delete(getGlobalpath(), new FilenameFilter() {
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean accept(File file, String filename) {
|
||||||
|
// String s = FileUtil.getFileNameWithoutExtension(filename);
|
||||||
|
// int day = autoClearDay < 0 ? autoClearDay : -1 * autoClearDay;
|
||||||
|
// String date = "crash-" + DateUtil.getOtherDay(day);
|
||||||
|
// return date.compareTo(s) >= 0;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.dahe.mylibrary.utils.CrashHandler.TAG;
|
||||||
|
|
||||||
|
public class FileUtil {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//移除文件,获取文件时间与当前时间对比,我这时间定位5天,删除五天前的文件
|
||||||
|
public static void removeFileByTime(String dirPath) {
|
||||||
|
//获取目录下所有文件
|
||||||
|
List<File> allFile = getDirAllFile(new File(dirPath));
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
//获取当前时间
|
||||||
|
Date end = new Date(System.currentTimeMillis());
|
||||||
|
try {
|
||||||
|
end = dateFormat.parse(dateFormat.format(new Date(System.currentTimeMillis())));
|
||||||
|
} catch (Exception e){
|
||||||
|
Log.d(TAG, "dataformat exeption e " + e.toString());
|
||||||
|
}
|
||||||
|
Log.d(TAG, "getNeedRemoveFile dirPath = " +dirPath);
|
||||||
|
for (File file : allFile) {//ComDef
|
||||||
|
try {
|
||||||
|
//文件时间减去当前时间
|
||||||
|
Date start = dateFormat.parse(dateFormat.format(new Date(file.lastModified())));
|
||||||
|
long diff = end.getTime() - start.getTime();//这样得到的差值是微秒级别
|
||||||
|
long days = diff / (1000 * 60 * 60 * 24);
|
||||||
|
// if(ComDef.LOGMAXKEEPTIME <= days){
|
||||||
|
if(5 <= days){
|
||||||
|
deleteFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e){
|
||||||
|
Log.d(TAG, "dataformat exeption e " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除文件夹及文件夹下所有文件
|
||||||
|
public static void deleteFile(File file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
File f = files[i];
|
||||||
|
deleteFile(f);
|
||||||
|
}
|
||||||
|
file.delete();
|
||||||
|
} else if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取指定目录下一级文件
|
||||||
|
public static List<File> getDirAllFile(File file) {
|
||||||
|
List<File> fileList = new ArrayList<>();
|
||||||
|
File[] fileArray = file.listFiles();
|
||||||
|
if(fileArray == null)
|
||||||
|
return fileList;
|
||||||
|
for (File f : fileArray) {
|
||||||
|
fileList.add(f);
|
||||||
|
}
|
||||||
|
fileSortByTime(fileList);
|
||||||
|
return fileList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//对文件进行时间排序
|
||||||
|
public static void fileSortByTime(List<File> fileList) {
|
||||||
|
Collections.sort(fileList, new Comparator<File>() {
|
||||||
|
public int compare(File p1, File p2) {
|
||||||
|
if (p1.lastModified() < p2.lastModified()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,204 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.MultiTransformation;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
import com.dahe.mylibrary.weight.GlideCircleWithBorder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2017/11/27 0027.
|
||||||
|
* 图片加载工具类
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ImageLoader {
|
||||||
|
public static ImageLoader mInstance = null;
|
||||||
|
|
||||||
|
public static ImageLoader getInstance() {
|
||||||
|
if (null == mInstance) {
|
||||||
|
synchronized (ImageLoader.class) {
|
||||||
|
if (null == mInstance) {
|
||||||
|
mInstance = new ImageLoader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通的加载图片 带占位图
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
* @param multiTransformation 同时设置scaleType在设置圆角或者圆形
|
||||||
|
*/
|
||||||
|
public void loadingImage(Context context, final Object url, final ImageView imageView, MultiTransformation multiTransformation, int placeholder) {
|
||||||
|
RequestOptions requestOptions = new RequestOptions();
|
||||||
|
if (null != context) {
|
||||||
|
if (placeholder != -1)
|
||||||
|
requestOptions = requestOptions.placeholder(placeholder).error(placeholder);
|
||||||
|
if (null != multiTransformation)
|
||||||
|
requestOptions = requestOptions.transform(multiTransformation);
|
||||||
|
Glide.with(context).load(url).apply(requestOptions).into(imageView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通的加载图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadingImage(Context context, final Object url, final ImageView imageView) {
|
||||||
|
loadingImage(context, url, imageView, null, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通的加载图片 带展位图
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadImage(Context context, final Object url, final ImageView imageView, RequestOptions requestOptions, int placeholder) {
|
||||||
|
if (null != context) {
|
||||||
|
if (placeholder != -1)
|
||||||
|
requestOptions = requestOptions.placeholder(placeholder).error(placeholder);
|
||||||
|
Glide.with(context).load(url).centerCrop().apply(requestOptions).into(imageView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通的加载图片 不带占位图的
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void loadImage(Context context, final Object url, final ImageView imageView) {
|
||||||
|
loadImage(context, url, imageView, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通的加载图片 不带占位图的
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadImage(Context context, final Object url, final ImageView imageView, int placeholder) {
|
||||||
|
RequestOptions requestOptions = new RequestOptions();
|
||||||
|
loadImage(context, url, imageView, requestOptions, placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆形图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadCircleImage(Context context, Object url, ImageView imageView, int placeholder) {
|
||||||
|
if (null != context) {
|
||||||
|
loadImage(context, url, imageView, RequestOptions.circleCropTransform(), placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆形图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadCircleImage(Context context, Object url, ImageView imageView) {
|
||||||
|
if (null != context) {
|
||||||
|
loadCircleImage(context, url, imageView, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆角图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param round
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadRoundImage(Context context, Object url, int round, ImageView imageView, int placeholder) {
|
||||||
|
if (null != context) {
|
||||||
|
RequestOptions requestOptions = RequestOptions.fitCenterTransform().transform(new CenterCrop(), new RoundedCorners(round));
|
||||||
|
// RequestOptions requestOptions = new RequestOptions();
|
||||||
|
// requestOptions.transform(new GlideRoundTransform(context, round));
|
||||||
|
loadImage(context, url, imageView, requestOptions, placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆角图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param round
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadRoundImage(Context context, Object url, int round, ImageView imageView) {
|
||||||
|
if (null != context) {
|
||||||
|
loadRoundImage(context, url, round, imageView, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆形带圆环图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadCircleWithBorderImage(Context context, Object url, int borderWidth, int borderColor, ImageView imageView, int placeholder) {
|
||||||
|
if (null != context) {
|
||||||
|
RequestOptions requestOptions = new RequestOptions();
|
||||||
|
requestOptions.transform(new GlideCircleWithBorder(context, borderWidth, ContextCompat.getColor(context, borderColor)));
|
||||||
|
loadImage(context, url, imageView, requestOptions, placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆形带圆环图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadCircleWithBorderImage(Context context, Object url,RequestOptions requestOptions, int borderWidth, int borderColor, ImageView imageView, int placeholder) {
|
||||||
|
if (null != context) {
|
||||||
|
requestOptions.transform(new GlideCircleWithBorder(context, borderWidth, ContextCompat.getColor(context, borderColor)));
|
||||||
|
loadImage(context, url, imageView, requestOptions, placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆形带圆环图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
public void loadCircleWithBorderImage(Context context, Object url, int borderWidth, int borderColor, ImageView imageView) {
|
||||||
|
if (null != context) {
|
||||||
|
loadCircleWithBorderImage(context, url, borderWidth, borderColor, imageView, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
public class MD5Utils {
|
||||||
|
|
||||||
|
private static final int BUFFERSIZE = 8196;
|
||||||
|
private static final String ALGORITHM = "MD5";
|
||||||
|
private static final String CHARSET = "UTF-8";
|
||||||
|
|
||||||
|
public MD5Utils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String md5(String input) {
|
||||||
|
return md5(input, CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String md5(String input, String charsetName) {
|
||||||
|
try {
|
||||||
|
MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);
|
||||||
|
byte md5Bytes[] = md5.digest(input.getBytes(charsetName));
|
||||||
|
return StringUtils.byte2hex(md5Bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String md5file(File filename) {
|
||||||
|
BufferedInputStream bufferedInputStream = null;
|
||||||
|
MessageDigest md;
|
||||||
|
try {
|
||||||
|
bufferedInputStream = new BufferedInputStream(new FileInputStream(filename), BUFFERSIZE);
|
||||||
|
md = MessageDigest.getInstance(ALGORITHM);
|
||||||
|
byte[] buffer = new byte[BUFFERSIZE];
|
||||||
|
int i = 0;
|
||||||
|
while ((i = bufferedInputStream.read(buffer)) != -1) {
|
||||||
|
md.update(buffer, 0, i);
|
||||||
|
}
|
||||||
|
return StringUtils.byte2hex(md.digest());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
bufferedInputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String md5reverse(String md5) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* author: Blankj
|
||||||
|
* blog : http://blankj.com
|
||||||
|
* time : 2017/03/13
|
||||||
|
* desc : constants of memory
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class MemoryConstants {
|
||||||
|
|
||||||
|
public static final int BYTE = 1;
|
||||||
|
public static final int KB = 1024;
|
||||||
|
public static final int MB = 1048576;
|
||||||
|
public static final int GB = 1073741824;
|
||||||
|
|
||||||
|
@IntDef({BYTE, KB, MB, GB})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Unit {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class PatternUtils {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则表达式:验证密码(包含大小写,数字,特殊字符,6-12位)
|
||||||
|
*/
|
||||||
|
// public static final String REGEX_PASSWORD = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\\.])[0-9a-zA-Z!@#$%^&*,\\\\.]{6,12}$";
|
||||||
|
public static final String REGEX_PASSWORD = "^(?=.*[0-9])(?=.*[a-z])(?=.*[!@#$%^&*,\\.])[0-9a-zA-Z!@#$%^&*,\\\\.]{6,12}$";
|
||||||
|
public static final String REGEX_WORD = "^[A-Za-z]+$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验密码
|
||||||
|
*
|
||||||
|
* @param password
|
||||||
|
* @return 校验通过返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public static boolean isPassword(String password) {
|
||||||
|
return Pattern.matches(REGEX_PASSWORD, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLetter(String password){
|
||||||
|
return Pattern.matches(REGEX_WORD, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
|
public class PhoneFormatCheckUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大陆号码或香港号码均可
|
||||||
|
*/
|
||||||
|
public static boolean isPhoneLegal(String str) throws PatternSyntaxException {
|
||||||
|
return isChinaPhoneLegal(str) || isHKPhoneLegal(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大陆手机号码11位数,匹配格式:前三位固定格式+后8位任意数
|
||||||
|
* 此方法中前三位格式有:
|
||||||
|
* 13+任意数
|
||||||
|
* 145,147,149
|
||||||
|
* 15+除4的任意数(不要写^4,这样的话字母也会被认为是正确的)
|
||||||
|
* 166
|
||||||
|
* 17+3,5,6,7,8
|
||||||
|
* 18+任意数
|
||||||
|
* 198,199
|
||||||
|
*/
|
||||||
|
public static boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
|
||||||
|
// ^ 匹配输入字符串开始的位置
|
||||||
|
// \d 匹配一个或多个数字,其中 \ 要转义,所以是 \\d
|
||||||
|
// $ 匹配输入字符串结尾的位置
|
||||||
|
String regExp = "^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(166)|(17[3,5,6,7,8])" +
|
||||||
|
"|(18[0-9])|(19[8,9]))\\d{8}$";
|
||||||
|
Pattern p = Pattern.compile(regExp);
|
||||||
|
Matcher m = p.matcher(str);
|
||||||
|
return m.matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 香港手机号码8位数,5|6|8|9开头+7位任意数
|
||||||
|
*/
|
||||||
|
public static boolean isHKPhoneLegal(String str) throws PatternSyntaxException {
|
||||||
|
// ^ 匹配输入字符串开始的位置
|
||||||
|
// \d 匹配一个或多个数字,其中 \ 要转义,所以是 \\d
|
||||||
|
// $ 匹配输入字符串结尾的位置
|
||||||
|
String regExp = "^(5|6|8|9)\\d{7}$";
|
||||||
|
Pattern p = Pattern.compile(regExp);
|
||||||
|
Matcher m = p.matcher(str);
|
||||||
|
return m.matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String hintPhone(String phone){
|
||||||
|
return phone.substring(0, 3) + "****" + phone.substring(7, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,366 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.adapter.GridImageAdapter;
|
||||||
|
import com.dahe.mylibrary.dialog.DialogPhotoSelect;
|
||||||
|
import com.dahe.mylibrary.net.CommonResponseBean;
|
||||||
|
import com.dahe.mylibrary.weight.GlideEngine;
|
||||||
|
import com.luck.picture.lib.PictureSelector;
|
||||||
|
import com.luck.picture.lib.config.PictureConfig;
|
||||||
|
import com.luck.picture.lib.config.PictureMimeType;
|
||||||
|
import com.luck.picture.lib.entity.LocalMedia;
|
||||||
|
import com.luck.picture.lib.listener.OnResultCallbackListener;
|
||||||
|
import com.luck.picture.lib.style.PictureCropParameterStyle;
|
||||||
|
import com.luck.picture.lib.style.PictureParameterStyle;
|
||||||
|
import com.luck.picture.lib.style.PictureSelectorUIStyle;
|
||||||
|
import com.luck.picture.lib.tools.SdkVersionUtils;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SelectPhotoUtils4 implements View.OnClickListener {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private Activity ctx;
|
||||||
|
private OnResultCallbackListener listener;
|
||||||
|
private GridImageAdapter mAdapter;
|
||||||
|
|
||||||
|
public void selectSimple(Activity ctx,ImageView imageView, OnResultCallbackListener callbackListener){
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.listener = callbackListener;
|
||||||
|
imageView.setOnClickListener(this);
|
||||||
|
imageView.performClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onAddPicClick() {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openGallery(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
.maxSelectNum(6)
|
||||||
|
.isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.isCamera(true)// 是否显示拍照按钮 true or false
|
||||||
|
.isEnableCrop(true)// 是否裁剪 true or false
|
||||||
|
.selectionData(mAdapter.getData())// 是否传入已选图片
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(new MyResultCallback(mAdapter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelPicClick(int postion, LocalMedia localMedia) {
|
||||||
|
// DataManager.getInstance().remove(localMedia.getId()+"")
|
||||||
|
// .compose(DataManager.setThread())
|
||||||
|
// .subscribe(new BaseObserver(ctx, new RxHttpCallBack(ctx) {
|
||||||
|
// @Override
|
||||||
|
// public void onSuccess(CommonResponseBean t) {
|
||||||
|
// super.onSuccess(t);
|
||||||
|
//// list.remove(index);
|
||||||
|
// mAdapter.getData().remove(postion);
|
||||||
|
// mAdapter.notifyItemRemoved(postion);
|
||||||
|
// mAdapter.notifyItemRangeChanged(postion, mAdapter.getData().size());
|
||||||
|
// }
|
||||||
|
// }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果回调
|
||||||
|
*/
|
||||||
|
private class MyResultCallback implements OnResultCallbackListener<LocalMedia> {
|
||||||
|
private WeakReference<GridImageAdapter> mAdapterWeakReference;
|
||||||
|
|
||||||
|
public MyResultCallback(GridImageAdapter adapter) {
|
||||||
|
super();
|
||||||
|
this.mAdapterWeakReference = new WeakReference<>(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(List<LocalMedia> result) {
|
||||||
|
// for (LocalMedia media : result) {
|
||||||
|
// Log.i(TAG, "是否压缩:" + media.isCompressed());
|
||||||
|
// Log.i(TAG, "压缩:" + media.getCompressPath());
|
||||||
|
// Log.i(TAG, "原图:" + media.getPath());
|
||||||
|
// Log.i(TAG, "绝对路径:" + media.getRealPath());
|
||||||
|
// Log.i(TAG, "是否裁剪:" + media.isCut());
|
||||||
|
// Log.i(TAG, "裁剪:" + media.getCutPath());
|
||||||
|
// Log.i(TAG, "是否开启原图:" + media.isOriginal());
|
||||||
|
// Log.i(TAG, "原图路径:" + media.getOriginalPath());
|
||||||
|
// Log.i(TAG, "Android Q 特有Path:" + media.getAndroidQToPath());
|
||||||
|
// Log.i(TAG, "宽高: " + media.getWidth() + "x" + media.getHeight());
|
||||||
|
// Log.i(TAG, "Size: " + media.getSize());
|
||||||
|
//
|
||||||
|
// Log.i("MMM", "onResult: " + media.toString());
|
||||||
|
// // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息,如旋转角度、经纬度等信息
|
||||||
|
// }
|
||||||
|
listener.onResult(result);
|
||||||
|
if (mAdapterWeakReference.get() != null) {
|
||||||
|
mAdapterWeakReference.get().setList(result);
|
||||||
|
mAdapterWeakReference.get().notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel() {
|
||||||
|
// Log.i(TAG, "PictureSelector Cancel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private PictureCropParameterStyle mCropParameterStyle;
|
||||||
|
|
||||||
|
private PictureParameterStyle getDefaultStyle() {
|
||||||
|
// 相册主题
|
||||||
|
PictureParameterStyle mPictureParameterStyle = new PictureParameterStyle();
|
||||||
|
// 是否改变状态栏字体颜色(黑白切换)
|
||||||
|
mPictureParameterStyle.isChangeStatusBarFontColor = false;
|
||||||
|
// 是否开启右下角已完成(0/9)风格
|
||||||
|
mPictureParameterStyle.isOpenCompletedNumStyle = false;
|
||||||
|
// 是否开启类似QQ相册带数字选择风格
|
||||||
|
mPictureParameterStyle.isOpenCheckNumStyle = false;
|
||||||
|
// 相册状态栏背景色
|
||||||
|
mPictureParameterStyle.pictureStatusBarColor = Color.parseColor("#393a3e");
|
||||||
|
// 相册列表标题栏背景色
|
||||||
|
mPictureParameterStyle.pictureTitleBarBackgroundColor = Color.parseColor("#393a3e");
|
||||||
|
// 相册父容器背景色
|
||||||
|
mPictureParameterStyle.pictureContainerBackgroundColor = ContextCompat.getColor(ctx, R.color.black);
|
||||||
|
// 相册列表标题栏右侧上拉箭头
|
||||||
|
mPictureParameterStyle.pictureTitleUpResId = R.drawable.picture_icon_arrow_up;
|
||||||
|
// 相册列表标题栏右侧下拉箭头
|
||||||
|
mPictureParameterStyle.pictureTitleDownResId = R.drawable.picture_icon_arrow_down;
|
||||||
|
// 相册文件夹列表选中圆点
|
||||||
|
mPictureParameterStyle.pictureFolderCheckedDotStyle = R.drawable.picture_orange_oval;
|
||||||
|
// 相册返回箭头
|
||||||
|
mPictureParameterStyle.pictureLeftBackIcon = R.drawable.picture_icon_back;
|
||||||
|
// 标题栏字体颜色
|
||||||
|
mPictureParameterStyle.pictureTitleTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 相册右侧取消按钮字体颜色 废弃 改用.pictureRightDefaultTextColor和.pictureRightDefaultTextColor
|
||||||
|
mPictureParameterStyle.pictureCancelTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 选择相册目录背景样式
|
||||||
|
// mPictureParameterStyle.pictureAlbumStyle = R.drawable.picture_new_item_select_bg;
|
||||||
|
// 相册列表勾选图片样式
|
||||||
|
mPictureParameterStyle.pictureCheckedStyle = R.drawable.picture_checkbox_selector;
|
||||||
|
// 相册列表底部背景色
|
||||||
|
mPictureParameterStyle.pictureBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
|
||||||
|
// 已选数量圆点背景样式
|
||||||
|
mPictureParameterStyle.pictureCheckNumBgStyle = R.drawable.picture_num_oval;
|
||||||
|
// 相册列表底下预览文字色值(预览按钮可点击时的色值)
|
||||||
|
mPictureParameterStyle.picturePreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
|
||||||
|
// 相册列表底下不可预览文字色值(预览按钮不可点击时的色值)
|
||||||
|
mPictureParameterStyle.pictureUnPreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 相册列表已完成色值(已完成 可点击色值)
|
||||||
|
mPictureParameterStyle.pictureCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
|
||||||
|
// 相册列表未完成色值(请选择 不可点击色值)
|
||||||
|
mPictureParameterStyle.pictureUnCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 预览界面底部背景色
|
||||||
|
mPictureParameterStyle.picturePreviewBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
|
||||||
|
// 外部预览界面删除按钮样式
|
||||||
|
mPictureParameterStyle.pictureExternalPreviewDeleteStyle = R.drawable.picture_icon_delete;
|
||||||
|
// 原图按钮勾选样式 需设置.isOriginalImageControl(true); 才有效
|
||||||
|
mPictureParameterStyle.pictureOriginalControlStyle = R.drawable.picture_original_wechat_checkbox;
|
||||||
|
// 原图文字颜色 需设置.isOriginalImageControl(true); 才有效
|
||||||
|
mPictureParameterStyle.pictureOriginalFontColor = ContextCompat.getColor(ctx, R.color.white);
|
||||||
|
// 外部预览界面是否显示删除按钮
|
||||||
|
mPictureParameterStyle.pictureExternalPreviewGonePreviewDelete = true;
|
||||||
|
// 设置NavBar Color SDK Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP有效
|
||||||
|
mPictureParameterStyle.pictureNavBarColor = Color.parseColor("#393a3e");
|
||||||
|
// 文件夹字体颜色
|
||||||
|
mPictureParameterStyle.folderTextColor = Color.parseColor("#4d4d4d");
|
||||||
|
// 文件夹字体大小
|
||||||
|
mPictureParameterStyle.folderTextSize = 16;
|
||||||
|
// // 自定义相册右侧文本内容设置
|
||||||
|
// mPictureParameterStyle.pictureRightDefaultText = "";
|
||||||
|
// // 自定义相册未完成文本内容
|
||||||
|
// mPictureParameterStyle.pictureUnCompleteText = "";
|
||||||
|
// // 自定义相册完成文本内容
|
||||||
|
// mPictureParameterStyle.pictureCompleteText = "";
|
||||||
|
// // 自定义相册列表不可预览文字
|
||||||
|
// mPictureParameterStyle.pictureUnPreviewText = "";
|
||||||
|
// // 自定义相册列表预览文字
|
||||||
|
// mPictureParameterStyle.picturePreviewText = "";
|
||||||
|
//
|
||||||
|
// // 自定义相册标题字体大小
|
||||||
|
// mPictureParameterStyle.pictureTitleTextSize = 18;
|
||||||
|
// // 自定义相册右侧文字大小
|
||||||
|
// mPictureParameterStyle.pictureRightTextSize = 14;
|
||||||
|
// // 自定义相册预览文字大小
|
||||||
|
// mPictureParameterStyle.picturePreviewTextSize = 14;
|
||||||
|
// // 自定义相册完成文字大小
|
||||||
|
// mPictureParameterStyle.pictureCompleteTextSize = 14;
|
||||||
|
// // 自定义原图文字大小
|
||||||
|
// mPictureParameterStyle.pictureOriginalTextSize = 14;
|
||||||
|
|
||||||
|
// 裁剪主题
|
||||||
|
mCropParameterStyle = new PictureCropParameterStyle(
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
Color.parseColor("#393a3e"),
|
||||||
|
ContextCompat.getColor(ctx, R.color.white),
|
||||||
|
mPictureParameterStyle.isChangeStatusBarFontColor);
|
||||||
|
|
||||||
|
return mPictureParameterStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相机拍照
|
||||||
|
*/
|
||||||
|
private void doTakePhoto(Activity ctx) {
|
||||||
|
|
||||||
|
// 裁剪主题
|
||||||
|
mCropParameterStyle = new PictureCropParameterStyle(
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
Color.parseColor("#393a3e"),
|
||||||
|
ContextCompat.getColor(ctx, R.color.white),
|
||||||
|
false);
|
||||||
|
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openCamera(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题
|
||||||
|
.minSelectNum(1)
|
||||||
|
.maxSelectNum(1)
|
||||||
|
.isSingleDirectReturn(true)// 单选模式下是否直接返回,PictureConfig.SINGLE模式下有效
|
||||||
|
// .setPictureUIStyle(PictureSelectorUIStyle.ofDefaultStyle())
|
||||||
|
.isEnableCrop(true)// 是否裁剪 true or false
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(listener);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 单独拍照
|
||||||
|
// PictureSelector.create(ctx)
|
||||||
|
// .openCamera(PictureMimeType.ofAll())// 单独拍照,也可录像或也可音频 看你传入的类型是图片or视频
|
||||||
|
// .theme(R.style.picture_default_style)// 主题样式设置 具体参考 values/styles
|
||||||
|
// .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项
|
||||||
|
// .maxSelectNum(1)// 最大图片选择数量
|
||||||
|
// .minSelectNum(1)// 最小选择数量
|
||||||
|
// .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true
|
||||||
|
// .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认false
|
||||||
|
// .selectionMode(cb_choose_mode.isChecked() ?
|
||||||
|
// PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选
|
||||||
|
// .loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用
|
||||||
|
// .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片
|
||||||
|
// .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频
|
||||||
|
// .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频
|
||||||
|
// .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮
|
||||||
|
// .isEnableCrop(cb_crop.isChecked())// 是否裁剪
|
||||||
|
// .isCompress(cb_compress.isChecked())// 是否压缩
|
||||||
|
// .compressQuality(60)// 图片压缩后输出质量
|
||||||
|
// .glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
|
||||||
|
// .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
|
||||||
|
// .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏,默认不显示
|
||||||
|
// .isGif(cb_isGif.isChecked())// 是否显示gif图片
|
||||||
|
// .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽
|
||||||
|
// .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪
|
||||||
|
// .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
|
||||||
|
// .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false
|
||||||
|
// .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音
|
||||||
|
// .selectionData(mAdapter.getData())// 是否传入已选图片
|
||||||
|
// .cutOutQuality(90)// 裁剪输出质量 默认100
|
||||||
|
// .minimumCompressSize(100)// 小于100kb的图片不压缩
|
||||||
|
// .forResult(new MyResultCallback(mAdapter));
|
||||||
|
}
|
||||||
|
|
||||||
|
//从本地相册中选择
|
||||||
|
private void doSelectPhoto(Activity ctx) {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openGallery(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
.isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.isCamera(false)// 是否显示拍照按钮 true or false
|
||||||
|
.isEnableCrop(true)// 是否裁剪 true or false
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(listener);
|
||||||
|
// .forResult(PictureConfig.CHOOSE_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
|
||||||
|
// PictureSelector.create(ctx)
|
||||||
|
// .openGallery(PictureMimeType.ofImage())
|
||||||
|
// .imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
// .selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
// .isSingleDirectReturn(true)
|
||||||
|
// .maxSelectNum(1)
|
||||||
|
// .minSelectNum(1)
|
||||||
|
// .isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
// .isGif(false)// 是否显示gif图片 true or false
|
||||||
|
// .isCamera(true)// 是否显示拍照按钮 true or false
|
||||||
|
// .isEnableCrop(true)// 是否裁剪 true or false
|
||||||
|
// .isCompress(true)// 是否压缩 true or false
|
||||||
|
// .circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
// .freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
// .cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
// .minimumCompressSize(100)// 小于100kb的图片不压缩
|
||||||
|
// .showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
// .showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
// .scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
// .forResult(listener);
|
||||||
|
|
||||||
|
|
||||||
|
DialogPhotoSelect dialogPhotoSelect = new DialogPhotoSelect(ctx);
|
||||||
|
dialogPhotoSelect.show();
|
||||||
|
dialogPhotoSelect.setOnSelectClickListener(new DialogPhotoSelect.onSelectClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onTakePhoto() {
|
||||||
|
doTakePhoto(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectPhoto() {
|
||||||
|
doSelectPhoto(ctx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,353 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.adapter.GridImageAdapter;
|
||||||
|
import com.dahe.mylibrary.dialog.DialogPhotoSelect;
|
||||||
|
import com.dahe.mylibrary.weight.GlideEngine;
|
||||||
|
import com.luck.picture.lib.PictureSelector;
|
||||||
|
import com.luck.picture.lib.config.PictureConfig;
|
||||||
|
import com.luck.picture.lib.config.PictureMimeType;
|
||||||
|
import com.luck.picture.lib.entity.LocalMedia;
|
||||||
|
import com.luck.picture.lib.listener.OnResultCallbackListener;
|
||||||
|
import com.luck.picture.lib.style.PictureCropParameterStyle;
|
||||||
|
import com.luck.picture.lib.style.PictureParameterStyle;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SelectPhotoUtils5 implements View.OnClickListener {
|
||||||
|
|
||||||
|
private SelectPhotoUtils5 selectPhotoUtils5;
|
||||||
|
private Activity ctx;
|
||||||
|
private OnResultCallbackListener listener;
|
||||||
|
private GridImageAdapter mAdapter;
|
||||||
|
|
||||||
|
public void selectSimple(Activity ctx, ImageView imageView, OnResultCallbackListener callbackListener) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.listener = callbackListener;
|
||||||
|
imageView.setOnClickListener(this);
|
||||||
|
imageView.performClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onAddPicClick() {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openGallery(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
.maxSelectNum(6)
|
||||||
|
.isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.isCamera(true)// 是否显示拍照按钮 true or false
|
||||||
|
.isEnableCrop(false)// 是否裁剪 true or false
|
||||||
|
.selectionData(mAdapter.getData())// 是否传入已选图片
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(new MyResultCallback(mAdapter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelPicClick(int postion, LocalMedia localMedia) {
|
||||||
|
// DataManager.getInstance().remove(localMedia.getId()+"")
|
||||||
|
// .compose(DataManager.setThread())
|
||||||
|
// .subscribe(new BaseObserver(ctx, new RxHttpCallBack(ctx) {
|
||||||
|
// @Override
|
||||||
|
// public void onSuccess(CommonResponseBean t) {
|
||||||
|
// super.onSuccess(t);
|
||||||
|
//// list.remove(index);
|
||||||
|
// mAdapter.getData().remove(postion);
|
||||||
|
// mAdapter.notifyItemRemoved(postion);
|
||||||
|
// mAdapter.notifyItemRangeChanged(postion, mAdapter.getData().size());
|
||||||
|
// }
|
||||||
|
// }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果回调
|
||||||
|
*/
|
||||||
|
private class MyResultCallback implements OnResultCallbackListener<LocalMedia> {
|
||||||
|
private WeakReference<GridImageAdapter> mAdapterWeakReference;
|
||||||
|
|
||||||
|
public MyResultCallback(GridImageAdapter adapter) {
|
||||||
|
super();
|
||||||
|
this.mAdapterWeakReference = new WeakReference<>(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(List<LocalMedia> result) {
|
||||||
|
// for (LocalMedia media : result) {
|
||||||
|
// Log.i(TAG, "是否压缩:" + media.isCompressed());
|
||||||
|
// Log.i(TAG, "压缩:" + media.getCompressPath());
|
||||||
|
// Log.i(TAG, "原图:" + media.getPath());
|
||||||
|
// Log.i(TAG, "绝对路径:" + media.getRealPath());
|
||||||
|
// Log.i(TAG, "是否裁剪:" + media.isCut());
|
||||||
|
// Log.i(TAG, "裁剪:" + media.getCutPath());
|
||||||
|
// Log.i(TAG, "是否开启原图:" + media.isOriginal());
|
||||||
|
// Log.i(TAG, "原图路径:" + media.getOriginalPath());
|
||||||
|
// Log.i(TAG, "Android Q 特有Path:" + media.getAndroidQToPath());
|
||||||
|
// Log.i(TAG, "宽高: " + media.getWidth() + "x" + media.getHeight());
|
||||||
|
// Log.i(TAG, "Size: " + media.getSize());
|
||||||
|
//
|
||||||
|
// Log.i("MMM", "onResult: " + media.toString());
|
||||||
|
// // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息,如旋转角度、经纬度等信息
|
||||||
|
// }
|
||||||
|
listener.onResult(result);
|
||||||
|
if (mAdapterWeakReference.get() != null) {
|
||||||
|
mAdapterWeakReference.get().setList(result);
|
||||||
|
mAdapterWeakReference.get().notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel() {
|
||||||
|
// Log.i(TAG, "PictureSelector Cancel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private PictureCropParameterStyle mCropParameterStyle;
|
||||||
|
|
||||||
|
private PictureParameterStyle getDefaultStyle() {
|
||||||
|
// 相册主题
|
||||||
|
PictureParameterStyle mPictureParameterStyle = new PictureParameterStyle();
|
||||||
|
// 是否改变状态栏字体颜色(黑白切换)
|
||||||
|
mPictureParameterStyle.isChangeStatusBarFontColor = false;
|
||||||
|
// 是否开启右下角已完成(0/9)风格
|
||||||
|
mPictureParameterStyle.isOpenCompletedNumStyle = false;
|
||||||
|
// 是否开启类似QQ相册带数字选择风格
|
||||||
|
mPictureParameterStyle.isOpenCheckNumStyle = false;
|
||||||
|
// 相册状态栏背景色
|
||||||
|
mPictureParameterStyle.pictureStatusBarColor = Color.parseColor("#393a3e");
|
||||||
|
// 相册列表标题栏背景色
|
||||||
|
mPictureParameterStyle.pictureTitleBarBackgroundColor = Color.parseColor("#393a3e");
|
||||||
|
// 相册父容器背景色
|
||||||
|
mPictureParameterStyle.pictureContainerBackgroundColor = ContextCompat.getColor(ctx, R.color.black);
|
||||||
|
// 相册列表标题栏右侧上拉箭头
|
||||||
|
mPictureParameterStyle.pictureTitleUpResId = R.drawable.picture_icon_arrow_up;
|
||||||
|
// 相册列表标题栏右侧下拉箭头
|
||||||
|
mPictureParameterStyle.pictureTitleDownResId = R.drawable.picture_icon_arrow_down;
|
||||||
|
// 相册文件夹列表选中圆点
|
||||||
|
mPictureParameterStyle.pictureFolderCheckedDotStyle = R.drawable.picture_orange_oval;
|
||||||
|
// 相册返回箭头
|
||||||
|
mPictureParameterStyle.pictureLeftBackIcon = R.drawable.picture_icon_back;
|
||||||
|
// 标题栏字体颜色
|
||||||
|
mPictureParameterStyle.pictureTitleTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 相册右侧取消按钮字体颜色 废弃 改用.pictureRightDefaultTextColor和.pictureRightDefaultTextColor
|
||||||
|
mPictureParameterStyle.pictureCancelTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 选择相册目录背景样式
|
||||||
|
// mPictureParameterStyle.pictureAlbumStyle = R.drawable.picture_new_item_select_bg;
|
||||||
|
// 相册列表勾选图片样式
|
||||||
|
mPictureParameterStyle.pictureCheckedStyle = R.drawable.picture_checkbox_selector;
|
||||||
|
// 相册列表底部背景色
|
||||||
|
mPictureParameterStyle.pictureBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
|
||||||
|
// 已选数量圆点背景样式
|
||||||
|
mPictureParameterStyle.pictureCheckNumBgStyle = R.drawable.picture_num_oval;
|
||||||
|
// 相册列表底下预览文字色值(预览按钮可点击时的色值)
|
||||||
|
mPictureParameterStyle.picturePreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
|
||||||
|
// 相册列表底下不可预览文字色值(预览按钮不可点击时的色值)
|
||||||
|
mPictureParameterStyle.pictureUnPreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 相册列表已完成色值(已完成 可点击色值)
|
||||||
|
mPictureParameterStyle.pictureCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
|
||||||
|
// 相册列表未完成色值(请选择 不可点击色值)
|
||||||
|
mPictureParameterStyle.pictureUnCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
|
||||||
|
// 预览界面底部背景色
|
||||||
|
mPictureParameterStyle.picturePreviewBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
|
||||||
|
// 外部预览界面删除按钮样式
|
||||||
|
mPictureParameterStyle.pictureExternalPreviewDeleteStyle = R.drawable.picture_icon_delete;
|
||||||
|
// 原图按钮勾选样式 需设置.isOriginalImageControl(true); 才有效
|
||||||
|
mPictureParameterStyle.pictureOriginalControlStyle = R.drawable.picture_original_wechat_checkbox;
|
||||||
|
// 原图文字颜色 需设置.isOriginalImageControl(true); 才有效
|
||||||
|
mPictureParameterStyle.pictureOriginalFontColor = ContextCompat.getColor(ctx, R.color.white);
|
||||||
|
// 外部预览界面是否显示删除按钮
|
||||||
|
mPictureParameterStyle.pictureExternalPreviewGonePreviewDelete = true;
|
||||||
|
// 设置NavBar Color SDK Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP有效
|
||||||
|
mPictureParameterStyle.pictureNavBarColor = Color.parseColor("#393a3e");
|
||||||
|
// 文件夹字体颜色
|
||||||
|
mPictureParameterStyle.folderTextColor = Color.parseColor("#4d4d4d");
|
||||||
|
// 文件夹字体大小
|
||||||
|
mPictureParameterStyle.folderTextSize = 16;
|
||||||
|
// // 自定义相册右侧文本内容设置
|
||||||
|
// mPictureParameterStyle.pictureRightDefaultText = "";
|
||||||
|
// // 自定义相册未完成文本内容
|
||||||
|
// mPictureParameterStyle.pictureUnCompleteText = "";
|
||||||
|
// // 自定义相册完成文本内容
|
||||||
|
// mPictureParameterStyle.pictureCompleteText = "";
|
||||||
|
// // 自定义相册列表不可预览文字
|
||||||
|
// mPictureParameterStyle.pictureUnPreviewText = "";
|
||||||
|
// // 自定义相册列表预览文字
|
||||||
|
// mPictureParameterStyle.picturePreviewText = "";
|
||||||
|
//
|
||||||
|
// // 自定义相册标题字体大小
|
||||||
|
// mPictureParameterStyle.pictureTitleTextSize = 18;
|
||||||
|
// // 自定义相册右侧文字大小
|
||||||
|
// mPictureParameterStyle.pictureRightTextSize = 14;
|
||||||
|
// // 自定义相册预览文字大小
|
||||||
|
// mPictureParameterStyle.picturePreviewTextSize = 14;
|
||||||
|
// // 自定义相册完成文字大小
|
||||||
|
// mPictureParameterStyle.pictureCompleteTextSize = 14;
|
||||||
|
// // 自定义原图文字大小
|
||||||
|
// mPictureParameterStyle.pictureOriginalTextSize = 14;
|
||||||
|
|
||||||
|
// 裁剪主题
|
||||||
|
mCropParameterStyle = new PictureCropParameterStyle(
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
Color.parseColor("#393a3e"),
|
||||||
|
ContextCompat.getColor(ctx, R.color.white),
|
||||||
|
mPictureParameterStyle.isChangeStatusBarFontColor);
|
||||||
|
|
||||||
|
return mPictureParameterStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相机拍照
|
||||||
|
*/
|
||||||
|
private void doTakePhoto(Activity ctx) {
|
||||||
|
|
||||||
|
// 裁剪主题
|
||||||
|
mCropParameterStyle = new PictureCropParameterStyle(
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
ContextCompat.getColor(ctx, R.color.picture_color_grey),
|
||||||
|
Color.parseColor("#393a3e"),
|
||||||
|
ContextCompat.getColor(ctx, R.color.white),
|
||||||
|
false);
|
||||||
|
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openCamera(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题
|
||||||
|
.minSelectNum(1)
|
||||||
|
.maxSelectNum(1)
|
||||||
|
.isSingleDirectReturn(true)// 单选模式下是否直接返回,PictureConfig.SINGLE模式下有效
|
||||||
|
// .setPictureUIStyle(PictureSelectorUIStyle.ofDefaultStyle())
|
||||||
|
.isEnableCrop(false)// 是否裁剪 true or false
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(listener);
|
||||||
|
|
||||||
|
|
||||||
|
// 单独拍照
|
||||||
|
// PictureSelector.create(ctx)
|
||||||
|
// .openCamera(PictureMimeType.ofAll())// 单独拍照,也可录像或也可音频 看你传入的类型是图片or视频
|
||||||
|
// .theme(R.style.picture_default_style)// 主题样式设置 具体参考 values/styles
|
||||||
|
// .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项
|
||||||
|
// .maxSelectNum(1)// 最大图片选择数量
|
||||||
|
// .minSelectNum(1)// 最小选择数量
|
||||||
|
// .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true
|
||||||
|
// .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认false
|
||||||
|
// .selectionMode(cb_choose_mode.isChecked() ?
|
||||||
|
// PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选
|
||||||
|
// .loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用
|
||||||
|
// .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片
|
||||||
|
// .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频
|
||||||
|
// .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频
|
||||||
|
// .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮
|
||||||
|
// .isEnableCrop(cb_crop.isChecked())// 是否裁剪
|
||||||
|
// .isCompress(cb_compress.isChecked())// 是否压缩
|
||||||
|
// .compressQuality(60)// 图片压缩后输出质量
|
||||||
|
// .glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
|
||||||
|
// .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
|
||||||
|
// .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏,默认不显示
|
||||||
|
// .isGif(cb_isGif.isChecked())// 是否显示gif图片
|
||||||
|
// .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽
|
||||||
|
// .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪
|
||||||
|
// .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
|
||||||
|
// .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false
|
||||||
|
// .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音
|
||||||
|
// .selectionData(mAdapter.getData())// 是否传入已选图片
|
||||||
|
// .cutOutQuality(90)// 裁剪输出质量 默认100
|
||||||
|
// .minimumCompressSize(100)// 小于100kb的图片不压缩
|
||||||
|
// .forResult(new MyResultCallback(mAdapter));
|
||||||
|
}
|
||||||
|
|
||||||
|
//从本地相册中选择
|
||||||
|
private void doSelectPhoto(Activity ctx) {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openGallery(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
.isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.isCamera(false)// 是否显示拍照按钮 true or false
|
||||||
|
.isEnableCrop(false)// 是否裁剪 true or false
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(listener);
|
||||||
|
// .forResult(PictureConfig.CHOOSE_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
|
||||||
|
// PictureSelector.create(ctx)
|
||||||
|
// .openGallery(PictureMimeType.ofImage())
|
||||||
|
// .imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
// .selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
// .isSingleDirectReturn(true)
|
||||||
|
// .maxSelectNum(1)
|
||||||
|
// .minSelectNum(1)
|
||||||
|
// .isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
// .isGif(false)// 是否显示gif图片 true or false
|
||||||
|
// .isCamera(true)// 是否显示拍照按钮 true or false
|
||||||
|
// .isEnableCrop(true)// 是否裁剪 true or false
|
||||||
|
// .isCompress(true)// 是否压缩 true or false
|
||||||
|
// .circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
// .freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
|
||||||
|
// .cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
// .minimumCompressSize(100)// 小于100kb的图片不压缩
|
||||||
|
// .showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
// .showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
// .scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
// .forResult(listener);
|
||||||
|
|
||||||
|
|
||||||
|
DialogPhotoSelect dialogPhotoSelect = new DialogPhotoSelect(ctx);
|
||||||
|
dialogPhotoSelect.show();
|
||||||
|
dialogPhotoSelect.setOnSelectClickListener(new DialogPhotoSelect.onSelectClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onTakePhoto() {
|
||||||
|
doTakePhoto(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectPhoto() {
|
||||||
|
doSelectPhoto(ctx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,318 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.adapter.GridImageAdapter;
|
||||||
|
import com.dahe.mylibrary.dialog.DialogPhotoSelect;
|
||||||
|
import com.dahe.mylibrary.net.CommonResponseBean;
|
||||||
|
import com.dahe.mylibrary.weight.FullyGridLayoutManager;
|
||||||
|
import com.dahe.mylibrary.weight.GlideEngine;
|
||||||
|
import com.luck.picture.lib.PictureSelector;
|
||||||
|
import com.luck.picture.lib.config.PictureConfig;
|
||||||
|
import com.luck.picture.lib.config.PictureMimeType;
|
||||||
|
import com.luck.picture.lib.decoration.GridSpacingItemDecoration;
|
||||||
|
import com.luck.picture.lib.entity.LocalMedia;
|
||||||
|
import com.luck.picture.lib.listener.OnResultCallbackListener;
|
||||||
|
import com.luck.picture.lib.tools.ScreenUtils;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SelectPhotoUtils6 implements View.OnClickListener {
|
||||||
|
private Activity ctx;
|
||||||
|
private OnResultCallbackListener listener;
|
||||||
|
private GridImageAdapter mAdapter;
|
||||||
|
private Build build;
|
||||||
|
|
||||||
|
private SelectPhotoUtils6(Build build, Activity ctx) {
|
||||||
|
this.build = build;
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.listener = build.listener;
|
||||||
|
if (null == listener) {
|
||||||
|
ToastUtils.showToast(ctx, "请初始化回调listener");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (build.isSingle) {//单选
|
||||||
|
if (null == build.imageView) {
|
||||||
|
ToastUtils.showToast(ctx, "请初始化ImageView");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectSimple(build.imageView);
|
||||||
|
} else {//多选
|
||||||
|
if (null == build.recyclerView || !(build.recyclerView instanceof RecyclerView)) {
|
||||||
|
ToastUtils.showToast(ctx, "请初始化RecycleView");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectMul(build.recyclerView);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Build {
|
||||||
|
private int maxSelect;
|
||||||
|
private boolean isSingle;
|
||||||
|
private boolean isOnlyShow;
|
||||||
|
private ImageView imageView;
|
||||||
|
private RecyclerView recyclerView;
|
||||||
|
private List<LocalMedia> pics;
|
||||||
|
private OnResultCallbackListener listener;
|
||||||
|
|
||||||
|
public Build maxSelect(int max) {
|
||||||
|
this.maxSelect = max;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Build isSingle(boolean isSingle) {
|
||||||
|
this.isSingle = isSingle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Build isOnlyShow(boolean isOnlyShow) {
|
||||||
|
this.isOnlyShow = isOnlyShow;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Build imageview(ImageView imageView) {
|
||||||
|
this.imageView = imageView;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Build recycleview(RecyclerView recyclerView) {
|
||||||
|
this.recyclerView = recyclerView;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Build newPics(List<LocalMedia> pics) {
|
||||||
|
this.pics = pics;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Build resultListener(OnResultCallbackListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectPhotoUtils6 create(Activity ctx) {
|
||||||
|
return new SelectPhotoUtils6(this, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GridImageAdapter getmAdapter() {
|
||||||
|
return mAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void selectSimple(ImageView imageView) {
|
||||||
|
imageView.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void selectMul(RecyclerView recyclerView) {
|
||||||
|
FullyGridLayoutManager manager = new FullyGridLayoutManager(ctx,
|
||||||
|
4, GridLayoutManager.VERTICAL, false);
|
||||||
|
|
||||||
|
recyclerView.addItemDecoration(new GridSpacingItemDecoration(40,
|
||||||
|
ScreenUtils.dip2px(ctx, 8), true
|
||||||
|
));
|
||||||
|
recyclerView.setLayoutManager(manager);
|
||||||
|
mAdapter = new GridImageAdapter(ctx, onAddPicClickListener);
|
||||||
|
mAdapter.setSelectMax(build.maxSelect);
|
||||||
|
mAdapter.setIsOnlyShow(build.isOnlyShow);
|
||||||
|
recyclerView.setAdapter(mAdapter);
|
||||||
|
|
||||||
|
mAdapter.setOnItemClickListener((v, position) -> {
|
||||||
|
List<LocalMedia> selectList = mAdapter.getData();
|
||||||
|
if (selectList.size() > 0) {
|
||||||
|
LocalMedia media = selectList.get(position);
|
||||||
|
String mimeType = media.getMimeType();
|
||||||
|
int mediaType = PictureMimeType.getMimeType(mimeType);
|
||||||
|
switch (mediaType) {
|
||||||
|
case PictureConfig.TYPE_VIDEO:
|
||||||
|
// 预览视频
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.themeStyle(R.style.picture_default_style)
|
||||||
|
// .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题
|
||||||
|
.externalPictureVideo(TextUtils.isEmpty(media.getAndroidQToPath()) ? media.getPath() : media.getAndroidQToPath());
|
||||||
|
break;
|
||||||
|
case PictureConfig.TYPE_AUDIO:
|
||||||
|
// 预览音频
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.externalPictureAudio(PictureMimeType.isContent(media.getPath()) ? media.getAndroidQToPath() : media.getPath());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 预览图片 可自定长按保存路径
|
||||||
|
// PictureWindowAnimationStyle animationStyle = new PictureWindowAnimationStyle();
|
||||||
|
// animationStyle.activityPreviewEnterAnimation = R.anim.picture_anim_up_in;
|
||||||
|
// animationStyle.activityPreviewExitAnimation = R.anim.picture_anim_down_out;
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.themeStyle(R.style.picture_default_style) // xml设置主题
|
||||||
|
// .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题
|
||||||
|
//.setPictureWindowAnimationStyle(animationStyle)// 自定义页面启动动画
|
||||||
|
.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)// 设置相册Activity方向,不设置默认使用系统
|
||||||
|
.isNotPreviewDownload(true)// 预览图片长按是否可以下载
|
||||||
|
//.bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义播放回调控制,用户可以使用自己的视频播放界面
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项
|
||||||
|
.openExternalPreview(position, selectList);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onAddPicClick() {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openGallery(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.selectionMode(build.isSingle ? PictureConfig.SINGLE : PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
.maxSelectNum(build.maxSelect)
|
||||||
|
.isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.isCamera(true)// 是否显示拍照按钮 true or false
|
||||||
|
.isEnableCrop(false)// 是否裁剪 true or false
|
||||||
|
.selectionData(mAdapter.getData())// 是否传入已选图片
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(false)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(false)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(new MyResultCallback(mAdapter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelPicClick(int postion, LocalMedia localMedia) {
|
||||||
|
// DataManager.getInstance().remove(localMedia.getId() + "")
|
||||||
|
// .compose(DataManager.setThread())
|
||||||
|
// .subscribe(new BaseObserver(ctx, new RxHttpCallBack(ctx) {
|
||||||
|
// @Override
|
||||||
|
// public void onSuccess(CommonResponseBean t) {
|
||||||
|
// super.onSuccess(t);
|
||||||
|
//// list.remove(index);
|
||||||
|
// mAdapter.getData().remove(postion);
|
||||||
|
// mAdapter.notifyItemRemoved(postion);
|
||||||
|
// mAdapter.notifyItemRangeChanged(postion, mAdapter.getData().size());
|
||||||
|
// }
|
||||||
|
// }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果回调
|
||||||
|
*/
|
||||||
|
private class MyResultCallback implements OnResultCallbackListener<LocalMedia> {
|
||||||
|
private WeakReference<GridImageAdapter> mAdapterWeakReference;
|
||||||
|
|
||||||
|
public MyResultCallback(GridImageAdapter adapter) {
|
||||||
|
super();
|
||||||
|
this.mAdapterWeakReference = new WeakReference<>(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(List<LocalMedia> result) {
|
||||||
|
// for (LocalMedia media : result) {
|
||||||
|
// Log.i(TAG, "是否压缩:" + media.isCompressed());
|
||||||
|
// Log.i(TAG, "压缩:" + media.getCompressPath());
|
||||||
|
// Log.i(TAG, "原图:" + media.getPath());
|
||||||
|
// Log.i(TAG, "绝对路径:" + media.getRealPath());
|
||||||
|
// Log.i(TAG, "是否裁剪:" + media.isCut());
|
||||||
|
// Log.i(TAG, "裁剪:" + media.getCutPath());
|
||||||
|
// Log.i(TAG, "是否开启原图:" + media.isOriginal());
|
||||||
|
// Log.i(TAG, "原图路径:" + media.getOriginalPath());
|
||||||
|
// Log.i(TAG, "Android Q 特有Path:" + media.getAndroidQToPath());
|
||||||
|
// Log.i(TAG, "宽高: " + media.getWidth() + "x" + media.getHeight());
|
||||||
|
// Log.i(TAG, "Size: " + media.getSize());
|
||||||
|
//
|
||||||
|
// Log.i("MMM", "onResult: " + media.toString());
|
||||||
|
// // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息,如旋转角度、经纬度等信息
|
||||||
|
// }
|
||||||
|
listener.onResult(result);
|
||||||
|
if (mAdapterWeakReference.get() != null) {
|
||||||
|
mAdapterWeakReference.get().setList(result);
|
||||||
|
mAdapterWeakReference.get().notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel() {
|
||||||
|
// Log.i(TAG, "PictureSelector Cancel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相机拍照
|
||||||
|
*/
|
||||||
|
private void doTakePhoto(Activity ctx) {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openCamera(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.isEnableCrop(false)// 是否裁剪 true or false
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(false)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
.rotateEnabled(false) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(false)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
//从本地相册中选择
|
||||||
|
private void doSelectPhoto(Activity ctx) {
|
||||||
|
PictureSelector.create(ctx)
|
||||||
|
.openGallery(PictureMimeType.ofImage())
|
||||||
|
.imageEngine(GlideEngine.createGlideEngine())
|
||||||
|
.selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
|
||||||
|
.isPreviewImage(true)// 是否可预览图片 true or fals
|
||||||
|
.isGif(false)// 是否显示gif图片 true or false
|
||||||
|
.isCamera(false)// 是否显示拍照按钮 true or false
|
||||||
|
.isEnableCrop(false)// 是否裁剪 true or false
|
||||||
|
.isCompress(true)// 是否压缩 true or false
|
||||||
|
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
|
||||||
|
.freeStyleCropEnabled(false)// 裁剪框是否可拖拽 true or false
|
||||||
|
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
|
||||||
|
.minimumCompressSize(30)// 小于100kb的图片不压缩
|
||||||
|
.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
|
||||||
|
.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
|
||||||
|
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
|
||||||
|
.scaleEnabled(false)// 裁剪是否可放大缩小图片 true or false
|
||||||
|
.forResult(listener);
|
||||||
|
// .forResult(PictureConfig.CHOOSE_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
DialogPhotoSelect dialogPhotoSelect = new DialogPhotoSelect(ctx);
|
||||||
|
dialogPhotoSelect.show();
|
||||||
|
dialogPhotoSelect.setOnSelectClickListener(new DialogPhotoSelect.onSelectClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onTakePhoto() {
|
||||||
|
doTakePhoto(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectPhoto() {
|
||||||
|
doSelectPhoto(ctx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
201
mylibrary/src/main/java/com/dahe/mylibrary/utils/ShellUtils.java
Normal file
201
mylibrary/src/main/java/com/dahe/mylibrary/utils/ShellUtils.java
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* author: Blankj
|
||||||
|
* blog : http://blankj.com
|
||||||
|
* time : 2016/08/07
|
||||||
|
* desc : utils about shell
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class ShellUtils {
|
||||||
|
|
||||||
|
private static final String LINE_SEP = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
private ShellUtils() {
|
||||||
|
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param command The command.
|
||||||
|
* @param isRooted True to use root, false otherwise.
|
||||||
|
* @return the single {@link CommandResult} instance
|
||||||
|
*/
|
||||||
|
public static CommandResult execCmd(final String command, final boolean isRooted) {
|
||||||
|
return execCmd(new String[]{command}, isRooted, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param commands The commands.
|
||||||
|
* @param isRooted True to use root, false otherwise.
|
||||||
|
* @return the single {@link CommandResult} instance
|
||||||
|
*/
|
||||||
|
public static CommandResult execCmd(final List<String> commands, final boolean isRooted) {
|
||||||
|
return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRooted, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param commands The commands.
|
||||||
|
* @param isRooted True to use root, false otherwise.
|
||||||
|
* @return the single {@link CommandResult} instance
|
||||||
|
*/
|
||||||
|
public static CommandResult execCmd(final String[] commands, final boolean isRooted) {
|
||||||
|
return execCmd(commands, isRooted, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param command The command.
|
||||||
|
* @param isRooted True to use root, false otherwise.
|
||||||
|
* @param isNeedResultMsg True to node_return the message of result, false otherwise.
|
||||||
|
* @return the single {@link CommandResult} instance
|
||||||
|
*/
|
||||||
|
public static CommandResult execCmd(final String command,
|
||||||
|
final boolean isRooted,
|
||||||
|
final boolean isNeedResultMsg) {
|
||||||
|
return execCmd(new String[]{command}, isRooted, isNeedResultMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param commands The commands.
|
||||||
|
* @param isRooted True to use root, false otherwise.
|
||||||
|
* @param isNeedResultMsg True to node_return the message of result, false otherwise.
|
||||||
|
* @return the single {@link CommandResult} instance
|
||||||
|
*/
|
||||||
|
public static CommandResult execCmd(final List<String> commands,
|
||||||
|
final boolean isRooted,
|
||||||
|
final boolean isNeedResultMsg) {
|
||||||
|
return execCmd(commands == null ? null : commands.toArray(new String[]{}),
|
||||||
|
isRooted,
|
||||||
|
isNeedResultMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param commands The commands.
|
||||||
|
* @param isRooted True to use root, false otherwise.
|
||||||
|
* @param isNeedResultMsg True to node_return the message of result, false otherwise.
|
||||||
|
* @return the single {@link CommandResult} instance
|
||||||
|
*/
|
||||||
|
public static CommandResult execCmd(final String[] commands,
|
||||||
|
final boolean isRooted,
|
||||||
|
final boolean isNeedResultMsg) {
|
||||||
|
int result = -1;
|
||||||
|
if (commands == null || commands.length == 0) {
|
||||||
|
return new CommandResult(result, "", "");
|
||||||
|
}
|
||||||
|
Process process = null;
|
||||||
|
BufferedReader successResult = null;
|
||||||
|
BufferedReader errorResult = null;
|
||||||
|
StringBuilder successMsg = null;
|
||||||
|
StringBuilder errorMsg = null;
|
||||||
|
DataOutputStream os = null;
|
||||||
|
try {
|
||||||
|
process = Runtime.getRuntime().exec(isRooted ? "su" : "sh");
|
||||||
|
os = new DataOutputStream(process.getOutputStream());
|
||||||
|
for (String command : commands) {
|
||||||
|
if (command == null) continue;
|
||||||
|
os.write(command.getBytes());
|
||||||
|
os.writeBytes(LINE_SEP);
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
os.writeBytes("exit" + LINE_SEP);
|
||||||
|
os.flush();
|
||||||
|
result = process.waitFor();
|
||||||
|
if (isNeedResultMsg) {
|
||||||
|
successMsg = new StringBuilder();
|
||||||
|
errorMsg = new StringBuilder();
|
||||||
|
successResult = new BufferedReader(
|
||||||
|
new InputStreamReader(process.getInputStream(), "UTF-8")
|
||||||
|
);
|
||||||
|
errorResult = new BufferedReader(
|
||||||
|
new InputStreamReader(process.getErrorStream(), "UTF-8")
|
||||||
|
);
|
||||||
|
String line;
|
||||||
|
if ((line = successResult.readLine()) != null) {
|
||||||
|
successMsg.append(line);
|
||||||
|
while ((line = successResult.readLine()) != null) {
|
||||||
|
successMsg.append(LINE_SEP).append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((line = errorResult.readLine()) != null) {
|
||||||
|
errorMsg.append(line);
|
||||||
|
while ((line = errorResult.readLine()) != null) {
|
||||||
|
errorMsg.append(LINE_SEP).append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (os != null) {
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (successResult != null) {
|
||||||
|
successResult.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (errorResult != null) {
|
||||||
|
errorResult.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new CommandResult(
|
||||||
|
result,
|
||||||
|
successMsg == null ? "" : successMsg.toString(),
|
||||||
|
errorMsg == null ? "" : errorMsg.toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of command.
|
||||||
|
*/
|
||||||
|
public static class CommandResult {
|
||||||
|
public int result;
|
||||||
|
public String successMsg;
|
||||||
|
public String errorMsg;
|
||||||
|
|
||||||
|
public CommandResult(final int result, final String successMsg, final String errorMsg) {
|
||||||
|
this.result = result;
|
||||||
|
this.successMsg = successMsg;
|
||||||
|
this.errorMsg = errorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "result: " + result + "\n" +
|
||||||
|
"successMsg: " + successMsg + "\n" +
|
||||||
|
"errorMsg: " + errorMsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名:SmsTimeUtils
|
||||||
|
*/
|
||||||
|
public class SmsTimeUtils {
|
||||||
|
|
||||||
|
/*倒计时时长 单位:秒*/
|
||||||
|
private final static int COUNT = 60;
|
||||||
|
/*当前做*/
|
||||||
|
private static int CURR_COUNT = 0;
|
||||||
|
/*发送验证码*/
|
||||||
|
public final static int SETTING_FINANCE_ACCOUNT_TIME = 1;
|
||||||
|
public final static int WITHDRAW_CASH = 4;
|
||||||
|
|
||||||
|
private static long SETTING_FINANCE_ACCOUNT_TIME_END = 0;
|
||||||
|
private static long WITHDRAW_CASH_END = 0;
|
||||||
|
|
||||||
|
private static Timer countdownTimer;
|
||||||
|
private static TextView tvSendCode;
|
||||||
|
private static Context mContext;
|
||||||
|
|
||||||
|
public static String currPhone;//记录获取验证码的手机号,倒计时结束后清空
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否超过60秒
|
||||||
|
* 给当前要从多少开始倒数赋值
|
||||||
|
*
|
||||||
|
* @param first true 表示第一次 false不是
|
||||||
|
* @return 是否需要调用startCountdown(TextView textView),主要用于判断在重新打开页,需不需要继续倒计时
|
||||||
|
*/
|
||||||
|
public static boolean check(int type, boolean first) {
|
||||||
|
long data = System.currentTimeMillis();
|
||||||
|
long time = 0;
|
||||||
|
switch (type) {
|
||||||
|
case SETTING_FINANCE_ACCOUNT_TIME:
|
||||||
|
time = SETTING_FINANCE_ACCOUNT_TIME_END;
|
||||||
|
break;
|
||||||
|
case WITHDRAW_CASH:
|
||||||
|
time = WITHDRAW_CASH_END;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (data > time) {
|
||||||
|
/*主要是区别于是否是第一次进入。第一次进入不需要赋值*/
|
||||||
|
if (!first) {
|
||||||
|
CURR_COUNT = COUNT;
|
||||||
|
time = data + COUNT * 1000;
|
||||||
|
switch (type) {
|
||||||
|
case SETTING_FINANCE_ACCOUNT_TIME:
|
||||||
|
SETTING_FINANCE_ACCOUNT_TIME_END = time;
|
||||||
|
break;
|
||||||
|
case WITHDRAW_CASH:
|
||||||
|
WITHDRAW_CASH_END = time;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int the_difference = ((int) (time - data)) / 1000;
|
||||||
|
CURR_COUNT = the_difference;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始倒计时
|
||||||
|
*
|
||||||
|
* @param textView 控制倒计时的view
|
||||||
|
*/
|
||||||
|
public static void startCountdown(TextView textView, Context context) {
|
||||||
|
tvSendCode = textView;
|
||||||
|
mContext = context;
|
||||||
|
if (countdownTimer == null) {
|
||||||
|
countdownTimer = new Timer();
|
||||||
|
countdownTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Message msg = new Message();
|
||||||
|
msg.what = CURR_COUNT--;
|
||||||
|
handler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
}, 0, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始倒计时
|
||||||
|
*
|
||||||
|
* @param textView 控制倒计时的view
|
||||||
|
*/
|
||||||
|
public static void startCountdown(TextView textView, Context context,String phone) {
|
||||||
|
currPhone = phone;
|
||||||
|
tvSendCode = textView;
|
||||||
|
mContext = context;
|
||||||
|
if (countdownTimer == null) {
|
||||||
|
countdownTimer = new Timer();
|
||||||
|
countdownTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Message msg = new Message();
|
||||||
|
msg.what = CURR_COUNT--;
|
||||||
|
handler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
}, 0, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Handler handler = new Handler() {
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
if (msg.what <= 0) {
|
||||||
|
if (countdownTimer != null) {
|
||||||
|
countdownTimer.cancel();
|
||||||
|
countdownTimer = null;
|
||||||
|
}
|
||||||
|
currPhone="";
|
||||||
|
tvSendCode.setText("获取验证码");
|
||||||
|
tvSendCode.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
tvSendCode.setText(msg.what + "s后重新获取");
|
||||||
|
tvSendCode.setEnabled(false);
|
||||||
|
}
|
||||||
|
super.handleMessage(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public static void stopCountdown(TextView textView, Context context){
|
||||||
|
tvSendCode = textView;
|
||||||
|
mContext = context;
|
||||||
|
if (countdownTimer != null) {
|
||||||
|
countdownTimer.cancel();
|
||||||
|
countdownTimer=null;
|
||||||
|
currPhone="";
|
||||||
|
SETTING_FINANCE_ACCOUNT_TIME_END =0;
|
||||||
|
tvSendCode.setText("获取验证码");
|
||||||
|
tvSendCode.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
mylibrary/src/main/java/com/dahe/mylibrary/utils/StatusBar.java
Normal file
111
mylibrary/src/main/java/com/dahe/mylibrary/utils/StatusBar.java
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
|
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils for status bar
|
||||||
|
* Created by qiu on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class StatusBar {
|
||||||
|
|
||||||
|
//Get alpha color
|
||||||
|
static int calculateStatusBarColor(int color, int alpha) {
|
||||||
|
float a = 1 - alpha / 255f;
|
||||||
|
int red = color >> 16 & 0xff;
|
||||||
|
int green = color >> 8 & 0xff;
|
||||||
|
int blue = color & 0xff;
|
||||||
|
red = (int) (red * a + 0.5);
|
||||||
|
green = (int) (green * a + 0.5);
|
||||||
|
blue = (int) (blue * a + 0.5);
|
||||||
|
return 0xff << 24 | red << 16 | green << 8 | blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set statusBarColor
|
||||||
|
* @param statusColor color
|
||||||
|
* @param alpha 0 - 255
|
||||||
|
*/
|
||||||
|
public static void setStatusBarColor(@NonNull Activity activity, @ColorInt int statusColor, int alpha) {
|
||||||
|
setStatusBarColor(activity, calculateStatusBarColor(statusColor, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setStatusBarColor(@NonNull Activity activity, @ColorInt int statusColor) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
StatusBarCompatLollipop.setStatusBarColor(activity, statusColor);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
StatusBarCompatKitKat.setStatusBarColor(activity, statusColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void translucentStatusBar(@NonNull Activity activity) {
|
||||||
|
translucentStatusBar(activity, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* change to full screen mode
|
||||||
|
* @param hideStatusBarBackground hide status bar alpha Background when SDK > 21, true if hide it
|
||||||
|
*/
|
||||||
|
public static void translucentStatusBar(@NonNull Activity activity, boolean hideStatusBarBackground) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
StatusBarCompatLollipop.translucentStatusBar(activity, hideStatusBarBackground);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
StatusBarCompatKitKat.translucentStatusBar(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setStatusBarColorForCollapsingToolbar(@NonNull Activity activity, AppBarLayout appBarLayout, CollapsingToolbarLayout collapsingToolbarLayout,
|
||||||
|
Toolbar toolbar, @ColorInt int statusColor) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
StatusBarCompatLollipop.setStatusBarColorForCollapsingToolbar(activity, appBarLayout, collapsingToolbarLayout, toolbar, statusColor);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
StatusBarCompatKitKat.setStatusBarColorForCollapsingToolbar(activity, appBarLayout, collapsingToolbarLayout, toolbar, statusColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeToLightStatusBar(@NonNull Activity activity) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (activity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
if (window == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
View decorView = window.getDecorView();
|
||||||
|
if (decorView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cancelLightStatusBar(@NonNull Activity activity) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (activity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
if (window == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
View decorView = window.getDecorView();
|
||||||
|
if (decorView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,221 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
|
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After kitkat add fake status bar
|
||||||
|
* Created by qiu on 8/27/16.
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
|
class StatusBarCompatKitKat {
|
||||||
|
|
||||||
|
private static final String TAG_FAKE_STATUS_BAR_VIEW = "statusBarView";
|
||||||
|
private static final String TAG_MARGIN_ADDED = "marginAdded";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* node_return statusBar's Height in pixels
|
||||||
|
*/
|
||||||
|
private static int getStatusBarHeight(Context context) {
|
||||||
|
int result = 0;
|
||||||
|
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||||
|
if (resId > 0) {
|
||||||
|
result = context.getResources().getDimensionPixelOffset(resId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add fake statusBarView.
|
||||||
|
* 2. set tag to statusBarView.
|
||||||
|
*/
|
||||||
|
private static View addFakeStatusBarView(Activity activity, int statusBarColor, int statusBarHeight) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
ViewGroup mDecorView = (ViewGroup) window.getDecorView();
|
||||||
|
|
||||||
|
View mStatusBarView = new View(activity);
|
||||||
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
|
||||||
|
layoutParams.gravity = Gravity.TOP;
|
||||||
|
mStatusBarView.setLayoutParams(layoutParams);
|
||||||
|
mStatusBarView.setBackgroundColor(statusBarColor);
|
||||||
|
mStatusBarView.setTag(TAG_FAKE_STATUS_BAR_VIEW);
|
||||||
|
|
||||||
|
mDecorView.addView(mStatusBarView);
|
||||||
|
return mStatusBarView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use reserved order to remove is more quickly.
|
||||||
|
*/
|
||||||
|
private static void removeFakeStatusBarViewIfExist(Activity activity) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
ViewGroup mDecorView = (ViewGroup) window.getDecorView();
|
||||||
|
|
||||||
|
View fakeView = mDecorView.findViewWithTag(TAG_FAKE_STATUS_BAR_VIEW);
|
||||||
|
if (fakeView != null) {
|
||||||
|
mDecorView.removeView(fakeView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add marginTop to simulate set FitsSystemWindow true
|
||||||
|
*/
|
||||||
|
private static void addMarginTopToContentChild(View mContentChild, int statusBarHeight) {
|
||||||
|
if (mContentChild == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
|
||||||
|
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
|
||||||
|
lp.topMargin += statusBarHeight;
|
||||||
|
mContentChild.setLayoutParams(lp);
|
||||||
|
mContentChild.setTag(TAG_MARGIN_ADDED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove marginTop to simulate set FitsSystemWindow false
|
||||||
|
*/
|
||||||
|
private static void removeMarginTopOfContentChild(View mContentChild, int statusBarHeight) {
|
||||||
|
if (mContentChild == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
|
||||||
|
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
|
||||||
|
lp.topMargin -= statusBarHeight;
|
||||||
|
mContentChild.setLayoutParams(lp);
|
||||||
|
mContentChild.setTag(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set StatusBarColor
|
||||||
|
*
|
||||||
|
* 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
|
||||||
|
* 2. removeFakeStatusBarViewIfExist
|
||||||
|
* 3. addFakeStatusBarView
|
||||||
|
* 4. addMarginTopToContentChild
|
||||||
|
* 5. cancel ContentChild's fitsSystemWindow
|
||||||
|
*/
|
||||||
|
static void setStatusBarColor(Activity activity, int statusColor) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
|
||||||
|
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
|
||||||
|
View mContentChild = mContentView.getChildAt(0);
|
||||||
|
int statusBarHeight = getStatusBarHeight(activity);
|
||||||
|
|
||||||
|
removeFakeStatusBarViewIfExist(activity);
|
||||||
|
addFakeStatusBarView(activity, statusColor, statusBarHeight);
|
||||||
|
addMarginTopToContentChild(mContentChild, statusBarHeight);
|
||||||
|
|
||||||
|
if (mContentChild != null) {
|
||||||
|
ViewCompat.setFitsSystemWindows(mContentChild, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translucentStatusBar
|
||||||
|
*
|
||||||
|
* 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
|
||||||
|
* 2. removeFakeStatusBarViewIfExist
|
||||||
|
* 3. removeMarginTopOfContentChild
|
||||||
|
* 4. cancel ContentChild's fitsSystemWindow
|
||||||
|
*/
|
||||||
|
static void translucentStatusBar(Activity activity) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
|
||||||
|
ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
|
||||||
|
View mContentChild = mContentView.getChildAt(0);
|
||||||
|
|
||||||
|
removeFakeStatusBarViewIfExist(activity);
|
||||||
|
removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));
|
||||||
|
if (mContentChild != null) {
|
||||||
|
ViewCompat.setFitsSystemWindows(mContentChild, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* compat for CollapsingToolbarLayout
|
||||||
|
*
|
||||||
|
* 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
|
||||||
|
* 2. set FitsSystemWindows for views.
|
||||||
|
* 3. add Toolbar's height, let it layout from top, then add paddingTop to layout normal.
|
||||||
|
* 4. removeFakeStatusBarViewIfExist
|
||||||
|
* 5. removeMarginTopOfContentChild
|
||||||
|
* 6. add OnOffsetChangedListener to change statusBarView's alpha
|
||||||
|
*/
|
||||||
|
static void setStatusBarColorForCollapsingToolbar(Activity activity, final AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout,
|
||||||
|
Toolbar toolbar, int statusColor) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
|
||||||
|
|
||||||
|
View mContentChild = mContentView.getChildAt(0);
|
||||||
|
mContentChild.setFitsSystemWindows(false);
|
||||||
|
((View) appBarLayout.getParent()).setFitsSystemWindows(false);
|
||||||
|
appBarLayout.setFitsSystemWindows(false);
|
||||||
|
collapsingToolbarLayout.setFitsSystemWindows(false);
|
||||||
|
collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);
|
||||||
|
|
||||||
|
toolbar.setFitsSystemWindows(false);
|
||||||
|
if (toolbar.getTag() == null) {
|
||||||
|
CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
|
||||||
|
int statusBarHeight = getStatusBarHeight(activity);
|
||||||
|
lp.height += statusBarHeight;
|
||||||
|
toolbar.setLayoutParams(lp);
|
||||||
|
toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
|
||||||
|
toolbar.setTag(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int statusBarHeight = getStatusBarHeight(activity);
|
||||||
|
removeFakeStatusBarViewIfExist(activity);
|
||||||
|
removeMarginTopOfContentChild(mContentChild, statusBarHeight);
|
||||||
|
final View statusView = addFakeStatusBarView(activity, statusColor, statusBarHeight);
|
||||||
|
|
||||||
|
CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
|
||||||
|
if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
|
||||||
|
int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
|
||||||
|
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
|
||||||
|
statusView.setAlpha(1f);
|
||||||
|
} else {
|
||||||
|
statusView.setAlpha(0f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
statusView.setAlpha(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
|
||||||
|
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
|
||||||
|
if (statusView.getAlpha() == 0) {
|
||||||
|
statusView.animate().cancel();
|
||||||
|
statusView.animate().alpha(1f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (statusView.getAlpha() == 1) {
|
||||||
|
statusView.animate().cancel();
|
||||||
|
statusView.animate().alpha(0f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator;
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import androidx.core.view.OnApplyWindowInsetsListener;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
|
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After Lollipop use system method.
|
||||||
|
* Created by qiu on 8/27/16.
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
class StatusBarCompatLollipop {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* node_return statusBar's Height in pixels
|
||||||
|
*/
|
||||||
|
private static int getStatusBarHeight(Context context) {
|
||||||
|
int result = 0;
|
||||||
|
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||||
|
if (resId > 0) {
|
||||||
|
result = context.getResources().getDimensionPixelOffset(resId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set StatusBarColor
|
||||||
|
*
|
||||||
|
* 1. set Flags to call setStatusBarColor
|
||||||
|
* 2. call setSystemUiVisibility to clear translucentStatusBar's Flag.
|
||||||
|
* 3. set FitsSystemWindows to false
|
||||||
|
*/
|
||||||
|
static void setStatusBarColor(Activity activity, int statusColor) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
window.setStatusBarColor(statusColor);
|
||||||
|
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||||
|
|
||||||
|
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
|
||||||
|
View mChildView = mContentView.getChildAt(0);
|
||||||
|
if (mChildView != null) {
|
||||||
|
ViewCompat.setFitsSystemWindows(mChildView, false);
|
||||||
|
ViewCompat.requestApplyInsets(mChildView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translucentStatusBar(full-screen)
|
||||||
|
*
|
||||||
|
* 1. set Flags to full-screen
|
||||||
|
* 2. set FitsSystemWindows to false
|
||||||
|
*
|
||||||
|
* @param hideStatusBarBackground hide statusBar's shadow
|
||||||
|
*/
|
||||||
|
static void translucentStatusBar(Activity activity, boolean hideStatusBarBackground) {
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
if (hideStatusBarBackground) {
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
window.setStatusBarColor(Color.TRANSPARENT);
|
||||||
|
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||||
|
} else {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
|
||||||
|
View mChildView = mContentView.getChildAt(0);
|
||||||
|
if (mChildView != null) {
|
||||||
|
ViewCompat.setFitsSystemWindows(mChildView, false);
|
||||||
|
ViewCompat.requestApplyInsets(mChildView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* compat for CollapsingToolbarLayout
|
||||||
|
*
|
||||||
|
* 1. change to full-screen mode(like translucentStatusBar).
|
||||||
|
* 2. cancel CollapsingToolbarLayout's WindowInsets, let it layout as normal(now setStatusBarScrimColor is useless).
|
||||||
|
* 3. set View's FitsSystemWindow to false.
|
||||||
|
* 4. add Toolbar's height, let it layout from top, then add paddingTop to layout normal.
|
||||||
|
* 5. change statusBarColor by AppBarLayout's offset.
|
||||||
|
* 6. add Listener to change statusBarColor
|
||||||
|
*/
|
||||||
|
static void setStatusBarColorForCollapsingToolbar(Activity activity, final AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout,
|
||||||
|
Toolbar toolbar, final int statusColor) {
|
||||||
|
final Window window = activity.getWindow();
|
||||||
|
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
window.setStatusBarColor(Color.TRANSPARENT);
|
||||||
|
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||||
|
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(collapsingToolbarLayout, new OnApplyWindowInsetsListener() {
|
||||||
|
@Override
|
||||||
|
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
|
||||||
|
return insets;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
|
||||||
|
View mChildView = mContentView.getChildAt(0);
|
||||||
|
if (mChildView != null) {
|
||||||
|
ViewCompat.setFitsSystemWindows(mChildView, false);
|
||||||
|
ViewCompat.requestApplyInsets(mChildView);
|
||||||
|
}
|
||||||
|
|
||||||
|
((View) appBarLayout.getParent()).setFitsSystemWindows(false);
|
||||||
|
appBarLayout.setFitsSystemWindows(false);
|
||||||
|
|
||||||
|
toolbar.setFitsSystemWindows(false);
|
||||||
|
if (toolbar.getTag() == null) {
|
||||||
|
CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
|
||||||
|
int statusBarHeight = getStatusBarHeight(activity);
|
||||||
|
lp.height += statusBarHeight;
|
||||||
|
toolbar.setLayoutParams(lp);
|
||||||
|
toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
|
||||||
|
toolbar.setTag(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
|
||||||
|
if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
|
||||||
|
int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
|
||||||
|
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
|
||||||
|
window.setStatusBarColor(statusColor);
|
||||||
|
} else {
|
||||||
|
window.setStatusBarColor(Color.TRANSPARENT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.setStatusBarColor(Color.TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsingToolbarLayout.setFitsSystemWindows(false);
|
||||||
|
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
|
||||||
|
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
|
||||||
|
if (window.getStatusBarColor() != statusColor) {
|
||||||
|
startColorAnimation(window.getStatusBarColor(), statusColor, collapsingToolbarLayout.getScrimAnimationDuration(), window);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (window.getStatusBarColor() != Color.TRANSPARENT) {
|
||||||
|
startColorAnimation(window.getStatusBarColor(), Color.TRANSPARENT, collapsingToolbarLayout.getScrimAnimationDuration(), window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);
|
||||||
|
collapsingToolbarLayout.setStatusBarScrimColor(statusColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use ValueAnimator to change statusBarColor when using collapsingToolbarLayout
|
||||||
|
*/
|
||||||
|
static void startColorAnimation(int startColor, int endColor, long duration, final Window window) {
|
||||||
|
if (sAnimator != null) {
|
||||||
|
sAnimator.cancel();
|
||||||
|
}
|
||||||
|
sAnimator = ValueAnimator.ofArgb(startColor, endColor)
|
||||||
|
.setDuration(duration);
|
||||||
|
sAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||||
|
if (window != null) {
|
||||||
|
window.setStatusBarColor((Integer) valueAnimator.getAnimatedValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ValueAnimator sAnimator;
|
||||||
|
}
|
||||||
@ -0,0 +1,99 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
public class StringUtils {
|
||||||
|
|
||||||
|
public static String byte2hex(byte[] b) {
|
||||||
|
|
||||||
|
String str = "";
|
||||||
|
String stmp = "";
|
||||||
|
|
||||||
|
int length = b.length;
|
||||||
|
|
||||||
|
for (int n = 0; n < length; n++) {
|
||||||
|
stmp = (Integer.toHexString(b[n] & 0XFF));
|
||||||
|
if (stmp.length() == 1) {
|
||||||
|
str += "0";
|
||||||
|
}
|
||||||
|
str += stmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String nullToStrTrim(String str) {
|
||||||
|
|
||||||
|
if (str == null) {
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNotEmpty(String str) {
|
||||||
|
|
||||||
|
return ((str != null) && (str.trim().length() > 0 && !"null".equals(str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmpty(String str) {
|
||||||
|
|
||||||
|
return !isNotEmpty(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getRealLength(String str) {
|
||||||
|
|
||||||
|
return getRealLength(str, "utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getRealLength(String str, String charsetName) {
|
||||||
|
|
||||||
|
str = nullToStrTrim(str);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return str.getBytes(charsetName).length;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static String encode(String str, String enc) {
|
||||||
|
|
||||||
|
String strEncode = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (str != null)
|
||||||
|
strEncode = URLEncoder.encode(str, enc);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return strEncode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decode(String str, String enc) {
|
||||||
|
|
||||||
|
String strDecode = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (str != null)
|
||||||
|
strDecode = URLDecoder.decode(str, enc);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return strDecode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encode(String str) {
|
||||||
|
|
||||||
|
return encode(str, "utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decode(String str) {
|
||||||
|
|
||||||
|
return decode(str, "utf-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* author: Blankj
|
||||||
|
* blog : http://blankj.com
|
||||||
|
* time : 2017/03/13
|
||||||
|
* desc : 时间相关常量
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class TimeConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 毫秒与毫秒的倍数
|
||||||
|
*/
|
||||||
|
public static final int MSEC = 1;
|
||||||
|
/**
|
||||||
|
* 秒与毫秒的倍数
|
||||||
|
*/
|
||||||
|
public static final int SEC = 1000;
|
||||||
|
/**
|
||||||
|
* 分与毫秒的倍数
|
||||||
|
*/
|
||||||
|
public static final int MIN = 60000;
|
||||||
|
/**
|
||||||
|
* 时与毫秒的倍数
|
||||||
|
*/
|
||||||
|
public static final int HOUR = 3600000;
|
||||||
|
/**
|
||||||
|
* 天与毫秒的倍数
|
||||||
|
*/
|
||||||
|
public static final int DAY = 86400000;
|
||||||
|
|
||||||
|
@IntDef({MSEC, SEC, MIN, HOUR, DAY})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Unit {
|
||||||
|
}
|
||||||
|
}
|
||||||
1703
mylibrary/src/main/java/com/dahe/mylibrary/utils/TimeUtil.java
Normal file
1703
mylibrary/src/main/java/com/dahe/mylibrary/utils/TimeUtil.java
Normal file
File diff suppressed because it is too large
Load Diff
145
mylibrary/src/main/java/com/dahe/mylibrary/utils/TimingX.java
Normal file
145
mylibrary/src/main/java/com/dahe/mylibrary/utils/TimingX.java
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.annotations.NonNull;
|
||||||
|
|
||||||
|
public class TimingX {
|
||||||
|
|
||||||
|
private volatile static TimingX sTimingX;
|
||||||
|
|
||||||
|
private static int sSecond = 0, sStatus = TimingEnum.STOP.val;
|
||||||
|
|
||||||
|
private static final Handler sHandler = new TimingXHandler();
|
||||||
|
|
||||||
|
private static final ArrayList<TextView> timingViews = new ArrayList<>(8);
|
||||||
|
|
||||||
|
private static String time = "";
|
||||||
|
|
||||||
|
private TimingX() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimingX builder(){
|
||||||
|
if(sTimingX == null){
|
||||||
|
synchronized (TimingX.class){
|
||||||
|
if(sTimingX == null){
|
||||||
|
sTimingX = new TimingX();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sTimingX;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TimingXHandler extends Handler {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(@NonNull Message msg) {
|
||||||
|
int status = msg.what;
|
||||||
|
if (status == TimingEnum.START.val) {
|
||||||
|
sSecond += 1;
|
||||||
|
time = format(sSecond);
|
||||||
|
sHandler.sendEmptyMessageDelayed(status, 1000);
|
||||||
|
} else if (status == TimingEnum.STOP.val) {
|
||||||
|
time = format(sSecond);
|
||||||
|
}
|
||||||
|
showTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showTime(){
|
||||||
|
for (TextView timingView : timingViews) {
|
||||||
|
timingView.setText(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus(){
|
||||||
|
return sStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TimingEnum {
|
||||||
|
STOP(0), // 停止计时
|
||||||
|
START(1), // 开始计时
|
||||||
|
CLEAR(-1); // 清除计时
|
||||||
|
int val;
|
||||||
|
TimingEnum(int val){
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加需要计时的 view
|
||||||
|
* @param view
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public TimingX add(TextView view){
|
||||||
|
if(!timingViews.contains(view)){
|
||||||
|
timingViews.add(view);
|
||||||
|
}
|
||||||
|
return sTimingX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除不需要计时的 view
|
||||||
|
* @param view
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public TimingX remove(TextView view){
|
||||||
|
timingViews.remove(view);
|
||||||
|
return sTimingX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始计时
|
||||||
|
*/
|
||||||
|
public void start(){
|
||||||
|
if(sStatus == TimingEnum.STOP.val){
|
||||||
|
sStatus = TimingEnum.START.val;
|
||||||
|
sHandler.sendEmptyMessageDelayed(sStatus, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止计时
|
||||||
|
*/
|
||||||
|
public void stop(){
|
||||||
|
if(sStatus == TimingEnum.START.val){
|
||||||
|
sStatus = TimingEnum.STOP.val;
|
||||||
|
sHandler.removeMessages(TimingEnum.START.val);
|
||||||
|
sHandler.sendEmptyMessage(sStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁 handler
|
||||||
|
*/
|
||||||
|
public void destroy(){
|
||||||
|
sStatus = TimingEnum.STOP.val;
|
||||||
|
sSecond = 0;
|
||||||
|
sHandler.removeMessages(TimingEnum.START.val);
|
||||||
|
timingViews.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将秒转化为分秒的形式(00:00)
|
||||||
|
* @param second
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String format(int second) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int minutes = second / 60;
|
||||||
|
int sec = second % 60;
|
||||||
|
if(minutes < 10){
|
||||||
|
sb.append(0);
|
||||||
|
}
|
||||||
|
sb.append(minutes);
|
||||||
|
sb.append(":");
|
||||||
|
if(sec < 10){
|
||||||
|
sb.append(0);
|
||||||
|
}
|
||||||
|
sb.append(sec);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.dahe.mylibrary.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2017/11/28 0028.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ToastUtils {
|
||||||
|
public static Toast mToast = null;
|
||||||
|
|
||||||
|
public static void showToast(Context mContext, String message) {
|
||||||
|
if (!TextUtils.isEmpty(message)) {
|
||||||
|
|
||||||
|
// if ( mToast != null) {
|
||||||
|
// mToast.cancel();
|
||||||
|
// }
|
||||||
|
// mToast = Toast.makeText(mContext, message, Toast.LENGTH_SHORT);
|
||||||
|
// mToast.show();
|
||||||
|
|
||||||
|
if (mToast == null) {
|
||||||
|
mToast = Toast.makeText(mContext, message, Toast.LENGTH_SHORT);
|
||||||
|
} else {
|
||||||
|
mToast.setText(message);
|
||||||
|
}
|
||||||
|
mToast.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cancelToast(){
|
||||||
|
if (mToast!=null)
|
||||||
|
mToast.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.dahe.mylibrary.wapper;
|
||||||
|
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SelectSimAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
|
||||||
|
private String selectString = "";
|
||||||
|
|
||||||
|
|
||||||
|
public SelectSimAdapter(int layoutResId, @Nullable List<String> data, String selectString) {
|
||||||
|
super(R.layout.item_select, data);
|
||||||
|
this.selectString = selectString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void convert(BaseViewHolder helper, String item) {
|
||||||
|
helper.setText(R.id.tv_content,item);
|
||||||
|
TextView tv = helper.getView(R.id.tv_content);
|
||||||
|
if (item.equals(selectString)){
|
||||||
|
tv.setSelected(true);
|
||||||
|
}else{
|
||||||
|
tv.setSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelect(String selectString){
|
||||||
|
this.selectString = selectString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,157 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.BounceInterpolator;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
/**
|
||||||
|
* 自定义View实现拖动并自动吸边效果
|
||||||
|
* <p>
|
||||||
|
* 处理滑动和贴边 {@link #onTouchEvent(MotionEvent)}
|
||||||
|
* 处理事件分发 {@link #dispatchTouchEvent(MotionEvent)}
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @attr customIsAttach //是否需要自动吸边
|
||||||
|
* @attr customIsDrag //是否可拖曳
|
||||||
|
*/
|
||||||
|
public class AttachButton extends View {
|
||||||
|
private float mLastRawX;
|
||||||
|
private float mLastRawY;
|
||||||
|
private final String TAG = "AttachButton";
|
||||||
|
private boolean isDrug = false;
|
||||||
|
private int mRootMeasuredWidth = 0;
|
||||||
|
private int mRootMeasuredHeight = 0;
|
||||||
|
private int mRootTopY = 0;
|
||||||
|
private boolean customIsAttach;
|
||||||
|
private boolean customIsDrag;
|
||||||
|
|
||||||
|
public AttachButton(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttachButton(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttachButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
initAttrs(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化自定义属性
|
||||||
|
*/
|
||||||
|
private void initAttrs(Context context, AttributeSet attrs) {
|
||||||
|
TypedArray mTypedAttay = context.obtainStyledAttributes(attrs, R.styleable.AttachButton);
|
||||||
|
customIsAttach = mTypedAttay.getBoolean(R.styleable.AttachButton_customIsAttach, true);
|
||||||
|
customIsDrag = mTypedAttay.getBoolean(R.styleable.AttachButton_customIsDrag, true);
|
||||||
|
mTypedAttay.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||||
|
super.dispatchTouchEvent(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent ev) {
|
||||||
|
//判断是否需要滑动
|
||||||
|
if (customIsDrag) {
|
||||||
|
//当前手指的坐标
|
||||||
|
float mRawX = ev.getRawX();
|
||||||
|
float mRawY = ev.getRawY();
|
||||||
|
switch (ev.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN://手指按下
|
||||||
|
isDrug = false;
|
||||||
|
//记录按下的位置
|
||||||
|
mLastRawX = mRawX;
|
||||||
|
mLastRawY = mRawY;
|
||||||
|
ViewGroup mViewGroup = (ViewGroup) getParent();
|
||||||
|
if (mViewGroup != null) {
|
||||||
|
int[] location = new int[2];
|
||||||
|
mViewGroup.getLocationInWindow(location);
|
||||||
|
//获取父布局的高度
|
||||||
|
mRootMeasuredHeight = mViewGroup.getMeasuredHeight();
|
||||||
|
mRootMeasuredWidth = mViewGroup.getMeasuredWidth();
|
||||||
|
//获取父布局顶点的坐标
|
||||||
|
mRootTopY = location[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE://手指滑动
|
||||||
|
if (mRawX >= 0 && mRawX <= mRootMeasuredWidth && mRawY >= mRootTopY && mRawY <= (mRootMeasuredHeight + mRootTopY)) {
|
||||||
|
//手指X轴滑动距离
|
||||||
|
float differenceValueX = mRawX - mLastRawX;
|
||||||
|
//手指Y轴滑动距离
|
||||||
|
float differenceValueY = mRawY - mLastRawY;
|
||||||
|
//判断是否为拖动操作
|
||||||
|
if (!isDrug) {
|
||||||
|
if (Math.sqrt(differenceValueX * differenceValueX + differenceValueY * differenceValueY) < 2) {
|
||||||
|
isDrug = false;
|
||||||
|
} else {
|
||||||
|
isDrug = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//获取手指按下的距离与控件本身X轴的距离
|
||||||
|
float ownX = getX();
|
||||||
|
//获取手指按下的距离与控件本身Y轴的距离
|
||||||
|
float ownY = getY();
|
||||||
|
//理论中X轴拖动的距离
|
||||||
|
float endX = ownX + differenceValueX;
|
||||||
|
//理论中Y轴拖动的距离
|
||||||
|
float endY = ownY + differenceValueY;
|
||||||
|
//X轴可以拖动的最大距离
|
||||||
|
float maxX = mRootMeasuredWidth - getWidth();
|
||||||
|
//Y轴可以拖动的最大距离
|
||||||
|
float maxY = mRootMeasuredHeight - getHeight();
|
||||||
|
//X轴边界限制
|
||||||
|
endX = endX < 0 ? 0 : endX > maxX ? maxX : endX;
|
||||||
|
//Y轴边界限制
|
||||||
|
endY = endY < 0 ? 0 : endY > maxY ? maxY : endY;
|
||||||
|
//开始移动
|
||||||
|
setX(endX);
|
||||||
|
setY(endY);
|
||||||
|
//记录位置
|
||||||
|
mLastRawX = mRawX;
|
||||||
|
mLastRawY = mRawY;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP://手指离开
|
||||||
|
//根据自定义属性判断是否需要贴边
|
||||||
|
if (customIsAttach) {
|
||||||
|
//判断是否为点击事件
|
||||||
|
if (isDrug) {
|
||||||
|
float center = mRootMeasuredWidth / 2;
|
||||||
|
//自动贴边
|
||||||
|
if (mLastRawX <= center) {
|
||||||
|
//向左贴边
|
||||||
|
AttachButton.this.animate()
|
||||||
|
.setInterpolator(new BounceInterpolator())
|
||||||
|
.setDuration(500)
|
||||||
|
.x(0)
|
||||||
|
.start();
|
||||||
|
} else {
|
||||||
|
//向右贴边
|
||||||
|
AttachButton.this.animate()
|
||||||
|
.setInterpolator(new BounceInterpolator())
|
||||||
|
.setDuration(500)
|
||||||
|
.x(mRootMeasuredWidth - getWidth())
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//是否拦截事件
|
||||||
|
return isDrug ? isDrug : super.onTouchEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* author:luck
|
||||||
|
* project:PictureSelector
|
||||||
|
* package:com.luck.picture.ui
|
||||||
|
* email:893855882@qq.com
|
||||||
|
* data:16/12/31
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FullyGridLayoutManager extends GridLayoutManager {
|
||||||
|
public FullyGridLayoutManager(Context context, int spanCount) {
|
||||||
|
super(context, spanCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
|
||||||
|
super(context, spanCount, orientation, reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] mMeasuredDimension = new int[2];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
|
||||||
|
final int widthMode = View.MeasureSpec.getMode(widthSpec);
|
||||||
|
final int heightMode = View.MeasureSpec.getMode(heightSpec);
|
||||||
|
final int widthSize = View.MeasureSpec.getSize(widthSpec);
|
||||||
|
final int heightSize = View.MeasureSpec.getSize(heightSpec);
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
int count = getItemCount();
|
||||||
|
int span = getSpanCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
measureScrapChild(recycler, i,
|
||||||
|
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||||
|
mMeasuredDimension);
|
||||||
|
|
||||||
|
if (getOrientation() == HORIZONTAL) {
|
||||||
|
if (i % span == 0) {
|
||||||
|
width = width + mMeasuredDimension[0];
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
height = mMeasuredDimension[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i % span == 0) {
|
||||||
|
height = height + mMeasuredDimension[1];
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
width = mMeasuredDimension[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (widthMode) {
|
||||||
|
case View.MeasureSpec.EXACTLY:
|
||||||
|
width = widthSize;
|
||||||
|
case View.MeasureSpec.AT_MOST:
|
||||||
|
case View.MeasureSpec.UNSPECIFIED:
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (heightMode) {
|
||||||
|
case View.MeasureSpec.EXACTLY:
|
||||||
|
height = heightSize;
|
||||||
|
case View.MeasureSpec.AT_MOST:
|
||||||
|
case View.MeasureSpec.UNSPECIFIED:
|
||||||
|
}
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
final RecyclerView.State mState = new RecyclerView.State();
|
||||||
|
|
||||||
|
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
|
||||||
|
int heightSpec, int[] measuredDimension) {
|
||||||
|
int itemCount = mState.getItemCount();
|
||||||
|
if (position < itemCount) {
|
||||||
|
try {
|
||||||
|
View view = recycler.getViewForPosition(0);
|
||||||
|
if (view != null) {
|
||||||
|
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||||
|
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
|
||||||
|
getPaddingLeft() + getPaddingRight(), p.width);
|
||||||
|
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
|
||||||
|
getPaddingTop() + getPaddingBottom(), p.height);
|
||||||
|
view.measure(childWidthSpec, childHeightSpec);
|
||||||
|
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
|
||||||
|
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
|
||||||
|
recycler.recycleView(view);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapShader;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
|
||||||
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆形头像带白色边框
|
||||||
|
*/
|
||||||
|
public class GlideCircleWithBorder extends BitmapTransformation {
|
||||||
|
private Paint mBorderPaint;
|
||||||
|
private float mBorderWidth;
|
||||||
|
|
||||||
|
public GlideCircleWithBorder(Context context, int borderWidth, int borderColor) {
|
||||||
|
mBorderWidth = Resources.getSystem().getDisplayMetrics().density * borderWidth;
|
||||||
|
mBorderPaint = new Paint();
|
||||||
|
mBorderPaint.setDither(true);
|
||||||
|
mBorderPaint.setAntiAlias(true);
|
||||||
|
mBorderPaint.setColor(borderColor);
|
||||||
|
mBorderPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
mBorderPaint.setStrokeWidth(mBorderWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
|
||||||
|
return circleCrop(pool, toTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap circleCrop(BitmapPool pool, Bitmap source) {
|
||||||
|
if (source == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int size = (int) (Math.min(source.getWidth(), source.getHeight()) - (mBorderWidth / 2));
|
||||||
|
int x = (source.getWidth() - size) / 2;
|
||||||
|
int y = (source.getHeight() - size) / 2;
|
||||||
|
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
|
||||||
|
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
|
||||||
|
if (result == null) {
|
||||||
|
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
|
}
|
||||||
|
//创建画笔 画布 手动描绘边框
|
||||||
|
Canvas canvas = new Canvas(result);
|
||||||
|
Paint paint = new Paint();
|
||||||
|
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
float r = size / 2f;
|
||||||
|
canvas.drawCircle(r, r, r, paint);
|
||||||
|
if (mBorderPaint != null) {
|
||||||
|
float borderRadius = r - mBorderWidth / 2;
|
||||||
|
canvas.drawCircle(r, r, borderRadius, mBorderPaint);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDiskCacheKey(MessageDigest messageDigest) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,233 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
import com.bumptech.glide.request.target.BitmapImageViewTarget;
|
||||||
|
import com.bumptech.glide.request.target.ImageViewTarget;
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.luck.picture.lib.engine.ImageEngine;
|
||||||
|
import com.luck.picture.lib.listener.OnImageCompleteCallback;
|
||||||
|
import com.luck.picture.lib.tools.MediaUtils;
|
||||||
|
import com.luck.picture.lib.widget.longimage.ImageSource;
|
||||||
|
import com.luck.picture.lib.widget.longimage.ImageViewState;
|
||||||
|
import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author:luck
|
||||||
|
* @date:2019-11-13 17:02
|
||||||
|
* @describe:Glide加载引擎
|
||||||
|
*/
|
||||||
|
public class GlideEngine implements ImageEngine {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
|
||||||
|
Glide.with(context)
|
||||||
|
.load(url)
|
||||||
|
.into(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载网络图片适配长图方案
|
||||||
|
* # 注意:此方法只有加载网络图片才会回调
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
* @param longImageView
|
||||||
|
* @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadImage(@NonNull Context context, @NonNull String url,
|
||||||
|
@NonNull final ImageView imageView,
|
||||||
|
final SubsamplingScaleImageView longImageView, final OnImageCompleteCallback callback) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.into(new ImageViewTarget<Bitmap>(imageView) {
|
||||||
|
@Override
|
||||||
|
public void onLoadStarted(@Nullable Drawable placeholder) {
|
||||||
|
super.onLoadStarted(placeholder);
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onShowLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||||
|
super.onLoadFailed(errorDrawable);
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onHideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setResource(@Nullable Bitmap resource) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onHideLoading();
|
||||||
|
}
|
||||||
|
if (resource != null) {
|
||||||
|
boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
|
||||||
|
resource.getHeight());
|
||||||
|
longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
|
||||||
|
imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
|
||||||
|
if (eqLongImage) {
|
||||||
|
// 加载长图
|
||||||
|
longImageView.setQuickScaleEnabled(true);
|
||||||
|
longImageView.setZoomEnabled(true);
|
||||||
|
longImageView.setDoubleTapZoomDuration(100);
|
||||||
|
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
|
||||||
|
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
|
||||||
|
longImageView.setImage(ImageSource.bitmap(resource),
|
||||||
|
new ImageViewState(0, new PointF(0, 0), 0));
|
||||||
|
} else {
|
||||||
|
// 普通图片
|
||||||
|
imageView.setImageBitmap(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载网络图片适配长图方案
|
||||||
|
* # 注意:此方法只有加载网络图片才会回调
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
* @param longImageView
|
||||||
|
* @ 已废弃
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadImage(@NonNull Context context, @NonNull String url,
|
||||||
|
@NonNull final ImageView imageView,
|
||||||
|
final SubsamplingScaleImageView longImageView) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.into(new ImageViewTarget<Bitmap>(imageView) {
|
||||||
|
@Override
|
||||||
|
protected void setResource(@Nullable Bitmap resource) {
|
||||||
|
if (resource != null) {
|
||||||
|
boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
|
||||||
|
resource.getHeight());
|
||||||
|
longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
|
||||||
|
imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
|
||||||
|
if (eqLongImage) {
|
||||||
|
// 加载长图
|
||||||
|
longImageView.setQuickScaleEnabled(true);
|
||||||
|
longImageView.setZoomEnabled(true);
|
||||||
|
longImageView.setDoubleTapZoomDuration(100);
|
||||||
|
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
|
||||||
|
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
|
||||||
|
longImageView.setImage(ImageSource.bitmap(resource),
|
||||||
|
new ImageViewState(0, new PointF(0, 0), 0));
|
||||||
|
} else {
|
||||||
|
// 普通图片
|
||||||
|
imageView.setImageBitmap(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载相册目录
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片路径
|
||||||
|
* @param imageView 承载图片ImageView
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadFolderImage(@NonNull final Context context, @NonNull String url, @NonNull final ImageView imageView) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.override(180, 180)
|
||||||
|
.centerCrop()
|
||||||
|
.sizeMultiplier(0.5f)
|
||||||
|
.apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
|
||||||
|
.into(new BitmapImageViewTarget(imageView) {
|
||||||
|
@Override
|
||||||
|
protected void setResource(Bitmap resource) {
|
||||||
|
RoundedBitmapDrawable circularBitmapDrawable =
|
||||||
|
RoundedBitmapDrawableFactory.
|
||||||
|
create(context.getResources(), resource);
|
||||||
|
circularBitmapDrawable.setCornerRadius(8);
|
||||||
|
imageView.setImageDrawable(circularBitmapDrawable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载gif
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片路径
|
||||||
|
* @param imageView 承载图片ImageView
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadAsGifImage(@NonNull Context context, @NonNull String url,
|
||||||
|
@NonNull ImageView imageView) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asGif()
|
||||||
|
.load(url)
|
||||||
|
.into(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载图片列表图片
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片路径
|
||||||
|
* @param imageView 承载图片ImageView
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
|
||||||
|
Glide.with(context)
|
||||||
|
.load(url)
|
||||||
|
.override(200, 200)
|
||||||
|
.centerCrop()
|
||||||
|
.apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
|
||||||
|
.into(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private GlideEngine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GlideEngine instance;
|
||||||
|
|
||||||
|
public static GlideEngine createGlideEngine() {
|
||||||
|
if (null == instance) {
|
||||||
|
synchronized (GlideEngine.class) {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new GlideEngine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,231 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.chad.library.adapter.base.BaseSectionQuickAdapter;
|
||||||
|
import com.chad.library.adapter.base.entity.SectionEntity;
|
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用于RecyclerView的GridLayoutManager,水平方向上固定间距大小,从而使条目宽度自适应。<br>
|
||||||
|
* 配合Brvah的Section使用,不对Head生效,仅对每个Head的子Grid列表生效<br>
|
||||||
|
* Section Grid中Item的宽度应设为MATCH_PARAENT
|
||||||
|
*
|
||||||
|
* @author : renpeng
|
||||||
|
* @since : 2018/9/29
|
||||||
|
*/
|
||||||
|
public class GridSectionAverageGapItemDecoration extends RecyclerView.ItemDecoration {
|
||||||
|
|
||||||
|
private class Section {
|
||||||
|
public int startPos = 0;
|
||||||
|
public int endPos = 0;
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return endPos - startPos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(int pos) {
|
||||||
|
return pos >= startPos && pos <= endPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Section{" +
|
||||||
|
"startPos=" + startPos +
|
||||||
|
", endPos=" + endPos +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float gapHorizontalDp;
|
||||||
|
private float gapVerticalDp;
|
||||||
|
private float sectionEdgeHPaddingDp;
|
||||||
|
private float sectionEdgeVPaddingDp;
|
||||||
|
private int gapHSizePx = -1;
|
||||||
|
private int gapVSizePx = -1;
|
||||||
|
private int sectionEdgeHPaddingPx;
|
||||||
|
private int eachItemHPaddingPx; //每个条目应该在水平方向上加的padding 总大小,即=paddingLeft+paddingRight
|
||||||
|
private int sectionEdgeVPaddingPx;
|
||||||
|
private List<Section> mSectionList = new ArrayList<>();
|
||||||
|
private BaseSectionQuickAdapter mAdapter;
|
||||||
|
private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
|
||||||
|
@Override
|
||||||
|
public void onChanged() {
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemRangeChanged(int positionStart, int itemCount) {
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemRangeInserted(int positionStart, int itemCount) {
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemRangeRemoved(int positionStart, int itemCount) {
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param gapHorizontalDp item之间的水平间距
|
||||||
|
* @param gapVerticalDp item之间的垂直间距
|
||||||
|
* @param sectionEdgeHPaddingDp section左右两端的padding大小
|
||||||
|
* @param sectionEdgeVPaddingDp section上下两端的padding大小
|
||||||
|
*/
|
||||||
|
public GridSectionAverageGapItemDecoration(float gapHorizontalDp, float gapVerticalDp, float sectionEdgeHPaddingDp, float sectionEdgeVPaddingDp) {
|
||||||
|
this.gapHorizontalDp = gapHorizontalDp;
|
||||||
|
this.gapVerticalDp = gapVerticalDp;
|
||||||
|
this.sectionEdgeHPaddingDp = sectionEdgeHPaddingDp;
|
||||||
|
this.sectionEdgeVPaddingDp = sectionEdgeVPaddingDp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
if (parent.getLayoutManager() instanceof GridLayoutManager && parent.getAdapter() instanceof BaseSectionQuickAdapter) {
|
||||||
|
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
|
||||||
|
BaseSectionQuickAdapter<SectionEntity, BaseViewHolder> adapter = (BaseSectionQuickAdapter) parent.getAdapter();
|
||||||
|
if (mAdapter != adapter) {
|
||||||
|
setUpWithAdapter(adapter);
|
||||||
|
}
|
||||||
|
int spanCount = layoutManager.getSpanCount();
|
||||||
|
int position = parent.getChildAdapterPosition(view) - mAdapter.getHeaderLayoutCount();
|
||||||
|
SectionEntity entity = adapter.getItem(position);
|
||||||
|
|
||||||
|
if (entity == null || entity.isHeader()) {
|
||||||
|
//不处理header
|
||||||
|
outRect.set(0, 0, 0, 0);
|
||||||
|
// Log.w("GridAverageGapItem", "pos=" + position + "," + outRect.toShortString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Section section = findSectionLastItemPos(position);
|
||||||
|
|
||||||
|
if (gapHSizePx < 0 || gapVSizePx < 0) {
|
||||||
|
transformGapDefinition(parent, spanCount);
|
||||||
|
}
|
||||||
|
outRect.top = gapVSizePx;
|
||||||
|
outRect.bottom = 0;
|
||||||
|
|
||||||
|
//下面的visualPos为单个Section内的视觉Pos
|
||||||
|
int visualPos = position + 1 - section.startPos;
|
||||||
|
if (visualPos % spanCount == 1) {
|
||||||
|
//第一列
|
||||||
|
outRect.left = sectionEdgeHPaddingPx;
|
||||||
|
outRect.right = eachItemHPaddingPx - sectionEdgeHPaddingPx;
|
||||||
|
} else if (visualPos % spanCount == 0) {
|
||||||
|
//最后一列
|
||||||
|
outRect.left = eachItemHPaddingPx - sectionEdgeHPaddingPx;
|
||||||
|
outRect.right = sectionEdgeHPaddingPx;
|
||||||
|
} else {
|
||||||
|
outRect.left = gapHSizePx - (eachItemHPaddingPx - sectionEdgeHPaddingPx);
|
||||||
|
outRect.right = eachItemHPaddingPx - outRect.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visualPos - spanCount <= 0) {
|
||||||
|
//第一行
|
||||||
|
outRect.top = sectionEdgeVPaddingPx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLastRow(visualPos, spanCount, section.getCount())) {
|
||||||
|
//最后一行
|
||||||
|
outRect.bottom = sectionEdgeVPaddingPx;
|
||||||
|
// Log.w("GridAverageGapItem", "last row pos=" + position);
|
||||||
|
}
|
||||||
|
// Log.w("GridAverageGapItem", "pos=" + position + ",vPos=" + visualPos + "," + outRect.toShortString());
|
||||||
|
} else {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpWithAdapter(BaseSectionQuickAdapter<SectionEntity, BaseViewHolder> adapter) {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
mAdapter.unregisterAdapterDataObserver(mDataObserver);
|
||||||
|
}
|
||||||
|
mAdapter = adapter;
|
||||||
|
mAdapter.registerAdapterDataObserver(mDataObserver);
|
||||||
|
markSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markSections() {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
BaseSectionQuickAdapter<SectionEntity, BaseViewHolder> adapter = mAdapter;
|
||||||
|
mSectionList.clear();
|
||||||
|
SectionEntity sectionEntity = null;
|
||||||
|
Section section = new Section();
|
||||||
|
for (int i = 0, size = adapter.getItemCount(); i < size; i++) {
|
||||||
|
sectionEntity = adapter.getItem(i);
|
||||||
|
if (sectionEntity != null && sectionEntity.isHeader()) {
|
||||||
|
//找到新Section起点
|
||||||
|
if (section != null && i != 0) {
|
||||||
|
//已经有待添加的section
|
||||||
|
section.endPos = i - 1;
|
||||||
|
mSectionList.add(section);
|
||||||
|
}
|
||||||
|
section = new Section();
|
||||||
|
section.startPos = i + 1;
|
||||||
|
} else {
|
||||||
|
section.endPos = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//处理末尾情况
|
||||||
|
if (!mSectionList.contains(section)) {
|
||||||
|
mSectionList.add(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.w("GridAverageGapItem", "section list=" + mSectionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transformGapDefinition(RecyclerView parent, int spanCount) {
|
||||||
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
|
parent.getDisplay().getMetrics(displayMetrics);
|
||||||
|
}
|
||||||
|
gapHSizePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gapHorizontalDp, displayMetrics);
|
||||||
|
gapVSizePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gapVerticalDp, displayMetrics);
|
||||||
|
sectionEdgeHPaddingPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sectionEdgeHPaddingDp, displayMetrics);
|
||||||
|
sectionEdgeVPaddingPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sectionEdgeVPaddingDp, displayMetrics);
|
||||||
|
eachItemHPaddingPx = (sectionEdgeHPaddingPx * 2 + gapHSizePx * (spanCount - 1)) / spanCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Section findSectionLastItemPos(int curPos) {
|
||||||
|
for (Section section : mSectionList) {
|
||||||
|
if (section.contains(curPos)) {
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLastRow(int visualPos, int spanCount, int sectionItemCount) {
|
||||||
|
int lastRowCount = sectionItemCount % spanCount;
|
||||||
|
lastRowCount = lastRowCount == 0 ? spanCount : lastRowCount;
|
||||||
|
return visualPos > sectionItemCount - lastRowCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.animation.OvershootInterpolator;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.utils.BaseUtils;
|
||||||
|
|
||||||
|
public class MovedImageButton extends androidx.appcompat.widget.AppCompatImageButton {
|
||||||
|
private int lastX;
|
||||||
|
private int lastY;
|
||||||
|
private float screenWidth;
|
||||||
|
|
||||||
|
public MovedImageButton(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovedImageButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovedImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||||
|
screenWidth = dm.widthPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
int x = (int) event.getX();
|
||||||
|
int y = (int) event.getY();
|
||||||
|
switch (event.getAction()){
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
int offsetX = x-lastX;
|
||||||
|
int offsetY = y-lastY;
|
||||||
|
//第一种方法
|
||||||
|
// layout(getLeft()+offsetX,
|
||||||
|
// getTop()+offsetY,
|
||||||
|
// getRight()+offsetX,
|
||||||
|
// getBottom()+offsetY);
|
||||||
|
//第二种方法
|
||||||
|
offsetLeftAndRight(offsetX);
|
||||||
|
offsetTopAndBottom(offsetY);
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
adsorbAnim(event.getRawX(), event.getRawY());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adsorbAnim(float rawX, float rawY){
|
||||||
|
//靠顶吸附
|
||||||
|
// if (rawY <= BaseUtils.dip2px(getContext(),200)){//注意rawY包含了标题栏的高
|
||||||
|
// animate().setDuration(400)
|
||||||
|
// .setInterpolator(new OvershootInterpolator())
|
||||||
|
// .yBy(-getY()-getHeight()/2.0f)
|
||||||
|
// .start();
|
||||||
|
// }else
|
||||||
|
|
||||||
|
if (rawX >= screenWidth/2){//靠右吸附
|
||||||
|
animate().setDuration(400)
|
||||||
|
.setInterpolator(new OvershootInterpolator())
|
||||||
|
.xBy(screenWidth - getX() - getWidth())
|
||||||
|
.start();
|
||||||
|
}else {//靠左吸附
|
||||||
|
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "x", getX(), 0);
|
||||||
|
animator.setInterpolator(new OvershootInterpolator());
|
||||||
|
animator.setDuration(400);
|
||||||
|
animator.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,191 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
import com.dahe.mylibrary.utils.ToastUtils;
|
||||||
|
|
||||||
|
public class MySlideBar extends RelativeLayout implements View.OnClickListener {
|
||||||
|
|
||||||
|
private boolean canSelect;
|
||||||
|
private TextView tvT1;
|
||||||
|
private TextView tvT2;
|
||||||
|
private TextView tvT3;
|
||||||
|
private TextView tvT4;
|
||||||
|
private TextView tvC1;
|
||||||
|
private TextView tvC2;
|
||||||
|
private TextView tvC3;
|
||||||
|
private TextView tvC4;
|
||||||
|
private View view1;
|
||||||
|
private View view2;
|
||||||
|
|
||||||
|
public MySlideBar(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySlideBar(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySlideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||||
|
this(context, attrs, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySlideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
init(context, attrs);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context, AttributeSet attrs) {
|
||||||
|
View inflate = View.inflate(context, R.layout.view_slide_bar, this);
|
||||||
|
tvT1 = (TextView) findViewById(R.id.tv_title1);
|
||||||
|
tvT2 = (TextView) findViewById(R.id.tv_title2);
|
||||||
|
tvT3 = (TextView) findViewById(R.id.tv_title3);
|
||||||
|
tvT4 = (TextView) findViewById(R.id.tv_title4);
|
||||||
|
tvC1 = (TextView) findViewById(R.id.tv_conten1);
|
||||||
|
tvC2 = (TextView) findViewById(R.id.tv_content2);
|
||||||
|
tvC3 = (TextView) findViewById(R.id.tv_content3);
|
||||||
|
tvC4 = (TextView) findViewById(R.id.tv_content4);
|
||||||
|
view1 = (View) findViewById(R.id.view1);
|
||||||
|
view2 = (View) findViewById(R.id.view2);
|
||||||
|
LinearLayout ll1 = (LinearLayout) findViewById(R.id.ll1);
|
||||||
|
LinearLayout ll2 = (LinearLayout) findViewById(R.id.ll2);
|
||||||
|
LinearLayout ll3 = (LinearLayout) findViewById(R.id.ll3);
|
||||||
|
LinearLayout ll4 = (LinearLayout) findViewById(R.id.ll4);
|
||||||
|
ll1.setOnClickListener(this);
|
||||||
|
ll2.setOnClickListener(this);
|
||||||
|
ll3.setOnClickListener(this);
|
||||||
|
ll4.setOnClickListener(this);
|
||||||
|
|
||||||
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MySlideBar);
|
||||||
|
int integer = a.getInteger(R.styleable.MySlideBar_proress, -1);
|
||||||
|
canSelect = a.getBoolean(R.styleable.MySlideBar_canSelect, false);
|
||||||
|
changeProress(integer,true);
|
||||||
|
|
||||||
|
a.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (canSelect) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.ll1) {
|
||||||
|
changeProress(0,canSelect);
|
||||||
|
} else if (id == R.id.ll2) {
|
||||||
|
changeProress(1,canSelect);
|
||||||
|
} else if (id == R.id.ll3) {
|
||||||
|
changeProress(2,canSelect);
|
||||||
|
} else if (id == R.id.ll4) {
|
||||||
|
changeProress(3,canSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProress(int proress){
|
||||||
|
changeProress(proress,canSelect);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeProress(int integer,boolean canSelect){
|
||||||
|
if (listener!=null&&canSelect){
|
||||||
|
listener.onChange(integer);
|
||||||
|
}
|
||||||
|
if (0 == integer) {
|
||||||
|
tvT1.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT2.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT3.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT4.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT1.setText("1");
|
||||||
|
tvT2.setText("2");
|
||||||
|
tvT3.setText("3");
|
||||||
|
tvT4.setText("4");
|
||||||
|
tvT1.setSelected(true);
|
||||||
|
tvT2.setSelected(false);
|
||||||
|
tvT3.setSelected(false);
|
||||||
|
tvT4.setSelected(false);
|
||||||
|
|
||||||
|
view1.setBackgroundResource(R.color.color_d5);
|
||||||
|
view2.setBackgroundResource(R.color.color_d5);
|
||||||
|
|
||||||
|
tvC1.setTextColor(getResources().getColor(R.color.mine_top_bg));
|
||||||
|
tvC2.setTextColor(getResources().getColor(R.color.color_9));
|
||||||
|
tvC3.setTextColor(getResources().getColor(R.color.color_9));
|
||||||
|
tvC4.setTextColor(getResources().getColor(R.color.color_9));
|
||||||
|
} else if (1 == integer) {
|
||||||
|
tvT1.setBackgroundResource(R.drawable.ok);
|
||||||
|
tvT2.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT3.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT4.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT1.setText("");
|
||||||
|
tvT2.setText("2");
|
||||||
|
tvT3.setText("3");
|
||||||
|
tvT4.setText("4");
|
||||||
|
tvT2.setSelected(true);
|
||||||
|
tvT3.setSelected(false);
|
||||||
|
tvT4.setSelected(false);
|
||||||
|
|
||||||
|
view1.setBackgroundResource(R.color.mine_top_bg);
|
||||||
|
view2.setBackgroundResource(R.color.color_d5);
|
||||||
|
|
||||||
|
tvC1.setTextColor(getResources().getColor(R.color.black));
|
||||||
|
tvC2.setTextColor(getResources().getColor(R.color.mine_top_bg));
|
||||||
|
tvC3.setTextColor(getResources().getColor(R.color.color_9));
|
||||||
|
tvC4.setTextColor(getResources().getColor(R.color.color_9));
|
||||||
|
} else if (2 == integer) {
|
||||||
|
tvT1.setBackgroundResource(R.drawable.ok);
|
||||||
|
tvT2.setBackgroundResource(R.drawable.ok);
|
||||||
|
tvT3.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT4.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT1.setText("");
|
||||||
|
tvT2.setText("");
|
||||||
|
tvT3.setText("3");
|
||||||
|
tvT4.setText("4");
|
||||||
|
tvT3.setSelected(true);
|
||||||
|
tvT4.setSelected(false);
|
||||||
|
|
||||||
|
view1.setBackgroundResource(R.color.mine_top_bg);
|
||||||
|
view2.setBackgroundResource(R.color.mine_top_bg);
|
||||||
|
|
||||||
|
tvC1.setTextColor(getResources().getColor(R.color.black));
|
||||||
|
tvC2.setTextColor(getResources().getColor(R.color.black));
|
||||||
|
tvC3.setTextColor(getResources().getColor(R.color.mine_top_bg));
|
||||||
|
tvC4.setTextColor(getResources().getColor(R.color.color_9));
|
||||||
|
} else if (3 == integer) {
|
||||||
|
tvT1.setBackgroundResource(R.drawable.ok);
|
||||||
|
tvT2.setBackgroundResource(R.drawable.ok);
|
||||||
|
tvT3.setBackgroundResource(R.drawable.ok);
|
||||||
|
tvT4.setBackgroundResource(R.drawable.select_slide_title);
|
||||||
|
tvT1.setText("");
|
||||||
|
tvT2.setText("");
|
||||||
|
tvT3.setText("");
|
||||||
|
tvT4.setText("4");
|
||||||
|
tvT4.setSelected(true);
|
||||||
|
|
||||||
|
tvC1.setTextColor(getResources().getColor(R.color.black));
|
||||||
|
tvC2.setTextColor(getResources().getColor(R.color.black));
|
||||||
|
tvC3.setTextColor(getResources().getColor(R.color.black));
|
||||||
|
tvC4.setTextColor(getResources().getColor(R.color.mine_top_bg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface OnChangeListener{
|
||||||
|
void onChange(int progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnChangeListener listener;
|
||||||
|
public void setOnChangeListener(OnChangeListener listener){
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
130
mylibrary/src/main/java/com/dahe/mylibrary/weight/SideBar.java
Normal file
130
mylibrary/src/main/java/com/dahe/mylibrary/weight/SideBar.java
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.os.Vibrator;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
public class SideBar extends View {
|
||||||
|
// 触摸事件
|
||||||
|
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
|
||||||
|
public static String[] b = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
|
||||||
|
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
|
||||||
|
"W", "X", "Y", "Z", "#" };
|
||||||
|
private int choose = -1;
|
||||||
|
private Paint paint = new Paint();
|
||||||
|
|
||||||
|
private TextView mTextDialog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为SideBar设置显示字母的TextView
|
||||||
|
* @param textDialog
|
||||||
|
*/
|
||||||
|
public void setTextView(TextView textDialog) {
|
||||||
|
this.mTextDialog = textDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SideBar(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SideBar(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SideBar(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
int height = getHeight();
|
||||||
|
int width = getWidth();
|
||||||
|
int singleHeight = height / b.length;// 获取每一个字母的高度
|
||||||
|
|
||||||
|
for (int i = 0; i < b.length; i++) {
|
||||||
|
paint.setColor(Color.rgb(33, 65, 98));
|
||||||
|
// paint.setColor(Color.WHITE);
|
||||||
|
paint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setTextSize(20);
|
||||||
|
if (i == choose) {// 选中的状态
|
||||||
|
paint.setColor(Color.parseColor("#999999"));
|
||||||
|
paint.setFakeBoldText(true);
|
||||||
|
}
|
||||||
|
// x坐标等于中间-字符串宽度的一半
|
||||||
|
float xPos = width / 2 - paint.measureText(b[i]) / 2;
|
||||||
|
float yPos = singleHeight * i + singleHeight;
|
||||||
|
canvas.drawText(b[i], xPos, yPos, paint);
|
||||||
|
paint.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||||
|
final int action = event.getAction();
|
||||||
|
final float y = event.getY();
|
||||||
|
final int oldChoose = choose;
|
||||||
|
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
|
||||||
|
final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
setBackground(new ColorDrawable(0x00000000));
|
||||||
|
choose = -1;//
|
||||||
|
invalidate();
|
||||||
|
if (mTextDialog != null) {
|
||||||
|
mTextDialog.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// setBackgroundResource(R.drawable.sidebar_background);
|
||||||
|
if (oldChoose != c) {
|
||||||
|
if (c >= 0 && c < b.length) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onTouchingLetterChanged(b[c]);
|
||||||
|
}
|
||||||
|
if (mTextDialog != null) {
|
||||||
|
mTextDialog.setText(b[c]);
|
||||||
|
mTextDialog.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
choose = c;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触摸事件
|
||||||
|
* @param onTouchingLetterChangedListener
|
||||||
|
*/
|
||||||
|
public void setOnTouchingLetterChangedListener(
|
||||||
|
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
|
||||||
|
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*/
|
||||||
|
public interface OnTouchingLetterChangedListener {
|
||||||
|
void onTouchingLetterChanged(String s);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,508 @@
|
|||||||
|
package com.dahe.mylibrary.weight;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.RadialGradient;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.AccelerateInterpolator;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hei hei hei
|
||||||
|
*/
|
||||||
|
public class SwitchView extends View {
|
||||||
|
|
||||||
|
private static final int STATE_SWITCH_ON = 4;
|
||||||
|
private static final int STATE_SWITCH_ON2 = 3;
|
||||||
|
private static final int STATE_SWITCH_OFF2 = 2;
|
||||||
|
private static final int STATE_SWITCH_OFF = 1;
|
||||||
|
|
||||||
|
private final AccelerateInterpolator interpolator = new AccelerateInterpolator(2);
|
||||||
|
private final Paint paint = new Paint();
|
||||||
|
private final Path sPath = new Path();
|
||||||
|
private final Path bPath = new Path();
|
||||||
|
private final RectF bRectF = new RectF();
|
||||||
|
private float sAnim, bAnim;
|
||||||
|
private RadialGradient shadowGradient;
|
||||||
|
|
||||||
|
protected float ratioAspect = 0.68f; // (0,1]
|
||||||
|
protected float animationSpeed = 0.1f; // (0,1]
|
||||||
|
|
||||||
|
private int state;
|
||||||
|
private int lastState;
|
||||||
|
private boolean isCanVisibleDrawing = false;
|
||||||
|
private OnClickListener mOnClickListener;
|
||||||
|
protected int colorPrimary;
|
||||||
|
protected int colorPrimaryDark;
|
||||||
|
protected int colorOff;
|
||||||
|
protected int colorOffDark;
|
||||||
|
protected int colorShadow;
|
||||||
|
protected boolean hasShadow;
|
||||||
|
protected boolean isOpened;
|
||||||
|
protected boolean canEnable;
|
||||||
|
|
||||||
|
private float sRight;
|
||||||
|
private float sCenterX, sCenterY;
|
||||||
|
private float sScale;
|
||||||
|
|
||||||
|
private float bOffset;
|
||||||
|
private float bRadius, bStrokeWidth;
|
||||||
|
private float bWidth;
|
||||||
|
private float bLeft;
|
||||||
|
private float bRight;
|
||||||
|
private float bOnLeftX, bOn2LeftX, bOff2LeftX, bOffLeftX;
|
||||||
|
|
||||||
|
private float shadowReservedHeight;
|
||||||
|
|
||||||
|
public SwitchView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
public SwitchView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setLayerType(LAYER_TYPE_SOFTWARE, null);
|
||||||
|
|
||||||
|
final int DEFAULT_COLOR_PRIMARY = 0xFF4BD763;
|
||||||
|
final int DEFAULT_COLOR_PRIMARY_DARK = 0xFF3AC652;
|
||||||
|
|
||||||
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwitchView);
|
||||||
|
colorPrimary = a.getColor(R.styleable.SwitchView_primaryColor, DEFAULT_COLOR_PRIMARY);
|
||||||
|
colorPrimaryDark = a.getColor(R.styleable.SwitchView_primaryColorDark, DEFAULT_COLOR_PRIMARY_DARK);
|
||||||
|
colorOff = a.getColor(R.styleable.SwitchView_offColor, 0xFFE3E3E3);
|
||||||
|
colorOffDark = a.getColor(R.styleable.SwitchView_offColorDark, 0xFFBFBFBF);
|
||||||
|
colorShadow = a.getColor(R.styleable.SwitchView_shadowColor, 0xFF333333);
|
||||||
|
ratioAspect = a.getFloat(R.styleable.SwitchView_ratioAspect, 0.68f);
|
||||||
|
hasShadow = a.getBoolean(R.styleable.SwitchView_hasShadow, true);
|
||||||
|
isOpened = a.getBoolean(R.styleable.SwitchView_isOpened, false);
|
||||||
|
canEnable = a.getBoolean(R.styleable.SwitchView_canEnable, true);
|
||||||
|
state = isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
|
||||||
|
lastState = state;
|
||||||
|
a.recycle();
|
||||||
|
|
||||||
|
if (colorPrimary == DEFAULT_COLOR_PRIMARY && colorPrimaryDark == DEFAULT_COLOR_PRIMARY_DARK) {
|
||||||
|
try {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
TypedValue primaryColorTypedValue = new TypedValue();
|
||||||
|
context.getTheme().resolveAttribute(android.R.attr.colorPrimary, primaryColorTypedValue, true);
|
||||||
|
if (primaryColorTypedValue.data > 0) colorPrimary = primaryColorTypedValue.data;
|
||||||
|
TypedValue primaryColorDarkTypedValue = new TypedValue();
|
||||||
|
context.getTheme().resolveAttribute(android.R.attr.colorPrimaryDark, primaryColorDarkTypedValue, true);
|
||||||
|
if (primaryColorDarkTypedValue.data > 0)
|
||||||
|
colorPrimaryDark = primaryColorDarkTypedValue.data;
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int newColorPrimary, int newColorPrimaryDark) {
|
||||||
|
setColor(newColorPrimary, newColorPrimaryDark, colorOff, colorOffDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int newColorPrimary, int newColorPrimaryDark, int newColorOff, int newColorOffDark) {
|
||||||
|
setColor(newColorPrimary, newColorPrimaryDark, newColorOff, newColorOffDark, colorShadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int newColorPrimary, int newColorPrimaryDark, int newColorOff, int newColorOffDark, int newColorShadow) {
|
||||||
|
colorPrimary = newColorPrimary;
|
||||||
|
colorPrimaryDark = newColorPrimaryDark;
|
||||||
|
colorOff = newColorOff;
|
||||||
|
colorOffDark = newColorOffDark;
|
||||||
|
colorShadow = newColorShadow;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCanEnable(boolean canEnable){
|
||||||
|
this.canEnable = canEnable;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShadow(boolean shadow) {
|
||||||
|
hasShadow = shadow;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpened() {
|
||||||
|
return isOpened;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpened(boolean isOpened) {
|
||||||
|
int wishState = isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
|
||||||
|
if (wishState == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refreshState(wishState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleSwitch(boolean isOpened) {
|
||||||
|
int wishState = isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
|
||||||
|
if (wishState == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((wishState == STATE_SWITCH_ON && (state == STATE_SWITCH_OFF || state == STATE_SWITCH_OFF2))
|
||||||
|
|| (wishState == STATE_SWITCH_OFF && (state == STATE_SWITCH_ON || state == STATE_SWITCH_ON2))) {
|
||||||
|
sAnim = 1;
|
||||||
|
}
|
||||||
|
bAnim = 1;
|
||||||
|
refreshState(wishState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshState(int newState) {
|
||||||
|
if (!isOpened && newState == STATE_SWITCH_ON) {
|
||||||
|
isOpened = true;
|
||||||
|
} else if (isOpened && newState == STATE_SWITCH_OFF) {
|
||||||
|
isOpened = false;
|
||||||
|
}
|
||||||
|
lastState = state;
|
||||||
|
state = newState;
|
||||||
|
postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
int resultWidth;
|
||||||
|
if (widthMode == MeasureSpec.EXACTLY) {
|
||||||
|
resultWidth = widthSize;
|
||||||
|
} else {
|
||||||
|
resultWidth = (int) (56 * getResources().getDisplayMetrics().density + 0.5f)
|
||||||
|
+ getPaddingLeft() + getPaddingRight();
|
||||||
|
if (widthMode == MeasureSpec.AT_MOST) {
|
||||||
|
resultWidth = Math.min(resultWidth, widthSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
|
int resultHeight;
|
||||||
|
if (heightMode == MeasureSpec.EXACTLY) {
|
||||||
|
resultHeight = heightSize;
|
||||||
|
} else {
|
||||||
|
resultHeight = (int) (resultWidth * ratioAspect) + getPaddingTop() + getPaddingBottom();
|
||||||
|
if (heightMode == MeasureSpec.AT_MOST) {
|
||||||
|
resultHeight = Math.min(resultHeight, heightSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setMeasuredDimension(resultWidth, resultHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
|
||||||
|
isCanVisibleDrawing = w > getPaddingLeft() + getPaddingRight() && h > getPaddingTop() + getPaddingBottom();
|
||||||
|
|
||||||
|
if (isCanVisibleDrawing) {
|
||||||
|
int actuallyDrawingAreaWidth = w - getPaddingLeft() - getPaddingRight();
|
||||||
|
int actuallyDrawingAreaHeight = h - getPaddingTop() - getPaddingBottom();
|
||||||
|
|
||||||
|
int actuallyDrawingAreaLeft;
|
||||||
|
int actuallyDrawingAreaRight;
|
||||||
|
int actuallyDrawingAreaTop;
|
||||||
|
int actuallyDrawingAreaBottom;
|
||||||
|
if (actuallyDrawingAreaWidth * ratioAspect < actuallyDrawingAreaHeight) {
|
||||||
|
actuallyDrawingAreaLeft = getPaddingLeft();
|
||||||
|
actuallyDrawingAreaRight = w - getPaddingRight();
|
||||||
|
int heightExtraSize = (int) (actuallyDrawingAreaHeight - actuallyDrawingAreaWidth * ratioAspect);
|
||||||
|
actuallyDrawingAreaTop = getPaddingTop() + heightExtraSize / 2;
|
||||||
|
actuallyDrawingAreaBottom = getHeight() - getPaddingBottom() - heightExtraSize / 2;
|
||||||
|
} else {
|
||||||
|
int widthExtraSize = (int) (actuallyDrawingAreaWidth - actuallyDrawingAreaHeight / ratioAspect);
|
||||||
|
actuallyDrawingAreaLeft = getPaddingLeft() + widthExtraSize / 2;
|
||||||
|
actuallyDrawingAreaRight = getWidth() - getPaddingRight() - widthExtraSize / 2;
|
||||||
|
actuallyDrawingAreaTop = getPaddingTop();
|
||||||
|
actuallyDrawingAreaBottom = getHeight() - getPaddingBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowReservedHeight = (int) ((actuallyDrawingAreaBottom - actuallyDrawingAreaTop) * 0.07f);
|
||||||
|
float sLeft = actuallyDrawingAreaLeft;
|
||||||
|
float sTop = actuallyDrawingAreaTop + shadowReservedHeight;
|
||||||
|
sRight = actuallyDrawingAreaRight;
|
||||||
|
float sBottom = actuallyDrawingAreaBottom - shadowReservedHeight;
|
||||||
|
|
||||||
|
float sHeight = sBottom - sTop;
|
||||||
|
sCenterX = (sRight + sLeft) / 2;
|
||||||
|
sCenterY = (sBottom + sTop) / 2;
|
||||||
|
|
||||||
|
bLeft = sLeft;
|
||||||
|
bWidth = sBottom - sTop;
|
||||||
|
bRight = sLeft + bWidth;
|
||||||
|
final float halfHeightOfS = bWidth / 2; // OfB
|
||||||
|
bRadius = halfHeightOfS * 0.95f;
|
||||||
|
bOffset = bRadius * 0.2f; // offset of switching
|
||||||
|
bStrokeWidth = (halfHeightOfS - bRadius) * 2;
|
||||||
|
bOnLeftX = sRight - bWidth;
|
||||||
|
bOn2LeftX = bOnLeftX - bOffset;
|
||||||
|
bOffLeftX = sLeft;
|
||||||
|
bOff2LeftX = bOffLeftX + bOffset;
|
||||||
|
sScale = 1 - bStrokeWidth / sHeight;
|
||||||
|
|
||||||
|
sPath.reset();
|
||||||
|
RectF sRectF = new RectF();
|
||||||
|
sRectF.top = sTop;
|
||||||
|
sRectF.bottom = sBottom;
|
||||||
|
sRectF.left = sLeft;
|
||||||
|
sRectF.right = sLeft + sHeight;
|
||||||
|
sPath.arcTo(sRectF, 90, 180);
|
||||||
|
sRectF.left = sRight - sHeight;
|
||||||
|
sRectF.right = sRight;
|
||||||
|
sPath.arcTo(sRectF, 270, 180);
|
||||||
|
sPath.close();
|
||||||
|
|
||||||
|
bRectF.left = bLeft;
|
||||||
|
bRectF.right = bRight;
|
||||||
|
bRectF.top = sTop + bStrokeWidth / 2; // bTop = sTop
|
||||||
|
bRectF.bottom = sBottom - bStrokeWidth / 2; // bBottom = sBottom
|
||||||
|
float bCenterX = (bRight + bLeft) / 2;
|
||||||
|
float bCenterY = (sBottom + sTop) / 2;
|
||||||
|
|
||||||
|
int red = colorShadow >> 16 & 0xFF;
|
||||||
|
int green = colorShadow >> 8 & 0xFF;
|
||||||
|
int blue = colorShadow & 0xFF;
|
||||||
|
shadowGradient = new RadialGradient(bCenterX, bCenterY, bRadius, Color.argb(200, red, green, blue),
|
||||||
|
Color.argb(25, red, green, blue), Shader.TileMode.CLAMP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calcBPath(float percent) {
|
||||||
|
bPath.reset();
|
||||||
|
bRectF.left = bLeft + bStrokeWidth / 2;
|
||||||
|
bRectF.right = bRight - bStrokeWidth / 2;
|
||||||
|
bPath.arcTo(bRectF, 90, 180);
|
||||||
|
bRectF.left = bLeft + percent * bOffset + bStrokeWidth / 2;
|
||||||
|
bRectF.right = bRight + percent * bOffset - bStrokeWidth / 2;
|
||||||
|
bPath.arcTo(bRectF, 270, 180);
|
||||||
|
bPath.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calcBTranslate(float percent) {
|
||||||
|
float result = 0;
|
||||||
|
switch (state - lastState) {
|
||||||
|
case 1:
|
||||||
|
if (state == STATE_SWITCH_OFF2) {
|
||||||
|
result = bOffLeftX; // off -> off2
|
||||||
|
} else if (state == STATE_SWITCH_ON) {
|
||||||
|
result = bOnLeftX - (bOnLeftX - bOn2LeftX) * percent; // on2 -> on
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (state == STATE_SWITCH_ON) {
|
||||||
|
result = bOnLeftX - (bOnLeftX - bOffLeftX) * percent; // off2 -> on
|
||||||
|
} else if (state == STATE_SWITCH_ON2) {
|
||||||
|
result = bOn2LeftX - (bOn2LeftX - bOffLeftX) * percent; // off -> on2
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
result = bOnLeftX - (bOnLeftX - bOffLeftX) * percent; // off -> on
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if (state == STATE_SWITCH_ON2) {
|
||||||
|
result = bOn2LeftX + (bOnLeftX - bOn2LeftX) * percent; // on -> on2
|
||||||
|
} else if (state == STATE_SWITCH_OFF) {
|
||||||
|
result = bOffLeftX; // off2 -> off
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
if (state == STATE_SWITCH_OFF) {
|
||||||
|
result = bOffLeftX + (bOn2LeftX - bOffLeftX) * percent; // on2 -> off
|
||||||
|
} else if (state == STATE_SWITCH_OFF2) {
|
||||||
|
result = bOff2LeftX + (bOnLeftX - bOff2LeftX) * percent; // on -> off2
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
result = bOffLeftX + (bOnLeftX - bOffLeftX) * percent; // on -> off
|
||||||
|
break;
|
||||||
|
default: // init
|
||||||
|
case 0:
|
||||||
|
if (state == STATE_SWITCH_OFF) {
|
||||||
|
result = bOffLeftX; // off -> off
|
||||||
|
} else if (state == STATE_SWITCH_ON) {
|
||||||
|
result = bOnLeftX; // on -> on
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result - bOffLeftX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
if (!isCanVisibleDrawing) return;
|
||||||
|
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
final boolean isOn = (state == STATE_SWITCH_ON || state == STATE_SWITCH_ON2);
|
||||||
|
// Draw background
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
paint.setColor(isOn ? colorPrimary : colorOff);
|
||||||
|
canvas.drawPath(sPath, paint);
|
||||||
|
|
||||||
|
sAnim = sAnim - animationSpeed > 0 ? sAnim - animationSpeed : 0;
|
||||||
|
bAnim = bAnim - animationSpeed > 0 ? bAnim - animationSpeed : 0;
|
||||||
|
|
||||||
|
final float dsAnim = interpolator.getInterpolation(sAnim);
|
||||||
|
final float dbAnim = interpolator.getInterpolation(bAnim);
|
||||||
|
// Draw background animation
|
||||||
|
final float scale = sScale * (isOn ? dsAnim : 1 - dsAnim);
|
||||||
|
final float scaleOffset = (sRight - sCenterX - bRadius) * (isOn ? 1 - dsAnim : dsAnim);
|
||||||
|
canvas.save();
|
||||||
|
canvas.scale(scale, scale, sCenterX + scaleOffset, sCenterY);
|
||||||
|
paint.setColor(0xFFFFFFFF);
|
||||||
|
canvas.drawPath(sPath, paint);
|
||||||
|
canvas.restore();
|
||||||
|
// To prepare center bar path
|
||||||
|
canvas.save();
|
||||||
|
canvas.translate(calcBTranslate(dbAnim), shadowReservedHeight);
|
||||||
|
final boolean isState2 = (state == STATE_SWITCH_ON2 || state == STATE_SWITCH_OFF2);
|
||||||
|
calcBPath(isState2 ? 1 - dbAnim : dbAnim);
|
||||||
|
// Use center bar path to draw shadow
|
||||||
|
if (hasShadow) {
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
paint.setShader(shadowGradient);
|
||||||
|
canvas.drawPath(bPath, paint);
|
||||||
|
paint.setShader(null);
|
||||||
|
}
|
||||||
|
canvas.translate(0, -shadowReservedHeight);
|
||||||
|
// draw bar
|
||||||
|
canvas.scale(0.98f, 0.98f, bWidth / 2, bWidth / 2);
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
paint.setColor(0xffffffff);
|
||||||
|
canvas.drawPath(bPath, paint);
|
||||||
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
|
paint.setStrokeWidth(bStrokeWidth * 0.5f);
|
||||||
|
paint.setColor(isOn ? colorPrimaryDark : colorOffDark);
|
||||||
|
canvas.drawPath(bPath, paint);
|
||||||
|
canvas.restore();
|
||||||
|
|
||||||
|
paint.reset();
|
||||||
|
if (sAnim > 0 || bAnim > 0) invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
if (!canEnable)
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
if ((state == STATE_SWITCH_ON || state == STATE_SWITCH_OFF) && (sAnim * bAnim == 0)) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
return true;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
lastState = state;
|
||||||
|
|
||||||
|
bAnim = 1;
|
||||||
|
if (state == STATE_SWITCH_OFF) {
|
||||||
|
refreshState(STATE_SWITCH_OFF2);
|
||||||
|
listener.toggleToOn(this);
|
||||||
|
} else if (state == STATE_SWITCH_ON) {
|
||||||
|
refreshState(STATE_SWITCH_ON2);
|
||||||
|
listener.toggleToOff(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOnClickListener != null) {
|
||||||
|
mOnClickListener.onClick(this);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnClickListener(OnClickListener l) {
|
||||||
|
super.setOnClickListener(l);
|
||||||
|
mOnClickListener = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnStateChangedListener {
|
||||||
|
void toggleToOn(SwitchView view);
|
||||||
|
|
||||||
|
void toggleToOff(SwitchView view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnStateChangedListener listener = new OnStateChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void toggleToOn(SwitchView view) {
|
||||||
|
toggleSwitch(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toggleToOff(SwitchView view) {
|
||||||
|
toggleSwitch(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void setOnStateChangedListener(OnStateChangedListener listener) {
|
||||||
|
if (listener == null) throw new IllegalArgumentException("empty listener");
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Parcelable onSaveInstanceState() {
|
||||||
|
Parcelable superState = super.onSaveInstanceState();
|
||||||
|
SavedState ss = new SavedState(superState);
|
||||||
|
ss.isOpened = isOpened;
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestoreInstanceState(Parcelable state) {
|
||||||
|
SavedState ss = (SavedState) state;
|
||||||
|
super.onRestoreInstanceState(ss.getSuperState());
|
||||||
|
this.isOpened = ss.isOpened;
|
||||||
|
this.state = this.isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class SavedState extends BaseSavedState {
|
||||||
|
private boolean isOpened;
|
||||||
|
|
||||||
|
SavedState(Parcelable superState) {
|
||||||
|
super(superState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SavedState(Parcel in) {
|
||||||
|
super(in);
|
||||||
|
isOpened = 1 == in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
|
super.writeToParcel(out, flags);
|
||||||
|
out.writeInt(isOpened ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixed by Night99 https://github.com/g19980115
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
|
||||||
|
@Override
|
||||||
|
public SavedState createFromParcel(Parcel in) {
|
||||||
|
return new SavedState(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SavedState[] newArray(int size) {
|
||||||
|
return new SavedState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
package com.dahe.mylibrary.weight.segmentcontrol;
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
// 圆角 Drawable 每个角的圆半径可以不同 (使用不同半径圆角图形的时候 使用这个类 以防止 系统提供的用 xml 实现的圆角 Drawable 在2.3 上 出现各个角位置错乱)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by caifangmao on 15/4/22.
|
||||||
|
*/
|
||||||
|
public class RadiusDrawable extends Drawable {
|
||||||
|
|
||||||
|
private int topLeftRadius;
|
||||||
|
private int topRightRadius;
|
||||||
|
private int bottomLeftRadius;
|
||||||
|
private int bottomRightRadius;
|
||||||
|
|
||||||
|
private int left;
|
||||||
|
private int top;
|
||||||
|
private int right;
|
||||||
|
private int bottom;
|
||||||
|
|
||||||
|
private final Paint paint;
|
||||||
|
private final boolean isStroke;
|
||||||
|
private int strokeWidth = 0;
|
||||||
|
private int strokeColor = Color.CYAN;
|
||||||
|
private int fillColor;
|
||||||
|
|
||||||
|
private Path path;
|
||||||
|
|
||||||
|
public RadiusDrawable(boolean isStroke) {
|
||||||
|
this(0, isStroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RadiusDrawable(int radius, boolean isStroke) {
|
||||||
|
setRadius(radius);
|
||||||
|
|
||||||
|
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
this.isStroke = isStroke;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeWidth(int width) {
|
||||||
|
strokeWidth = width;
|
||||||
|
setBounds(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor(int strokeColor) {
|
||||||
|
this.strokeColor = strokeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor(int fillColor) {
|
||||||
|
this.fillColor = fillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius(int radius) {
|
||||||
|
this.topLeftRadius = this.topRightRadius = this.bottomLeftRadius = this.bottomRightRadius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius(int topLeftRadius, int topRightRadius, int bottomLeftRadius, int bottomRightRadius) {
|
||||||
|
this.topLeftRadius = topLeftRadius;
|
||||||
|
this.topRightRadius = topRightRadius;
|
||||||
|
this.bottomLeftRadius = bottomLeftRadius;
|
||||||
|
this.bottomRightRadius = bottomRightRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBounds(int left, int top, int right, int bottom) {
|
||||||
|
super.setBounds(left, top, right, bottom);
|
||||||
|
|
||||||
|
this.left = left;
|
||||||
|
this.top = top;
|
||||||
|
this.right = right;
|
||||||
|
this.bottom = bottom;
|
||||||
|
|
||||||
|
if (isStroke) {
|
||||||
|
int halfStrokeWidth = strokeWidth / 2;
|
||||||
|
left += halfStrokeWidth;
|
||||||
|
top += halfStrokeWidth;
|
||||||
|
right -= halfStrokeWidth;
|
||||||
|
bottom -= halfStrokeWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = new Path();
|
||||||
|
path.moveTo(left + topLeftRadius, top);
|
||||||
|
path.lineTo(right - topRightRadius, top);
|
||||||
|
path.arcTo(new RectF(right - topRightRadius * 2, top, right, top + topRightRadius * 2),
|
||||||
|
-90, 90);
|
||||||
|
// path.quadTo(right, top, right, top + topRightRadius);
|
||||||
|
path.lineTo(right, bottom - bottomRightRadius);
|
||||||
|
path.arcTo(new RectF(right - bottomRightRadius * 2, bottom - bottomRightRadius * 2, right,
|
||||||
|
bottom), 0, 90);
|
||||||
|
// path.quadTo(right, bottom, right - bottomRightRadius, bottom);
|
||||||
|
path.lineTo(left + bottomLeftRadius, bottom);
|
||||||
|
path.arcTo(new RectF(left, bottom - bottomLeftRadius * 2, left + bottomLeftRadius * 2,
|
||||||
|
bottom), 90, 90);
|
||||||
|
// path.quadTo(left, bottom, left, bottom - bottomLeftRadius);
|
||||||
|
path.lineTo(left, top + topLeftRadius);
|
||||||
|
path.arcTo(new RectF(left, top, left + topLeftRadius * 2, top + topLeftRadius * 2), 180, 90);
|
||||||
|
// path.quadTo(left, top, left + topLeftRadius, top);
|
||||||
|
path.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
if (fillColor != 0) {
|
||||||
|
paint.setColor(fillColor);
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strokeWidth > 0) {
|
||||||
|
paint.setColor(strokeColor);
|
||||||
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
|
paint.setStrokeJoin(Paint.Join.MITER);
|
||||||
|
paint.setStrokeWidth(strokeWidth);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorFilter(ColorFilter cf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
|
return PixelFormat.TRANSLUCENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,526 @@
|
|||||||
|
package com.dahe.mylibrary.weight.segmentcontrol;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
|
import com.dahe.mylibrary.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by 7heaven on 15/4/22.
|
||||||
|
*/
|
||||||
|
public class SegmentControl extends View {
|
||||||
|
|
||||||
|
private String[] mTexts;
|
||||||
|
private Rect[] mCacheBounds;
|
||||||
|
private Rect[] mTextBounds;
|
||||||
|
|
||||||
|
private RadiusDrawable mBackgroundDrawable;
|
||||||
|
private RadiusDrawable mSelectedDrawable;
|
||||||
|
|
||||||
|
private int mCurrentIndex;
|
||||||
|
|
||||||
|
private int mTouchSlop;
|
||||||
|
private boolean inTapRegion;
|
||||||
|
private float mStartX;
|
||||||
|
private float mStartY;
|
||||||
|
private float mCurrentX;
|
||||||
|
private float mCurrentY;
|
||||||
|
|
||||||
|
private int mHorizonGap;
|
||||||
|
private int mVerticalGap;
|
||||||
|
|
||||||
|
/** 外边框的width */
|
||||||
|
private int mBoundWidth = 4;
|
||||||
|
/** 内边框的width */
|
||||||
|
private int mSeparatorWidth = mBoundWidth / 2;
|
||||||
|
|
||||||
|
private int mSingleChildWidth;
|
||||||
|
private int mSingleChildHeight;
|
||||||
|
|
||||||
|
private Paint mPaint;
|
||||||
|
|
||||||
|
private int mTextSize;
|
||||||
|
private ColorStateList mBackgroundColors;
|
||||||
|
private ColorStateList mTextColors;
|
||||||
|
private int mCornerRadius;
|
||||||
|
|
||||||
|
private int DEFAULT_SELECTED_COLOR = 0xFF32ADFF;
|
||||||
|
private int DEFAULT_NORMAL_COLOR = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
private Paint.FontMetrics mCachedFM;
|
||||||
|
|
||||||
|
public enum Direction {
|
||||||
|
HORIZONTAL(0), VERTICAL(1);
|
||||||
|
|
||||||
|
int value;
|
||||||
|
|
||||||
|
Direction(int v) {
|
||||||
|
value = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Direction mDirection;
|
||||||
|
|
||||||
|
public SegmentControl(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SegmentControl(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SegmentControl(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
|
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SegmentControl);
|
||||||
|
|
||||||
|
String textArray = ta.getString(R.styleable.SegmentControl_texts);
|
||||||
|
if (textArray != null) {
|
||||||
|
mTexts = textArray.split("\\|");
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextSize = ta.getDimensionPixelSize(R.styleable.SegmentControl_android_textSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, context.getResources().getDisplayMetrics()));
|
||||||
|
mCornerRadius = ta.getDimensionPixelSize(R.styleable.SegmentControl_cornerRadius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, context.getResources().getDisplayMetrics()));
|
||||||
|
mDirection = Direction.values()[ta.getInt(R.styleable.SegmentControl_android_orientation, 0)];
|
||||||
|
|
||||||
|
mHorizonGap = ta.getDimensionPixelSize(R.styleable.SegmentControl_horizonGap, 0);
|
||||||
|
mVerticalGap = ta.getDimensionPixelSize(R.styleable.SegmentControl_verticalGap, 0);
|
||||||
|
|
||||||
|
int gap = ta.getDimensionPixelSize(R.styleable.SegmentControl_gaps, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, context.getResources().getDisplayMetrics()));
|
||||||
|
|
||||||
|
if(mHorizonGap == 0) {
|
||||||
|
mHorizonGap = gap;
|
||||||
|
}
|
||||||
|
if(mVerticalGap == 0) {
|
||||||
|
mVerticalGap = gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
mBackgroundDrawable = new RadiusDrawable(mCornerRadius, true);
|
||||||
|
mBackgroundDrawable.setStrokeWidth(2);
|
||||||
|
|
||||||
|
DEFAULT_NORMAL_COLOR = ta.getColor(R.styleable.SegmentControl_normalColor, DEFAULT_NORMAL_COLOR);
|
||||||
|
DEFAULT_SELECTED_COLOR = ta.getColor(R.styleable.SegmentControl_selectedColor, DEFAULT_SELECTED_COLOR);
|
||||||
|
|
||||||
|
mBackgroundColors = ta.getColorStateList(R.styleable.SegmentControl_backgroundColors);
|
||||||
|
mTextColors = ta.getColorStateList(R.styleable.SegmentControl_textColors);
|
||||||
|
if (mBackgroundColors == null) {
|
||||||
|
mBackgroundColors = new ColorStateList(new int[][]{{android.R.attr.state_selected}, {-android.R.attr.state_selected}}, new int[]{DEFAULT_SELECTED_COLOR, DEFAULT_NORMAL_COLOR});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mTextColors == null){
|
||||||
|
mTextColors = new ColorStateList(new int[][]{{android.R.attr.state_selected}, {-android.R.attr.state_selected}}, new int[]{DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR});
|
||||||
|
}
|
||||||
|
|
||||||
|
mBoundWidth = ta.getDimensionPixelSize(R.styleable.SegmentControl_boundWidth, mBoundWidth);
|
||||||
|
mSeparatorWidth = ta.getDimensionPixelSize(R.styleable.SegmentControl_separatorWidth, mSeparatorWidth);
|
||||||
|
|
||||||
|
ta.recycle();
|
||||||
|
|
||||||
|
mBackgroundDrawable = new RadiusDrawable(mCornerRadius, true);
|
||||||
|
mBackgroundDrawable.setStrokeWidth(mBoundWidth);
|
||||||
|
mBackgroundDrawable.setStrokeColor(getSelectedBGColor());
|
||||||
|
mBackgroundDrawable.setFillColor(getNormalBGColor());
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < 16) {
|
||||||
|
setBackgroundDrawable(mBackgroundDrawable);
|
||||||
|
} else {
|
||||||
|
setBackground(mBackgroundDrawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSelectedDrawable = new RadiusDrawable(false);
|
||||||
|
mSelectedDrawable.setFillColor(getSelectedBGColor());
|
||||||
|
|
||||||
|
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
mPaint.setTextSize(mTextSize);
|
||||||
|
mCachedFM = mPaint.getFontMetrics();
|
||||||
|
|
||||||
|
int touchSlop = 0;
|
||||||
|
if (context == null) {
|
||||||
|
touchSlop = ViewConfiguration.getTouchSlop();
|
||||||
|
} else {
|
||||||
|
final ViewConfiguration config = ViewConfiguration.get(context);
|
||||||
|
touchSlop = config.getScaledTouchSlop();
|
||||||
|
}
|
||||||
|
mTouchSlop = touchSlop * touchSlop;
|
||||||
|
inTapRegion = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String... texts) {
|
||||||
|
mTexts = texts;
|
||||||
|
if (mTexts != null) {
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文字颜色
|
||||||
|
*
|
||||||
|
* @param color 需要设置的颜色
|
||||||
|
*/
|
||||||
|
public void setSelectedTextColors(ColorStateList color) {
|
||||||
|
mTextColors = color;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置背景颜色
|
||||||
|
*
|
||||||
|
* @param colors 颜色
|
||||||
|
*/
|
||||||
|
public void setColors(ColorStateList colors) {
|
||||||
|
mBackgroundColors = colors;
|
||||||
|
|
||||||
|
if (mBackgroundDrawable != null) {
|
||||||
|
mBackgroundDrawable.setStrokeColor(getSelectedBGColor());
|
||||||
|
mBackgroundDrawable.setFillColor(getNormalBGColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSelectedDrawable != null) {
|
||||||
|
mSelectedDrawable.setFillColor(getSelectedBGColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCornerRadius(int cornerRadius) {
|
||||||
|
mCornerRadius = cornerRadius;
|
||||||
|
|
||||||
|
if (mBackgroundDrawable != null) {
|
||||||
|
mBackgroundDrawable.setRadius(cornerRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirection(Direction direction) {
|
||||||
|
Direction tDirection = mDirection;
|
||||||
|
|
||||||
|
mDirection = direction;
|
||||||
|
|
||||||
|
if (tDirection != direction) {
|
||||||
|
requestLayout();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextSize(int textSize_sp) {
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize_sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextSize(int unit, int textSize) {
|
||||||
|
mPaint.setTextSize((int) (TypedValue.applyDimension(unit, textSize, getContext().getResources().getDisplayMetrics())));
|
||||||
|
|
||||||
|
if (textSize != mTextSize) {
|
||||||
|
mTextSize = textSize;
|
||||||
|
mCachedFM = mPaint.getFontMetrics();
|
||||||
|
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedIndex(int index) {
|
||||||
|
mCurrentIndex = index;
|
||||||
|
|
||||||
|
if(mOnSegmentControlClickListener != null) {
|
||||||
|
mOnSegmentControlClickListener.onSegmentControlClick(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
|
||||||
|
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
|
|
||||||
|
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
if (mTexts != null && mTexts.length > 0) {
|
||||||
|
|
||||||
|
mSingleChildHeight = 0;
|
||||||
|
mSingleChildWidth = 0;
|
||||||
|
|
||||||
|
if (mCacheBounds == null || mCacheBounds.length != mTexts.length) {
|
||||||
|
mCacheBounds = new Rect[mTexts.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTextBounds == null || mTextBounds.length != mTexts.length) {
|
||||||
|
mTextBounds = new Rect[mTexts.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mTexts.length; i++) {
|
||||||
|
String text = mTexts[i];
|
||||||
|
|
||||||
|
if(text != null){
|
||||||
|
|
||||||
|
if(mTextBounds[i] == null) {
|
||||||
|
mTextBounds[i] = new Rect();
|
||||||
|
}
|
||||||
|
|
||||||
|
mPaint.getTextBounds(text, 0, text.length(), mTextBounds[i]);
|
||||||
|
|
||||||
|
if(mSingleChildWidth < mTextBounds[i].width() + mHorizonGap * 2) {
|
||||||
|
mSingleChildWidth = mTextBounds[i].width() + mHorizonGap * 2;
|
||||||
|
}
|
||||||
|
if(mSingleChildHeight < mTextBounds[i].height() + mVerticalGap * 2) {
|
||||||
|
mSingleChildHeight = mTextBounds[i].height() + mVerticalGap * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (widthMode) {
|
||||||
|
case MeasureSpec.AT_MOST:
|
||||||
|
if (mDirection == Direction.HORIZONTAL) {
|
||||||
|
if (widthSize <= mSingleChildWidth * mTexts.length) {
|
||||||
|
mSingleChildWidth = widthSize / mTexts.length;
|
||||||
|
width = widthSize;
|
||||||
|
} else {
|
||||||
|
width = mSingleChildWidth * mTexts.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
width = widthSize <= mSingleChildWidth ? widthSize : mSingleChildWidth;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MeasureSpec.EXACTLY:
|
||||||
|
width = widthSize;
|
||||||
|
break;
|
||||||
|
case MeasureSpec.UNSPECIFIED:
|
||||||
|
default:
|
||||||
|
if (mDirection == Direction.HORIZONTAL) {
|
||||||
|
width = mSingleChildWidth * mTexts.length;
|
||||||
|
} else {
|
||||||
|
width = mSingleChildWidth;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (heightMode) {
|
||||||
|
case MeasureSpec.AT_MOST:
|
||||||
|
if (mDirection == Direction.VERTICAL) {
|
||||||
|
if (heightSize <= mSingleChildHeight * mTexts.length) {
|
||||||
|
mSingleChildHeight = heightSize / mTexts.length;
|
||||||
|
height = heightSize;
|
||||||
|
} else {
|
||||||
|
height = mSingleChildHeight * mTexts.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = heightSize <= mSingleChildHeight ? heightSize : mSingleChildHeight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MeasureSpec.EXACTLY:
|
||||||
|
height = heightSize;
|
||||||
|
break;
|
||||||
|
case MeasureSpec.UNSPECIFIED:
|
||||||
|
default:
|
||||||
|
if (mDirection == Direction.VERTICAL) {
|
||||||
|
height = mSingleChildHeight * mTexts.length;
|
||||||
|
} else {
|
||||||
|
height = mSingleChildHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mDirection) {
|
||||||
|
case HORIZONTAL:
|
||||||
|
if (mSingleChildWidth != width / mTexts.length) {
|
||||||
|
mSingleChildWidth = width / mTexts.length;
|
||||||
|
}
|
||||||
|
mSingleChildHeight = height;
|
||||||
|
break;
|
||||||
|
case VERTICAL:
|
||||||
|
if(mSingleChildHeight != height / mTexts.length) {
|
||||||
|
mSingleChildHeight = height / mTexts.length;
|
||||||
|
}
|
||||||
|
mSingleChildWidth = width;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mTexts.length; i++) {
|
||||||
|
|
||||||
|
if (mCacheBounds[i] == null) {
|
||||||
|
mCacheBounds[i] = new Rect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDirection == Direction.HORIZONTAL) {
|
||||||
|
mCacheBounds[i].left = i * mSingleChildWidth;
|
||||||
|
mCacheBounds[i].top = 0;
|
||||||
|
} else {
|
||||||
|
mCacheBounds[i].left = 0;
|
||||||
|
mCacheBounds[i].top = i * mSingleChildHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCacheBounds[i].right = mCacheBounds[i].left + mSingleChildWidth;
|
||||||
|
mCacheBounds[i].bottom = mCacheBounds[i].top + mSingleChildHeight;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
width = widthMode == MeasureSpec.UNSPECIFIED ? 0 : widthSize;
|
||||||
|
height = heightMode == MeasureSpec.UNSPECIFIED ? 0 : heightSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
switch (event.getAction() & MotionEvent.ACTION_MASK) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
inTapRegion = true;
|
||||||
|
|
||||||
|
mStartX = event.getX();
|
||||||
|
mStartY = event.getY();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
mCurrentX = event.getX();
|
||||||
|
mCurrentY = event.getY();
|
||||||
|
|
||||||
|
int dx = (int) (mCurrentX - mStartX);
|
||||||
|
int dy = (int) (mCurrentY - mStartY);
|
||||||
|
|
||||||
|
int distance = dx * dx + dy * dy;
|
||||||
|
|
||||||
|
if (distance > mTouchSlop) {
|
||||||
|
inTapRegion = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
if (inTapRegion) {
|
||||||
|
int index = 0;
|
||||||
|
if (mDirection == Direction.HORIZONTAL) {
|
||||||
|
index = (int) (mStartX / mSingleChildWidth);
|
||||||
|
} else {
|
||||||
|
index = (int) (mStartY / mSingleChildHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedIndex(index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelectedTextColor(){
|
||||||
|
return mTextColors.getColorForState(new int[]{android.R.attr.state_selected}, DEFAULT_NORMAL_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNormalTextColor(){
|
||||||
|
return mTextColors.getColorForState(new int[]{-android.R.attr.state_selected}, DEFAULT_SELECTED_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelectedBGColor(){
|
||||||
|
return mBackgroundColors.getColorForState(new int[]{android.R.attr.state_selected}, DEFAULT_SELECTED_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNormalBGColor(){
|
||||||
|
return mBackgroundColors.getColorForState(new int[]{-android.R.attr.state_selected}, DEFAULT_NORMAL_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
if (mTexts != null && mTexts.length > 0) {
|
||||||
|
|
||||||
|
for (int i = 0; i < mTexts.length; i++) {
|
||||||
|
|
||||||
|
//draw separate lines
|
||||||
|
if (i < mTexts.length - 1) {
|
||||||
|
mPaint.setColor(getSelectedBGColor());
|
||||||
|
mPaint.setStrokeWidth(mSeparatorWidth);
|
||||||
|
if (mDirection == Direction.HORIZONTAL) {
|
||||||
|
canvas.drawLine(mCacheBounds[i].right, 0, mCacheBounds[i].right, getHeight(), mPaint);
|
||||||
|
} else {
|
||||||
|
canvas.drawLine(mCacheBounds[i].left, mSingleChildHeight * (i + 1), mCacheBounds[i].right, mSingleChildHeight * (i + 1), mPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw selected drawable
|
||||||
|
if (i == mCurrentIndex && mSelectedDrawable != null) {
|
||||||
|
int topLeftRadius = 0;
|
||||||
|
int topRightRadius = 0;
|
||||||
|
int bottomLeftRadius = 0;
|
||||||
|
int bottomRightRadius = 0;
|
||||||
|
|
||||||
|
if(mTexts.length == 1){
|
||||||
|
topLeftRadius = mCornerRadius;
|
||||||
|
bottomLeftRadius = mCornerRadius;
|
||||||
|
topRightRadius = mCornerRadius;
|
||||||
|
bottomRightRadius = mCornerRadius;
|
||||||
|
}else{
|
||||||
|
if (mDirection == Direction.HORIZONTAL) {
|
||||||
|
if (i == 0) {
|
||||||
|
topLeftRadius = mCornerRadius;
|
||||||
|
bottomLeftRadius = mCornerRadius;
|
||||||
|
} else if (i == mTexts.length - 1) {
|
||||||
|
topRightRadius = mCornerRadius;
|
||||||
|
bottomRightRadius = mCornerRadius;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i == 0) {
|
||||||
|
topLeftRadius = mCornerRadius;
|
||||||
|
topRightRadius = mCornerRadius;
|
||||||
|
} else if (i == mTexts.length - 1) {
|
||||||
|
bottomLeftRadius = mCornerRadius;
|
||||||
|
bottomRightRadius = mCornerRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mSelectedDrawable.setRadius(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
|
||||||
|
mSelectedDrawable.setBounds(mCacheBounds[i]);
|
||||||
|
mSelectedDrawable.draw(canvas);
|
||||||
|
|
||||||
|
mPaint.setColor(getSelectedTextColor());
|
||||||
|
} else {
|
||||||
|
mPaint.setColor(getNormalTextColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw texts
|
||||||
|
|
||||||
|
float baseline = mCacheBounds[i].top + ((mSingleChildHeight - mCachedFM.ascent + mCachedFM.descent) / 2) - mCachedFM.descent;
|
||||||
|
canvas.drawText(mTexts[i], mCacheBounds[i].left + (mSingleChildWidth - mTextBounds[i].width()) / 2, baseline, mPaint);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// OnSegmentControlClickListener
|
||||||
|
// =========================================================
|
||||||
|
private OnSegmentControlClickListener mOnSegmentControlClickListener;
|
||||||
|
|
||||||
|
public void setOnSegmentControlClickListener(OnSegmentControlClickListener listener) {
|
||||||
|
mOnSegmentControlClickListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnSegmentControlClickListener getOnSegmentControlClicklistener() {
|
||||||
|
return mOnSegmentControlClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnSegmentControlClickListener {
|
||||||
|
void onSegmentControlClick(int index);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
mylibrary/src/main/res/anim/anim_bottom_in.xml
Normal file
11
mylibrary/src/main/res/anim/anim_bottom_in.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<translate
|
||||||
|
android:fromYDelta="100%"
|
||||||
|
android:toYDelta="0%"
|
||||||
|
android:duration="300"
|
||||||
|
android:fillAfter="true"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</set>
|
||||||
9
mylibrary/src/main/res/anim/anim_bottom_out.xml
Normal file
9
mylibrary/src/main/res/anim/anim_bottom_out.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<translate
|
||||||
|
android:duration="300"
|
||||||
|
android:fillAfter="true"
|
||||||
|
android:fromYDelta="0"
|
||||||
|
android:toYDelta="100%"
|
||||||
|
/>
|
||||||
|
</set>
|
||||||
7
mylibrary/src/main/res/color/select_text_color.xml
Normal file
7
mylibrary/src/main/res/color/select_text_color.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item android:color="@color/text_bg_blue" android:state_selected="true"></item>
|
||||||
|
<item android:color="@color/black" android:state_selected="false"></item>
|
||||||
|
<item android:color="@color/black"></item>
|
||||||
|
</selector>
|
||||||
BIN
mylibrary/src/main/res/drawable-hdpi/left.png
Normal file
BIN
mylibrary/src/main/res/drawable-hdpi/left.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 489 B |
BIN
mylibrary/src/main/res/drawable-xhdpi/black_back.png
Normal file
BIN
mylibrary/src/main/res/drawable-xhdpi/black_back.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
mylibrary/src/main/res/drawable-xhdpi/fab_add.png
Normal file
BIN
mylibrary/src/main/res/drawable-xhdpi/fab_add.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 229 B |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user