kotlin转化
This commit is contained in:
parent
89164dbd44
commit
90200b5348
@ -11,6 +11,7 @@
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/mylibrary" />
|
||||
</set>
|
||||
</option>
|
||||
</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_loading_all.xml" value="0.2171875" />
|
||||
<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>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
@ -83,40 +83,20 @@ dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||
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 'org.jetbrains:annotations:15.0'
|
||||
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.scwang.smart:refresh-layout-kernel: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.lxj:xpopup:2.2.8'
|
||||
//更新版本
|
||||
implementation 'com.github.jenly1314.AppUpdater:app-updater:1.1.0'
|
||||
implementation 'com.github.jenly1314.AppUpdater:app-dialog:1.1.0'
|
||||
//轮播插件
|
||||
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:AddressPicker:3.1.1'
|
||||
//EventBus
|
||||
@ -125,13 +105,6 @@ dependencies {
|
||||
//工具类
|
||||
implementation 'cn.hutool:hutool-all:5.7.11'
|
||||
//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
|
||||
@ -142,21 +115,10 @@ dependencies {
|
||||
//xui
|
||||
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.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
|
||||
|
||||
implementation 'com.github.tbruyelle:rxpermissions:0.12'
|
||||
|
||||
|
||||
implementation 'com.amap.api:3dmap:8.0.0'
|
||||
implementation 'com.amap.api:location:5.4.0'
|
||||
implementation 'com.amap.api:search:7.9.0'
|
||||
implementation project(path: ':mylibrary')
|
||||
}
|
||||
Binary file not shown.
@ -12,7 +12,7 @@
|
||||
"filters": [],
|
||||
"versionCode": 27,
|
||||
"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_height="@dimen/dp_22"
|
||||
android:layout_marginLeft="@dimen/dp_4"
|
||||
android:background="@drawable/selector_location"></ImageView>
|
||||
></ImageView>
|
||||
</LinearLayout>
|
||||
|
||||
<com.oneclouds.cargo.util.view.BaseRecyclerView
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/dp_6"
|
||||
android:background="@color/transparent"
|
||||
android:background="#00000000"
|
||||
android:hint="请输入车牌号/手机号进行搜索"
|
||||
android:inputType="text|textAutoComplete"
|
||||
android:singleLine="true"
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/dp_6"
|
||||
android:background="@color/transparent"
|
||||
android:background="#00000000"
|
||||
android:hint="请输入关键字"
|
||||
android:inputType="text|textAutoComplete"
|
||||
android:singleLine="true"
|
||||
|
||||
@ -31,4 +31,5 @@
|
||||
<color name="tab_select">@color/color_theme</color>
|
||||
<color name="tab_select_no">#C9C9C9</color>
|
||||
<color name="gray">#999999</color>
|
||||
<color name="red">#FF0000</color>
|
||||
</resources>
|
||||
@ -1,5 +1,8 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
apply from: "compile.gradle"
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = "1.5.0"
|
||||
repositories {
|
||||
google()
|
||||
// jcenter() // 这个
|
||||
@ -18,6 +21,7 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
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
|
||||
// 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