desc:导入common lib
@ -0,0 +1 @@
|
|||||||
|
/build
|
@ -0,0 +1,72 @@
|
|||||||
|
apply from: "${rootProject.rootDir}/buildCommon/commonLibConfig.gradle"
|
||||||
|
project.ext.setLibDefaultConfig project
|
||||||
|
|
||||||
|
android {
|
||||||
|
defaultConfig {
|
||||||
|
ndk {
|
||||||
|
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
jni.srcDirs = []
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
buildConfigField 'String', 'BASE_URL_CONFIG_PATH', '"baseUrl.properties"'
|
||||||
|
}
|
||||||
|
release {
|
||||||
|
minifyEnabled true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
buildConfigField 'String', 'BASE_URL_CONFIG_PATH', '"baseUrl.properties"'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||||
|
implementation 'com.google.android.material:material:1.4.0'
|
||||||
|
|
||||||
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||||
|
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||||
|
|
||||||
|
implementation 'com.airbnb.android:lottie:5.0.2'
|
||||||
|
|
||||||
|
implementation(rootProject.ext.dependencies.mmkv)
|
||||||
|
|
||||||
|
// 添加kotlin依赖
|
||||||
|
implementation(rootProject.ext.dependencies.kotlin)
|
||||||
|
implementation(rootProject.ext.dependencies.kotlin_android)
|
||||||
|
// 添加okhttp依赖
|
||||||
|
implementation(rootProject.ext.dependencies.okhttp)
|
||||||
|
// 添加okhttp日志
|
||||||
|
implementation(rootProject.ext.dependencies.okhttp_logger)
|
||||||
|
// 添加retrofit依赖
|
||||||
|
implementation rootProject.ext.dependencies.retrofit
|
||||||
|
// 添加retrofit转化gson能力依赖
|
||||||
|
implementation rootProject.ext.dependencies.converter_gson
|
||||||
|
// 添加rxjava依赖
|
||||||
|
implementation rootProject.ext.dependencies.rxjava
|
||||||
|
// 添加rxAndroid依赖
|
||||||
|
implementation rootProject.ext.dependencies.rxandroid
|
||||||
|
// 添加retrofit和rxjava适配器
|
||||||
|
implementation rootProject.ext.dependencies.retrofit_rxjava
|
||||||
|
|
||||||
|
//luban图片压缩
|
||||||
|
implementation rootProject.ext.dependencies.luban
|
||||||
|
|
||||||
|
// glide
|
||||||
|
implementation rootProject.ext.dependencies.glide
|
||||||
|
// glide替换为OkHttp3代理请求
|
||||||
|
implementation rootProject.ext.dependencies.gilde_integration
|
||||||
|
// lifecycle_process
|
||||||
|
implementation rootProject.ext.dependencies.lifecycle_process
|
||||||
|
// glide注解
|
||||||
|
kapt rootProject.ext.dependencies.annotationProcessor
|
||||||
|
}
|
@ -0,0 +1,940 @@
|
|||||||
|
# compiler: R8
|
||||||
|
# compiler_version: 3.0.73
|
||||||
|
# pg_map_id: 11aaacb
|
||||||
|
# common_typos_disable
|
||||||
|
com.common.commonlib.CommonApplication -> com.common.commonlib.CommonApplication:
|
||||||
|
# {"id":"sourceFile","fileName":"CommonApplication.kt"}
|
||||||
|
1:1:void <init>():16:16 -> <init>
|
||||||
|
1:1:void onCreate():18:18 -> onCreate
|
||||||
|
2:2:void intLibs(android.content.Context):26:26 -> onCreate
|
||||||
|
2:2:void onCreate():19 -> onCreate
|
||||||
|
3:3:void initNet():32:32 -> onCreate
|
||||||
|
3:3:void intLibs(android.content.Context):28 -> onCreate
|
||||||
|
3:3:void onCreate():19 -> onCreate
|
||||||
|
com.common.commonlib.image.module.OkHttpLibraryGlideModule -> com.common.commonlib.image.module.OkHttpLibraryGlideModule:
|
||||||
|
# {"id":"sourceFile","fileName":"OkHttpLibraryGlideModule.kt"}
|
||||||
|
1:1:void <init>():19:19 -> <init>
|
||||||
|
1:1:void registerComponents(android.content.Context,com.bumptech.glide.Glide,com.bumptech.glide.Registry):23:23 -> registerComponents
|
||||||
|
com.common.commonlib.net.manager.RequestManager -> a.a:
|
||||||
|
# {"id":"sourceFile","fileName":"RequestManager.kt"}
|
||||||
|
com.common.commonlib.net.manager.RequestManager INSTANCE -> a
|
||||||
|
1:17:void <clinit>():22:38 -> <clinit>
|
||||||
|
1:1:void <init>():20:20 -> <init>
|
||||||
|
1:1:void loggingInterceptor$lambda-0(java.lang.String):39:39 -> a
|
||||||
|
2:59:void com.common.commonlib.log.Logger.d(java.lang.String,java.lang.Object):0:57 -> a
|
||||||
|
2:59:void loggingInterceptor$lambda-0(java.lang.String):39 -> a
|
||||||
|
60:138:void com.common.commonlib.log.Logger.d(java.lang.String,java.lang.Object,boolean):0:78 -> a
|
||||||
|
60:138:void com.common.commonlib.log.Logger.d(java.lang.String,java.lang.Object):57 -> a
|
||||||
|
60:138:void loggingInterceptor$lambda-0(java.lang.String):39 -> a
|
||||||
|
com.common.commonlib.net.bean.BaseResponse -> com.common.commonlib.net.bean.BaseResponse:
|
||||||
|
# {"id":"sourceFile","fileName":"BaseResponse.kt"}
|
||||||
|
1:1:void <init>():12:12 -> <init>
|
||||||
|
com.common.commonlib.net.bean.BaseResponse$Creator -> com.common.commonlib.net.bean.BaseResponse$a:
|
||||||
|
# {"id":"sourceFile","fileName":"BaseResponse.kt"}
|
||||||
|
1:1:com.common.commonlib.net.bean.BaseResponse createFromParcel(android.os.Parcel):0:0 -> createFromParcel
|
||||||
|
1:1:java.lang.Object createFromParcel(android.os.Parcel):0 -> createFromParcel
|
||||||
|
1:1:com.common.commonlib.net.bean.BaseResponse[] newArray(int):0:0 -> newArray
|
||||||
|
1:1:java.lang.Object[] newArray(int):0 -> newArray
|
||||||
|
com.common.commonlib.utils.BaseUtils -> com.common.commonlib.utils.BaseUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"BaseUtils.kt"}
|
||||||
|
1:1:void <init>():10:10 -> <init>
|
||||||
|
1:1:void enableBasicLog():39:39 -> enableBasicLog
|
||||||
|
2:2:void com.common.commonlib.net.manager.RequestManager.openBasicLog():102:102 -> enableBasicLog
|
||||||
|
2:2:void enableBasicLog():39 -> enableBasicLog
|
||||||
|
1:1:void enableFullLog():32:32 -> enableFullLog
|
||||||
|
2:2:void com.common.commonlib.net.manager.RequestManager.openFullLog():95:95 -> enableFullLog
|
||||||
|
2:2:void enableFullLog():32 -> enableFullLog
|
||||||
|
1:1:void enableHeadersLog():46:46 -> enableHeadersLog
|
||||||
|
2:2:void com.common.commonlib.net.manager.RequestManager.openHeadLog():109:109 -> enableHeadersLog
|
||||||
|
2:2:void enableHeadersLog():46 -> enableHeadersLog
|
||||||
|
1:1:java.lang.String getExternalStorageDirectory(android.content.Context):25:25 -> getExternalStorageDirectory
|
||||||
|
1:1:java.lang.String getExternalStoragePath(android.content.Context):21:21 -> getExternalStoragePath
|
||||||
|
1:1:boolean isListEmpty(java.util.List):14:14 -> isListEmpty
|
||||||
|
com.common.commonlib.utils.DateUtils -> com.common.commonlib.utils.DateUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"DateUtils.kt"}
|
||||||
|
1:1:void <init>():10:10 -> <init>
|
||||||
|
1:18:java.lang.String getDurationTimeByInt(int):61:78 -> getDurationTimeByInt
|
||||||
|
1:1:java.util.Date getNow():42:42 -> getNow
|
||||||
|
1:2:java.lang.String getNowTimeFormat(java.lang.String):47:48 -> getNowTimeFormat
|
||||||
|
com.common.commonlib.utils.DisplayUtils -> com.common.commonlib.utils.DisplayUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"DisplayUtils.kt"}
|
||||||
|
1:1:void <init>():8:8 -> <init>
|
||||||
|
1:1:int dp2px(android.content.Context,float):14:14 -> dp2px
|
||||||
|
1:1:int px2dp(android.content.Context,float):22:22 -> px2dp
|
||||||
|
com.common.commonlib.utils.FTPUtils -> com.common.commonlib.utils.FTPUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"FTPUtils.kt"}
|
||||||
|
1:1:void <init>():17:17 -> <init>
|
||||||
|
1:5:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):103:107 -> ftpDown
|
||||||
|
6:6:int org.apache.commons.net.ftp.FTP.getReplyCode():670:670 -> ftpDown
|
||||||
|
6:6:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):108 -> ftpDown
|
||||||
|
7:7:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):109:109 -> ftpDown
|
||||||
|
8:8:void org.apache.commons.net.ftp.FTPClient.setBufferSize(int):3451:3451 -> ftpDown
|
||||||
|
8:8:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):110 -> ftpDown
|
||||||
|
9:9:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):111:111 -> ftpDown
|
||||||
|
10:10:void org.apache.commons.net.ftp.FTP.setControlEncoding(java.lang.String):418:418 -> ftpDown
|
||||||
|
10:10:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):111 -> ftpDown
|
||||||
|
11:15:void org.apache.commons.net.ftp.FTPClient.enterLocalPassiveMode():1233:1237 -> ftpDown
|
||||||
|
11:15:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):112 -> ftpDown
|
||||||
|
16:19:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):113:116 -> ftpDown
|
||||||
|
20:20:int org.apache.commons.net.ftp.FTP.quit():864:864 -> ftpDown
|
||||||
|
20:20:boolean org.apache.commons.net.ftp.FTPClient.logout():1109 -> ftpDown
|
||||||
|
20:20:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):117 -> ftpDown
|
||||||
|
21:34:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):118:131 -> ftpDown
|
||||||
|
35:42:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):124:131 -> ftpDown
|
||||||
|
43:44:com.common.commonlib.utils.FTPUtils$RESULT ftpDown(java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):130:131 -> ftpDown
|
||||||
|
1:6:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):51:56 -> ftpUpload
|
||||||
|
7:7:int org.apache.commons.net.ftp.FTP.getReplyCode():670:670 -> ftpUpload
|
||||||
|
7:7:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):57 -> ftpUpload
|
||||||
|
8:8:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):58:58 -> ftpUpload
|
||||||
|
9:9:void org.apache.commons.net.ftp.FTPClient.setBufferSize(int):3451:3451 -> ftpUpload
|
||||||
|
9:9:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):59 -> ftpUpload
|
||||||
|
10:10:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):60:60 -> ftpUpload
|
||||||
|
11:11:void org.apache.commons.net.ftp.FTP.setControlEncoding(java.lang.String):418:418 -> ftpUpload
|
||||||
|
11:11:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):60 -> ftpUpload
|
||||||
|
12:12:int org.apache.commons.net.ftp.FTP.type(int):1081:1081 -> ftpUpload
|
||||||
|
12:12:boolean org.apache.commons.net.ftp.FTPClient.setFileType(int):1519 -> ftpUpload
|
||||||
|
12:12:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):61 -> ftpUpload
|
||||||
|
13:13:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608:608 -> ftpUpload
|
||||||
|
13:13:int org.apache.commons.net.ftp.FTP.type(int):1081 -> ftpUpload
|
||||||
|
13:13:boolean org.apache.commons.net.ftp.FTPClient.setFileType(int):1519 -> ftpUpload
|
||||||
|
13:13:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):61 -> ftpUpload
|
||||||
|
14:16:boolean org.apache.commons.net.ftp.FTPClient.setFileType(int):1519:1521 -> ftpUpload
|
||||||
|
14:16:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):61 -> ftpUpload
|
||||||
|
17:21:void org.apache.commons.net.ftp.FTPClient.enterLocalPassiveMode():1233:1237 -> ftpUpload
|
||||||
|
17:21:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):62 -> ftpUpload
|
||||||
|
22:22:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):63:63 -> ftpUpload
|
||||||
|
23:23:boolean org.apache.commons.net.ftp.FTPClient.storeFile(java.lang.String,java.io.InputStream):1976:1976 -> ftpUpload
|
||||||
|
23:23:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):64 -> ftpUpload
|
||||||
|
24:36:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):65:77 -> ftpUpload
|
||||||
|
37:44:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):70:77 -> ftpUpload
|
||||||
|
45:48:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):74:77 -> ftpUpload
|
||||||
|
49:50:com.common.commonlib.utils.FTPUtils$RESULT ftpUpload(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String):76:77 -> ftpUpload
|
||||||
|
com.common.commonlib.utils.FTPUtils$RESULT -> com.common.commonlib.utils.FTPUtils$RESULT:
|
||||||
|
# {"id":"sourceFile","fileName":"FTPUtils.kt"}
|
||||||
|
1:1:void <clinit>():31:31 -> <clinit>
|
||||||
|
1:1:void <init>(java.lang.String,int):31:31 -> <init>
|
||||||
|
com.common.commonlib.utils.MMKVUtils -> com.common.commonlib.utils.MMKVUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"MMKVUtils.kt"}
|
||||||
|
1:1:void <init>():12:12 -> <init>
|
||||||
|
1:1:boolean getBoolean(java.lang.String,java.lang.Object[]):43:43 -> getBoolean
|
||||||
|
1:1:byte[] getByteArray(java.lang.String,java.lang.Object[]):39:39 -> getByteArray
|
||||||
|
1:1:float getFloat(java.lang.String,java.lang.Object[]):47:47 -> getFloat
|
||||||
|
1:1:int getInt(java.lang.String,java.lang.Object[]):51:51 -> getInt
|
||||||
|
1:4:com.tencent.mmkv.MMKV getKV(java.lang.Object[]):67:70 -> getKV
|
||||||
|
5:5:com.tencent.mmkv.MMKV getKV(java.lang.Object[]):69:69 -> getKV
|
||||||
|
6:6:com.tencent.mmkv.MMKV getKV(java.lang.Object[]):68:68 -> getKV
|
||||||
|
1:1:long getLong(java.lang.String,java.lang.Object[]):55:55 -> getLong
|
||||||
|
1:1:java.lang.String getString(java.lang.String,java.lang.Object[]):59:59 -> getString
|
||||||
|
1:1:java.util.Set getStringSet(java.lang.String,java.lang.Object[]):63:63 -> getStringSet
|
||||||
|
1:11:void put(java.lang.String,java.lang.Object,java.lang.Object[]):23:33 -> put
|
||||||
|
12:12:void com.common.commonlib.log.Logger.e(java.lang.String,java.lang.Object):0:0 -> put
|
||||||
|
12:12:void put(java.lang.String,java.lang.Object,java.lang.Object[]):33 -> put
|
||||||
|
13:109:void com.common.commonlib.log.Logger.e(java.lang.String,java.lang.Object,boolean):0:96 -> put
|
||||||
|
13:109:void com.common.commonlib.log.Logger.e(java.lang.String,java.lang.Object):65 -> put
|
||||||
|
13:109:void put(java.lang.String,java.lang.Object,java.lang.Object[]):33 -> put
|
||||||
|
com.common.commonlib.utils.PhotoUtils -> com.common.commonlib.utils.PhotoUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"PhotoUtils.kt"}
|
||||||
|
1:1:void <init>():18:18 -> <init>
|
||||||
|
1:5:void compressPicture(android.content.Context,java.io.File,java.lang.String,top.zibin.luban.OnCompressListener):73:77 -> compressPicture
|
||||||
|
1:10:java.io.File generatePhotoFileByTime(android.content.Context,java.lang.String):25:34 -> generatePhotoFileByTime
|
||||||
|
1:6:java.lang.String getImageParentPath(android.content.Context,java.lang.String):54:59 -> getImageParentPath
|
||||||
|
1:9:java.lang.String initPicPath(android.content.Context,java.lang.String):39:47 -> initPicPath
|
||||||
|
1:1:void tans2PNGSave(java.io.File,java.lang.String,com.common.commonlib.utils.PhotoUtils$TransformCallBack):86:86 -> tans2PNGSave
|
||||||
|
com.common.commonlib.utils.PhotoUtils$TransformCallBack -> com.common.commonlib.utils.PhotoUtils$TransformCallBack:
|
||||||
|
# {"id":"sourceFile","fileName":"PhotoUtils.kt"}
|
||||||
|
com.common.commonlib.utils.PhotoUtils$tans2PNGSave$1 -> com.common.commonlib.utils.PhotoUtils$tans2PNGSave$1:
|
||||||
|
# {"id":"sourceFile","fileName":"PhotoUtils.kt"}
|
||||||
|
1:12:java.lang.Object invokeSuspend(java.lang.Object):86:97 -> invokeSuspend
|
||||||
|
13:22:java.lang.Object invokeSuspend(java.lang.Object):95:104 -> invokeSuspend
|
||||||
|
23:30:java.lang.Object invokeSuspend(java.lang.Object):97:104 -> invokeSuspend
|
||||||
|
com.common.commonlib.utils.PhotoUtils$tans2PNGSave$1$1 -> com.common.commonlib.utils.PhotoUtils$tans2PNGSave$1$1:
|
||||||
|
# {"id":"sourceFile","fileName":"PhotoUtils.kt"}
|
||||||
|
1:4:java.lang.Object invokeSuspend(java.lang.Object):100:103 -> invokeSuspend
|
||||||
|
com.common.commonlib.utils.SpManager -> com.common.commonlib.utils.SpManager:
|
||||||
|
# {"id":"sourceFile","fileName":"SpManager.kt"}
|
||||||
|
1:1:void <init>():13:13 -> <init>
|
||||||
|
1:1:boolean getBoolean(java.lang.String):30:30 -> getBoolean
|
||||||
|
1:1:int getInt(java.lang.String):39:39 -> getInt
|
||||||
|
1:1:long getLong(java.lang.String):57:57 -> getLong
|
||||||
|
1:1:java.lang.String getString(java.lang.String):48:48 -> getString
|
||||||
|
1:2:void init(android.content.Context,java.lang.String,int):20:21 -> init
|
||||||
|
1:2:void putBoolean(java.lang.String,boolean):25:26 -> putBoolean
|
||||||
|
1:2:void putInt(java.lang.String,int):34:35 -> putInt
|
||||||
|
1:2:void putLong(java.lang.String,long):52:53 -> putLong
|
||||||
|
1:2:void putString(java.lang.String,java.lang.String):43:44 -> putString
|
||||||
|
com.common.commonlib.utils.StringUtils -> com.common.commonlib.utils.StringUtils:
|
||||||
|
# {"id":"sourceFile","fileName":"StringUtils.kt"}
|
||||||
|
1:1:void <init>():8:8 -> <init>
|
||||||
|
1:4:java.util.List getListByString(java.lang.String):29:32 -> getListByString
|
||||||
|
1:6:java.lang.String getStringSeparateByLine(java.util.List):14:19 -> getStringSeparateByLine
|
||||||
|
com.common.commonlib.view.CommonTitleView -> com.common.commonlib.view.CommonTitleView:
|
||||||
|
android.content.Context mContext -> a
|
||||||
|
java.lang.String title -> g
|
||||||
|
int bgColor -> o
|
||||||
|
int fixedHeight -> i
|
||||||
|
int showStyle -> f
|
||||||
|
android.widget.ImageView ivRight -> d
|
||||||
|
android.widget.ImageView ivLeft -> b
|
||||||
|
com.common.commonlib.view.CommonTitleView$RightIconListener rightIconListener -> q
|
||||||
|
android.view.View rlRightHotZone -> k
|
||||||
|
android.view.View rlLeftHotZone -> j
|
||||||
|
android.widget.TextView tv_title -> c
|
||||||
|
android.view.View rlEditZone -> l
|
||||||
|
android.widget.TextView tv_edit -> e
|
||||||
|
android.graphics.drawable.Drawable leftDrawable -> m
|
||||||
|
com.common.commonlib.view.CommonTitleView$EditListener editListener -> r
|
||||||
|
boolean isFixedHeight -> h
|
||||||
|
android.graphics.drawable.Drawable rightDrawable -> n
|
||||||
|
com.common.commonlib.view.CommonTitleView$LeftIconListener leftIconListener -> p
|
||||||
|
1:1:void <init>(android.content.Context):52:52 -> <init>
|
||||||
|
2:2:void <init>(android.content.Context,android.util.AttributeSet):56:56 -> <init>
|
||||||
|
3:5:void <init>(android.content.Context,android.util.AttributeSet,int):60:62 -> <init>
|
||||||
|
1:10:void initAttrs(android.util.AttributeSet):89:98 -> a
|
||||||
|
1:10:void init(android.util.AttributeSet):66 -> a
|
||||||
|
11:25:void init(android.util.AttributeSet):67:81 -> a
|
||||||
|
26:86:void initStyle():114:174 -> a
|
||||||
|
26:86:void init(android.util.AttributeSet):83 -> a
|
||||||
|
87:96:void initStyle():156:165 -> a
|
||||||
|
87:96:void init(android.util.AttributeSet):83 -> a
|
||||||
|
97:102:void initStyle():140:145 -> a
|
||||||
|
97:102:void init(android.util.AttributeSet):83 -> a
|
||||||
|
103:124:void initStyle():132:153 -> a
|
||||||
|
103:124:void init(android.util.AttributeSet):83 -> a
|
||||||
|
125:130:void initStyle():124:129 -> a
|
||||||
|
125:130:void init(android.util.AttributeSet):83 -> a
|
||||||
|
131:136:void initStyle():116:121 -> a
|
||||||
|
131:136:void init(android.util.AttributeSet):83 -> a
|
||||||
|
137:137:void init(android.util.AttributeSet):84:84 -> a
|
||||||
|
1:3:int getEditState():234:236 -> getEditState
|
||||||
|
1:12:void onClick(android.view.View):187:198 -> onClick
|
||||||
|
1:5:void onMeasure(int,int):105:109 -> onMeasure
|
||||||
|
1:1:void setEditListener(com.common.commonlib.view.CommonTitleView$EditListener):230:230 -> setEditListener
|
||||||
|
1:5:void setEditText(int):245:249 -> setEditText
|
||||||
|
1:1:void setLeftIconListener(com.common.commonlib.view.CommonTitleView$LeftIconListener):210:210 -> setLeftIconListener
|
||||||
|
1:1:void setRightIconListener(com.common.commonlib.view.CommonTitleView$RightIconListener):220:220 -> setRightIconListener
|
||||||
|
1:2:void setTitle(java.lang.String):180:181 -> setTitle
|
||||||
|
com.common.commonlib.view.MikeView -> com.common.commonlib.view.MikeView:
|
||||||
|
int mImageW -> n
|
||||||
|
int mImageH -> o
|
||||||
|
int mCurrentPosition -> l
|
||||||
|
int mBackgroundRound -> m
|
||||||
|
int SCREEN_WIDTH -> j
|
||||||
|
int mVoiceRectStart -> k
|
||||||
|
int SCREEN_HEIGHT -> i
|
||||||
|
int mVoiceRectMarginTop -> d
|
||||||
|
int mVoiceRectH -> b
|
||||||
|
int mInterval -> c
|
||||||
|
android.graphics.Bitmap mVoiceRecording -> h
|
||||||
|
int mVoiceRectW -> a
|
||||||
|
android.graphics.Paint mBackgroundPaint -> g
|
||||||
|
android.graphics.Paint mVoiceRectPaint -> f
|
||||||
|
android.graphics.Paint mImagePaint -> e
|
||||||
|
int mMarginTop -> p
|
||||||
|
int mTextMarginBottom -> q
|
||||||
|
1:1:void <init>(android.content.Context):55:55 -> <init>
|
||||||
|
2:2:void <init>(android.content.Context,android.util.AttributeSet):59:59 -> <init>
|
||||||
|
3:3:void <init>(android.content.Context,android.util.AttributeSet,int):63:63 -> <init>
|
||||||
|
4:39:void <init>(android.content.Context,android.util.AttributeSet,int):29:64 -> <init>
|
||||||
|
1:22:void init():68:89 -> a
|
||||||
|
23:31:android.graphics.Bitmap scaleBitmap(android.graphics.Bitmap,int,int):149:157 -> a
|
||||||
|
23:31:void init():89 -> a
|
||||||
|
32:34:void init():89:91 -> a
|
||||||
|
1:21:void onDraw(android.graphics.Canvas):96:116 -> onDraw
|
||||||
|
1:2:void setIndex(int):128:129 -> setIndex
|
||||||
|
3:3:void setIndex(double):134:134 -> setIndex
|
||||||
|
com.common.commonlib.view.SlideRecyclerView -> com.common.commonlib.view.SlideRecyclerView:
|
||||||
|
android.view.VelocityTracker mVelocityTracker -> a
|
||||||
|
int mPosition -> j
|
||||||
|
float mFirstY -> g
|
||||||
|
int mMenuViewWidth -> k
|
||||||
|
android.widget.Scroller mScroller -> d
|
||||||
|
float mFirstX -> f
|
||||||
|
float mLastX -> e
|
||||||
|
android.view.ViewGroup mFlingView -> i
|
||||||
|
boolean mIsSlide -> h
|
||||||
|
int mTouchSlop -> b
|
||||||
|
android.graphics.Rect mTouchFrame -> c
|
||||||
|
1:1:void <init>(android.content.Context):41:41 -> <init>
|
||||||
|
2:2:void <init>(android.content.Context,android.util.AttributeSet):45:45 -> <init>
|
||||||
|
3:5:void <init>(android.content.Context,android.util.AttributeSet,int):49:51 -> <init>
|
||||||
|
1:4:void releaseVelocity():164:167 -> a
|
||||||
|
1:2:void closeMenu():213:214 -> closeMenu
|
||||||
|
1:3:void computeScroll():202:204 -> computeScroll
|
||||||
|
1:2:boolean onInterceptTouchEvent(android.view.MotionEvent):56:57 -> onInterceptTouchEvent
|
||||||
|
3:6:void obtainVelocity(android.view.MotionEvent):172:175 -> onInterceptTouchEvent
|
||||||
|
3:6:boolean onInterceptTouchEvent(android.view.MotionEvent):58 -> onInterceptTouchEvent
|
||||||
|
7:48:boolean onInterceptTouchEvent(android.view.MotionEvent):59:100 -> onInterceptTouchEvent
|
||||||
|
49:91:boolean onInterceptTouchEvent(android.view.MotionEvent):61:103 -> onInterceptTouchEvent
|
||||||
|
1:2:boolean onTouchEvent(android.view.MotionEvent):108:109 -> onTouchEvent
|
||||||
|
3:6:void obtainVelocity(android.view.MotionEvent):172:175 -> onTouchEvent
|
||||||
|
3:6:boolean onTouchEvent(android.view.MotionEvent):110 -> onTouchEvent
|
||||||
|
7:56:boolean onTouchEvent(android.view.MotionEvent):111:160 -> onTouchEvent
|
||||||
|
1:14:int pointToPosition(int,int):179:192 -> pointToPosition
|
||||||
|
com.common.commonlib.view.SpaceItemDecoration -> com.common.commonlib.view.SpaceItemDecoration:
|
||||||
|
1:1:void <init>():16:16 -> <init>
|
||||||
|
1:7:void getItemOffsets(android.graphics.Rect,android.view.View,androidx.recyclerview.widget.RecyclerView,androidx.recyclerview.widget.RecyclerView$State):29:35 -> getItemOffsets
|
||||||
|
com.common.commonlib.view.activity.BaseActivity -> com.common.commonlib.view.activity.BaseActivity:
|
||||||
|
1:1:void <init>():18:18 -> <init>
|
||||||
|
1:1:void onCreate(android.os.Bundle):22:22 -> onCreate
|
||||||
|
2:7:void initStatusBar():27:32 -> onCreate
|
||||||
|
2:7:void onCreate(android.os.Bundle):23 -> onCreate
|
||||||
|
com.common.commonlib.view.activity.PermissionCompatActivity -> com.common.commonlib.view.activity.PermissionCompatActivity:
|
||||||
|
android.app.Dialog mPermissionDialog -> a
|
||||||
|
1:1:void <init>():35:35 -> <init>
|
||||||
|
1:1:void onCreate(android.os.Bundle):44:44 -> onCreate
|
||||||
|
1:6:void onRequestPermissionsResult(int,java.lang.String[],int[]):81:86 -> onRequestPermissionsResult
|
||||||
|
7:28:void showPermissionDialog():102:123 -> onRequestPermissionsResult
|
||||||
|
7:28:void onRequestPermissionsResult(int,java.lang.String[],int[]):93 -> onRequestPermissionsResult
|
||||||
|
29:29:void onRequestPermissionsResult(int,java.lang.String[],int[]):96:96 -> onRequestPermissionsResult
|
||||||
|
1:1:void onRestart():49:49 -> onRestart
|
||||||
|
com.common.commonlib.view.activity.PermissionCompatActivity$1 -> b.a:
|
||||||
|
com.common.commonlib.view.activity.PermissionCompatActivity this$0 -> a
|
||||||
|
1:1:void <init>(com.common.commonlib.view.activity.PermissionCompatActivity):114:114 -> <init>
|
||||||
|
1:1:void onClick(android.content.DialogInterface,int):118:118 -> onClick
|
||||||
|
2:3:void com.common.commonlib.view.activity.PermissionCompatActivity.cancelPermissionDialog():128:129 -> onClick
|
||||||
|
2:3:void com.common.commonlib.view.activity.PermissionCompatActivity.access$000(com.common.commonlib.view.activity.PermissionCompatActivity):35 -> onClick
|
||||||
|
2:3:void onClick(android.content.DialogInterface,int):118 -> onClick
|
||||||
|
4:4:void onClick(android.content.DialogInterface,int):119:119 -> onClick
|
||||||
|
com.common.commonlib.view.activity.PermissionCompatActivity$2 -> b.b:
|
||||||
|
com.common.commonlib.view.activity.PermissionCompatActivity this$0 -> a
|
||||||
|
1:1:void <init>(com.common.commonlib.view.activity.PermissionCompatActivity):105:105 -> <init>
|
||||||
|
1:1:void onClick(android.content.DialogInterface,int):108:108 -> onClick
|
||||||
|
2:3:void com.common.commonlib.view.activity.PermissionCompatActivity.cancelPermissionDialog():128:129 -> onClick
|
||||||
|
2:3:void com.common.commonlib.view.activity.PermissionCompatActivity.access$000(com.common.commonlib.view.activity.PermissionCompatActivity):35 -> onClick
|
||||||
|
2:3:void onClick(android.content.DialogInterface,int):108 -> onClick
|
||||||
|
4:7:void onClick(android.content.DialogInterface,int):109:112 -> onClick
|
||||||
|
com.common.commonlib.view.fragment.BaseFragment -> com.common.commonlib.view.fragment.BaseFragment:
|
||||||
|
1:1:void <init>():10:10 -> <init>
|
||||||
|
1:2:void onAttach(android.content.Context):15:16 -> onAttach
|
||||||
|
com.common.commonlib.view.fragment.BaseNavigationFragment -> com.common.commonlib.view.fragment.BaseNavigationFragment:
|
||||||
|
# {"id":"sourceFile","fileName":"BaseNavigationFragment.kt"}
|
||||||
|
android.view.View lastView -> b
|
||||||
|
boolean isNavigationViewInit -> a
|
||||||
|
1:1:void <init>():8:8 -> <init>
|
||||||
|
1:1:boolean getIsNavigationViewInit():53:53 -> getIsNavigationViewInit
|
||||||
|
1:10:android.view.View onCreateView(android.view.LayoutInflater,android.view.ViewGroup,android.os.Bundle):16:25 -> onCreateView
|
||||||
|
1:6:void onViewCreated(android.view.View,android.os.Bundle):29:34 -> onViewCreated
|
||||||
|
1:1:void setIsNavigationViewInit(boolean):57:57 -> setIsNavigationViewInit
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.AutoPlayRecyclerView -> com.common.commonlib.view.viewpagerlayoutmanager.AutoPlayRecyclerView:
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper autoPlaySnapHelper -> a
|
||||||
|
1:1:void <init>(android.content.Context):17:17 -> <init>
|
||||||
|
2:2:void <init>(android.content.Context,android.util.AttributeSet):21:21 -> <init>
|
||||||
|
3:8:void <init>(android.content.Context,android.util.AttributeSet,int):25:30 -> <init>
|
||||||
|
1:9:boolean dispatchTouchEvent(android.view.MotionEvent):35:43 -> dispatchTouchEvent
|
||||||
|
10:12:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.start():91:93 -> dispatchTouchEvent
|
||||||
|
10:12:boolean dispatchTouchEvent(android.view.MotionEvent):44 -> dispatchTouchEvent
|
||||||
|
13:13:boolean dispatchTouchEvent(android.view.MotionEvent):38:38 -> dispatchTouchEvent
|
||||||
|
14:16:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.pause():84:86 -> dispatchTouchEvent
|
||||||
|
14:16:boolean dispatchTouchEvent(android.view.MotionEvent):39 -> dispatchTouchEvent
|
||||||
|
1:2:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):60:61 -> setLayoutManager
|
||||||
|
3:3:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):38:38 -> setLayoutManager
|
||||||
|
3:3:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
4:5:void com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper.destroyCallbacks():155:156 -> setLayoutManager
|
||||||
|
4:5:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.destroyCallbacks():76 -> setLayoutManager
|
||||||
|
4:5:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):42 -> setLayoutManager
|
||||||
|
4:5:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
6:8:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.destroyCallbacks():77:79 -> setLayoutManager
|
||||||
|
6:8:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):42 -> setLayoutManager
|
||||||
|
6:8:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
9:12:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):44:47 -> setLayoutManager
|
||||||
|
9:12:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
13:17:void com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper.setupCallbacks():144:148 -> setLayoutManager
|
||||||
|
13:17:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):49 -> setLayoutManager
|
||||||
|
13:17:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
18:21:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):50:53 -> setLayoutManager
|
||||||
|
18:21:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
22:27:void com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager.setInfinite(boolean):822:827 -> setLayoutManager
|
||||||
|
22:27:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):56 -> setLayoutManager
|
||||||
|
22:27:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
28:40:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):58:70 -> setLayoutManager
|
||||||
|
28:40:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
41:41:void com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper.setupCallbacks():145:145 -> setLayoutManager
|
||||||
|
41:41:void com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.attachToRecyclerView(androidx.recyclerview.widget.RecyclerView):49 -> setLayoutManager
|
||||||
|
41:41:void setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager):61 -> setLayoutManager
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper -> com.common.commonlib.view.viewpagerlayoutmanager.b:
|
||||||
|
android.os.Handler handler -> e
|
||||||
|
java.lang.Runnable autoPlayRunnable -> g
|
||||||
|
int direction -> i
|
||||||
|
int timeInterval -> f
|
||||||
|
boolean runnableAdded -> h
|
||||||
|
1:6:void <init>(int,int):28:33 -> <init>
|
||||||
|
1:1:void checkDirection(int):109:109 -> a
|
||||||
|
1:1:void checkTimeInterval(int):114:114 -> b
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper$1 -> com.common.commonlib.view.viewpagerlayoutmanager.a:
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper this$0 -> b
|
||||||
|
androidx.recyclerview.widget.RecyclerView$LayoutManager val$layoutManager -> a
|
||||||
|
1:1:void <init>(com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper,androidx.recyclerview.widget.RecyclerView$LayoutManager):58:58 -> <init>
|
||||||
|
1:4:void run():61:64 -> run
|
||||||
|
5:5:int com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.access$000(com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper):16:16 -> run
|
||||||
|
5:5:void run():65 -> run
|
||||||
|
6:8:void run():64:66 -> run
|
||||||
|
9:9:android.os.Handler com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.access$300(com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper):16:16 -> run
|
||||||
|
9:9:void run():66 -> run
|
||||||
|
10:10:java.lang.Runnable com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.access$100(com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper):16:16 -> run
|
||||||
|
10:10:void run():66 -> run
|
||||||
|
11:11:int com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper.access$200(com.common.commonlib.view.viewpagerlayoutmanager.AutoPlaySnapHelper):16:16 -> run
|
||||||
|
11:11:void run():66 -> run
|
||||||
|
12:12:void run():66:66 -> run
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.CarouselLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.CarouselLayoutManager:
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
1:1:float setInterval():83:83 -> k
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper -> com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper:
|
||||||
|
androidx.recyclerview.widget.RecyclerView$OnScrollListener mScrollListener -> d
|
||||||
|
android.widget.Scroller mGravityScroller -> b
|
||||||
|
androidx.recyclerview.widget.RecyclerView mRecyclerView -> a
|
||||||
|
boolean snapToCenter -> c
|
||||||
|
1:14:void <init>():9:22 -> <init>
|
||||||
|
1:1:boolean access$002(com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper,boolean):9:9 -> a
|
||||||
|
2:5:int com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager.getOffsetToCenter():798:801 -> a
|
||||||
|
2:5:void snapToCenterView(com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager,com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$OnPageChangeListener):124 -> a
|
||||||
|
6:13:void snapToCenterView(com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager,com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$OnPageChangeListener):126:133 -> a
|
||||||
|
1:5:boolean onFling(int,int):60:64 -> onFling
|
||||||
|
6:6:boolean com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager.getInfinite():818:818 -> onFling
|
||||||
|
6:6:boolean onFling(int,int):69 -> onFling
|
||||||
|
7:30:boolean onFling(int,int):69:92 -> onFling
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper$1 -> com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper$a:
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper this$0 -> b
|
||||||
|
boolean mScrolled -> a
|
||||||
|
1:3:void <init>(com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper):23:25 -> <init>
|
||||||
|
1:13:void onScrollStateChanged(androidx.recyclerview.widget.RecyclerView,int):29:41 -> onScrollStateChanged
|
||||||
|
14:14:boolean com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper.access$000(com.common.commonlib.view.viewpagerlayoutmanager.CenterSnapHelper):9:9 -> onScrollStateChanged
|
||||||
|
14:14:void onScrollStateChanged(androidx.recyclerview.widget.RecyclerView,int):41 -> onScrollStateChanged
|
||||||
|
15:18:void onScrollStateChanged(androidx.recyclerview.widget.RecyclerView,int):42:45 -> onScrollStateChanged
|
||||||
|
1:1:void onScrolled(androidx.recyclerview.widget.RecyclerView,int,int):53:53 -> onScrolled
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.CircleLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.CircleLayoutManager:
|
||||||
|
int radius -> q
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
float maxRemoveOffset() -> i
|
||||||
|
float minRemoveOffset() -> j
|
||||||
|
float setInterval() -> k
|
||||||
|
1:1:void setUp():181:181 -> l
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.CircleScaleLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.CircleScaleLayoutManager:
|
||||||
|
int radius -> q
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
float maxRemoveOffset() -> i
|
||||||
|
float minRemoveOffset() -> j
|
||||||
|
float setInterval() -> k
|
||||||
|
1:1:void setUp():194:194 -> l
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.GalleryLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.GalleryLayoutManager:
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
1:1:float setInterval():138:138 -> k
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper -> com.common.commonlib.view.viewpagerlayoutmanager.e:
|
||||||
|
androidx.recyclerview.widget.RecyclerView$LayoutManager mLayoutManager -> a
|
||||||
|
1:1:void <init>(androidx.recyclerview.widget.RecyclerView$LayoutManager,com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper$1):26:26 -> <init>
|
||||||
|
2:2:void <init>(androidx.recyclerview.widget.RecyclerView$LayoutManager):40:40 -> <init>
|
||||||
|
3:6:void <init>(androidx.recyclerview.widget.RecyclerView$LayoutManager):38:41 -> <init>
|
||||||
|
int getDecoratedMeasurement(android.view.View) -> a
|
||||||
|
int getStartAfterPadding() -> a
|
||||||
|
int getDecoratedMeasurementInOther(android.view.View) -> b
|
||||||
|
int getTotalSpace() -> b
|
||||||
|
int getTotalSpaceInOther() -> c
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper$1 -> com.common.commonlib.view.viewpagerlayoutmanager.c:
|
||||||
|
1:1:void <init>(androidx.recyclerview.widget.RecyclerView$LayoutManager):233:233 -> <init>
|
||||||
|
1:1:int getStartAfterPadding():246:246 -> a
|
||||||
|
2:3:int getDecoratedMeasurement(android.view.View):252:253 -> a
|
||||||
|
1:2:int getDecoratedMeasurementInOther(android.view.View):260:261 -> b
|
||||||
|
3:4:int getTotalSpace():293:294 -> b
|
||||||
|
1:2:int getTotalSpaceInOther():299:300 -> c
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper$2 -> com.common.commonlib.view.viewpagerlayoutmanager.d:
|
||||||
|
1:1:void <init>(androidx.recyclerview.widget.RecyclerView$LayoutManager):327:327 -> <init>
|
||||||
|
1:1:int getStartAfterPadding():340:340 -> a
|
||||||
|
2:3:int getDecoratedMeasurement(android.view.View):346:347 -> a
|
||||||
|
1:2:int getDecoratedMeasurementInOther(android.view.View):354:355 -> b
|
||||||
|
3:4:int getTotalSpace():387:388 -> b
|
||||||
|
1:2:int getTotalSpaceInOther():393:394 -> c
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.PageSnapHelper -> com.common.commonlib.view.viewpagerlayoutmanager.PageSnapHelper:
|
||||||
|
1:1:void <init>():5:5 -> <init>
|
||||||
|
1:5:boolean onFling(int,int):9:13 -> onFling
|
||||||
|
6:6:boolean com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager.getInfinite():818:818 -> onFling
|
||||||
|
6:6:boolean onFling(int,int):18 -> onFling
|
||||||
|
7:28:boolean onFling(int,int):18:39 -> onFling
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.RotateLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.RotateLayoutManager:
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
1:1:float setInterval():94:94 -> k
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ScaleLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.ScaleLayoutManager:
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
1:1:float setInterval():109:109 -> k
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ScrollHelper -> com.common.commonlib.view.viewpagerlayoutmanager.f:
|
||||||
|
1:5:void smoothScrollToPosition(androidx.recyclerview.widget.RecyclerView,com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager,int):10:14 -> a
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager -> com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager:
|
||||||
|
boolean mRecycleChildrenOnDetach -> n
|
||||||
|
int mPendingScrollPosition -> l
|
||||||
|
boolean mInfinite -> o
|
||||||
|
boolean mReverseLayout -> i
|
||||||
|
float mInterval -> g
|
||||||
|
boolean mShouldReverseLayout -> j
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper mOrientationHelper -> f
|
||||||
|
int mOrientation -> h
|
||||||
|
boolean mSmoothScrollbarEnabled -> k
|
||||||
|
float mOffset -> e
|
||||||
|
int mSpaceInOther -> d
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState mPendingSavedState -> m
|
||||||
|
int mDecoratedMeasurementInOther -> b
|
||||||
|
int mSpaceMain -> c
|
||||||
|
int mDecoratedMeasurement -> a
|
||||||
|
int mDistanceToBottom -> p
|
||||||
|
1:5:android.view.View getMeasureView(androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State,int):386:390 -> a
|
||||||
|
6:14:int computeScrollExtent():520:528 -> a
|
||||||
|
15:36:int scrollBy(int,androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):560:581 -> a
|
||||||
|
37:38:void layoutItems(androidx.recyclerview.widget.RecyclerView$Recycler):590:591 -> a
|
||||||
|
37:38:int scrollBy(int,androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):584 -> a
|
||||||
|
39:44:int getOffsetToPosition(int):805:810 -> a
|
||||||
|
1:7:int computeScrollOffset():506:512 -> b
|
||||||
|
8:19:float getOffsetOfRightAdapterPosition():778:789 -> b
|
||||||
|
8:19:int computeScrollOffset():515 -> b
|
||||||
|
20:20:int computeScrollOffset():516:516 -> b
|
||||||
|
1:9:int computeScrollRange():532:540 -> c
|
||||||
|
1:1:boolean canScrollHorizontally():200:200 -> canScrollHorizontally
|
||||||
|
1:1:boolean canScrollVertically():208:208 -> canScrollVertically
|
||||||
|
1:1:int computeHorizontalScrollExtent(androidx.recyclerview.widget.RecyclerView$State):487:487 -> computeHorizontalScrollExtent
|
||||||
|
1:1:int computeHorizontalScrollOffset(androidx.recyclerview.widget.RecyclerView$State):477:477 -> computeHorizontalScrollOffset
|
||||||
|
1:1:int computeHorizontalScrollRange(androidx.recyclerview.widget.RecyclerView$State):497:497 -> computeHorizontalScrollRange
|
||||||
|
1:1:int computeVerticalScrollExtent(androidx.recyclerview.widget.RecyclerView$State):492:492 -> computeVerticalScrollExtent
|
||||||
|
1:1:int computeVerticalScrollOffset(androidx.recyclerview.widget.RecyclerView$State):482:482 -> computeVerticalScrollOffset
|
||||||
|
1:1:int computeVerticalScrollRange(androidx.recyclerview.widget.RecyclerView$State):502:502 -> computeVerticalScrollRange
|
||||||
|
1:14:int getCurrentPosition():726:739 -> d
|
||||||
|
1:2:int getCurrentPositionOffset():769:770 -> e
|
||||||
|
1:2:void ensureLayoutState():445:446 -> ensureLayoutState
|
||||||
|
3:3:com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper.createVerticalHelper(androidx.recyclerview.widget.RecyclerView$LayoutManager):327:327 -> ensureLayoutState
|
||||||
|
3:3:com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper.createOrientationHelper(androidx.recyclerview.widget.RecyclerView$LayoutManager,int):220 -> ensureLayoutState
|
||||||
|
3:3:void ensureLayoutState():446 -> ensureLayoutState
|
||||||
|
4:4:com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper.createOrientationHelper(androidx.recyclerview.widget.RecyclerView$LayoutManager,int):222:222 -> ensureLayoutState
|
||||||
|
4:4:void ensureLayoutState():446 -> ensureLayoutState
|
||||||
|
5:5:com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper.createHorizontalHelper(androidx.recyclerview.widget.RecyclerView$LayoutManager):233:233 -> ensureLayoutState
|
||||||
|
5:5:com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper com.common.commonlib.view.viewpagerlayoutmanager.OrientationHelper.createOrientationHelper(androidx.recyclerview.widget.RecyclerView$LayoutManager,int):218 -> ensureLayoutState
|
||||||
|
5:5:void ensureLayoutState():446 -> ensureLayoutState
|
||||||
|
6:6:void ensureLayoutState():446:446 -> ensureLayoutState
|
||||||
|
float getDistanceRatio() -> f
|
||||||
|
1:3:android.view.View findViewByPosition(int):744:746 -> findViewByPosition
|
||||||
|
1:1:float getMaxOffset():677:677 -> g
|
||||||
|
1:1:androidx.recyclerview.widget.RecyclerView$LayoutParams generateDefaultLayoutParams():134:134 -> generateDefaultLayoutParams
|
||||||
|
1:1:int getOrientation():218:218 -> getOrientation
|
||||||
|
1:1:boolean getRecycleChildrenOnDetach():146:146 -> getRecycleChildrenOnDetach
|
||||||
|
1:1:boolean getReverseLayout():285:285 -> getReverseLayout
|
||||||
|
1:1:float getMinOffset():681:681 -> h
|
||||||
|
1:1:float maxRemoveOffset():710:710 -> i
|
||||||
|
1:1:float minRemoveOffset():718:718 -> j
|
||||||
|
float setInterval() -> k
|
||||||
|
void setUp() -> l
|
||||||
|
1:2:void onAdapterChanged(androidx.recyclerview.widget.RecyclerView$Adapter,androidx.recyclerview.widget.RecyclerView$Adapter):463:464 -> onAdapterChanged
|
||||||
|
1:4:boolean onAddFocusables(androidx.recyclerview.widget.RecyclerView,java.util.ArrayList,int,int):403:406 -> onAddFocusables
|
||||||
|
5:17:int getMovement(int):425:437 -> onAddFocusables
|
||||||
|
5:17:boolean onAddFocusables(androidx.recyclerview.widget.RecyclerView,java.util.ArrayList,int,int):407 -> onAddFocusables
|
||||||
|
18:21:boolean onAddFocusables(androidx.recyclerview.widget.RecyclerView,java.util.ArrayList,int,int):411:414 -> onAddFocusables
|
||||||
|
1:4:void onDetachedFromWindow(androidx.recyclerview.widget.RecyclerView,androidx.recyclerview.widget.RecyclerView$Recycler):168:171 -> onDetachedFromWindow
|
||||||
|
1:7:void onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):334:340 -> onLayoutChildren
|
||||||
|
8:11:void resolveShouldLayoutReverse():271:274 -> onLayoutChildren
|
||||||
|
8:11:void onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):341 -> onLayoutChildren
|
||||||
|
12:12:void resolveShouldLayoutReverse():272:272 -> onLayoutChildren
|
||||||
|
12:12:void onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):341 -> onLayoutChildren
|
||||||
|
13:48:void onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):344:379 -> onLayoutChildren
|
||||||
|
49:50:void layoutItems(androidx.recyclerview.widget.RecyclerView$Recycler):590:591 -> onLayoutChildren
|
||||||
|
49:50:void onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):382 -> onLayoutChildren
|
||||||
|
1:3:void onLayoutCompleted(androidx.recyclerview.widget.RecyclerView$State):396:398 -> onLayoutCompleted
|
||||||
|
1:3:void onRestoreInstanceState(android.os.Parcelable):189:191 -> onRestoreInstanceState
|
||||||
|
1:7:android.os.Parcelable onSaveInstanceState():177:183 -> onSaveInstanceState
|
||||||
|
1:4:int scrollHorizontallyBy(int,androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):545:548 -> scrollHorizontallyBy
|
||||||
|
1:4:void scrollToPosition(int):469:472 -> scrollToPosition
|
||||||
|
1:4:int scrollVerticallyBy(int,androidx.recyclerview.widget.RecyclerView$Recycler,androidx.recyclerview.widget.RecyclerView$State):553:556 -> scrollVerticallyBy
|
||||||
|
1:10:void setOrientation(int):229:238 -> setOrientation
|
||||||
|
1:1:void setRecycleChildrenOnDetach(boolean):163:163 -> setRecycleChildrenOnDetach
|
||||||
|
1:6:void setReverseLayout(boolean):289:294 -> setReverseLayout
|
||||||
|
1:1:void setSmoothScrollbarEnabled(boolean):882:882 -> setSmoothScrollbarEnabled
|
||||||
|
1:23:void smoothScrollToPosition(androidx.recyclerview.widget.RecyclerView,androidx.recyclerview.widget.RecyclerView$State,int):306:328 -> smoothScrollToPosition
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$OnPageChangeListener -> com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$a:
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState -> com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState:
|
||||||
|
float offset -> b
|
||||||
|
boolean isReverseLayout -> c
|
||||||
|
int position -> a
|
||||||
|
1:1:void <clinit>():892:892 -> <clinit>
|
||||||
|
1:1:void <init>():908:908 -> <init>
|
||||||
|
2:5:void <init>(android.os.Parcel):912:915 -> <init>
|
||||||
|
6:9:void <init>(com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState):918:921 -> <init>
|
||||||
|
1:3:void writeToParcel(android.os.Parcel,int):931:933 -> writeToParcel
|
||||||
|
com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState$1 -> com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState$a:
|
||||||
|
1:1:void <init>():893:893 -> <init>
|
||||||
|
1:1:com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState createFromParcel(android.os.Parcel):896:896 -> createFromParcel
|
||||||
|
1:1:java.lang.Object createFromParcel(android.os.Parcel):893 -> createFromParcel
|
||||||
|
1:1:com.common.commonlib.view.viewpagerlayoutmanager.ViewPagerLayoutManager$SavedState[] newArray(int):901:901 -> newArray
|
||||||
|
1:1:java.lang.Object[] newArray(int):893 -> newArray
|
||||||
|
org.apache.commons.net.MalformedServerReplyException -> c.a:
|
||||||
|
1:1:void <init>(java.lang.String):53:53 -> <init>
|
||||||
|
org.apache.commons.net.ProtocolCommandEvent -> c.b:
|
||||||
|
1:5:void <init>(java.lang.Object,java.lang.String,java.lang.String):57:61 -> <init>
|
||||||
|
6:10:void <init>(java.lang.Object,int,java.lang.String):81:85 -> <init>
|
||||||
|
org.apache.commons.net.ProtocolCommandListener -> c.c:
|
||||||
|
void protocolCommandSent(org.apache.commons.net.ProtocolCommandEvent) -> a
|
||||||
|
void protocolReplyReceived(org.apache.commons.net.ProtocolCommandEvent) -> b
|
||||||
|
org.apache.commons.net.ProtocolCommandSupport -> c.d:
|
||||||
|
1:3:void <init>(java.lang.Object):50:52 -> <init>
|
||||||
|
1:5:void fireCommandSent(java.lang.String,java.lang.String):71:75 -> a
|
||||||
|
6:10:void fireReplyReceived(int,java.lang.String):95:99 -> a
|
||||||
|
11:11:int getListenerCount():131:131 -> a
|
||||||
|
org.apache.commons.net.SocketClient -> c.e:
|
||||||
|
javax.net.SocketFactory _socketFactory_ -> d
|
||||||
|
javax.net.ServerSocketFactory _serverSocketFactory_ -> e
|
||||||
|
javax.net.SocketFactory __DEFAULT_SOCKET_FACTORY -> f
|
||||||
|
java.io.OutputStream _output_ -> c
|
||||||
|
javax.net.ServerSocketFactory __DEFAULT_SERVER_SOCKET_FACTORY -> g
|
||||||
|
java.net.Socket _socket_ -> a
|
||||||
|
java.io.InputStream _input_ -> b
|
||||||
|
1:5:void <clinit>():64:68 -> <clinit>
|
||||||
|
1:1:void <init>():124:124 -> <init>
|
||||||
|
2:19:void <init>():114:131 -> <init>
|
||||||
|
1:1:void connect(java.lang.String,int):203:203 -> a
|
||||||
|
2:10:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):175:183 -> a
|
||||||
|
2:10:void connect(java.lang.String,int):203 -> a
|
||||||
|
11:13:void org.apache.commons.net.SocketClient._connectAction_():153:155 -> a
|
||||||
|
11:13:void org.apache.commons.net.ftp.FTP._connectAction_():378 -> a
|
||||||
|
11:13:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
11:13:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
11:13:void connect(java.lang.String,int):203 -> a
|
||||||
|
14:14:void org.apache.commons.net.ftp.FTP._connectAction_():379:379 -> a
|
||||||
|
14:14:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
14:14:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
14:14:void connect(java.lang.String,int):203 -> a
|
||||||
|
15:15:java.lang.String org.apache.commons.net.ftp.FTP.getControlEncoding():427:427 -> a
|
||||||
|
15:15:void org.apache.commons.net.ftp.FTP._connectAction_():379 -> a
|
||||||
|
15:15:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
15:15:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
15:15:void connect(java.lang.String,int):203 -> a
|
||||||
|
16:18:void org.apache.commons.net.ftp.FTP._connectAction_():379:381 -> a
|
||||||
|
16:18:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
16:18:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
16:18:void connect(java.lang.String,int):203 -> a
|
||||||
|
19:19:java.lang.String org.apache.commons.net.ftp.FTP.getControlEncoding():427:427 -> a
|
||||||
|
19:19:void org.apache.commons.net.ftp.FTP._connectAction_():381 -> a
|
||||||
|
19:19:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
19:19:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
19:19:void connect(java.lang.String,int):203 -> a
|
||||||
|
20:20:void org.apache.commons.net.ftp.FTP._connectAction_():381:381 -> a
|
||||||
|
20:20:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
20:20:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
20:20:void connect(java.lang.String,int):203 -> a
|
||||||
|
21:21:void org.apache.commons.net.ftp.FTP.__getReply():294:294 -> a
|
||||||
|
21:21:void org.apache.commons.net.ftp.FTP._connectAction_():400 -> a
|
||||||
|
21:21:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
21:21:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
21:21:void connect(java.lang.String,int):203 -> a
|
||||||
|
22:22:void org.apache.commons.net.ftp.FTP._connectAction_():402:402 -> a
|
||||||
|
22:22:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
22:22:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
22:22:void connect(java.lang.String,int):203 -> a
|
||||||
|
23:23:void org.apache.commons.net.ftp.FTP.__getReply():294:294 -> a
|
||||||
|
23:23:void org.apache.commons.net.ftp.FTP._connectAction_():403 -> a
|
||||||
|
23:23:void org.apache.commons.net.ftp.FTPClient._connectAction_():924 -> a
|
||||||
|
23:23:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
23:23:void connect(java.lang.String,int):203 -> a
|
||||||
|
24:24:void org.apache.commons.net.ftp.FTPClient._connectAction_():925:925 -> a
|
||||||
|
24:24:void org.apache.commons.net.SocketClient.connect(java.net.InetAddress,int):183 -> a
|
||||||
|
24:24:void connect(java.lang.String,int):203 -> a
|
||||||
|
org.apache.commons.net.ftp.FTP -> d.a:
|
||||||
|
java.lang.String _replyString -> k
|
||||||
|
boolean _newReplyString -> j
|
||||||
|
java.io.BufferedReader _controlInput_ -> n
|
||||||
|
int _replyCode -> h
|
||||||
|
java.util.ArrayList _replyLines -> i
|
||||||
|
java.lang.String _controlEncoding -> l
|
||||||
|
java.io.BufferedWriter _controlOutput_ -> o
|
||||||
|
org.apache.commons.net.ProtocolCommandSupport _commandSupport_ -> m
|
||||||
|
1:7:void <init>():265:271 -> <init>
|
||||||
|
1:1:java.lang.String org.apache.commons.net.ftp.FTPCmd.getCommand():113:113 -> a
|
||||||
|
1:1:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608 -> a
|
||||||
|
1:1:int sendCommand(org.apache.commons.net.ftp.FTPCmd):582 -> a
|
||||||
|
2:2:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608:608 -> a
|
||||||
|
2:2:int sendCommand(org.apache.commons.net.ftp.FTPCmd):582 -> a
|
||||||
|
3:47:void __getReply(boolean):311:355 -> a
|
||||||
|
48:48:boolean org.apache.commons.net.ftp.FTP.__lenientCheck(java.lang.String):285:285 -> a
|
||||||
|
48:48:void __getReply(boolean):361 -> a
|
||||||
|
49:62:void __getReply(boolean):351:364 -> a
|
||||||
|
63:76:java.lang.String org.apache.commons.net.ftp.FTP.getReplyString():720:733 -> a
|
||||||
|
63:76:void __getReply(boolean):364 -> a
|
||||||
|
77:77:org.apache.commons.net.ProtocolCommandSupport org.apache.commons.net.ftp.FTP.getCommandSupport():1789:1789 -> a
|
||||||
|
77:77:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):778 -> a
|
||||||
|
77:77:void __getReply(boolean):364 -> a
|
||||||
|
78:78:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):778:778 -> a
|
||||||
|
78:78:void __getReply(boolean):364 -> a
|
||||||
|
79:79:org.apache.commons.net.ProtocolCommandSupport org.apache.commons.net.ftp.FTP.getCommandSupport():1789:1789 -> a
|
||||||
|
79:79:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):779 -> a
|
||||||
|
79:79:void __getReply(boolean):364 -> a
|
||||||
|
80:80:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):779:779 -> a
|
||||||
|
80:80:void __getReply(boolean):364 -> a
|
||||||
|
81:82:void __getReply(boolean):366:367 -> a
|
||||||
|
83:83:void __getReply(boolean):337:337 -> a
|
||||||
|
84:84:void __getReply(boolean):325:325 -> a
|
||||||
|
85:85:void __getReply(boolean):317:317 -> a
|
||||||
|
86:96:java.lang.String __buildMessage(java.lang.String,java.lang.String):488:498 -> a
|
||||||
|
97:98:void __send(java.lang.String):504:505 -> a
|
||||||
|
99:103:boolean org.apache.commons.net.SocketClient.isConnected():346:350 -> a
|
||||||
|
99:103:void __send(java.lang.String):509 -> a
|
||||||
|
104:108:void __send(java.lang.String):511:515 -> a
|
||||||
|
109:132:int eprt(java.net.InetAddress,int):964:987 -> a
|
||||||
|
133:133:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608:608 -> a
|
||||||
|
133:133:int eprt(java.net.InetAddress,int):987 -> a
|
||||||
|
1:7:int sendCommand(java.lang.String,java.lang.String):473:479 -> b
|
||||||
|
8:8:org.apache.commons.net.ProtocolCommandSupport org.apache.commons.net.ftp.FTP.getCommandSupport():1789:1789 -> b
|
||||||
|
8:8:void org.apache.commons.net.SocketClient.fireCommandSent(java.lang.String,java.lang.String):791 -> b
|
||||||
|
8:8:int sendCommand(java.lang.String,java.lang.String):481 -> b
|
||||||
|
9:9:void org.apache.commons.net.SocketClient.fireCommandSent(java.lang.String,java.lang.String):791:791 -> b
|
||||||
|
9:9:int sendCommand(java.lang.String,java.lang.String):481 -> b
|
||||||
|
10:10:org.apache.commons.net.ProtocolCommandSupport org.apache.commons.net.ftp.FTP.getCommandSupport():1789:1789 -> b
|
||||||
|
10:10:void org.apache.commons.net.SocketClient.fireCommandSent(java.lang.String,java.lang.String):792 -> b
|
||||||
|
10:10:int sendCommand(java.lang.String,java.lang.String):481 -> b
|
||||||
|
11:11:void org.apache.commons.net.SocketClient.fireCommandSent(java.lang.String,java.lang.String):792:792 -> b
|
||||||
|
11:11:int sendCommand(java.lang.String,java.lang.String):481 -> b
|
||||||
|
12:12:void org.apache.commons.net.ftp.FTP.__getReply():294:294 -> b
|
||||||
|
12:12:int sendCommand(java.lang.String,java.lang.String):483 -> b
|
||||||
|
13:13:int sendCommand(java.lang.String,java.lang.String):484:484 -> b
|
||||||
|
14:14:int sendCommand(java.lang.String,java.lang.String):474:474 -> b
|
||||||
|
org.apache.commons.net.ftp.FTPClient -> d.b:
|
||||||
|
java.util.HashMap __featuresMap -> x
|
||||||
|
java.util.regex.Pattern __PARMS_PAT -> y
|
||||||
|
boolean __remoteVerificationEnabled -> u
|
||||||
|
int __bufferSize -> v
|
||||||
|
int __fileType -> t
|
||||||
|
boolean __passiveNatWorkaround -> w
|
||||||
|
int __passivePort -> r
|
||||||
|
java.lang.String __passiveHost -> s
|
||||||
|
int __dataConnectionMode -> p
|
||||||
|
int __dataTimeout -> q
|
||||||
|
1:1:void <clinit>():401:401 -> <clinit>
|
||||||
|
1:1:void <init>():458:458 -> <init>
|
||||||
|
2:72:void <init>():396:466 -> <init>
|
||||||
|
1:1:java.lang.String org.apache.commons.net.ftp.FTPCmd.getCommand():113:113 -> a
|
||||||
|
1:1:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
2:8:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):633:639 -> a
|
||||||
|
2:8:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
9:12:java.io.OutputStream org.apache.commons.net.ftp.FTPClient.getBufferedOutputStream(java.io.OutputStream):3644:3647 -> a
|
||||||
|
9:12:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):639 -> a
|
||||||
|
9:12:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
13:14:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):641:642 -> a
|
||||||
|
13:14:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
15:15:int org.apache.commons.net.ftp.FTPClient.getBufferSize():3459:3459 -> a
|
||||||
|
15:15:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):653 -> a
|
||||||
|
15:15:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
16:30:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):653:667 -> a
|
||||||
|
16:30:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
31:31:void org.apache.commons.net.ftp.FTP.__getReply():294:294 -> a
|
||||||
|
31:31:int org.apache.commons.net.ftp.FTP.getReply():692 -> a
|
||||||
|
31:31:boolean org.apache.commons.net.ftp.FTPClient.completePendingCommand():1813 -> a
|
||||||
|
31:31:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):672 -> a
|
||||||
|
31:31:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
32:32:int org.apache.commons.net.ftp.FTP.getReply():693:693 -> a
|
||||||
|
32:32:boolean org.apache.commons.net.ftp.FTPClient.completePendingCommand():1813 -> a
|
||||||
|
32:32:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):672 -> a
|
||||||
|
32:32:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
33:33:boolean org.apache.commons.net.ftp.FTPClient.completePendingCommand():1813:1813 -> a
|
||||||
|
33:33:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):672 -> a
|
||||||
|
33:33:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
34:34:void org.apache.commons.net.io.Util.closeQuietly(java.net.Socket):370:370 -> a
|
||||||
|
34:34:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):659 -> a
|
||||||
|
34:34:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
35:35:boolean org.apache.commons.net.ftp.FTPClient._storeFile(java.lang.String,java.lang.String,java.io.InputStream):663:663 -> a
|
||||||
|
35:35:boolean __storeFile(org.apache.commons.net.ftp.FTPCmd,java.lang.String,java.io.InputStream):624 -> a
|
||||||
|
36:42:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1854:1860 -> a
|
||||||
|
36:42:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
43:46:java.io.InputStream org.apache.commons.net.ftp.FTPClient.getBufferedInputStream(java.io.InputStream):3651:3654 -> a
|
||||||
|
43:46:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1860 -> a
|
||||||
|
43:46:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
47:48:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1861:1862 -> a
|
||||||
|
47:48:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
49:49:int org.apache.commons.net.ftp.FTPClient.getBufferSize():3459:3459 -> a
|
||||||
|
49:49:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1873 -> a
|
||||||
|
49:49:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
50:50:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1873:1873 -> a
|
||||||
|
50:50:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
51:51:void org.apache.commons.net.io.Util.closeQuietly(java.io.Closeable):354:354 -> a
|
||||||
|
51:51:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1877 -> a
|
||||||
|
51:51:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
52:52:void org.apache.commons.net.io.Util.closeQuietly(java.net.Socket):370:370 -> a
|
||||||
|
52:52:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1878 -> a
|
||||||
|
52:52:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
53:53:void org.apache.commons.net.ftp.FTP.__getReply():294:294 -> a
|
||||||
|
53:53:int org.apache.commons.net.ftp.FTP.getReply():692 -> a
|
||||||
|
53:53:boolean org.apache.commons.net.ftp.FTPClient.completePendingCommand():1813 -> a
|
||||||
|
53:53:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1885 -> a
|
||||||
|
53:53:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
54:54:int org.apache.commons.net.ftp.FTP.getReply():693:693 -> a
|
||||||
|
54:54:boolean org.apache.commons.net.ftp.FTPClient.completePendingCommand():1813 -> a
|
||||||
|
54:54:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1885 -> a
|
||||||
|
54:54:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
55:55:boolean org.apache.commons.net.ftp.FTPClient.completePendingCommand():1813:1813 -> a
|
||||||
|
55:55:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1885 -> a
|
||||||
|
55:55:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
56:56:void org.apache.commons.net.io.Util.closeQuietly(java.io.Closeable):354:354 -> a
|
||||||
|
56:56:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1877 -> a
|
||||||
|
56:56:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
57:57:void org.apache.commons.net.io.Util.closeQuietly(java.net.Socket):370:370 -> a
|
||||||
|
57:57:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1878 -> a
|
||||||
|
57:57:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
58:58:boolean org.apache.commons.net.ftp.FTPClient._retrieveFile(java.lang.String,java.lang.String,java.io.OutputStream):1880:1880 -> a
|
||||||
|
58:58:boolean retrieveFile(java.lang.String,java.io.OutputStream):1845 -> a
|
||||||
|
1:16:void __initDefaults():473:488 -> b
|
||||||
|
1:1:void org.apache.commons.net.SocketClient.disconnect():312:312 -> c
|
||||||
|
1:1:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
1:1:void disconnect():986 -> c
|
||||||
|
2:2:void org.apache.commons.net.SocketClient.closeQuietly(java.net.Socket):323:323 -> c
|
||||||
|
2:2:void org.apache.commons.net.SocketClient.disconnect():312 -> c
|
||||||
|
2:2:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
2:2:void disconnect():986 -> c
|
||||||
|
3:3:void org.apache.commons.net.SocketClient.disconnect():313:313 -> c
|
||||||
|
3:3:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
3:3:void disconnect():986 -> c
|
||||||
|
4:4:void org.apache.commons.net.SocketClient.closeQuietly(java.io.Closeable):332:332 -> c
|
||||||
|
4:4:void org.apache.commons.net.SocketClient.disconnect():313 -> c
|
||||||
|
4:4:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
4:4:void disconnect():986 -> c
|
||||||
|
5:5:void org.apache.commons.net.SocketClient.disconnect():314:314 -> c
|
||||||
|
5:5:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
5:5:void disconnect():986 -> c
|
||||||
|
6:6:void org.apache.commons.net.SocketClient.closeQuietly(java.io.Closeable):332:332 -> c
|
||||||
|
6:6:void org.apache.commons.net.SocketClient.disconnect():314 -> c
|
||||||
|
6:6:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
6:6:void disconnect():986 -> c
|
||||||
|
7:9:void org.apache.commons.net.SocketClient.disconnect():315:317 -> c
|
||||||
|
7:9:void org.apache.commons.net.ftp.FTP.disconnect():443 -> c
|
||||||
|
7:9:void disconnect():986 -> c
|
||||||
|
10:13:void org.apache.commons.net.ftp.FTP.disconnect():444:447 -> c
|
||||||
|
10:13:void disconnect():986 -> c
|
||||||
|
14:14:void disconnect():987:987 -> c
|
||||||
|
15:15:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):784:784 -> c
|
||||||
|
16:16:java.net.InetAddress org.apache.commons.net.SocketClient.getRemoteAddress():658:658 -> c
|
||||||
|
16:16:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):789 -> c
|
||||||
|
17:25:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):789:797 -> c
|
||||||
|
26:26:java.net.InetAddress org.apache.commons.net.SocketClient.getLocalAddress():633:633 -> c
|
||||||
|
26:26:java.net.InetAddress org.apache.commons.net.ftp.FTPClient.getHostAddress():1396 -> c
|
||||||
|
26:26:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):797 -> c
|
||||||
|
27:27:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):797:797 -> c
|
||||||
|
28:28:java.net.InetAddress org.apache.commons.net.SocketClient.getLocalAddress():633:633 -> c
|
||||||
|
28:28:java.net.InetAddress org.apache.commons.net.ftp.FTPClient.getHostAddress():1396 -> c
|
||||||
|
28:28:java.net.InetAddress org.apache.commons.net.ftp.FTPClient.getReportHostAddress():1412 -> c
|
||||||
|
28:28:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):808 -> c
|
||||||
|
29:66:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):808:845 -> c
|
||||||
|
67:67:java.net.InetAddress org.apache.commons.net.SocketClient.getLocalAddress():633:633 -> c
|
||||||
|
67:67:java.net.InetAddress org.apache.commons.net.ftp.FTPClient.getHostAddress():1396 -> c
|
||||||
|
67:67:java.net.InetAddress org.apache.commons.net.ftp.FTPClient.getReportHostAddress():1412 -> c
|
||||||
|
67:67:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):812 -> c
|
||||||
|
68:68:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):812:812 -> c
|
||||||
|
69:79:int org.apache.commons.net.ftp.FTP.port(java.net.InetAddress,int):922:932 -> c
|
||||||
|
69:79:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):812 -> c
|
||||||
|
80:80:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608:608 -> c
|
||||||
|
80:80:int org.apache.commons.net.ftp.FTP.port(java.net.InetAddress,int):932 -> c
|
||||||
|
80:80:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):812 -> c
|
||||||
|
81:114:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):812:845 -> c
|
||||||
|
115:139:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):821:845 -> c
|
||||||
|
140:156:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):829:845 -> c
|
||||||
|
157:157:int org.apache.commons.net.ftp.FTP.epsv():1028:1028 -> c
|
||||||
|
157:157:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):859 -> c
|
||||||
|
158:158:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):861:861 -> c
|
||||||
|
159:177:void org.apache.commons.net.ftp.FTPClient._parseExtendedPassiveModeReply(java.lang.String):589:607 -> c
|
||||||
|
159:177:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):861 -> c
|
||||||
|
178:178:java.net.InetAddress org.apache.commons.net.SocketClient.getRemoteAddress():658:658 -> c
|
||||||
|
178:178:void org.apache.commons.net.ftp.FTPClient._parseExtendedPassiveModeReply(java.lang.String):617 -> c
|
||||||
|
178:178:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):861 -> c
|
||||||
|
179:180:void org.apache.commons.net.ftp.FTPClient._parseExtendedPassiveModeReply(java.lang.String):617:618 -> c
|
||||||
|
179:180:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):861 -> c
|
||||||
|
181:181:void org.apache.commons.net.ftp.FTPClient._parseExtendedPassiveModeReply(java.lang.String):611:611 -> c
|
||||||
|
181:181:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):861 -> c
|
||||||
|
182:182:void org.apache.commons.net.ftp.FTPClient._parseExtendedPassiveModeReply(java.lang.String):600:600 -> c
|
||||||
|
182:182:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):861 -> c
|
||||||
|
183:183:int org.apache.commons.net.ftp.FTP.pasv():1007:1007 -> c
|
||||||
|
183:183:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):869 -> c
|
||||||
|
184:184:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872:872 -> c
|
||||||
|
185:209:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):546:570 -> c
|
||||||
|
185:209:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
210:210:java.net.InetAddress org.apache.commons.net.SocketClient.getRemoteAddress():658:658 -> c
|
||||||
|
210:210:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):571 -> c
|
||||||
|
210:210:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
211:213:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):572:574 -> c
|
||||||
|
211:213:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
214:214:org.apache.commons.net.ProtocolCommandSupport org.apache.commons.net.ftp.FTP.getCommandSupport():1789:1789 -> c
|
||||||
|
214:214:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):778 -> c
|
||||||
|
214:214:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):574 -> c
|
||||||
|
214:214:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
215:215:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):778:778 -> c
|
||||||
|
215:215:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):574 -> c
|
||||||
|
215:215:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
216:216:org.apache.commons.net.ProtocolCommandSupport org.apache.commons.net.ftp.FTP.getCommandSupport():1789:1789 -> c
|
||||||
|
216:216:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):779 -> c
|
||||||
|
216:216:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):574 -> c
|
||||||
|
216:216:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
217:217:void org.apache.commons.net.SocketClient.fireReplyReceived(int,java.lang.String):779:779 -> c
|
||||||
|
217:217:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):574 -> c
|
||||||
|
217:217:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
218:222:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):576:580 -> c
|
||||||
|
218:222:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
223:256:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):875:908 -> c
|
||||||
|
257:257:boolean org.apache.commons.net.SocketClient.verifyRemote(java.net.Socket):675:675 -> c
|
||||||
|
257:257:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):908 -> c
|
||||||
|
258:258:java.net.InetAddress org.apache.commons.net.SocketClient.getRemoteAddress():658:658 -> c
|
||||||
|
258:258:boolean org.apache.commons.net.SocketClient.verifyRemote(java.net.Socket):676 -> c
|
||||||
|
258:258:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):908 -> c
|
||||||
|
259:259:boolean org.apache.commons.net.SocketClient.verifyRemote(java.net.Socket):678:678 -> c
|
||||||
|
259:259:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):908 -> c
|
||||||
|
260:262:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):910:912 -> c
|
||||||
|
263:263:java.net.InetAddress org.apache.commons.net.SocketClient.getRemoteAddress():658:658 -> c
|
||||||
|
263:263:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):912 -> c
|
||||||
|
264:264:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):912:912 -> c
|
||||||
|
265:265:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):562:562 -> c
|
||||||
|
265:265:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
266:266:void org.apache.commons.net.ftp.FTPClient._parsePassiveModeReply(java.lang.String):548:548 -> c
|
||||||
|
266:266:java.net.Socket _openDataConnection_(java.lang.String,java.lang.String):872 -> c
|
||||||
|
1:1:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608:608 -> d
|
||||||
|
1:1:int org.apache.commons.net.ftp.FTP.user(java.lang.String):753 -> d
|
||||||
|
1:1:boolean login(java.lang.String,java.lang.String):1034 -> d
|
||||||
|
2:8:boolean login(java.lang.String,java.lang.String):1036:1042 -> d
|
||||||
|
9:9:int org.apache.commons.net.ftp.FTP.sendCommand(org.apache.commons.net.ftp.FTPCmd,java.lang.String):608:608 -> d
|
||||||
|
9:9:int org.apache.commons.net.ftp.FTP.pass(java.lang.String):771 -> d
|
||||||
|
9:9:boolean login(java.lang.String,java.lang.String):1046 -> d
|
||||||
|
10:10:boolean login(java.lang.String,java.lang.String):1046:1046 -> d
|
||||||
|
org.apache.commons.net.ftp.FTPCmd -> d.c:
|
||||||
|
org.apache.commons.net.ftp.FTPCmd STOR -> e
|
||||||
|
org.apache.commons.net.ftp.FTPCmd QUIT -> d
|
||||||
|
org.apache.commons.net.ftp.FTPCmd PASV -> c
|
||||||
|
org.apache.commons.net.ftp.FTPCmd FEAT -> b
|
||||||
|
org.apache.commons.net.ftp.FTPCmd[] $VALUES -> f
|
||||||
|
org.apache.commons.net.ftp.FTPCmd EPSV -> a
|
||||||
|
1:40:void <clinit>():25:64 -> <clinit>
|
||||||
|
41:41:void <clinit>():24:24 -> <clinit>
|
||||||
|
1:1:void <init>(java.lang.String,int):24:24 -> <init>
|
||||||
|
1:1:org.apache.commons.net.ftp.FTPCmd valueOf(java.lang.String):24:24 -> valueOf
|
||||||
|
1:1:org.apache.commons.net.ftp.FTPCmd[] values():24:24 -> values
|
||||||
|
org.apache.commons.net.ftp.FTPConnectionClosedException -> d.d:
|
||||||
|
1:1:void <init>(java.lang.String):53:53 -> <init>
|
||||||
|
org.apache.commons.net.ftp.FTPReply -> d.e:
|
||||||
|
boolean isPositiveCompletion(int) -> a
|
||||||
|
boolean isPositivePreliminary(int) -> b
|
||||||
|
org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory -> e.a:
|
||||||
|
1:1:void <clinit>():46:46 -> <clinit>
|
||||||
|
org.apache.commons.net.io.CRLFLineReader -> f.a:
|
||||||
|
1:1:void <init>(java.io.Reader):43:43 -> <init>
|
||||||
|
1:19:java.lang.String readLine():54:72 -> readLine
|
||||||
|
20:20:java.lang.String readLine():70:70 -> readLine
|
||||||
|
org.apache.commons.net.io.CopyStreamException -> f.b:
|
||||||
|
1:3:void <init>(java.lang.String,long,java.io.IOException):47:49 -> <init>
|
||||||
|
org.apache.commons.net.io.CopyStreamListener -> f.c:
|
||||||
|
org.apache.commons.net.io.FromNetASCIIInputStream -> f.d:
|
||||||
|
boolean _noConversionRequired -> b
|
||||||
|
byte[] _lineSeparatorBytes -> c
|
||||||
|
int __length -> a
|
||||||
|
1:6:void <clinit>():42:47 -> <clinit>
|
||||||
|
1:1:void <init>(java.io.InputStream):73:73 -> <init>
|
||||||
|
2:2:void <init>(java.io.InputStream):51:51 -> <init>
|
||||||
|
1:16:int __read():81:96 -> a
|
||||||
|
1:4:int available():214:217 -> available
|
||||||
|
5:5:int available():215:215 -> available
|
||||||
|
1:5:int read():122:126 -> read
|
||||||
|
6:6:int read(byte[]):144:144 -> read
|
||||||
|
7:37:int read(byte[],int,int):165:195 -> read
|
||||||
|
org.apache.commons.net.io.ToNetASCIIOutputStream -> f.e:
|
||||||
|
boolean __lastWasCR -> a
|
||||||
|
1:2:void <init>(java.io.OutputStream):47:48 -> <init>
|
||||||
|
1:11:void write(int):70:80 -> write
|
||||||
|
12:12:void write(byte[]):97:97 -> write
|
||||||
|
13:13:void write(byte[],int,int):116:116 -> write
|
||||||
|
org.apache.commons.net.io.Util -> f.f:
|
||||||
|
1:39:long copyStream(java.io.InputStream,java.io.OutputStream,int,long,org.apache.commons.net.io.CopyStreamListener,boolean):96:134 -> a
|
||||||
|
org.apache.commons.net.util.ListenerList -> g.a:
|
||||||
|
1:2:void <init>():35:36 -> <init>
|
||||||
|
1:1:int getListenerCount():51:51 -> a
|
||||||
|
1:1:java.util.Iterator iterator():63:63 -> iterator
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.common.commonlib">
|
||||||
|
|
||||||
|
<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" />
|
||||||
|
</manifest>
|
@ -0,0 +1,2 @@
|
|||||||
|
debug1 = https://www.wanandroid.com
|
||||||
|
debug2 = https://www.baidu
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.common.commonlib
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleObserver
|
||||||
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
|
import com.common.commonlib.utils.BaseUtils
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础Application
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
open class CommonApplication : Application(), LifecycleObserver {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
||||||
|
intLibs(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun intLibs(context: Context) {
|
||||||
|
commonContext = context
|
||||||
|
|
||||||
|
// 初始化MMKV
|
||||||
|
MMKV.initialize(this)
|
||||||
|
|
||||||
|
initNet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initNet() {
|
||||||
|
BaseUtils.enableFullLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var commonContext: Context? = null
|
||||||
|
|
||||||
|
fun getContext(): Context? {
|
||||||
|
return commonContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_START)
|
||||||
|
open fun onAppForeground(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||||
|
open fun onAppBackground(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.common.commonlib.bean
|
||||||
|
|
||||||
|
data class GridPicBean(val imagePath:String, val isConverting: Boolean)
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.common.commonlib.image.config
|
||||||
|
|
||||||
|
import com.bumptech.glide.MemoryCategory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片加载基础配置
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object GlideBaseConfig {
|
||||||
|
|
||||||
|
enum class MemoryType(var memoryCategory: MemoryCategory) {
|
||||||
|
/**
|
||||||
|
* Tells Glide's memory cache and bitmap pool to use at most half of their initial maximum size.
|
||||||
|
*/
|
||||||
|
LOW(MemoryCategory.LOW),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells Glide's memory cache and bitmap pool to use at most their initial maximum size.
|
||||||
|
*/
|
||||||
|
NORMAL(MemoryCategory.NORMAL),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells Glide's memory cache and bitmap pool to use at most one and a half times their initial
|
||||||
|
* maximum size.
|
||||||
|
*/
|
||||||
|
HIGH(MemoryCategory.HIGH)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class LoadMode {
|
||||||
|
/**
|
||||||
|
* default loading type
|
||||||
|
*/
|
||||||
|
DEFAULT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cache all resource
|
||||||
|
*/
|
||||||
|
ALL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skip loading from disk
|
||||||
|
*/
|
||||||
|
SKIP_DISK,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skip loading from memory cache
|
||||||
|
*/
|
||||||
|
SKIP_MEM,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skip loading form all cache
|
||||||
|
*/
|
||||||
|
SKIP_CACHE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* don't load form internet
|
||||||
|
*/
|
||||||
|
SKIP_NET
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.common.commonlib.image.config
|
||||||
|
|
||||||
|
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换配置
|
||||||
|
* @param time 动画时长
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
class GlideTransitionConfig(time: Int?) {
|
||||||
|
val transition: DrawableTransitionOptions = if (time != null) {
|
||||||
|
DrawableTransitionOptions.withCrossFade(time)
|
||||||
|
} else {
|
||||||
|
DrawableTransitionOptions.withCrossFade()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.common.commonlib.image.loader
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import com.bumptech.glide.RequestBuilder
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||||
|
import com.common.commonlib.image.config.GlideBaseConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载配置辅助类
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object ConfigHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带有过渡效果的加载
|
||||||
|
* @param requestBuilder 请求构建器
|
||||||
|
* @param transformations 过渡效果
|
||||||
|
*
|
||||||
|
* @return 请求构建器
|
||||||
|
*/
|
||||||
|
fun loadWithTransformation(
|
||||||
|
requestBuilder: RequestBuilder<Drawable>,
|
||||||
|
transformations: List<BitmapTransformation>
|
||||||
|
): RequestBuilder<Drawable> {
|
||||||
|
var temp = requestBuilder
|
||||||
|
for (item in transformations) {
|
||||||
|
temp = temp.transform(item)
|
||||||
|
}
|
||||||
|
return temp
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带有缓存模式的加载
|
||||||
|
* @param requestBuilder 请求构建器
|
||||||
|
* @param loadingMode 加载缓存模式
|
||||||
|
*
|
||||||
|
* @return 请求构建器
|
||||||
|
*/
|
||||||
|
fun loadWithMod(
|
||||||
|
requestBuilder: RequestBuilder<Drawable>,
|
||||||
|
loadingMode: GlideBaseConfig.LoadMode
|
||||||
|
): RequestBuilder<Drawable> {
|
||||||
|
var request = requestBuilder
|
||||||
|
request = when (loadingMode) {
|
||||||
|
GlideBaseConfig.LoadMode.DEFAULT ->
|
||||||
|
request
|
||||||
|
GlideBaseConfig.LoadMode.ALL ->
|
||||||
|
request.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
|
GlideBaseConfig.LoadMode.SKIP_CACHE ->
|
||||||
|
request.skipMemoryCache(true)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
GlideBaseConfig.LoadMode.SKIP_DISK ->
|
||||||
|
request.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
GlideBaseConfig.LoadMode.SKIP_MEM ->
|
||||||
|
request.skipMemoryCache(true)
|
||||||
|
GlideBaseConfig.LoadMode.SKIP_NET ->
|
||||||
|
request.onlyRetrieveFromCache(true)
|
||||||
|
}
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.common.commonlib.image.loader
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import com.bumptech.glide.RequestBuilder
|
||||||
|
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
||||||
|
import com.common.commonlib.image.config.GlideHolderConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局配置适配器
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object GlobalConfigHelper {
|
||||||
|
/**
|
||||||
|
* 全局占位符配置
|
||||||
|
*/
|
||||||
|
var globalHolderConfig: GlideHolderConfig? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局过渡效果
|
||||||
|
*/
|
||||||
|
var globalTransition: DrawableTransitionOptions? = null
|
||||||
|
|
||||||
|
fun loadWithGlobalConfig(requestBuilder: RequestBuilder<Drawable>): RequestBuilder<Drawable> {
|
||||||
|
return loadWithGlobalConfig(requestBuilder, globalHolderConfig, globalTransition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadWithGlobalConfig(
|
||||||
|
requestBuilder: RequestBuilder<Drawable>,
|
||||||
|
holderConfig: GlideHolderConfig?
|
||||||
|
): RequestBuilder<Drawable> {
|
||||||
|
return loadWithGlobalConfig(requestBuilder, holderConfig, globalTransition)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadWithGlobalConfig(
|
||||||
|
requestBuilder: RequestBuilder<Drawable>,
|
||||||
|
holderConfig: GlideHolderConfig?,
|
||||||
|
transition: DrawableTransitionOptions?
|
||||||
|
): RequestBuilder<Drawable> {
|
||||||
|
var request = requestBuilder
|
||||||
|
if (holderConfig != null) {
|
||||||
|
if (holderConfig.holderDrawable != null) {
|
||||||
|
request = request.placeholder(holderConfig.holderDrawable)
|
||||||
|
}
|
||||||
|
if (holderConfig.holderId != -1) {
|
||||||
|
request = request.placeholder(holderConfig.holderId)
|
||||||
|
}
|
||||||
|
if (holderConfig.errorDrawable != null) {
|
||||||
|
request = request.error(holderConfig.errorDrawable)
|
||||||
|
}
|
||||||
|
if (holderConfig.errorId != -1) {
|
||||||
|
request = request.error(holderConfig.errorId)
|
||||||
|
}
|
||||||
|
if (holderConfig.errorBuilder != null) {
|
||||||
|
request = request.error(holderConfig.errorBuilder)
|
||||||
|
}
|
||||||
|
if (holderConfig.fallBackDrawable != null) {
|
||||||
|
request = request.fallback(holderConfig.fallBackDrawable)
|
||||||
|
}
|
||||||
|
if (holderConfig.fallBackId != -1) {
|
||||||
|
request = request.fallback(holderConfig.fallBackId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transition != null) {
|
||||||
|
request = request.transition(transition)
|
||||||
|
}
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package com.common.commonlib.image.loader
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.ImageView
|
||||||
|
import com.common.commonlib.image.config.GlideBaseConfig
|
||||||
|
import com.common.commonlib.image.config.GlideHolderConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片加载器接口
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
interface ILoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
* @param context 上下文
|
||||||
|
* @param memoryCategory 缓存类型
|
||||||
|
*/
|
||||||
|
fun init(context: Context, memoryCategory: GlideBaseConfig.MemoryType)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载图片
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片链接
|
||||||
|
* @param view 图片控件
|
||||||
|
*/
|
||||||
|
fun load(context: Context, url: String?, view: ImageView)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载圆角图片
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片链接
|
||||||
|
* @param view 图片控件
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
|
fun loadRound(context: Context, url: String?, view: ImageView, radius: Float)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载图片
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片链接
|
||||||
|
* @param view 图片控件
|
||||||
|
* @param loadingMode 加载模式
|
||||||
|
*/
|
||||||
|
fun loadWithMode(
|
||||||
|
context: Context,
|
||||||
|
url: String?,
|
||||||
|
view: ImageView,
|
||||||
|
loadingMode: GlideBaseConfig.LoadMode
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载图片
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片链接
|
||||||
|
* @param view 图片控件
|
||||||
|
* @param placeGlideHolder 占位图
|
||||||
|
*/
|
||||||
|
fun loadWithPlaceHolder(
|
||||||
|
context: Context,
|
||||||
|
url: String,
|
||||||
|
view: ImageView,
|
||||||
|
placeGlideHolder: GlideHolderConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理内存缓存
|
||||||
|
* @param context 上下文
|
||||||
|
*/
|
||||||
|
fun clearMemoryCache(context: Context)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理磁盘缓存
|
||||||
|
* @param context 上下文
|
||||||
|
*/
|
||||||
|
fun clearDiskCache(context: Context)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理缓存
|
||||||
|
* @param context 上下文
|
||||||
|
*/
|
||||||
|
fun clearAllCache(context: Context)
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.common.commonlib.image.module
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
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 com.bumptech.glide.module.LibraryGlideModule
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* okhttp配置
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
@GlideModule
|
||||||
|
class OkHttpLibraryGlideModule : LibraryGlideModule() {
|
||||||
|
|
||||||
|
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
||||||
|
// 替换网路请求使用okhttp
|
||||||
|
registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.common.commonlib.log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志敏感信息处理
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object LogSecureHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一个间隔一个将数据替换成*
|
||||||
|
*/
|
||||||
|
fun cast2Star(source: String): String {
|
||||||
|
val sourceTemp = source.toCharArray()
|
||||||
|
for (item in sourceTemp.withIndex()) {
|
||||||
|
if (item.index / 2 == 0) {
|
||||||
|
sourceTemp[item.index] = '*'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sourceTemp.toString()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package com.common.commonlib.log
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log工具类
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object Logger {
|
||||||
|
var commonTag = ""
|
||||||
|
var needSecurity = false
|
||||||
|
|
||||||
|
fun init(tag: String, security: Boolean) {
|
||||||
|
commonTag = tag
|
||||||
|
needSecurity = security
|
||||||
|
}
|
||||||
|
|
||||||
|
fun w(msg: Any?) {
|
||||||
|
w(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun d(msg: Any?) {
|
||||||
|
d(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun i(msg: Any?) {
|
||||||
|
i(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun e(msg: Any?) {
|
||||||
|
e(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun w(msg: Any?, needSecurity: Boolean) {
|
||||||
|
w(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun d(msg: Any?, needSecurity: Boolean) {
|
||||||
|
d(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun i(msg: Any?, needSecurity: Boolean) {
|
||||||
|
i(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun e(msg: Any?, needSecurity: Boolean) {
|
||||||
|
e(commonTag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun w(tag: String, msg: Any?) {
|
||||||
|
w(tag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun d(tag: String, msg: Any?) {
|
||||||
|
d(tag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun i(tag: String, msg: Any?) {
|
||||||
|
i(tag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun e(tag: String, msg: Any?) {
|
||||||
|
e(tag, msg.toString(), needSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun w(tag: String, msg: Any?, needSecurity: Boolean) {
|
||||||
|
Log.w(
|
||||||
|
tag, if (needSecurity)
|
||||||
|
LogSecureHelper.cast2Star(msg.toString())
|
||||||
|
else
|
||||||
|
msg.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun d(tag: String, msg: Any?, needSecurity: Boolean) {
|
||||||
|
Log.d(
|
||||||
|
tag, if (needSecurity)
|
||||||
|
LogSecureHelper.cast2Star(msg.toString())
|
||||||
|
else
|
||||||
|
msg.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun i(tag: String, msg: Any?, needSecurity: Boolean) {
|
||||||
|
Log.i(
|
||||||
|
tag, if (needSecurity)
|
||||||
|
LogSecureHelper.cast2Star(msg.toString())
|
||||||
|
else
|
||||||
|
msg.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun e(tag: String, msg: Any?, needSecurity: Boolean) {
|
||||||
|
Log.e(
|
||||||
|
tag, if (needSecurity)
|
||||||
|
LogSecureHelper.cast2Star(msg.toString())
|
||||||
|
else
|
||||||
|
msg.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
package com.common.commonlib.net
|
||||||
|
|
||||||
|
import android.net.ParseException
|
||||||
|
import android.util.Log
|
||||||
|
import com.common.commonlib.log.Logger
|
||||||
|
import com.common.commonlib.net.callback.RequestCallBack
|
||||||
|
import com.common.commonlib.net.interfaces.ITypedCommon
|
||||||
|
import com.common.commonlib.net.manager.RequestManager
|
||||||
|
import com.google.gson.JsonParseException
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.rxjava3.core.Observable
|
||||||
|
import io.reactivex.rxjava3.core.Observer
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import org.json.JSONException
|
||||||
|
import retrofit2.HttpException
|
||||||
|
import java.net.ConnectException
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.net.ssl.SSLHandshakeException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求基类
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
open class BaseObserve<T> : ITypedCommon {
|
||||||
|
var api: T
|
||||||
|
|
||||||
|
constructor(clazz: Class<T>) {
|
||||||
|
api = RequestManager.create(clazz, null, getType())
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(clazz: Class<T>, interceptors: List<Interceptor>) {
|
||||||
|
api = RequestManager.create(clazz, interceptors, getType())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供方法给外部获取API
|
||||||
|
*/
|
||||||
|
fun getAPI(): T {
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用接口
|
||||||
|
* @param observable 可订阅
|
||||||
|
* @param callBack 请求回调
|
||||||
|
*/
|
||||||
|
fun <R> observe(observable: Observable<R>?, callBack: RequestCallBack<R>?) {
|
||||||
|
if (observable == null) {
|
||||||
|
Logger.e("BaseObserve", "observe observable is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
observable
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.unsubscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : Observer<R> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(t: R) {
|
||||||
|
callBack?.onResult(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
e.message?.let { Log.e(TAG, it) }
|
||||||
|
callBack?.onError(dealError(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
callBack?.onComplete()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理错误
|
||||||
|
* @param e 异常
|
||||||
|
*/
|
||||||
|
private fun dealError(e: Throwable): String? {
|
||||||
|
if (e is HttpException) {
|
||||||
|
return when (e.code()) {
|
||||||
|
UNAUTHORIZED -> "登录验证过期"
|
||||||
|
INTERNAL_SERVER_ERROR -> "服务器错误"
|
||||||
|
FORBIDDEN, NOT_FOUND -> "无效的请求"
|
||||||
|
REQUEST_TIMEOUT, GATEWAY_TIMEOUT, BAD_GATEWAY, SERVICE_UNAVAILABLE -> e.message()
|
||||||
|
else -> e.message()
|
||||||
|
}
|
||||||
|
} else if (e is ConnectException) {
|
||||||
|
return "网络连接异常,请检查您的网络状态"
|
||||||
|
} else if (e is SocketTimeoutException) {
|
||||||
|
return "网络连接超时,请检查您的网络状态,稍后重试"
|
||||||
|
} else if (e is UnknownHostException) {
|
||||||
|
return "网络异常,请检查您的网络状态"
|
||||||
|
} else if (e is JsonParseException || e is JSONException || e is ParseException) {
|
||||||
|
return "数据解析错误"
|
||||||
|
} else if (e is SSLHandshakeException) {
|
||||||
|
return "网络异常,请检查您的网络状态"
|
||||||
|
} else if (e is RuntimeException) {
|
||||||
|
return "运行时异常"
|
||||||
|
}
|
||||||
|
return e.message
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG: String = "BaseLoader"
|
||||||
|
const val UNAUTHORIZED = 401
|
||||||
|
const val FORBIDDEN = 403
|
||||||
|
const val NOT_FOUND = 404
|
||||||
|
const val REQUEST_TIMEOUT = 408
|
||||||
|
const val INTERNAL_SERVER_ERROR = 500
|
||||||
|
const val BAD_GATEWAY = 502
|
||||||
|
const val SERVICE_UNAVAILABLE = 503
|
||||||
|
const val GATEWAY_TIMEOUT = 504
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): String {
|
||||||
|
return BaseObserve<T>::javaClass.name
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.common.commonlib.net.bean
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础响应类
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
open class BaseResponse : Parcelable {
|
||||||
|
var errorCode: Int = 0
|
||||||
|
var errorMessage: String = ""
|
||||||
|
|
||||||
|
fun getMErrorCode(): Int {
|
||||||
|
return errorCode
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMErrorMessage(): String {
|
||||||
|
return errorMessage
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.common.commonlib.net.bean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
data class RequestParam(var baseUrl: String) {
|
||||||
|
var params: Map<String, String>? = null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.common.commonlib.net.callback
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求回调
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
interface RequestCallBack<T> {
|
||||||
|
fun onResult(result: T)
|
||||||
|
fun onError(error: String?)
|
||||||
|
fun onComplete()
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.common.commonlib.net.callback
|
||||||
|
|
||||||
|
import com.common.commonlib.log.Logger
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不关注结果的的回调
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/8/2
|
||||||
|
*/
|
||||||
|
abstract class RequestNoResultCallBack<T> : RequestCallBack<T> {
|
||||||
|
override fun onResult(result: T) {
|
||||||
|
Logger.d("result ignore")
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract override fun onError(error: String?)
|
||||||
|
|
||||||
|
abstract override fun onComplete()
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.common.commonlib.net.callback
|
||||||
|
|
||||||
|
import com.common.commonlib.log.Logger
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不需要关注onComplete的请求回调
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/8/2
|
||||||
|
*/
|
||||||
|
abstract class RequestResultCallBack<T> : RequestCallBack<T> {
|
||||||
|
abstract override fun onResult(result: T)
|
||||||
|
|
||||||
|
abstract override fun onError(error: String?)
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
Logger.d("RequestResultCallBack: onComplete")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.common.commonlib.net.interceptor
|
||||||
|
|
||||||
|
import com.common.commonlib.net.interfaces.ITypedCommon
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用拦截器基类
|
||||||
|
*
|
||||||
|
* @author Alex Wang
|
||||||
|
* @since 2022-2-24
|
||||||
|
*/
|
||||||
|
abstract class CommonInterceptor : Interceptor, ITypedCommon {
|
||||||
|
/**
|
||||||
|
* 获取拦截器类型
|
||||||
|
*/
|
||||||
|
override fun getType(): String {
|
||||||
|
return CommonInterceptor::class.java.simpleName
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取拦截器key
|
||||||
|
*/
|
||||||
|
open fun getKey(): String {
|
||||||
|
return CommonInterceptor::class.java.simpleName
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package com.common.commonlib.net.interceptor
|
||||||
|
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
|
import com.common.commonlib.BuildConfig
|
||||||
|
import com.common.commonlib.CommonApplication
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HOST拦截器:动态替换HOST
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
class HostInterceptor : Interceptor {
|
||||||
|
/**
|
||||||
|
* 拦截替换BaseUrl
|
||||||
|
*/
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val oldRequest: Request = chain.request()
|
||||||
|
val requestBuilder: Request.Builder = oldRequest.newBuilder()
|
||||||
|
val headKey = BASE_URL_KEY
|
||||||
|
val headValue: String? = oldRequest.header(headKey)
|
||||||
|
// 判断是否需要替换BaseUrl,不需要则直接跳转
|
||||||
|
if (TextUtils.isEmpty(headValue)) {
|
||||||
|
return chain.proceed(chain.request())
|
||||||
|
}
|
||||||
|
// 该HEAD只用于替换BaseUrl,将对应的自定义HEAD去除
|
||||||
|
requestBuilder.removeHeader(headKey)
|
||||||
|
// 尝试获取新BaseUrl
|
||||||
|
val newUrlValue = getValueFromProperties(headValue)
|
||||||
|
val newBaseUrl: HttpUrl? = newUrlValue.toHttpUrlOrNull()
|
||||||
|
// 获取到新BaseUrl进行替换
|
||||||
|
return if (newBaseUrl != null) {
|
||||||
|
val oldHttpUrl: HttpUrl = oldRequest.url
|
||||||
|
val newUrl = oldHttpUrl.newBuilder()
|
||||||
|
.scheme(newBaseUrl.scheme)
|
||||||
|
.host(newBaseUrl.host)
|
||||||
|
.port(newBaseUrl.port)
|
||||||
|
.build()
|
||||||
|
chain.proceed(requestBuilder.url(newUrl).build())
|
||||||
|
} else {
|
||||||
|
chain.proceed(chain.request())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过KEY从配置文件中获取值
|
||||||
|
*/
|
||||||
|
private fun getValueFromProperties(key: String?): String {
|
||||||
|
val prop = Properties()
|
||||||
|
var value = ""
|
||||||
|
try {
|
||||||
|
val context = CommonApplication.getContext()
|
||||||
|
if (context == null) {
|
||||||
|
Log.e(TAG, "got context null, please init context!")
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
val mAssets = context.assets
|
||||||
|
if (mAssets == null) {
|
||||||
|
Log.e(TAG, "got assets null, please check the assets folder")
|
||||||
|
}
|
||||||
|
// 通过输入缓冲流进行读取配置文件
|
||||||
|
val inputStream =
|
||||||
|
BufferedInputStream(mAssets.open((BuildConfig.BASE_URL_CONFIG_PATH)))
|
||||||
|
// 加载输入流
|
||||||
|
prop.load(inputStream)
|
||||||
|
// 根据关键字获取value值
|
||||||
|
value = prop.getProperty(key);
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, e.toString())
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "BaseUrlInterceptor"
|
||||||
|
const val BASE_URL_KEY = "baseurl"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.common.commonlib.net.interceptor
|
||||||
|
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公共请求拦截器
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
open class RequestHeadInterceptor : CommonInterceptor() {
|
||||||
|
/**
|
||||||
|
* 请求头部参数
|
||||||
|
*/
|
||||||
|
var mHeaderHashMap: HashMap<String, String> = HashMap()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截请求并添加参数
|
||||||
|
*/
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val oldRequest: Request = chain.request()
|
||||||
|
val requestBuilder: Request.Builder = oldRequest.newBuilder()
|
||||||
|
requestBuilder.method(oldRequest.method, oldRequest.body)
|
||||||
|
if (mHeaderHashMap.size > 0) {
|
||||||
|
for (item: Map.Entry<String, String> in mHeaderHashMap.entries) {
|
||||||
|
requestBuilder.addHeader(item.key, item.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chain.proceed(requestBuilder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builder构造函数
|
||||||
|
*/
|
||||||
|
class Builder {
|
||||||
|
private var mHttpCommonInterceptor: RequestHeadInterceptor? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
mHttpCommonInterceptor = RequestHeadInterceptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHeadParams(key: String, value: String): Builder {
|
||||||
|
mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHeadParams(key: String, value: Int): Builder {
|
||||||
|
mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHeadParams(key: String, value: Long): Builder {
|
||||||
|
mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHeadParams(key: String, value: Float): Builder {
|
||||||
|
mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHeadParams(key: String, value: Double): Builder {
|
||||||
|
mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(): RequestHeadInterceptor {
|
||||||
|
return mHttpCommonInterceptor!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.common.commonlib.net.interceptor
|
||||||
|
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应头部拦截器
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
open class ResponseHeadInterceptor(private var callBack: ResponseCallBack?) : CommonInterceptor() {
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
// 获取响应
|
||||||
|
val response = chain.proceed(chain.request())
|
||||||
|
callBack?.onResult(response)
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResponseCallBack {
|
||||||
|
fun onResult(response: Response)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.common.commonlib.net.interfaces
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求类别基础接口
|
||||||
|
*
|
||||||
|
* @author Alex Wang
|
||||||
|
* @since 2022-2-25
|
||||||
|
*/
|
||||||
|
interface ITypedCommon {
|
||||||
|
/**
|
||||||
|
* 获取请求类别
|
||||||
|
*/
|
||||||
|
fun getType(): String
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package com.common.commonlib.net.manager
|
||||||
|
|
||||||
|
import com.common.commonlib.net.interceptor.CommonInterceptor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用拦截器管理类
|
||||||
|
* 用于请求的通用拦截器管理
|
||||||
|
*
|
||||||
|
* @author Alex Wang
|
||||||
|
* @since 2022-2-24
|
||||||
|
*/
|
||||||
|
object CommonInterceptorManager {
|
||||||
|
const val TAG = "CommonInterceptorManager"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截器
|
||||||
|
*/
|
||||||
|
private val mInterceptors: HashMap<String, HashMap<Any, CommonInterceptor>> = HashMap()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类型获取该类型拦截器列表
|
||||||
|
*
|
||||||
|
* @param type 拦截器类型
|
||||||
|
*
|
||||||
|
* @return 拦截器列表
|
||||||
|
*/
|
||||||
|
fun getInterceptorsByType(type: String): Map<Any, CommonInterceptor>? {
|
||||||
|
return mInterceptors[type]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类型获取该类型拦截器列表
|
||||||
|
*
|
||||||
|
* @param type 拦截器类型
|
||||||
|
*
|
||||||
|
* @return 拦截器列表
|
||||||
|
*/
|
||||||
|
fun getInterceptorsByType(type: String, key: String): CommonInterceptor? {
|
||||||
|
return mInterceptors[type]?.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类型列表获取通用拦截器
|
||||||
|
* @param typeList 拦截器类型
|
||||||
|
*
|
||||||
|
* @return 拦截器map
|
||||||
|
*/
|
||||||
|
fun getInterceptorsByTypeList(typeList: ArrayList<String>): HashMap<Any, CommonInterceptor> {
|
||||||
|
val result = HashMap<Any, CommonInterceptor>()
|
||||||
|
for (item in typeList) {
|
||||||
|
if (!getInterceptorsByType(item).isNullOrEmpty()) {
|
||||||
|
result.putAll(getInterceptorsByType(item)!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加新的通用拦截器
|
||||||
|
*
|
||||||
|
* @param interceptor 拦截器
|
||||||
|
*/
|
||||||
|
fun addInterceptorByType(interceptor: CommonInterceptor) {
|
||||||
|
val type = interceptor.getType()
|
||||||
|
val key = interceptor.getKey()
|
||||||
|
var map = mInterceptors[type]
|
||||||
|
if (map.isNullOrEmpty()) {
|
||||||
|
map = HashMap()
|
||||||
|
mInterceptors[type] = map
|
||||||
|
}
|
||||||
|
map[key] = interceptor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除通用拦截器
|
||||||
|
*
|
||||||
|
* @param type 请求类型
|
||||||
|
* @param key 拦截器key
|
||||||
|
*/
|
||||||
|
fun removeInterceptorByType(type: String, key: String) {
|
||||||
|
val map = mInterceptors[type]
|
||||||
|
if (!map.isNullOrEmpty()) {
|
||||||
|
map.remove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除通用拦截器
|
||||||
|
*
|
||||||
|
* @param type 请求类型
|
||||||
|
*/
|
||||||
|
fun removeInterceptorByType(type: String) {
|
||||||
|
mInterceptors.remove(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除通用拦截器
|
||||||
|
*
|
||||||
|
* @param interceptor 拦截器
|
||||||
|
*/
|
||||||
|
fun removeInterceptorByType(interceptor: CommonInterceptor) {
|
||||||
|
removeInterceptorByType(interceptor.getType(), interceptor.getKey())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.common.commonlib.net.manager
|
||||||
|
|
||||||
|
import com.common.commonlib.log.Logger.d
|
||||||
|
import com.common.commonlib.net.interceptor.HostInterceptor
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络请求管理器
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object RequestManager {
|
||||||
|
const val TAG = "RequestManager"
|
||||||
|
private var logLevel = HttpLoggingInterceptor.Level.NONE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认超时时间(s)
|
||||||
|
*/
|
||||||
|
private const val defaultTimeOut: Long = 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认读取超时时间(s)
|
||||||
|
*/
|
||||||
|
private const val defaultReadTimeOut: Long = 10
|
||||||
|
|
||||||
|
private var mRetrofit: Retrofit? = null
|
||||||
|
|
||||||
|
private val loggingInterceptor = HttpLoggingInterceptor {
|
||||||
|
d(TAG, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建retrofit
|
||||||
|
*
|
||||||
|
* @param service 类型
|
||||||
|
* @param interceptors 拦截器
|
||||||
|
* @param loaderType 请求类别
|
||||||
|
*/
|
||||||
|
fun <T> create(service: Class<T>, interceptors: List<Interceptor>?, loaderType: String): T {
|
||||||
|
init(interceptors, loaderType)
|
||||||
|
return mRetrofit!!.create(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun init(interceptors: List<Interceptor>?, loaderType: String) {
|
||||||
|
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||||
|
builder.connectTimeout(defaultTimeOut, TimeUnit.SECONDS)
|
||||||
|
builder.readTimeout(defaultReadTimeOut, TimeUnit.SECONDS)
|
||||||
|
|
||||||
|
// 动态HOST替换拦截器
|
||||||
|
builder.addInterceptor(HostInterceptor())
|
||||||
|
// 添加通用拦截器
|
||||||
|
val interceptorList = CommonInterceptorManager.getInterceptorsByType(loaderType)
|
||||||
|
if (!interceptorList.isNullOrEmpty()) {
|
||||||
|
d(TAG, "got common interceptor list")
|
||||||
|
for (item in interceptorList.values) {
|
||||||
|
builder.addInterceptor(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 添加接口自定义的拦截器
|
||||||
|
if (!interceptors.isNullOrEmpty()) {
|
||||||
|
for (intercept in interceptors) {
|
||||||
|
builder.addInterceptor(intercept)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加日志拦截器 日志拦截器,需要添加在所有拦截器之后
|
||||||
|
loggingInterceptor.level = logLevel
|
||||||
|
builder.addInterceptor(loggingInterceptor)
|
||||||
|
|
||||||
|
mRetrofit = Retrofit.Builder()
|
||||||
|
.client(builder.build())
|
||||||
|
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.baseUrl("https://www")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开完整日志
|
||||||
|
*/
|
||||||
|
fun openFullLog() {
|
||||||
|
logLevel = HttpLoggingInterceptor.Level.BODY
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开基础日志
|
||||||
|
*/
|
||||||
|
fun openBasicLog() {
|
||||||
|
logLevel = HttpLoggingInterceptor.Level.BASIC
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开头部日志
|
||||||
|
*/
|
||||||
|
fun openHeadLog() {
|
||||||
|
logLevel = HttpLoggingInterceptor.Level.HEADERS
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.common.commonlib.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Environment
|
||||||
|
import com.common.commonlib.net.manager.RequestManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础工具类
|
||||||
|
*/
|
||||||
|
object BaseUtils {
|
||||||
|
private const val TAG: String = "BaseUtils"
|
||||||
|
|
||||||
|
fun <T> isListEmpty(list: List<T>?): Boolean {
|
||||||
|
return list == null || list.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用中文件存储
|
||||||
|
*/
|
||||||
|
fun getExternalStoragePath(context: Context): String? {
|
||||||
|
return context.getExternalFilesDir(null)?.path
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getExternalStorageDirectory(context: Context): String? {
|
||||||
|
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开网络请求日志
|
||||||
|
*/
|
||||||
|
fun enableFullLog() {
|
||||||
|
RequestManager.openFullLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开网络请求基础日志
|
||||||
|
*/
|
||||||
|
fun enableBasicLog() {
|
||||||
|
RequestManager.openBasicLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开网络请求日志
|
||||||
|
*/
|
||||||
|
fun enableHeadersLog() {
|
||||||
|
RequestManager.openHeadLog()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.common.commonlib.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间工具类
|
||||||
|
*/
|
||||||
|
object DateUtils {
|
||||||
|
/**
|
||||||
|
* 如果使用大写HH标识使用24小时显示格式,如果使用小写hh就表示使用12小时制格式
|
||||||
|
*/
|
||||||
|
const val DATE_TO_STRING_DETAIL_PATTERN = "yyyy-MM-dd HH:mm:ss"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年-月-日 显示格式
|
||||||
|
* */
|
||||||
|
const val DATE_TO_STRING_SHORT_PATTERN = "yyyy.MM.dd"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年-月-日 显示格式
|
||||||
|
* */
|
||||||
|
const val DATE_TO_STRING_LONG_PATTERN = "yyyy_MM_dd HH:mm:ss"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 60秒
|
||||||
|
*/
|
||||||
|
const val SECONDS = 60
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 60分钟
|
||||||
|
*/
|
||||||
|
const val MINUS = 60
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到现在时间
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private fun getNow(): Date {
|
||||||
|
return Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SimpleDateFormat")
|
||||||
|
fun getNowTimeFormat(format: String): String {
|
||||||
|
val formatter = SimpleDateFormat(format)
|
||||||
|
return formatter.format(getNow())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将int型的数据转化成 XX:XX:XX" 形式的字符串
|
||||||
|
*/
|
||||||
|
fun getDurationTimeByInt(source: Int): String {
|
||||||
|
var temp = source
|
||||||
|
var h = 0
|
||||||
|
var m = 0
|
||||||
|
var s = 0
|
||||||
|
var result = ""
|
||||||
|
if (temp >= SECONDS * MINUS) {
|
||||||
|
h = temp / (SECONDS * MINUS)
|
||||||
|
temp -= h * (SECONDS * MINUS)
|
||||||
|
}
|
||||||
|
if (temp >= SECONDS) {
|
||||||
|
m = temp / SECONDS
|
||||||
|
temp -= m * SECONDS
|
||||||
|
}
|
||||||
|
s = temp
|
||||||
|
|
||||||
|
result = when {
|
||||||
|
h > 0 -> {
|
||||||
|
"$h:$m:$s\""
|
||||||
|
}
|
||||||
|
m > 0 -> {
|
||||||
|
"$m:$s\""
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
"$s\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.common.commonlib.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 界面工具类
|
||||||
|
*/
|
||||||
|
object DisplayUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp 转 px
|
||||||
|
*/
|
||||||
|
fun dp2px(context: Context, dpVale: Float): Int {
|
||||||
|
val density = context.resources.displayMetrics.density
|
||||||
|
return ((dpVale * density + 0.5f).toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* px 转 dp
|
||||||
|
*/
|
||||||
|
fun px2dp(context: Context, pxVale: Float): Int {
|
||||||
|
val density = context.resources.displayMetrics.density
|
||||||
|
return ((pxVale / density + 0.5f).toInt())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.common.commonlib.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkRequest
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleObserver
|
||||||
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
|
|
||||||
|
object NetworkHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络状态监听
|
||||||
|
*/
|
||||||
|
inline fun observerNetworkState(activity: FragmentActivity, crossinline callback: (Boolean) -> Unit) {
|
||||||
|
val manager = activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
val networkCallback = object : ConnectivityManager.NetworkCallback() {
|
||||||
|
override fun onAvailable(network: Network) {
|
||||||
|
super.onAvailable(network)
|
||||||
|
if (activity.isAlive) {
|
||||||
|
activity.runOnUiThread { callback(true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLost(network: Network) {
|
||||||
|
super.onLost(network)
|
||||||
|
if (activity.isAlive) {
|
||||||
|
activity.runOnUiThread { callback(false) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manager.requestNetwork(NetworkRequest.Builder().build(), networkCallback)
|
||||||
|
|
||||||
|
activity.lifecycle.addObserver(object : LifecycleObserver {
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||||
|
fun onDestroy() {
|
||||||
|
manager.unregisterNetworkCallback(networkCallback)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
fun isNetworkConnect(context: Context): Boolean {
|
||||||
|
val cm = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
return cm.activeNetworkInfo?.isAvailable ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toNetworkSetting(context: Context) {
|
||||||
|
val intent = Intent(Settings.ACTION_WIFI_SETTINGS)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.common.commonlib.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sharedPreference管理类
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
object SpManager {
|
||||||
|
const val HAS_INIT = "has_init"
|
||||||
|
private var sp: SharedPreferences? = null
|
||||||
|
private var editor: SharedPreferences.Editor? = null
|
||||||
|
|
||||||
|
@SuppressLint("CommitPrefEdits")
|
||||||
|
fun init(context: Context, name: String, mod: Int) {
|
||||||
|
sp = context.getSharedPreferences(name, mod)
|
||||||
|
editor = sp!!.edit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putBoolean(key: String, boolean: Boolean) {
|
||||||
|
editor!!.putBoolean(key, boolean)
|
||||||
|
editor!!.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBoolean(key: String): Boolean {
|
||||||
|
return sp!!.getBoolean(key, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putInt(key: String, value: Int) {
|
||||||
|
editor!!.putInt(key, value)
|
||||||
|
editor!!.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInt(key: String): Int {
|
||||||
|
return sp!!.getInt(key, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putString(key: String, value: String) {
|
||||||
|
editor!!.putString(key, value)
|
||||||
|
editor!!.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getString(key: String): String? {
|
||||||
|
return sp!!.getString(key, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putLong(key: String, value: Long) {
|
||||||
|
editor!!.putLong(key, value)
|
||||||
|
editor!!.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLong(key: String): Long {
|
||||||
|
return sp!!.getLong(key, -1L)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.common.commonlib.utils
|
||||||
|
|
||||||
|
import android.text.TextUtils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串工具类
|
||||||
|
*/
|
||||||
|
class StringUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字符串List转化为用 | 分割的字符串
|
||||||
|
*/
|
||||||
|
fun getStringSeparateByLine(list: List<String>): String {
|
||||||
|
var result = ""
|
||||||
|
for (item in list.withIndex()) {
|
||||||
|
result = if (item.index == (list.size - 1)) {
|
||||||
|
"$result${item.value}"
|
||||||
|
} else {
|
||||||
|
"$result${item.value}|"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 | 分割符转化为list
|
||||||
|
*/
|
||||||
|
fun getListByString(source: String): List<String> {
|
||||||
|
if (TextUtils.isEmpty(source)) {
|
||||||
|
return ArrayList()
|
||||||
|
}
|
||||||
|
return source.split("|")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
package com.common.commonlib.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.common.commonlib.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mic自定义View
|
||||||
|
*
|
||||||
|
* @author miracle
|
||||||
|
* @since 2021/8/2
|
||||||
|
*/
|
||||||
|
public class MikeView extends View {
|
||||||
|
//进度条格数
|
||||||
|
private final int COUNT = 16;
|
||||||
|
//宽、高、间隔、进度条居上距离
|
||||||
|
private int mVoiceRectW = 1;
|
||||||
|
private int mVoiceRectH = 10;
|
||||||
|
private int mInterval = 3;
|
||||||
|
private int mVoiceRectMarginTop = 83;
|
||||||
|
//mic 文字 进度条 背景
|
||||||
|
private Paint mImagePaint;
|
||||||
|
private Paint mVoiceRectPaint;
|
||||||
|
private Paint mBackgroundPaint;
|
||||||
|
|
||||||
|
private Bitmap mVoiceRecording;//mic图片
|
||||||
|
|
||||||
|
//屏幕宽高
|
||||||
|
private int SCREEN_HEIGHT = 0;
|
||||||
|
private int SCREEN_WIDTH = 0;
|
||||||
|
|
||||||
|
private int mVoiceRectStart = 0, mDescriptionW = 0;//进度条开始左边位置、文字长度
|
||||||
|
|
||||||
|
private int mCurrentPosition = 0;//当前位置
|
||||||
|
private int mBackgroundRound = 3;//背景圆角
|
||||||
|
|
||||||
|
private int mImageW = 42;//新mic图片宽
|
||||||
|
private int mImageH = 42;//新mic图片高
|
||||||
|
|
||||||
|
private int mMarginTop = 25, mTextMarginBottom = 11;//mic图片居上距离 文字居底部距离
|
||||||
|
|
||||||
|
public MikeView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MikeView(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MikeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||||
|
|
||||||
|
mImageW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mImageW, dm);
|
||||||
|
mImageH = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mImageH, dm);
|
||||||
|
mMarginTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMarginTop, dm);
|
||||||
|
mTextMarginBottom = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mTextMarginBottom, dm);
|
||||||
|
mVoiceRectW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mVoiceRectW, dm);
|
||||||
|
mVoiceRectH = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mVoiceRectH, dm);
|
||||||
|
mInterval = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mInterval, dm);
|
||||||
|
mVoiceRectMarginTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mVoiceRectMarginTop, dm);
|
||||||
|
mBackgroundRound = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBackgroundRound, dm);
|
||||||
|
|
||||||
|
mImagePaint = new Paint();
|
||||||
|
|
||||||
|
mVoiceRectPaint = new Paint();
|
||||||
|
mVoiceRectPaint.setColor(Color.WHITE);
|
||||||
|
|
||||||
|
mBackgroundPaint = new Paint();
|
||||||
|
mBackgroundPaint.setColor(Color.TRANSPARENT);//背景颜色
|
||||||
|
|
||||||
|
mVoiceRecording = BitmapFactory.decodeResource(getResources(), R.drawable.mike);
|
||||||
|
mVoiceRecording = scaleBitmap(mVoiceRecording, mImageW, mImageH);
|
||||||
|
|
||||||
|
setWillNotDraw(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
if (SCREEN_HEIGHT == 0 || SCREEN_WIDTH == 0) {
|
||||||
|
SCREEN_HEIGHT = getHeight();
|
||||||
|
SCREEN_WIDTH = getWidth();
|
||||||
|
}
|
||||||
|
if (mVoiceRectStart <= 0) {
|
||||||
|
mVoiceRectStart = SCREEN_WIDTH / 2 - (COUNT * mVoiceRectW + (COUNT - 1) * mInterval) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawRoundRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mBackgroundRound, mBackgroundRound, mBackgroundPaint);//画灰色背景和圆角
|
||||||
|
|
||||||
|
canvas.drawBitmap(mVoiceRecording, SCREEN_WIDTH / 2 - mVoiceRecording.getWidth() / 2, mMarginTop, mImagePaint);//画mic图片
|
||||||
|
|
||||||
|
//画前几个是白色 后几个是灰色
|
||||||
|
for (int i = 0; i < COUNT; i++) {
|
||||||
|
if (i < mCurrentPosition) {
|
||||||
|
mVoiceRectPaint.setColor(Color.WHITE);
|
||||||
|
} else {
|
||||||
|
mVoiceRectPaint.setColor(Color.parseColor("#73FFFFFF"));
|
||||||
|
}
|
||||||
|
canvas.drawRect(i * mVoiceRectW + (i * mInterval) + mVoiceRectStart, mVoiceRectMarginTop, i * mVoiceRectW + (i * mInterval) + mVoiceRectW + mVoiceRectStart, mVoiceRectMarginTop + mVoiceRectH, mVoiceRectPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int p) {
|
||||||
|
if (p < 0) {
|
||||||
|
p = 0;
|
||||||
|
}
|
||||||
|
if (p >= COUNT) {
|
||||||
|
p = COUNT - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentPosition = p;
|
||||||
|
postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(double percent) {
|
||||||
|
int p = (int) (COUNT * percent);
|
||||||
|
setIndex(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bitmap 缩放
|
||||||
|
*
|
||||||
|
* @param origin 源
|
||||||
|
* @param newWidth 宽
|
||||||
|
* @param newHeight 高
|
||||||
|
* @return bitmap
|
||||||
|
*/
|
||||||
|
private Bitmap scaleBitmap(Bitmap origin, int newWidth, int newHeight) {
|
||||||
|
if (origin == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int height = origin.getHeight();
|
||||||
|
int width = origin.getWidth();
|
||||||
|
float scaleWidth = ((float) newWidth) / width;
|
||||||
|
float scaleHeight = ((float) newHeight) / height;
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postScale(scaleWidth, scaleHeight);// 使用后乘
|
||||||
|
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
|
||||||
|
if (!origin.isRecycled()) {
|
||||||
|
origin.recycle();
|
||||||
|
}
|
||||||
|
return newBM;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.common.commonlib.view;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rv辅助类
|
||||||
|
*
|
||||||
|
* @author wangym
|
||||||
|
* @since 2021/7/28
|
||||||
|
*/
|
||||||
|
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
|
||||||
|
/**
|
||||||
|
* 默认图片展示单行数量
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_MEDIA_SIZE = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认图片展示间距
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_MEDIA_OFFSET = 30;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(@NotNull Rect outRect, @NotNull View view, RecyclerView parent, @NotNull RecyclerView.State state) {
|
||||||
|
int temp = parent.getChildAdapterPosition(view) % DEFAULT_MEDIA_SIZE;
|
||||||
|
outRect.left = DEFAULT_MEDIA_OFFSET * (temp);
|
||||||
|
|
||||||
|
if (parent.getChildAdapterPosition(view) >= DEFAULT_MEDIA_SIZE) {
|
||||||
|
outRect.top = DEFAULT_MEDIA_OFFSET;
|
||||||
|
} else {
|
||||||
|
outRect.top = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.common.commonlib.view.activity;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.common.commonlib.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础activity
|
||||||
|
*
|
||||||
|
* @author miracle
|
||||||
|
* @since 2021/8/2
|
||||||
|
*/
|
||||||
|
public class BaseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
initStatusBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initStatusBar() {
|
||||||
|
Window window = getWindow();
|
||||||
|
//After LOLLIPOP not translucent status bar
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
//Then call setStatusBarColor.
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
window.setStatusBarColor(getResources().getColor(R.color.title_bar_bg_color));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,164 @@
|
|||||||
|
package com.common.commonlib.view.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
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.common.commonlib.R;
|
||||||
|
import com.common.commonlib.bean.GridPicBean;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PicGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
private static final int TYPE_ONE = 0;
|
||||||
|
private static final int TYPE_TWO = 1;
|
||||||
|
private final List<GridPicBean> gridPicBeanList = new ArrayList<>();
|
||||||
|
private Context mContext;
|
||||||
|
private onAddClickListener onAddClickListener;
|
||||||
|
|
||||||
|
public PicGridAdapter(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (position == gridPicBeanList.size()) {
|
||||||
|
return TYPE_ONE;
|
||||||
|
} else {
|
||||||
|
return TYPE_TWO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
RecyclerView.ViewHolder viewHolder;
|
||||||
|
if (viewType == TYPE_ONE) {
|
||||||
|
View inflate = LayoutInflater.from(mContext).inflate(R.layout.item_grid_pic_add, parent, false);
|
||||||
|
viewHolder = new AddIconViewHolder(inflate);
|
||||||
|
} else {
|
||||||
|
View inflate = LayoutInflater.from(mContext).inflate(R.layout.item_grid_pic_show, parent, false);
|
||||||
|
viewHolder = new PicViewHolder(inflate);
|
||||||
|
}
|
||||||
|
return viewHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||||
|
if (position < gridPicBeanList.size()) {
|
||||||
|
if (holder instanceof PicViewHolder) {
|
||||||
|
PicViewHolder viewHolder = (PicViewHolder) holder;
|
||||||
|
GridPicBean gridPicBean = gridPicBeanList.get(position);
|
||||||
|
Glide.with(mContext).load(gridPicBean.getImagePath())
|
||||||
|
.transform(new MultiTransformation(new CenterCrop(), new RoundedCorners(5)))
|
||||||
|
.into(viewHolder.imageView);
|
||||||
|
viewHolder.imageDeleteView.setOnClickListener(l -> {
|
||||||
|
gridPicBeanList.remove(holder.getAdapterPosition());
|
||||||
|
notifyItemRemoved(holder.getAdapterPosition());
|
||||||
|
});
|
||||||
|
|
||||||
|
AnimatedVectorDrawable drawable = (AnimatedVectorDrawable) viewHolder.ivLoading.getDrawable();
|
||||||
|
if (gridPicBean.isConverting()) {
|
||||||
|
viewHolder.ivLoading.setVisibility(View.VISIBLE);
|
||||||
|
viewHolder.imageDeleteView.setVisibility(View.GONE);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
drawable.reset();
|
||||||
|
}
|
||||||
|
drawable.start();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
drawable.reset();
|
||||||
|
}
|
||||||
|
viewHolder.ivLoading.setVisibility(View.GONE);
|
||||||
|
viewHolder.imageDeleteView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (holder instanceof AddIconViewHolder) {
|
||||||
|
AddIconViewHolder viewHolder = (AddIconViewHolder) holder;
|
||||||
|
viewHolder.imageView.setOnClickListener(v -> {
|
||||||
|
if (gridPicBeanList.size() < 4) {
|
||||||
|
if (onAddClickListener != null) {
|
||||||
|
onAddClickListener.onClick(viewHolder.getAdapterPosition());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Toast.makeText(mContext, "最多添加四张!", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return gridPicBeanList.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnAddClickListener(PicGridAdapter.onAddClickListener onAddClickListener) {
|
||||||
|
this.onAddClickListener = onAddClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPicData(GridPicBean gridPicBean) {
|
||||||
|
gridPicBeanList.add(gridPicBean);
|
||||||
|
notifyItemRangeChanged(gridPicBeanList.size() - 1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPicData() {
|
||||||
|
gridPicBeanList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceData(int position, GridPicBean gridPicBean) {
|
||||||
|
gridPicBeanList.set(position, gridPicBean);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getImagePathList() {
|
||||||
|
List<String> images = new ArrayList<>();
|
||||||
|
for (GridPicBean gridPicBean : gridPicBeanList) {
|
||||||
|
images.add(gridPicBean.getImagePath());
|
||||||
|
}
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface onAddClickListener {
|
||||||
|
void onClick(int position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AddIconViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private ImageView imageView;
|
||||||
|
|
||||||
|
public AddIconViewHolder(@NonNull @NotNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
imageView = (ImageView) itemView.findViewById(R.id.bg_pic_add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PicViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private ImageView imageView;
|
||||||
|
private ImageView imageDeleteView;
|
||||||
|
private ImageView ivLoading;
|
||||||
|
|
||||||
|
public PicViewHolder(@NonNull @NotNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
imageView = itemView.findViewById(R.id.pic_iv);
|
||||||
|
imageDeleteView = itemView.findViewById(R.id.pic_delete_iv);
|
||||||
|
ivLoading = itemView.findViewById(R.id.iv_loading);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.common.commonlib.view.fragment;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class BaseFragment extends Fragment {
|
||||||
|
public Context mContext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull @NotNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.common.commonlib.view.fragment
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
|
||||||
|
abstract class BaseNavigationFragment : BaseFragment() {
|
||||||
|
private var isNavigationViewInit = false//记录是否已经初始化过一次视图
|
||||||
|
private var lastView: View? = null//记录上次创建的view
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
doPrepare()
|
||||||
|
//如果fragment的view已经创建则不再重新创建
|
||||||
|
if (lastView == null) {
|
||||||
|
lastView = getRootView(
|
||||||
|
inflater,
|
||||||
|
container,
|
||||||
|
savedInstanceState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return lastView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
if (!isNavigationViewInit) {//初始化过视图则不再进行view和data初始化
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
initView()
|
||||||
|
initData()
|
||||||
|
initOthers()
|
||||||
|
isNavigationViewInit = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun getRootView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View?
|
||||||
|
|
||||||
|
abstract fun initData()
|
||||||
|
|
||||||
|
abstract fun initView()
|
||||||
|
|
||||||
|
abstract fun initOthers()
|
||||||
|
|
||||||
|
abstract fun doPrepare()
|
||||||
|
|
||||||
|
fun getIsNavigationViewInit():Boolean{
|
||||||
|
return isNavigationViewInit
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setIsNavigationViewInit(isNavigationViewInit:Boolean){
|
||||||
|
this.isNavigationViewInit=isNavigationViewInit
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.common.commonlib.R;
|
||||||
|
|
||||||
|
public class AutoPlayRecyclerView extends RecyclerView {
|
||||||
|
private AutoPlaySnapHelper autoPlaySnapHelper;
|
||||||
|
|
||||||
|
public AutoPlayRecyclerView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoPlayRecyclerView(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoPlayRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoPlayRecyclerView);
|
||||||
|
final int timeInterval = typedArray.getInt(R.styleable.AutoPlayRecyclerView_timeInterval, AutoPlaySnapHelper.TIME_INTERVAL);
|
||||||
|
final int direction = typedArray.getInt(R.styleable.AutoPlayRecyclerView_direction, AutoPlaySnapHelper.RIGHT);
|
||||||
|
typedArray.recycle();
|
||||||
|
autoPlaySnapHelper = new AutoPlaySnapHelper(timeInterval, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||||
|
boolean result = super.dispatchTouchEvent(ev);
|
||||||
|
switch (ev.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
if (autoPlaySnapHelper != null) {
|
||||||
|
autoPlaySnapHelper.pause();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
if (autoPlaySnapHelper != null) {
|
||||||
|
autoPlaySnapHelper.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
autoPlaySnapHelper.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pause() {
|
||||||
|
autoPlaySnapHelper.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutManager(LayoutManager layout) {
|
||||||
|
super.setLayoutManager(layout);
|
||||||
|
autoPlaySnapHelper.attachToRecyclerView(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.view.animation.DecelerateInterpolator;
|
||||||
|
import android.widget.Scroller;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@link AutoPlayRecyclerView} to implement auto play effect
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AutoPlaySnapHelper extends CenterSnapHelper {
|
||||||
|
final static int TIME_INTERVAL = 2000;
|
||||||
|
|
||||||
|
final static int LEFT = 1;
|
||||||
|
final static int RIGHT = 2;
|
||||||
|
|
||||||
|
private Handler handler;
|
||||||
|
private int timeInterval;
|
||||||
|
private Runnable autoPlayRunnable;
|
||||||
|
private boolean runnableAdded;
|
||||||
|
private int direction;
|
||||||
|
|
||||||
|
AutoPlaySnapHelper(int timeInterval, int direction) {
|
||||||
|
checkTimeInterval(timeInterval);
|
||||||
|
checkDirection(direction);
|
||||||
|
handler = new Handler(Looper.getMainLooper());
|
||||||
|
this.timeInterval = timeInterval;
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachToRecyclerView(@Nullable RecyclerView recyclerView) throws IllegalStateException {
|
||||||
|
if (mRecyclerView == recyclerView) {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
|
if (mRecyclerView != null) {
|
||||||
|
destroyCallbacks();
|
||||||
|
}
|
||||||
|
mRecyclerView = recyclerView;
|
||||||
|
if (mRecyclerView != null) {
|
||||||
|
final RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
|
||||||
|
if (!(layoutManager instanceof ViewPagerLayoutManager)) return;
|
||||||
|
|
||||||
|
setupCallbacks();
|
||||||
|
mGravityScroller = new Scroller(mRecyclerView.getContext(),
|
||||||
|
new DecelerateInterpolator());
|
||||||
|
|
||||||
|
snapToCenterView((ViewPagerLayoutManager) layoutManager,
|
||||||
|
((ViewPagerLayoutManager) layoutManager).onPageChangeListener);
|
||||||
|
|
||||||
|
((ViewPagerLayoutManager) layoutManager).setInfinite(true);
|
||||||
|
|
||||||
|
autoPlayRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final int currentPosition =
|
||||||
|
((ViewPagerLayoutManager) layoutManager).getCurrentPositionOffset() *
|
||||||
|
(((ViewPagerLayoutManager) layoutManager).getReverseLayout() ? -1 : 1);
|
||||||
|
ScrollHelper.smoothScrollToPosition(mRecyclerView,
|
||||||
|
(ViewPagerLayoutManager) layoutManager, direction == RIGHT ? currentPosition + 1 : currentPosition - 1);
|
||||||
|
handler.postDelayed(autoPlayRunnable, timeInterval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.postDelayed(autoPlayRunnable, timeInterval);
|
||||||
|
runnableAdded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void destroyCallbacks() {
|
||||||
|
super.destroyCallbacks();
|
||||||
|
if (runnableAdded) {
|
||||||
|
handler.removeCallbacks(autoPlayRunnable);
|
||||||
|
runnableAdded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pause() {
|
||||||
|
if (runnableAdded) {
|
||||||
|
handler.removeCallbacks(autoPlayRunnable);
|
||||||
|
runnableAdded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
if (!runnableAdded) {
|
||||||
|
handler.postDelayed(autoPlayRunnable, timeInterval);
|
||||||
|
runnableAdded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTimeInterval(int timeInterval) {
|
||||||
|
checkTimeInterval(timeInterval);
|
||||||
|
this.timeInterval = timeInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDirection(int direction) {
|
||||||
|
checkDirection(direction);
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDirection(int direction) {
|
||||||
|
if (direction != LEFT && direction != RIGHT)
|
||||||
|
throw new IllegalArgumentException("direction should be one of left or right");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTimeInterval(int timeInterval) {
|
||||||
|
if (timeInterval <= 0)
|
||||||
|
throw new IllegalArgumentException("time interval should greater than 0");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,167 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ViewPagerLayoutManager}
|
||||||
|
* which layouts items like carousel
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class CarouselLayoutManager extends ViewPagerLayoutManager {
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private float minScale;
|
||||||
|
private float moveSpeed;
|
||||||
|
|
||||||
|
public CarouselLayoutManager(Context context, int itemSpace) {
|
||||||
|
this(new Builder(context, itemSpace));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CarouselLayoutManager(Context context, int itemSpace, int orientation) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CarouselLayoutManager(Context context, int itemSpace, int orientation, boolean reverseLayout) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CarouselLayoutManager(Builder builder) {
|
||||||
|
this(builder.context, builder.itemSpace, builder.minScale, builder.orientation,
|
||||||
|
builder.maxVisibleItemCount, builder.moveSpeed, builder.distanceToBottom,
|
||||||
|
builder.reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CarouselLayoutManager(Context context, int itemSpace, float minScale, int orientation,
|
||||||
|
int maxVisibleItemCount, float moveSpeed, int distanceToBottom,
|
||||||
|
boolean reverseLayout) {
|
||||||
|
super(context, orientation, reverseLayout);
|
||||||
|
setEnableBringCenterToFront(true);
|
||||||
|
setDistanceToBottom(distanceToBottom);
|
||||||
|
setMaxVisibleItemCount(maxVisibleItemCount);
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.minScale = minScale;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemSpace() {
|
||||||
|
return itemSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinScale() {
|
||||||
|
return minScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMoveSpeed() {
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemSpace(int itemSpace) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.itemSpace == itemSpace) return;
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinScale(float minScale) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (minScale > 1f) minScale = 1f;
|
||||||
|
if (this.minScale == minScale) return;
|
||||||
|
this.minScale = minScale;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.moveSpeed == moveSpeed) return;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setInterval() {
|
||||||
|
return (mDecoratedMeasurement - itemSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setItemViewProperty(View itemView, float targetOffset) {
|
||||||
|
float scale = calculateScale(targetOffset + mSpaceMain);
|
||||||
|
itemView.setScaleX(scale);
|
||||||
|
itemView.setScaleY(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
if (moveSpeed == 0) return Float.MAX_VALUE;
|
||||||
|
return 1 / moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setViewElevation(View itemView, float targetOffset) {
|
||||||
|
return itemView.getScaleX() * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calculateScale(float x) {
|
||||||
|
float deltaX = Math.abs(x - (mOrientationHelper.getTotalSpace() - mDecoratedMeasurement) / 2f);
|
||||||
|
return (minScale - 1) * deltaX / (mOrientationHelper.getTotalSpace() / 2f) + 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private static final float DEFAULT_SPEED = 1f;
|
||||||
|
private static final float MIN_SCALE = 0.5f;
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private int itemSpace;
|
||||||
|
private int orientation;
|
||||||
|
private float minScale;
|
||||||
|
private float moveSpeed;
|
||||||
|
private int maxVisibleItemCount;
|
||||||
|
private boolean reverseLayout;
|
||||||
|
private int distanceToBottom;
|
||||||
|
|
||||||
|
public Builder(Context context, int itemSpace) {
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.context = context;
|
||||||
|
orientation = HORIZONTAL;
|
||||||
|
minScale = MIN_SCALE;
|
||||||
|
this.moveSpeed = DEFAULT_SPEED;
|
||||||
|
reverseLayout = false;
|
||||||
|
maxVisibleItemCount = ViewPagerLayoutManager.DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
distanceToBottom = ViewPagerLayoutManager.INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setOrientation(int orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMinScale(float minScale) {
|
||||||
|
this.minScale = minScale;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseLayout(boolean reverseLayout) {
|
||||||
|
this.reverseLayout = reverseLayout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMoveSpeed(float moveSpeed) {
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxVisibleItemCount(int maxVisibleItemCount) {
|
||||||
|
this.maxVisibleItemCount = maxVisibleItemCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDistanceToBottom(int distanceToBottom) {
|
||||||
|
this.distanceToBottom = distanceToBottom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CarouselLayoutManager build() {
|
||||||
|
return new CarouselLayoutManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.view.animation.DecelerateInterpolator;
|
||||||
|
import android.widget.Scroller;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class CenterSnapHelper extends RecyclerView.OnFlingListener {
|
||||||
|
|
||||||
|
RecyclerView mRecyclerView;
|
||||||
|
Scroller mGravityScroller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when the dataSet is extremely large
|
||||||
|
* {@link #snapToCenterView(ViewPagerLayoutManager, ViewPagerLayoutManager.OnPageChangeListener)}
|
||||||
|
* may keep calling itself because the accuracy of float
|
||||||
|
*/
|
||||||
|
private boolean snapToCenter = false;
|
||||||
|
|
||||||
|
// Handles the snap on scroll case.
|
||||||
|
private final RecyclerView.OnScrollListener mScrollListener =
|
||||||
|
new RecyclerView.OnScrollListener() {
|
||||||
|
|
||||||
|
boolean mScrolled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||||
|
super.onScrollStateChanged(recyclerView, newState);
|
||||||
|
|
||||||
|
final ViewPagerLayoutManager layoutManager =
|
||||||
|
(ViewPagerLayoutManager) recyclerView.getLayoutManager();
|
||||||
|
final ViewPagerLayoutManager.OnPageChangeListener onPageChangeListener =
|
||||||
|
layoutManager.onPageChangeListener;
|
||||||
|
if (onPageChangeListener != null) {
|
||||||
|
onPageChangeListener.onPageScrollStateChanged(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newState == RecyclerView.SCROLL_STATE_IDLE && mScrolled) {
|
||||||
|
mScrolled = false;
|
||||||
|
if (!snapToCenter) {
|
||||||
|
snapToCenter = true;
|
||||||
|
snapToCenterView(layoutManager, onPageChangeListener);
|
||||||
|
} else {
|
||||||
|
snapToCenter = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||||
|
if (dx != 0 || dy != 0) {
|
||||||
|
mScrolled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onFling(int velocityX, int velocityY) {
|
||||||
|
ViewPagerLayoutManager layoutManager = (ViewPagerLayoutManager) mRecyclerView.getLayoutManager();
|
||||||
|
if (layoutManager == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
|
||||||
|
if (adapter == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!layoutManager.getInfinite() &&
|
||||||
|
(layoutManager.mOffset == layoutManager.getMaxOffset()
|
||||||
|
|| layoutManager.mOffset == layoutManager.getMinOffset())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int minFlingVelocity = mRecyclerView.getMinFlingVelocity();
|
||||||
|
mGravityScroller.fling(0, 0, velocityX, velocityY,
|
||||||
|
Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
if (layoutManager.mOrientation == ViewPagerLayoutManager.VERTICAL
|
||||||
|
&& Math.abs(velocityY) > minFlingVelocity) {
|
||||||
|
final int currentPosition = layoutManager.getCurrentPositionOffset();
|
||||||
|
final int offsetPosition = (int) (mGravityScroller.getFinalY() /
|
||||||
|
layoutManager.mInterval / layoutManager.getDistanceRatio());
|
||||||
|
ScrollHelper.smoothScrollToPosition(mRecyclerView, layoutManager, layoutManager.getReverseLayout() ?
|
||||||
|
-currentPosition - offsetPosition : currentPosition + offsetPosition);
|
||||||
|
return true;
|
||||||
|
} else if (layoutManager.mOrientation == ViewPagerLayoutManager.HORIZONTAL
|
||||||
|
&& Math.abs(velocityX) > minFlingVelocity) {
|
||||||
|
final int currentPosition = layoutManager.getCurrentPositionOffset();
|
||||||
|
final int offsetPosition = (int) (mGravityScroller.getFinalX() /
|
||||||
|
layoutManager.mInterval / layoutManager.getDistanceRatio());
|
||||||
|
ScrollHelper.smoothScrollToPosition(mRecyclerView, layoutManager, layoutManager.getReverseLayout() ?
|
||||||
|
-currentPosition - offsetPosition : currentPosition + offsetPosition);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attachToRecyclerView(@Nullable RecyclerView recyclerView)
|
||||||
|
throws IllegalStateException {
|
||||||
|
if (mRecyclerView == recyclerView) {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
|
if (mRecyclerView != null) {
|
||||||
|
destroyCallbacks();
|
||||||
|
}
|
||||||
|
mRecyclerView = recyclerView;
|
||||||
|
if (mRecyclerView != null) {
|
||||||
|
final RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
|
||||||
|
if (!(layoutManager instanceof ViewPagerLayoutManager)) return;
|
||||||
|
|
||||||
|
setupCallbacks();
|
||||||
|
mGravityScroller = new Scroller(mRecyclerView.getContext(),
|
||||||
|
new DecelerateInterpolator());
|
||||||
|
|
||||||
|
snapToCenterView((ViewPagerLayoutManager) layoutManager,
|
||||||
|
((ViewPagerLayoutManager) layoutManager).onPageChangeListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void snapToCenterView(ViewPagerLayoutManager layoutManager,
|
||||||
|
ViewPagerLayoutManager.OnPageChangeListener listener) {
|
||||||
|
final int delta = layoutManager.getOffsetToCenter();
|
||||||
|
if (delta != 0) {
|
||||||
|
if (layoutManager.getOrientation()
|
||||||
|
== RecyclerView.VERTICAL)
|
||||||
|
mRecyclerView.smoothScrollBy(0, delta);
|
||||||
|
else
|
||||||
|
mRecyclerView.smoothScrollBy(delta, 0);
|
||||||
|
} else {
|
||||||
|
// set it false to make smoothScrollToPosition keep trigger the listener
|
||||||
|
snapToCenter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listener != null)
|
||||||
|
listener.onPageSelected(layoutManager.getCurrentPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an instance of a {@link RecyclerView} is attached.
|
||||||
|
*/
|
||||||
|
void setupCallbacks() throws IllegalStateException {
|
||||||
|
if (mRecyclerView.getOnFlingListener() != null) {
|
||||||
|
throw new IllegalStateException("An instance of OnFlingListener already set.");
|
||||||
|
}
|
||||||
|
mRecyclerView.addOnScrollListener(mScrollListener);
|
||||||
|
mRecyclerView.setOnFlingListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the instance of a {@link RecyclerView} is detached.
|
||||||
|
*/
|
||||||
|
void destroyCallbacks() {
|
||||||
|
mRecyclerView.removeOnScrollListener(mScrollListener);
|
||||||
|
mRecyclerView.setOnFlingListener(null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,357 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ViewPagerLayoutManager}
|
||||||
|
* which layouts item in a circle
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class CircleLayoutManager extends ViewPagerLayoutManager {
|
||||||
|
public static final int LEFT = 10;
|
||||||
|
public static final int RIGHT = 11;
|
||||||
|
public static final int TOP = 12;
|
||||||
|
public static final int BOTTOM = 13;
|
||||||
|
|
||||||
|
public static final int LEFT_ON_TOP = 4;
|
||||||
|
public static final int RIGHT_ON_TOP = 5;
|
||||||
|
public static final int CENTER_ON_TOP = 6;
|
||||||
|
|
||||||
|
private int radius;
|
||||||
|
private int angleInterval;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float maxRemoveAngle;
|
||||||
|
private float minRemoveAngle;
|
||||||
|
private int gravity;
|
||||||
|
private boolean flipRotate;
|
||||||
|
private int zAlignment;
|
||||||
|
|
||||||
|
public CircleLayoutManager(Context context) {
|
||||||
|
this(new Builder(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleLayoutManager(Context context, boolean reverseLayout) {
|
||||||
|
this(new Builder(context).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleLayoutManager(Context context, int gravity, boolean reverseLayout) {
|
||||||
|
this(new Builder(context).setGravity(gravity).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleLayoutManager(Builder builder) {
|
||||||
|
this(builder.context, builder.radius, builder.angleInterval, builder.moveSpeed, builder.maxRemoveAngle,
|
||||||
|
builder.minRemoveAngle, builder.gravity, builder.zAlignment, builder.flipRotate,
|
||||||
|
builder.maxVisibleItemCount, builder.distanceToBottom, builder.reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CircleLayoutManager(Context context, int radius, int angleInterval, float moveSpeed,
|
||||||
|
float max, float min, int gravity, int zAlignment, boolean flipRotate,
|
||||||
|
int maxVisibleItemCount, int distanceToBottom, boolean reverseLayout) {
|
||||||
|
super(context, (gravity == LEFT || gravity == RIGHT) ? VERTICAL : HORIZONTAL, reverseLayout);
|
||||||
|
setEnableBringCenterToFront(true);
|
||||||
|
setMaxVisibleItemCount(maxVisibleItemCount);
|
||||||
|
setDistanceToBottom(distanceToBottom);
|
||||||
|
this.radius = radius;
|
||||||
|
this.angleInterval = angleInterval;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
this.maxRemoveAngle = max;
|
||||||
|
this.minRemoveAngle = min;
|
||||||
|
this.gravity = gravity;
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
this.zAlignment = zAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertGravity(int gravity) {
|
||||||
|
if (gravity != LEFT && gravity != RIGHT && gravity != TOP && gravity != BOTTOM) {
|
||||||
|
throw new IllegalArgumentException("gravity must be one of LEFT RIGHT TOP and BOTTOM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertZAlignmentState(int zAlignment) {
|
||||||
|
if (zAlignment != LEFT_ON_TOP && zAlignment != RIGHT_ON_TOP && zAlignment != CENTER_ON_TOP) {
|
||||||
|
throw new IllegalArgumentException("zAlignment must be one of LEFT_ON_TOP RIGHT_ON_TOP and CENTER_ON_TOP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRadius() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius(int radius) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.radius == radius) return;
|
||||||
|
this.radius = radius;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAngleInterval() {
|
||||||
|
return angleInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngleInterval(int angleInterval) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.angleInterval == angleInterval) return;
|
||||||
|
this.angleInterval = angleInterval;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMoveSpeed() {
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.moveSpeed == moveSpeed) return;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxRemoveAngle() {
|
||||||
|
return maxRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxRemoveAngle(float maxRemoveAngle) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.maxRemoveAngle == maxRemoveAngle) return;
|
||||||
|
this.maxRemoveAngle = maxRemoveAngle;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinRemoveAngle() {
|
||||||
|
return minRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinRemoveAngle(float minRemoveAngle) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.minRemoveAngle == minRemoveAngle) return;
|
||||||
|
this.minRemoveAngle = minRemoveAngle;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGravity() {
|
||||||
|
return gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGravity(int gravity) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
assertGravity(gravity);
|
||||||
|
if (this.gravity == gravity) return;
|
||||||
|
this.gravity = gravity;
|
||||||
|
if (gravity == LEFT || gravity == RIGHT) {
|
||||||
|
setOrientation(RecyclerView.VERTICAL);
|
||||||
|
} else {
|
||||||
|
setOrientation(RecyclerView.HORIZONTAL);
|
||||||
|
}
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getFlipRotate() {
|
||||||
|
return flipRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlipRotate(boolean flipRotate) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.flipRotate == flipRotate) return;
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZAlignment() {
|
||||||
|
return zAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZAlignment(int zAlignment) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
assertZAlignmentState(zAlignment);
|
||||||
|
if (this.zAlignment == zAlignment) return;
|
||||||
|
this.zAlignment = zAlignment;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setInterval() {
|
||||||
|
return angleInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() {
|
||||||
|
radius = radius == Builder.INVALID_VALUE ? mDecoratedMeasurementInOther : radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float maxRemoveOffset() {
|
||||||
|
return maxRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float minRemoveOffset() {
|
||||||
|
return minRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calItemLeft(View itemView, float targetOffset) {
|
||||||
|
switch (gravity) {
|
||||||
|
case LEFT:
|
||||||
|
return (int) (radius * Math.sin(Math.toRadians(90 - targetOffset)) - radius);
|
||||||
|
case RIGHT:
|
||||||
|
return (int) (radius - radius * Math.sin(Math.toRadians(90 - targetOffset)));
|
||||||
|
case TOP:
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
return (int) (radius * Math.cos(Math.toRadians(90 - targetOffset)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calItemTop(View itemView, float targetOffset) {
|
||||||
|
switch (gravity) {
|
||||||
|
case LEFT:
|
||||||
|
case RIGHT:
|
||||||
|
return (int) (radius * Math.cos(Math.toRadians(90 - targetOffset)));
|
||||||
|
case TOP:
|
||||||
|
return (int) (radius * Math.sin(Math.toRadians(90 - targetOffset)) - radius);
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
return (int) (radius - radius * Math.sin(Math.toRadians(90 - targetOffset)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setItemViewProperty(View itemView, float targetOffset) {
|
||||||
|
switch (gravity) {
|
||||||
|
case RIGHT:
|
||||||
|
case TOP:
|
||||||
|
if (flipRotate) {
|
||||||
|
itemView.setRotation(targetOffset);
|
||||||
|
} else {
|
||||||
|
itemView.setRotation(360 - targetOffset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
if (flipRotate) {
|
||||||
|
itemView.setRotation(360 - targetOffset);
|
||||||
|
} else {
|
||||||
|
itemView.setRotation(targetOffset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setViewElevation(View itemView, float targetOffset) {
|
||||||
|
if (zAlignment == LEFT_ON_TOP)
|
||||||
|
return (540 - targetOffset) / 72;
|
||||||
|
else if (zAlignment == RIGHT_ON_TOP)
|
||||||
|
return (targetOffset - 540) / 72;
|
||||||
|
else
|
||||||
|
return (360 - Math.abs(targetOffset)) / 72;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
if (moveSpeed == 0) return Float.MAX_VALUE;
|
||||||
|
return 1 / moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private static int INTERVAL_ANGLE = 30;// The default mInterval angle between each items
|
||||||
|
private static float DISTANCE_RATIO = 10f; // Finger swipe distance divide item rotate angle
|
||||||
|
private static int INVALID_VALUE = Integer.MIN_VALUE;
|
||||||
|
private static int MAX_REMOVE_ANGLE = 90;
|
||||||
|
private static int MIN_REMOVE_ANGLE = -90;
|
||||||
|
|
||||||
|
private int radius;
|
||||||
|
private int angleInterval;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float maxRemoveAngle;
|
||||||
|
private float minRemoveAngle;
|
||||||
|
private boolean reverseLayout;
|
||||||
|
private Context context;
|
||||||
|
private int gravity;
|
||||||
|
private boolean flipRotate;
|
||||||
|
private int zAlignment;
|
||||||
|
private int maxVisibleItemCount;
|
||||||
|
private int distanceToBottom;
|
||||||
|
|
||||||
|
public Builder(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
radius = INVALID_VALUE;
|
||||||
|
angleInterval = INTERVAL_ANGLE;
|
||||||
|
moveSpeed = 1 / DISTANCE_RATIO;
|
||||||
|
maxRemoveAngle = MAX_REMOVE_ANGLE;
|
||||||
|
minRemoveAngle = MIN_REMOVE_ANGLE;
|
||||||
|
reverseLayout = false;
|
||||||
|
flipRotate = false;
|
||||||
|
gravity = BOTTOM;
|
||||||
|
zAlignment = LEFT_ON_TOP;
|
||||||
|
maxVisibleItemCount = ViewPagerLayoutManager.DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
distanceToBottom = ViewPagerLayoutManager.INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setRadius(int radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAngleInterval(int angleInterval) {
|
||||||
|
this.angleInterval = angleInterval;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMoveSpeed(int moveSpeed) {
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxRemoveAngle(float maxRemoveAngle) {
|
||||||
|
this.maxRemoveAngle = maxRemoveAngle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMinRemoveAngle(float minRemoveAngle) {
|
||||||
|
this.minRemoveAngle = minRemoveAngle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseLayout(boolean reverseLayout) {
|
||||||
|
this.reverseLayout = reverseLayout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setGravity(int gravity) {
|
||||||
|
assertGravity(gravity);
|
||||||
|
this.gravity = gravity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setFlipRotate(boolean flipRotate) {
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setZAlignment(int zAlignment) {
|
||||||
|
assertZAlignmentState(zAlignment);
|
||||||
|
this.zAlignment = zAlignment;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxVisibleItemCount(int maxVisibleItemCount) {
|
||||||
|
this.maxVisibleItemCount = maxVisibleItemCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDistanceToBottom(int distanceToBottom) {
|
||||||
|
this.distanceToBottom = distanceToBottom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleLayoutManager build() {
|
||||||
|
return new CircleLayoutManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,395 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ViewPagerLayoutManager}
|
||||||
|
* which layouts item in a circle and will change the child's centerScale while scrolling
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class CircleScaleLayoutManager extends ViewPagerLayoutManager {
|
||||||
|
public static final int LEFT = 10;
|
||||||
|
public static final int RIGHT = 11;
|
||||||
|
public static final int TOP = 12;
|
||||||
|
public static final int BOTTOM = 13;
|
||||||
|
|
||||||
|
public static final int LEFT_ON_TOP = 4;
|
||||||
|
public static final int RIGHT_ON_TOP = 5;
|
||||||
|
public static final int CENTER_ON_TOP = 6;
|
||||||
|
|
||||||
|
private int radius;
|
||||||
|
private int angleInterval;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float centerScale;
|
||||||
|
private float maxRemoveAngle;
|
||||||
|
private float minRemoveAngle;
|
||||||
|
private int gravity;
|
||||||
|
private boolean flipRotate;
|
||||||
|
private int zAlignment;
|
||||||
|
|
||||||
|
public CircleScaleLayoutManager(Context context) {
|
||||||
|
this(new Builder(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleScaleLayoutManager(Context context, int gravity, boolean reverseLayout) {
|
||||||
|
this(new Builder(context).setGravity(gravity).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleScaleLayoutManager(Context context, boolean reverseLayout) {
|
||||||
|
this(new Builder(context).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleScaleLayoutManager(Builder builder) {
|
||||||
|
this(builder.context, builder.radius, builder.angleInterval, builder.centerScale, builder.moveSpeed,
|
||||||
|
builder.maxRemoveAngle, builder.minRemoveAngle, builder.gravity, builder.zAlignment,
|
||||||
|
builder.flipRotate, builder.maxVisibleItemCount, builder.distanceToBottom, builder.reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CircleScaleLayoutManager(Context context, int radius, int angleInterval, float centerScale,
|
||||||
|
float moveSpeed, float max, float min, int gravity, int zAlignment,
|
||||||
|
boolean flipRotate, int maxVisibleItemCount, int distanceToBottom, boolean reverseLayout) {
|
||||||
|
super(context, HORIZONTAL, reverseLayout);
|
||||||
|
setEnableBringCenterToFront(true);
|
||||||
|
setMaxVisibleItemCount(maxVisibleItemCount);
|
||||||
|
setDistanceToBottom(distanceToBottom);
|
||||||
|
this.radius = radius;
|
||||||
|
this.angleInterval = angleInterval;
|
||||||
|
this.centerScale = centerScale;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
this.maxRemoveAngle = max;
|
||||||
|
this.minRemoveAngle = min;
|
||||||
|
this.gravity = gravity;
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
this.zAlignment = zAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertGravity(int gravity) {
|
||||||
|
if (gravity != LEFT && gravity != RIGHT && gravity != TOP && gravity != BOTTOM) {
|
||||||
|
throw new IllegalArgumentException("gravity must be one of LEFT RIGHT TOP and BOTTOM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertZAlignmentState(int zAlignment) {
|
||||||
|
if (zAlignment != LEFT_ON_TOP && zAlignment != RIGHT_ON_TOP && zAlignment != CENTER_ON_TOP) {
|
||||||
|
throw new IllegalArgumentException("zAlignment must be one of LEFT_ON_TOP RIGHT_ON_TOP and CENTER_ON_TOP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRadius() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius(int radius) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.radius == radius) return;
|
||||||
|
this.radius = radius;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAngleInterval() {
|
||||||
|
return angleInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngleInterval(int angleInterval) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.angleInterval == angleInterval) return;
|
||||||
|
this.angleInterval = angleInterval;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getCenterScale() {
|
||||||
|
return centerScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCenterScale(float centerScale) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.centerScale == centerScale) return;
|
||||||
|
this.centerScale = centerScale;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMoveSpeed() {
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.moveSpeed == moveSpeed) return;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxRemoveAngle() {
|
||||||
|
return maxRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxRemoveAngle(float maxRemoveAngle) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.maxRemoveAngle == maxRemoveAngle) return;
|
||||||
|
this.maxRemoveAngle = maxRemoveAngle;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinRemoveAngle() {
|
||||||
|
return minRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinRemoveAngle(float minRemoveAngle) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.minRemoveAngle == minRemoveAngle) return;
|
||||||
|
this.minRemoveAngle = minRemoveAngle;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGravity() {
|
||||||
|
return gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGravity(int gravity) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
assertGravity(gravity);
|
||||||
|
if (this.gravity == gravity) return;
|
||||||
|
this.gravity = gravity;
|
||||||
|
if (gravity == LEFT || gravity == RIGHT) {
|
||||||
|
setOrientation(RecyclerView.VERTICAL);
|
||||||
|
} else {
|
||||||
|
setOrientation(RecyclerView.HORIZONTAL);
|
||||||
|
}
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getFlipRotate() {
|
||||||
|
return flipRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlipRotate(boolean flipRotate) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.flipRotate == flipRotate) return;
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZAlignment() {
|
||||||
|
return zAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZAlignment(int zAlignment) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
assertZAlignmentState(zAlignment);
|
||||||
|
if (this.zAlignment == zAlignment) return;
|
||||||
|
this.zAlignment = zAlignment;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setInterval() {
|
||||||
|
return angleInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() {
|
||||||
|
radius = radius == Builder.INVALID_VALUE ? mDecoratedMeasurementInOther : radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float maxRemoveOffset() {
|
||||||
|
return maxRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float minRemoveOffset() {
|
||||||
|
return minRemoveAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calItemLeft(View itemView, float targetOffset) {
|
||||||
|
switch (gravity) {
|
||||||
|
case LEFT:
|
||||||
|
return (int) (radius * Math.sin(Math.toRadians(90 - targetOffset)) - radius);
|
||||||
|
case RIGHT:
|
||||||
|
return (int) (radius - radius * Math.sin(Math.toRadians(90 - targetOffset)));
|
||||||
|
case TOP:
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
return (int) (radius * Math.cos(Math.toRadians(90 - targetOffset)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calItemTop(View itemView, float targetOffset) {
|
||||||
|
switch (gravity) {
|
||||||
|
case LEFT:
|
||||||
|
case RIGHT:
|
||||||
|
return (int) (radius * Math.cos(Math.toRadians(90 - targetOffset)));
|
||||||
|
case TOP:
|
||||||
|
return (int) (radius * Math.sin(Math.toRadians(90 - targetOffset)) - radius);
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
return (int) (radius - radius * Math.sin(Math.toRadians(90 - targetOffset)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setItemViewProperty(View itemView, float targetOffset) {
|
||||||
|
float scale = 1f;
|
||||||
|
switch (gravity) {
|
||||||
|
case RIGHT:
|
||||||
|
case TOP:
|
||||||
|
if (flipRotate) {
|
||||||
|
itemView.setRotation(targetOffset);
|
||||||
|
if (targetOffset < angleInterval && targetOffset > -angleInterval) {
|
||||||
|
float diff = Math.abs(Math.abs(itemView.getRotation() - angleInterval) - angleInterval);
|
||||||
|
scale = (centerScale - 1f) / -angleInterval * diff + centerScale;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
itemView.setRotation(360 - targetOffset);
|
||||||
|
if (targetOffset < angleInterval && targetOffset > -angleInterval) {
|
||||||
|
float diff = Math.abs(Math.abs(360 - itemView.getRotation() - angleInterval) - angleInterval);
|
||||||
|
scale = (centerScale - 1f) / -angleInterval * diff + centerScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
if (flipRotate) {
|
||||||
|
itemView.setRotation(360 - targetOffset);
|
||||||
|
if (targetOffset < angleInterval && targetOffset > -angleInterval) {
|
||||||
|
float diff = Math.abs(Math.abs(360 - itemView.getRotation() - angleInterval) - angleInterval);
|
||||||
|
scale = (centerScale - 1f) / -angleInterval * diff + centerScale;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
itemView.setRotation(targetOffset);
|
||||||
|
if (targetOffset < angleInterval && targetOffset > -angleInterval) {
|
||||||
|
float diff = Math.abs(Math.abs(itemView.getRotation() - angleInterval) - angleInterval);
|
||||||
|
scale = (centerScale - 1f) / -angleInterval * diff + centerScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
itemView.setScaleX(scale);
|
||||||
|
itemView.setScaleY(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setViewElevation(View itemView, float targetOffset) {
|
||||||
|
if (zAlignment == LEFT_ON_TOP)
|
||||||
|
return (540 - targetOffset) / 72;
|
||||||
|
else if (zAlignment == RIGHT_ON_TOP)
|
||||||
|
return (targetOffset - 540) / 72;
|
||||||
|
else
|
||||||
|
return (360 - Math.abs(targetOffset)) / 72;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
if (moveSpeed == 0) return Float.MAX_VALUE;
|
||||||
|
return 1 / moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private static final float SCALE_RATE = 1.2f;
|
||||||
|
private static int INTERVAL_ANGLE = 30;// The default mInterval angle between each items
|
||||||
|
private static float DISTANCE_RATIO = 10f; // Finger swipe distance divide item rotate angle
|
||||||
|
private static int INVALID_VALUE = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
private int radius;
|
||||||
|
private int angleInterval;
|
||||||
|
private float centerScale;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float maxRemoveAngle;
|
||||||
|
private float minRemoveAngle;
|
||||||
|
private boolean reverseLayout;
|
||||||
|
private Context context;
|
||||||
|
private int gravity;
|
||||||
|
private boolean flipRotate;
|
||||||
|
private int zAlignment;
|
||||||
|
private int maxVisibleItemCount;
|
||||||
|
private int distanceToBottom;
|
||||||
|
|
||||||
|
public Builder(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
radius = INVALID_VALUE;
|
||||||
|
angleInterval = INTERVAL_ANGLE;
|
||||||
|
centerScale = SCALE_RATE;
|
||||||
|
moveSpeed = 1 / DISTANCE_RATIO;
|
||||||
|
maxRemoveAngle = 90;
|
||||||
|
minRemoveAngle = -90;
|
||||||
|
reverseLayout = false;
|
||||||
|
flipRotate = false;
|
||||||
|
gravity = BOTTOM;
|
||||||
|
zAlignment = CENTER_ON_TOP;
|
||||||
|
distanceToBottom = ViewPagerLayoutManager.INVALID_SIZE;
|
||||||
|
maxVisibleItemCount = ViewPagerLayoutManager.DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setRadius(int radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAngleInterval(int angleInterval) {
|
||||||
|
this.angleInterval = angleInterval;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setCenterScale(float centerScale) {
|
||||||
|
this.centerScale = centerScale;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMoveSpeed(int moveSpeed) {
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxRemoveAngle(float maxRemoveAngle) {
|
||||||
|
this.maxRemoveAngle = maxRemoveAngle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMinRemoveAngle(float minRemoveAngle) {
|
||||||
|
this.minRemoveAngle = minRemoveAngle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseLayout(boolean reverseLayout) {
|
||||||
|
this.reverseLayout = reverseLayout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setGravity(int gravity) {
|
||||||
|
assertGravity(gravity);
|
||||||
|
this.gravity = gravity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setFlipRotate(boolean flipRotate) {
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setZAlignment(int zAlignment) {
|
||||||
|
assertZAlignmentState(zAlignment);
|
||||||
|
this.zAlignment = zAlignment;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxVisibleItemCount(int maxVisibleItemCount) {
|
||||||
|
this.maxVisibleItemCount = maxVisibleItemCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDistanceToBottom(int distanceToBottom) {
|
||||||
|
this.distanceToBottom = distanceToBottom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleScaleLayoutManager build() {
|
||||||
|
return new CircleScaleLayoutManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,288 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ViewPagerLayoutManager}
|
||||||
|
* which will change rotate x or rotate y
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class GalleryLayoutManager extends ViewPagerLayoutManager {
|
||||||
|
private final float MAX_ELEVATION = 5F;
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float maxAlpha;
|
||||||
|
private float minAlpha;
|
||||||
|
private float angle;
|
||||||
|
private boolean flipRotate;
|
||||||
|
private boolean rotateFromEdge;
|
||||||
|
|
||||||
|
public GalleryLayoutManager(Context context, int itemSpace) {
|
||||||
|
this(new Builder(context, itemSpace));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GalleryLayoutManager(Context context, int itemSpace, int orientation) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GalleryLayoutManager(Context context, int itemSpace, int orientation, boolean reverseLayout) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GalleryLayoutManager(Builder builder) {
|
||||||
|
this(builder.context, builder.itemSpace, builder.angle, builder.maxAlpha, builder.minAlpha,
|
||||||
|
builder.orientation, builder.moveSpeed, builder.flipRotate, builder.rotateFromEdge,
|
||||||
|
builder.maxVisibleItemCount, builder.distanceToBottom, builder.reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GalleryLayoutManager(Context context, int itemSpace, float angle, float maxAlpha, float minAlpha,
|
||||||
|
int orientation, float moveSpeed, boolean flipRotate, boolean rotateFromEdge,
|
||||||
|
int maxVisibleItemCount, int distanceToBottom, boolean reverseLayout) {
|
||||||
|
super(context, orientation, reverseLayout);
|
||||||
|
setDistanceToBottom(distanceToBottom);
|
||||||
|
setMaxVisibleItemCount(maxVisibleItemCount);
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
this.angle = angle;
|
||||||
|
this.maxAlpha = maxAlpha;
|
||||||
|
this.minAlpha = minAlpha;
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
this.rotateFromEdge = rotateFromEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemSpace() {
|
||||||
|
return itemSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemSpace(int itemSpace) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.itemSpace == itemSpace) return;
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxAlpha() {
|
||||||
|
return maxAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxAlpha(float maxAlpha) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (maxAlpha > 1) maxAlpha = 1;
|
||||||
|
if (this.maxAlpha == maxAlpha) return;
|
||||||
|
this.maxAlpha = maxAlpha;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinAlpha() {
|
||||||
|
return minAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinAlpha(float minAlpha) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (minAlpha < 0) minAlpha = 0;
|
||||||
|
if (this.minAlpha == minAlpha) return;
|
||||||
|
this.minAlpha = minAlpha;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAngle() {
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngle(float angle) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.angle == angle) return;
|
||||||
|
this.angle = angle;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMoveSpeed() {
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.moveSpeed == moveSpeed) return;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getFlipRotate() {
|
||||||
|
return flipRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlipRotate(boolean flipRotate) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.flipRotate == flipRotate) return;
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getRotateFromEdge() {
|
||||||
|
return rotateFromEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotateFromEdge(boolean rotateFromEdge) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.rotateFromEdge == rotateFromEdge) return;
|
||||||
|
this.rotateFromEdge = rotateFromEdge;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setInterval() {
|
||||||
|
return mDecoratedMeasurement + itemSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setItemViewProperty(View itemView, float targetOffset) {
|
||||||
|
final float rotation = calRotation(targetOffset);
|
||||||
|
if (getOrientation() == RecyclerView.HORIZONTAL) {
|
||||||
|
if (rotateFromEdge) {
|
||||||
|
itemView.setPivotX(rotation > 0 ? 0 : mDecoratedMeasurement);
|
||||||
|
itemView.setPivotY(mDecoratedMeasurementInOther * 0.5f);
|
||||||
|
}
|
||||||
|
if (flipRotate) {
|
||||||
|
itemView.setRotationX(rotation);
|
||||||
|
} else {
|
||||||
|
itemView.setRotationY(rotation);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rotateFromEdge) {
|
||||||
|
itemView.setPivotY(rotation > 0 ? 0 : mDecoratedMeasurement);
|
||||||
|
itemView.setPivotX(mDecoratedMeasurementInOther * 0.5f);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (flipRotate) {
|
||||||
|
itemView.setRotationY(-rotation);
|
||||||
|
} else {
|
||||||
|
itemView.setRotationX(-rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final float alpha = calAlpha(targetOffset);
|
||||||
|
itemView.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setViewElevation(View itemView, float targetOffset) {
|
||||||
|
final float ele = Math.max(Math.abs(itemView.getRotationX()), Math.abs(itemView.getRotationY())) * MAX_ELEVATION / 360;
|
||||||
|
return MAX_ELEVATION - ele;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
if (moveSpeed == 0) return Float.MAX_VALUE;
|
||||||
|
return 1 / moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calRotation(float targetOffset) {
|
||||||
|
return -angle / mInterval * targetOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calAlpha(float targetOffset) {
|
||||||
|
final float offset = Math.abs(targetOffset);
|
||||||
|
float alpha = (minAlpha - maxAlpha) / mInterval * offset + maxAlpha;
|
||||||
|
if (offset >= mInterval) alpha = minAlpha;
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private static final float DEFAULT_SPEED = 1f;
|
||||||
|
private static float INTERVAL_ANGLE = 30f;
|
||||||
|
private static float MIN_ALPHA = 0.5f;
|
||||||
|
private static float MAX_ALPHA = 1f;
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private float moveSpeed;
|
||||||
|
private int orientation;
|
||||||
|
private float maxAlpha;
|
||||||
|
private float minAlpha;
|
||||||
|
private float angle;
|
||||||
|
private boolean flipRotate;
|
||||||
|
private boolean reverseLayout;
|
||||||
|
private Context context;
|
||||||
|
private int maxVisibleItemCount;
|
||||||
|
private int distanceToBottom;
|
||||||
|
private boolean rotateFromEdge;
|
||||||
|
|
||||||
|
public Builder(Context context, int itemSpace) {
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.context = context;
|
||||||
|
orientation = HORIZONTAL;
|
||||||
|
angle = INTERVAL_ANGLE;
|
||||||
|
maxAlpha = MAX_ALPHA;
|
||||||
|
minAlpha = MIN_ALPHA;
|
||||||
|
this.moveSpeed = DEFAULT_SPEED;
|
||||||
|
reverseLayout = false;
|
||||||
|
flipRotate = false;
|
||||||
|
rotateFromEdge = false;
|
||||||
|
distanceToBottom = ViewPagerLayoutManager.INVALID_SIZE;
|
||||||
|
maxVisibleItemCount = ViewPagerLayoutManager.DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setItemSpace(int itemSpace) {
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMoveSpeed(float moveSpeed) {
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setOrientation(int orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxAlpha(float maxAlpha) {
|
||||||
|
if (maxAlpha > 1) maxAlpha = 1;
|
||||||
|
this.maxAlpha = maxAlpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMinAlpha(float minAlpha) {
|
||||||
|
if (minAlpha < 0) minAlpha = 0;
|
||||||
|
this.minAlpha = minAlpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAngle(float angle) {
|
||||||
|
this.angle = angle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setFlipRotate(boolean flipRotate) {
|
||||||
|
this.flipRotate = flipRotate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseLayout(boolean reverseLayout) {
|
||||||
|
this.reverseLayout = reverseLayout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxVisibleItemCount(int maxVisibleItemCount) {
|
||||||
|
this.maxVisibleItemCount = maxVisibleItemCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDistanceToBottom(int distanceToBottom) {
|
||||||
|
this.distanceToBottom = distanceToBottom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setRotateFromEdge(boolean rotateFromEdge) {
|
||||||
|
this.rotateFromEdge = rotateFromEdge;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GalleryLayoutManager build() {
|
||||||
|
return new GalleryLayoutManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess","unused"})
|
||||||
|
public abstract class OrientationHelper {
|
||||||
|
|
||||||
|
private static final int INVALID_SIZE = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
protected final RecyclerView.LayoutManager mLayoutManager;
|
||||||
|
|
||||||
|
public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
|
||||||
|
|
||||||
|
public static final int VERTICAL = LinearLayout.VERTICAL;
|
||||||
|
|
||||||
|
private int mLastTotalSpace = INVALID_SIZE;
|
||||||
|
|
||||||
|
final Rect mTmpRect = new Rect();
|
||||||
|
|
||||||
|
private OrientationHelper(RecyclerView.LayoutManager layoutManager) {
|
||||||
|
mLayoutManager = layoutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method after onLayout method is complete if state is NOT pre-layout.
|
||||||
|
* This method records information like layout bounds that might be useful in the next layout
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
public void onLayoutComplete() {
|
||||||
|
mLastTotalSpace = getTotalSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the layout space change between the previous layout pass and current layout pass.
|
||||||
|
* <p>
|
||||||
|
* Make sure you call {@link #onLayoutComplete()} at the end of your LayoutManager's
|
||||||
|
* {@link RecyclerView.LayoutManager#onLayoutChildren(RecyclerView.Recycler,
|
||||||
|
* RecyclerView.State)} method.
|
||||||
|
*
|
||||||
|
* @return The difference between the current total space and previous layout's total space.
|
||||||
|
* @see #onLayoutComplete()
|
||||||
|
*/
|
||||||
|
public int getTotalSpaceChange() {
|
||||||
|
return INVALID_SIZE == mLastTotalSpace ? 0 : getTotalSpace() - mLastTotalSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the start of the view including its decoration and margin.
|
||||||
|
* <p>
|
||||||
|
* For example, for the horizontal helper, if a View's left is at pixel 20, has 2px left
|
||||||
|
* decoration and 3px left margin, returned value will be 15px.
|
||||||
|
*
|
||||||
|
* @param view The view element to check
|
||||||
|
* @return The first pixel of the element
|
||||||
|
* @see #getDecoratedEnd(View)
|
||||||
|
*/
|
||||||
|
public abstract int getDecoratedStart(View view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the end of the view including its decoration and margin.
|
||||||
|
* <p>
|
||||||
|
* For example, for the horizontal helper, if a View's right is at pixel 200, has 2px right
|
||||||
|
* decoration and 3px right margin, returned value will be 205.
|
||||||
|
*
|
||||||
|
* @param view The view element to check
|
||||||
|
* @return The last pixel of the element
|
||||||
|
* @see #getDecoratedStart(View)
|
||||||
|
*/
|
||||||
|
public abstract int getDecoratedEnd(View view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the end of the View after its matrix transformations are applied to its layout
|
||||||
|
* position.
|
||||||
|
* <p>
|
||||||
|
* This method is useful when trying to detect the visible edge of a View.
|
||||||
|
* <p>
|
||||||
|
* It includes the decorations but does not include the margins.
|
||||||
|
*
|
||||||
|
* @param view The view whose transformed end will be returned
|
||||||
|
* @return The end of the View after its decor insets and transformation matrix is applied to
|
||||||
|
* its position
|
||||||
|
* @see RecyclerView.LayoutManager#getTransformedBoundingBox(View, boolean, Rect)
|
||||||
|
*/
|
||||||
|
public abstract int getTransformedEndWithDecoration(View view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the start of the View after its matrix transformations are applied to its layout
|
||||||
|
* position.
|
||||||
|
* <p>
|
||||||
|
* This method is useful when trying to detect the visible edge of a View.
|
||||||
|
* <p>
|
||||||
|
* It includes the decorations but does not include the margins.
|
||||||
|
*
|
||||||
|
* @param view The view whose transformed start will be returned
|
||||||
|
* @return The start of the View after its decor insets and transformation matrix is applied to
|
||||||
|
* its position
|
||||||
|
* @see RecyclerView.LayoutManager#getTransformedBoundingBox(View, boolean, Rect)
|
||||||
|
*/
|
||||||
|
public abstract int getTransformedStartWithDecoration(View view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the space occupied by this View in the current orientation including decorations and
|
||||||
|
* margins.
|
||||||
|
*
|
||||||
|
* @param view The view element to check
|
||||||
|
* @return Total space occupied by this view
|
||||||
|
* @see #getDecoratedMeasurementInOther(View)
|
||||||
|
*/
|
||||||
|
public abstract int getDecoratedMeasurement(View view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the space occupied by this View in the perpendicular orientation including
|
||||||
|
* decorations and margins.
|
||||||
|
*
|
||||||
|
* @param view The view element to check
|
||||||
|
* @return Total space occupied by this view in the perpendicular orientation to current one
|
||||||
|
* @see #getDecoratedMeasurement(View)
|
||||||
|
*/
|
||||||
|
public abstract int getDecoratedMeasurementInOther(View view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the start position of the layout after the start padding is added.
|
||||||
|
*
|
||||||
|
* @return The very first pixel we can draw.
|
||||||
|
*/
|
||||||
|
public abstract int getStartAfterPadding();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the end position of the layout after the end padding is removed.
|
||||||
|
*
|
||||||
|
* @return The end boundary for this layout.
|
||||||
|
*/
|
||||||
|
public abstract int getEndAfterPadding();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the end position of the layout without taking padding into account.
|
||||||
|
*
|
||||||
|
* @return The end boundary for this layout without considering padding.
|
||||||
|
*/
|
||||||
|
public abstract int getEnd();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total space to layout. This number is the difference between
|
||||||
|
* {@link #getEndAfterPadding()} and {@link #getStartAfterPadding()}.
|
||||||
|
*
|
||||||
|
* @return Total space to layout children
|
||||||
|
*/
|
||||||
|
public abstract int getTotalSpace();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total space in other direction to layout. This number is the difference between
|
||||||
|
* {@link #getEndAfterPadding()} and {@link #getStartAfterPadding()}.
|
||||||
|
*
|
||||||
|
* @return Total space to layout children
|
||||||
|
*/
|
||||||
|
public abstract int getTotalSpaceInOther();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the padding at the end of the layout. For horizontal helper, this is the right
|
||||||
|
* padding and for vertical helper, this is the bottom padding. This method does not check
|
||||||
|
* whether the layout is RTL or not.
|
||||||
|
*
|
||||||
|
* @return The padding at the end of the layout.
|
||||||
|
*/
|
||||||
|
public abstract int getEndPadding();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the MeasureSpec mode for the current orientation from the LayoutManager.
|
||||||
|
*
|
||||||
|
* @return The current measure spec mode.
|
||||||
|
* @see View.MeasureSpec
|
||||||
|
* @see RecyclerView.LayoutManager#getWidthMode()
|
||||||
|
* @see RecyclerView.LayoutManager#getHeightMode()
|
||||||
|
*/
|
||||||
|
public abstract int getMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the MeasureSpec mode for the perpendicular orientation from the LayoutManager.
|
||||||
|
*
|
||||||
|
* @return The current measure spec mode.
|
||||||
|
* @see View.MeasureSpec
|
||||||
|
* @see RecyclerView.LayoutManager#getWidthMode()
|
||||||
|
* @see RecyclerView.LayoutManager#getHeightMode()
|
||||||
|
*/
|
||||||
|
public abstract int getModeInOther();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an OrientationHelper for the given LayoutManager and orientation.
|
||||||
|
*
|
||||||
|
* @param layoutManager LayoutManager to attach to
|
||||||
|
* @param orientation Desired orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}
|
||||||
|
* @return A new OrientationHelper
|
||||||
|
*/
|
||||||
|
public static OrientationHelper createOrientationHelper(
|
||||||
|
RecyclerView.LayoutManager layoutManager, int orientation) {
|
||||||
|
switch (orientation) {
|
||||||
|
case HORIZONTAL:
|
||||||
|
return createHorizontalHelper(layoutManager);
|
||||||
|
case VERTICAL:
|
||||||
|
return createVerticalHelper(layoutManager);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("invalid orientation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a horizontal OrientationHelper for the given LayoutManager.
|
||||||
|
*
|
||||||
|
* @param layoutManager The LayoutManager to attach to.
|
||||||
|
* @return A new OrientationHelper
|
||||||
|
*/
|
||||||
|
public static OrientationHelper createHorizontalHelper(
|
||||||
|
RecyclerView.LayoutManager layoutManager) {
|
||||||
|
return new OrientationHelper(layoutManager) {
|
||||||
|
@Override
|
||||||
|
public int getEndAfterPadding() {
|
||||||
|
return mLayoutManager.getWidth() - mLayoutManager.getPaddingRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEnd() {
|
||||||
|
return mLayoutManager.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartAfterPadding() {
|
||||||
|
return mLayoutManager.getPaddingLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedMeasurement(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedMeasuredWidth(view) + params.leftMargin
|
||||||
|
+ params.rightMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedMeasurementInOther(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedMeasuredHeight(view) + params.topMargin
|
||||||
|
+ params.bottomMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedEnd(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedRight(view) + params.rightMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedStart(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedLeft(view) - params.leftMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTransformedEndWithDecoration(View view) {
|
||||||
|
mLayoutManager.getTransformedBoundingBox(view, true, mTmpRect);
|
||||||
|
return mTmpRect.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTransformedStartWithDecoration(View view) {
|
||||||
|
mLayoutManager.getTransformedBoundingBox(view, true, mTmpRect);
|
||||||
|
return mTmpRect.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTotalSpace() {
|
||||||
|
return mLayoutManager.getWidth() - mLayoutManager.getPaddingLeft()
|
||||||
|
- mLayoutManager.getPaddingRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTotalSpaceInOther() {
|
||||||
|
return mLayoutManager.getHeight() - mLayoutManager.getPaddingTop()
|
||||||
|
- mLayoutManager.getPaddingBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEndPadding() {
|
||||||
|
return mLayoutManager.getPaddingRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMode() {
|
||||||
|
return mLayoutManager.getWidthMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getModeInOther() {
|
||||||
|
return mLayoutManager.getHeightMode();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a vertical OrientationHelper for the given LayoutManager.
|
||||||
|
*
|
||||||
|
* @param layoutManager The LayoutManager to attach to.
|
||||||
|
* @return A new OrientationHelper
|
||||||
|
*/
|
||||||
|
public static OrientationHelper createVerticalHelper(RecyclerView.LayoutManager layoutManager) {
|
||||||
|
return new OrientationHelper(layoutManager) {
|
||||||
|
@Override
|
||||||
|
public int getEndAfterPadding() {
|
||||||
|
return mLayoutManager.getHeight() - mLayoutManager.getPaddingBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEnd() {
|
||||||
|
return mLayoutManager.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartAfterPadding() {
|
||||||
|
return mLayoutManager.getPaddingTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedMeasurement(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedMeasuredHeight(view) + params.topMargin
|
||||||
|
+ params.bottomMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedMeasurementInOther(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedMeasuredWidth(view) + params.leftMargin
|
||||||
|
+ params.rightMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedEnd(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedBottom(view) + params.bottomMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDecoratedStart(View view) {
|
||||||
|
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||||
|
view.getLayoutParams();
|
||||||
|
return mLayoutManager.getDecoratedTop(view) - params.topMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTransformedEndWithDecoration(View view) {
|
||||||
|
mLayoutManager.getTransformedBoundingBox(view, true, mTmpRect);
|
||||||
|
return mTmpRect.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTransformedStartWithDecoration(View view) {
|
||||||
|
mLayoutManager.getTransformedBoundingBox(view, true, mTmpRect);
|
||||||
|
return mTmpRect.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTotalSpace() {
|
||||||
|
return mLayoutManager.getHeight() - mLayoutManager.getPaddingTop()
|
||||||
|
- mLayoutManager.getPaddingBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTotalSpaceInOther() {
|
||||||
|
return mLayoutManager.getWidth() - mLayoutManager.getPaddingLeft()
|
||||||
|
- mLayoutManager.getPaddingRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEndPadding() {
|
||||||
|
return mLayoutManager.getPaddingBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMode() {
|
||||||
|
return mLayoutManager.getHeightMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getModeInOther() {
|
||||||
|
return mLayoutManager.getWidthMode();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class PageSnapHelper extends CenterSnapHelper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onFling(int velocityX, int velocityY) {
|
||||||
|
ViewPagerLayoutManager layoutManager = (ViewPagerLayoutManager) mRecyclerView.getLayoutManager();
|
||||||
|
if (layoutManager == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
|
||||||
|
if (adapter == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!layoutManager.getInfinite() &&
|
||||||
|
(layoutManager.mOffset == layoutManager.getMaxOffset()
|
||||||
|
|| layoutManager.mOffset == layoutManager.getMinOffset())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int minFlingVelocity = mRecyclerView.getMinFlingVelocity();
|
||||||
|
mGravityScroller.fling(0, 0, velocityX, velocityY,
|
||||||
|
Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
if (layoutManager.mOrientation == ViewPagerLayoutManager.VERTICAL
|
||||||
|
&& Math.abs(velocityY) > minFlingVelocity) {
|
||||||
|
final int currentPosition = layoutManager.getCurrentPositionOffset();
|
||||||
|
final int offsetPosition = mGravityScroller.getFinalY() * layoutManager.getDistanceRatio() > layoutManager.mInterval ? 1 : 0;
|
||||||
|
ScrollHelper.smoothScrollToPosition(mRecyclerView, layoutManager, layoutManager.getReverseLayout() ?
|
||||||
|
-currentPosition - offsetPosition : currentPosition + offsetPosition);
|
||||||
|
return true;
|
||||||
|
} else if (layoutManager.mOrientation == ViewPagerLayoutManager.HORIZONTAL
|
||||||
|
&& Math.abs(velocityX) > minFlingVelocity) {
|
||||||
|
final int currentPosition = layoutManager.getCurrentPositionOffset();
|
||||||
|
final int offsetPosition = mGravityScroller.getFinalX() * layoutManager.getDistanceRatio() > layoutManager.mInterval ? 1 : 0;
|
||||||
|
ScrollHelper.smoothScrollToPosition(mRecyclerView, layoutManager, layoutManager.getReverseLayout() ?
|
||||||
|
-currentPosition - offsetPosition : currentPosition + offsetPosition);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ViewPagerLayoutManager}
|
||||||
|
* which rotates items
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class RotateLayoutManager extends ViewPagerLayoutManager {
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private float angle;
|
||||||
|
private float moveSpeed;
|
||||||
|
private boolean reverseRotate;
|
||||||
|
|
||||||
|
public RotateLayoutManager(Context context, int itemSpace) {
|
||||||
|
this(new Builder(context, itemSpace));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RotateLayoutManager(Context context, int itemSpace, int orientation) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RotateLayoutManager(Context context, int itemSpace, int orientation, boolean reverseLayout) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RotateLayoutManager(Builder builder) {
|
||||||
|
this(builder.context, builder.itemSpace, builder.angle, builder.orientation, builder.moveSpeed,
|
||||||
|
builder.reverseRotate, builder.maxVisibleItemCount, builder.distanceToBottom,
|
||||||
|
builder.reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RotateLayoutManager(Context context, int itemSpace, float angle, int orientation, float moveSpeed,
|
||||||
|
boolean reverseRotate, int maxVisibleItemCount, int distanceToBottom,
|
||||||
|
boolean reverseLayout) {
|
||||||
|
super(context, orientation, reverseLayout);
|
||||||
|
setDistanceToBottom(distanceToBottom);
|
||||||
|
setMaxVisibleItemCount(maxVisibleItemCount);
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.angle = angle;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
this.reverseRotate = reverseRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemSpace() {
|
||||||
|
return itemSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAngle() {
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMoveSpeed() {
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getReverseRotate() {
|
||||||
|
return reverseRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemSpace(int itemSpace) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.itemSpace == itemSpace) return;
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngle(float centerScale) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.angle == centerScale) return;
|
||||||
|
this.angle = centerScale;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.moveSpeed == moveSpeed) return;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReverseRotate(boolean reverseRotate) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.reverseRotate == reverseRotate) return;
|
||||||
|
this.reverseRotate = reverseRotate;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setInterval() {
|
||||||
|
return mDecoratedMeasurement + itemSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setItemViewProperty(View itemView, float targetOffset) {
|
||||||
|
itemView.setRotation(calRotation(targetOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
if (moveSpeed == 0) return Float.MAX_VALUE;
|
||||||
|
return 1 / moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calRotation(float targetOffset) {
|
||||||
|
final float realAngle = reverseRotate ? angle : -angle;
|
||||||
|
return realAngle / mInterval * targetOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private static float INTERVAL_ANGLE = 360f;
|
||||||
|
private static final float DEFAULT_SPEED = 1f;
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private int orientation;
|
||||||
|
private float angle;
|
||||||
|
private float moveSpeed;
|
||||||
|
private boolean reverseRotate;
|
||||||
|
private boolean reverseLayout;
|
||||||
|
private Context context;
|
||||||
|
private int maxVisibleItemCount;
|
||||||
|
private int distanceToBottom;
|
||||||
|
|
||||||
|
public Builder(Context context, int itemSpace) {
|
||||||
|
this.context = context;
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
orientation = HORIZONTAL;
|
||||||
|
angle = INTERVAL_ANGLE;
|
||||||
|
this.moveSpeed = DEFAULT_SPEED;
|
||||||
|
reverseRotate = false;
|
||||||
|
reverseLayout = false;
|
||||||
|
distanceToBottom = ViewPagerLayoutManager.INVALID_SIZE;
|
||||||
|
maxVisibleItemCount = ViewPagerLayoutManager.DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setOrientation(int orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAngle(float angle) {
|
||||||
|
this.angle = angle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseLayout(boolean reverseLayout) {
|
||||||
|
this.reverseLayout = reverseLayout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMoveSpeed(float moveSpeed) {
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseRotate(boolean reverseRotate) {
|
||||||
|
this.reverseRotate = reverseRotate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxVisibleItemCount(int maxVisibleItemCount) {
|
||||||
|
this.maxVisibleItemCount = maxVisibleItemCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDistanceToBottom(int distanceToBottom) {
|
||||||
|
this.distanceToBottom = distanceToBottom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RotateLayoutManager build() {
|
||||||
|
return new RotateLayoutManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,221 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ViewPagerLayoutManager}
|
||||||
|
* which zooms the center item
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class ScaleLayoutManager extends ViewPagerLayoutManager {
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private float minScale;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float maxAlpha;
|
||||||
|
private float minAlpha;
|
||||||
|
|
||||||
|
public ScaleLayoutManager(Context context, int itemSpace) {
|
||||||
|
this(new Builder(context, itemSpace));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScaleLayoutManager(Context context, int itemSpace, int orientation) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScaleLayoutManager(Context context, int itemSpace, int orientation, boolean reverseLayout) {
|
||||||
|
this(new Builder(context, itemSpace).setOrientation(orientation).setReverseLayout(reverseLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScaleLayoutManager(Builder builder) {
|
||||||
|
this(builder.context, builder.itemSpace, builder.minScale, builder.maxAlpha, builder.minAlpha,
|
||||||
|
builder.orientation, builder.moveSpeed, builder.maxVisibleItemCount, builder.distanceToBottom,
|
||||||
|
builder.reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScaleLayoutManager(Context context, int itemSpace, float minScale, float maxAlpha, float minAlpha,
|
||||||
|
int orientation, float moveSpeed, int maxVisibleItemCount, int distanceToBottom,
|
||||||
|
boolean reverseLayout) {
|
||||||
|
super(context, orientation, reverseLayout);
|
||||||
|
setDistanceToBottom(distanceToBottom);
|
||||||
|
setMaxVisibleItemCount(maxVisibleItemCount);
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.minScale = minScale;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
this.maxAlpha = maxAlpha;
|
||||||
|
this.minAlpha = minAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemSpace() {
|
||||||
|
return itemSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinScale() {
|
||||||
|
return minScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMoveSpeed() {
|
||||||
|
return moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxAlpha() {
|
||||||
|
return maxAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinAlpha() {
|
||||||
|
return minAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemSpace(int itemSpace) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.itemSpace == itemSpace) return;
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinScale(float minScale) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.minScale == minScale) return;
|
||||||
|
this.minScale = minScale;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxAlpha(float maxAlpha) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (maxAlpha > 1) maxAlpha = 1;
|
||||||
|
if (this.maxAlpha == maxAlpha) return;
|
||||||
|
this.maxAlpha = maxAlpha;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinAlpha(float minAlpha) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (minAlpha < 0) minAlpha = 0;
|
||||||
|
if (this.minAlpha == minAlpha) return;
|
||||||
|
this.minAlpha = minAlpha;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.moveSpeed == moveSpeed) return;
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float setInterval() {
|
||||||
|
return itemSpace + mDecoratedMeasurement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setItemViewProperty(View itemView, float targetOffset) {
|
||||||
|
float scale = calculateScale(targetOffset + mSpaceMain);
|
||||||
|
itemView.setScaleX(scale);
|
||||||
|
itemView.setScaleY(scale);
|
||||||
|
final float alpha = calAlpha(targetOffset);
|
||||||
|
itemView.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calAlpha(float targetOffset) {
|
||||||
|
final float offset = Math.abs(targetOffset);
|
||||||
|
float alpha = (minAlpha - maxAlpha) / mInterval * offset + maxAlpha;
|
||||||
|
if (offset >= mInterval) alpha = minAlpha;
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
if (moveSpeed == 0) return Float.MAX_VALUE;
|
||||||
|
return 1 / moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param x start positon of the view you want scale
|
||||||
|
* @return the scale rate of current scroll mOffset
|
||||||
|
*/
|
||||||
|
private float calculateScale(float x) {
|
||||||
|
float deltaX = Math.abs(x - mSpaceMain);
|
||||||
|
if (deltaX - mDecoratedMeasurement > 0) deltaX = mDecoratedMeasurement;
|
||||||
|
return 1f - deltaX / mDecoratedMeasurement * (1f - minScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private static final float SCALE_RATE = 0.8f;
|
||||||
|
private static final float DEFAULT_SPEED = 1f;
|
||||||
|
private static float MIN_ALPHA = 1f;
|
||||||
|
private static float MAX_ALPHA = 1f;
|
||||||
|
|
||||||
|
private int itemSpace;
|
||||||
|
private int orientation;
|
||||||
|
private float minScale;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float maxAlpha;
|
||||||
|
private float minAlpha;
|
||||||
|
private boolean reverseLayout;
|
||||||
|
private Context context;
|
||||||
|
private int maxVisibleItemCount;
|
||||||
|
private int distanceToBottom;
|
||||||
|
|
||||||
|
public Builder(Context context, int itemSpace) {
|
||||||
|
this.itemSpace = itemSpace;
|
||||||
|
this.context = context;
|
||||||
|
orientation = HORIZONTAL;
|
||||||
|
minScale = SCALE_RATE;
|
||||||
|
this.moveSpeed = DEFAULT_SPEED;
|
||||||
|
maxAlpha = MAX_ALPHA;
|
||||||
|
minAlpha = MIN_ALPHA;
|
||||||
|
reverseLayout = false;
|
||||||
|
distanceToBottom = ViewPagerLayoutManager.INVALID_SIZE;
|
||||||
|
maxVisibleItemCount = ViewPagerLayoutManager.DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setOrientation(int orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMinScale(float minScale) {
|
||||||
|
this.minScale = minScale;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setReverseLayout(boolean reverseLayout) {
|
||||||
|
this.reverseLayout = reverseLayout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxAlpha(float maxAlpha) {
|
||||||
|
if (maxAlpha > 1) maxAlpha = 1;
|
||||||
|
this.maxAlpha = maxAlpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMinAlpha(float minAlpha) {
|
||||||
|
if (minAlpha < 0) minAlpha = 0;
|
||||||
|
this.minAlpha = minAlpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMoveSpeed(float moveSpeed) {
|
||||||
|
this.moveSpeed = moveSpeed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxVisibleItemCount(int maxVisibleItemCount) {
|
||||||
|
this.maxVisibleItemCount = maxVisibleItemCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDistanceToBottom(int distanceToBottom) {
|
||||||
|
this.distanceToBottom = distanceToBottom;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScaleLayoutManager build() {
|
||||||
|
return new ScaleLayoutManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class ScrollHelper {
|
||||||
|
/* package */
|
||||||
|
static void smoothScrollToPosition(RecyclerView recyclerView, ViewPagerLayoutManager viewPagerLayoutManager, int targetPosition) {
|
||||||
|
final int delta = viewPagerLayoutManager.getOffsetToPosition(targetPosition);
|
||||||
|
if (viewPagerLayoutManager.getOrientation() == RecyclerView.VERTICAL) {
|
||||||
|
recyclerView.smoothScrollBy(0, delta);
|
||||||
|
} else {
|
||||||
|
recyclerView.smoothScrollBy(delta, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void smoothScrollToTargetView(RecyclerView recyclerView, View targetView) {
|
||||||
|
final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
|
if (!(layoutManager instanceof ViewPagerLayoutManager)) return;
|
||||||
|
final int targetPosition = ((ViewPagerLayoutManager) layoutManager).getLayoutPositionOfView(targetView);
|
||||||
|
smoothScrollToPosition(recyclerView, (ViewPagerLayoutManager) layoutManager, targetPosition);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,936 @@
|
|||||||
|
package com.common.commonlib.view.viewpagerlayoutmanager;
|
||||||
|
|
||||||
|
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue"})
|
||||||
|
public abstract class ViewPagerLayoutManager extends LinearLayoutManager {
|
||||||
|
|
||||||
|
public static final int DETERMINE_BY_MAX_AND_MIN = -1;
|
||||||
|
|
||||||
|
public static final int HORIZONTAL = OrientationHelper.HORIZONTAL;
|
||||||
|
|
||||||
|
public static final int VERTICAL = OrientationHelper.VERTICAL;
|
||||||
|
protected static final int INVALID_SIZE = Integer.MAX_VALUE;
|
||||||
|
private static final int DIRECTION_NO_WHERE = -1;
|
||||||
|
private static final int DIRECTION_FORWARD = 0;
|
||||||
|
private static final int DIRECTION_BACKWARD = 1;
|
||||||
|
protected int mDecoratedMeasurement;
|
||||||
|
protected int mDecoratedMeasurementInOther;
|
||||||
|
protected int mSpaceMain;
|
||||||
|
protected int mSpaceInOther;
|
||||||
|
/**
|
||||||
|
* The offset of property which will change while scrolling
|
||||||
|
*/
|
||||||
|
protected float mOffset;
|
||||||
|
/**
|
||||||
|
* Many calculations are made depending on orientation. To keep it clean, this interface
|
||||||
|
* helps {@link LinearLayoutManager} make those decisions.
|
||||||
|
* Based on {@link #mOrientation}, an implementation is lazily created in
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
protected OrientationHelper mOrientationHelper;
|
||||||
|
protected float mInterval; //the mInterval of each item's mOffset
|
||||||
|
/**
|
||||||
|
* Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}
|
||||||
|
*/
|
||||||
|
int mOrientation;
|
||||||
|
/* package */ OnPageChangeListener onPageChangeListener;
|
||||||
|
private SparseArray<View> positionCache = new SparseArray<>();
|
||||||
|
/**
|
||||||
|
* Defines if layout should be calculated from end to start.
|
||||||
|
*/
|
||||||
|
private boolean mReverseLayout = false;
|
||||||
|
/**
|
||||||
|
* This keeps the final value for how LayoutManager should start laying out views.
|
||||||
|
* It is calculated by checking {@link #getReverseLayout()} and View's layout direction.
|
||||||
|
* {@link #onLayoutChildren(RecyclerView.Recycler, RecyclerView.State)} is run.
|
||||||
|
*/
|
||||||
|
private boolean mShouldReverseLayout = false;
|
||||||
|
/**
|
||||||
|
* Works the same way as {@link android.widget.AbsListView#setSmoothScrollbarEnabled(boolean)}.
|
||||||
|
* see {@link android.widget.AbsListView#setSmoothScrollbarEnabled(boolean)}
|
||||||
|
*/
|
||||||
|
private boolean mSmoothScrollbarEnabled = true;
|
||||||
|
/**
|
||||||
|
* When LayoutManager needs to scroll to a position, it sets this variable and requests a
|
||||||
|
* layout which will check this variable and re-layout accordingly.
|
||||||
|
*/
|
||||||
|
private int mPendingScrollPosition = NO_POSITION;
|
||||||
|
private SavedState mPendingSavedState = null;
|
||||||
|
private boolean mRecycleChildrenOnDetach;
|
||||||
|
|
||||||
|
private boolean mInfinite = false;
|
||||||
|
|
||||||
|
private boolean mEnableBringCenterToFront;
|
||||||
|
|
||||||
|
private int mLeftItems;
|
||||||
|
|
||||||
|
private int mRightItems;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max visible item count
|
||||||
|
*/
|
||||||
|
private int mMaxVisibleItemCount = DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
|
||||||
|
private Interpolator mSmoothScrollInterpolator;
|
||||||
|
|
||||||
|
private int mDistanceToBottom = INVALID_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use for handle focus
|
||||||
|
*/
|
||||||
|
private View currentFocusView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a horizontal ViewPagerLayoutManager
|
||||||
|
*/
|
||||||
|
public ViewPagerLayoutManager(Context context) {
|
||||||
|
this(context, HORIZONTAL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param orientation Layout orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}
|
||||||
|
* @param reverseLayout When set to true, layouts from end to start
|
||||||
|
*/
|
||||||
|
public ViewPagerLayoutManager(Context context, int orientation, boolean reverseLayout) {
|
||||||
|
super(context);
|
||||||
|
setOrientation(orientation);
|
||||||
|
setReverseLayout(reverseLayout);
|
||||||
|
setAutoMeasureEnabled(true);
|
||||||
|
setItemPrefetchEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the mInterval of each item's mOffset
|
||||||
|
*/
|
||||||
|
protected abstract float setInterval();
|
||||||
|
|
||||||
|
protected abstract void setItemViewProperty(View itemView, float targetOffset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cause elevation is not support below api 21,
|
||||||
|
* so you can set your elevation here for supporting it below api 21
|
||||||
|
* or you can just setElevation in {@link #setItemViewProperty(View, float)}
|
||||||
|
*/
|
||||||
|
protected float setViewElevation(View itemView, float targetOffset) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
|
||||||
|
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether LayoutManager will recycle its children when it is detached from
|
||||||
|
* RecyclerView.
|
||||||
|
*
|
||||||
|
* @return true if LayoutManager will recycle its children when it is detached from
|
||||||
|
* RecyclerView.
|
||||||
|
*/
|
||||||
|
public boolean getRecycleChildrenOnDetach() {
|
||||||
|
return mRecycleChildrenOnDetach;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether LayoutManager will recycle its children when it is detached from
|
||||||
|
* RecyclerView.
|
||||||
|
* <p>
|
||||||
|
* If you are using a {@link RecyclerView.RecycledViewPool}, it might be a good idea to set
|
||||||
|
* this flag to <code>true</code> so that views will be available to other RecyclerViews
|
||||||
|
* immediately.
|
||||||
|
* <p>
|
||||||
|
* Note that, setting this flag will result in a performance drop if RecyclerView
|
||||||
|
* is restored.
|
||||||
|
*
|
||||||
|
* @param recycleChildrenOnDetach Whether children should be recycled in detach or not.
|
||||||
|
*/
|
||||||
|
public void setRecycleChildrenOnDetach(boolean recycleChildrenOnDetach) {
|
||||||
|
mRecycleChildrenOnDetach = recycleChildrenOnDetach;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
|
||||||
|
super.onDetachedFromWindow(view, recycler);
|
||||||
|
if (mRecycleChildrenOnDetach) {
|
||||||
|
removeAndRecycleAllViews(recycler);
|
||||||
|
recycler.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Parcelable onSaveInstanceState() {
|
||||||
|
if (mPendingSavedState != null) {
|
||||||
|
return new SavedState(mPendingSavedState);
|
||||||
|
}
|
||||||
|
SavedState savedState = new SavedState();
|
||||||
|
savedState.position = mPendingScrollPosition;
|
||||||
|
savedState.offset = mOffset;
|
||||||
|
savedState.isReverseLayout = mShouldReverseLayout;
|
||||||
|
return savedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestoreInstanceState(Parcelable state) {
|
||||||
|
if (state instanceof SavedState) {
|
||||||
|
mPendingSavedState = new SavedState((SavedState) state);
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if {@link #getOrientation()} is {@link #HORIZONTAL}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canScrollHorizontally() {
|
||||||
|
return mOrientation == HORIZONTAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if {@link #getOrientation()} is {@link #VERTICAL}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canScrollVertically() {
|
||||||
|
return mOrientation == VERTICAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current orientation of the layout.
|
||||||
|
*
|
||||||
|
* @return Current orientation, either {@link #HORIZONTAL} or {@link #VERTICAL}
|
||||||
|
* @see #setOrientation(int)
|
||||||
|
*/
|
||||||
|
public int getOrientation() {
|
||||||
|
return mOrientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the orientation of the layout. {@link ViewPagerLayoutManager}
|
||||||
|
* will do its best to keep scroll position.
|
||||||
|
*
|
||||||
|
* @param orientation {@link #HORIZONTAL} or {@link #VERTICAL}
|
||||||
|
*/
|
||||||
|
public void setOrientation(int orientation) {
|
||||||
|
if (orientation != HORIZONTAL && orientation != VERTICAL) {
|
||||||
|
throw new IllegalArgumentException("invalid orientation:" + orientation);
|
||||||
|
}
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (orientation == mOrientation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mOrientation = orientation;
|
||||||
|
mOrientationHelper = null;
|
||||||
|
mDistanceToBottom = INVALID_SIZE;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the max visible item count, {@link #DETERMINE_BY_MAX_AND_MIN} means it haven't been set now
|
||||||
|
* And it will use {@link #maxRemoveOffset()} and {@link #minRemoveOffset()} to handle the range
|
||||||
|
*
|
||||||
|
* @return Max visible item count
|
||||||
|
*/
|
||||||
|
public int getMaxVisibleItemCount() {
|
||||||
|
return mMaxVisibleItemCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the max visible item count, {@link #DETERMINE_BY_MAX_AND_MIN} means it haven't been set now
|
||||||
|
* And it will use {@link #maxRemoveOffset()} and {@link #minRemoveOffset()} to handle the range
|
||||||
|
*
|
||||||
|
* @param mMaxVisibleItemCount Max visible item count
|
||||||
|
*/
|
||||||
|
public void setMaxVisibleItemCount(int mMaxVisibleItemCount) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.mMaxVisibleItemCount == mMaxVisibleItemCount) return;
|
||||||
|
this.mMaxVisibleItemCount = mMaxVisibleItemCount;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the view layout order. (e.g. from end to start or start to end)
|
||||||
|
* RTL layout support is applied automatically. So if layout is RTL and
|
||||||
|
* {@link #getReverseLayout()} is {@code true}, elements will be laid out starting from left.
|
||||||
|
*/
|
||||||
|
private void resolveShouldLayoutReverse() {
|
||||||
|
// A == B is the same result, but we rather keep it readable
|
||||||
|
if (mOrientation == VERTICAL || !isLayoutRTL()) {
|
||||||
|
mShouldReverseLayout = mReverseLayout;
|
||||||
|
} else {
|
||||||
|
mShouldReverseLayout = !mReverseLayout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if views are laid out from the opposite direction of the layout.
|
||||||
|
*
|
||||||
|
* @return If layout is reversed or not.
|
||||||
|
* @see #setReverseLayout(boolean)
|
||||||
|
*/
|
||||||
|
public boolean getReverseLayout() {
|
||||||
|
return mReverseLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReverseLayout(boolean reverseLayout) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (reverseLayout == mReverseLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mReverseLayout = reverseLayout;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSmoothScrollInterpolator(Interpolator smoothScrollInterpolator) {
|
||||||
|
this.mSmoothScrollInterpolator = smoothScrollInterpolator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
|
||||||
|
final int offsetPosition;
|
||||||
|
|
||||||
|
// fix wrong scroll direction when infinite enable
|
||||||
|
if (mInfinite) {
|
||||||
|
final int currentPosition = getCurrentPosition();
|
||||||
|
final int total = getItemCount();
|
||||||
|
final int targetPosition;
|
||||||
|
if (position < currentPosition) {
|
||||||
|
int d1 = currentPosition - position;
|
||||||
|
int d2 = total - currentPosition + position;
|
||||||
|
targetPosition = d1 < d2 ? (currentPosition - d1) : (currentPosition + d2);
|
||||||
|
} else {
|
||||||
|
int d1 = position - currentPosition;
|
||||||
|
int d2 = currentPosition + total - position;
|
||||||
|
targetPosition = d1 < d2 ? (currentPosition + d1) : (currentPosition - d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
offsetPosition = getOffsetToPosition(targetPosition);
|
||||||
|
} else {
|
||||||
|
offsetPosition = getOffsetToPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOrientation == VERTICAL) {
|
||||||
|
recyclerView.smoothScrollBy(0, offsetPosition, mSmoothScrollInterpolator);
|
||||||
|
} else {
|
||||||
|
recyclerView.smoothScrollBy(offsetPosition, 0, mSmoothScrollInterpolator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
if (state.getItemCount() == 0) {
|
||||||
|
removeAndRecycleAllViews(recycler);
|
||||||
|
mOffset = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureLayoutState();
|
||||||
|
resolveShouldLayoutReverse();
|
||||||
|
|
||||||
|
//make sure properties are correct while measure more than once
|
||||||
|
View scrap = getMeasureView(recycler, state, 0);
|
||||||
|
if (scrap == null) {
|
||||||
|
removeAndRecycleAllViews(recycler);
|
||||||
|
mOffset = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
measureChildWithMargins(scrap, 0, 0);
|
||||||
|
mDecoratedMeasurement = mOrientationHelper.getDecoratedMeasurement(scrap);
|
||||||
|
mDecoratedMeasurementInOther = mOrientationHelper.getDecoratedMeasurementInOther(scrap);
|
||||||
|
mSpaceMain = (mOrientationHelper.getTotalSpace() - mDecoratedMeasurement) / 2;
|
||||||
|
if (mDistanceToBottom == INVALID_SIZE) {
|
||||||
|
mSpaceInOther = (mOrientationHelper.getTotalSpaceInOther() - mDecoratedMeasurementInOther) / 2;
|
||||||
|
} else {
|
||||||
|
mSpaceInOther = mOrientationHelper.getTotalSpaceInOther() - mDecoratedMeasurementInOther - mDistanceToBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInterval = setInterval();
|
||||||
|
setUp();
|
||||||
|
if (mInterval == 0) {
|
||||||
|
mLeftItems = 1;
|
||||||
|
mRightItems = 1;
|
||||||
|
} else {
|
||||||
|
mLeftItems = (int) Math.abs(minRemoveOffset() / mInterval) + 1;
|
||||||
|
mRightItems = (int) Math.abs(maxRemoveOffset() / mInterval) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPendingSavedState != null) {
|
||||||
|
mShouldReverseLayout = mPendingSavedState.isReverseLayout;
|
||||||
|
mPendingScrollPosition = mPendingSavedState.position;
|
||||||
|
mOffset = mPendingSavedState.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPendingScrollPosition != NO_POSITION) {
|
||||||
|
mOffset = mShouldReverseLayout ?
|
||||||
|
mPendingScrollPosition * -mInterval : mPendingScrollPosition * mInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutItems(recycler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private View getMeasureView(RecyclerView.Recycler recycler, RecyclerView.State state, int index) {
|
||||||
|
if (index >= state.getItemCount() || index < 0) return null;
|
||||||
|
try {
|
||||||
|
return recycler.getViewForPosition(index);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return getMeasureView(recycler, state, index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLayoutCompleted(RecyclerView.State state) {
|
||||||
|
super.onLayoutCompleted(state);
|
||||||
|
mPendingSavedState = null;
|
||||||
|
mPendingScrollPosition = NO_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onAddFocusables(RecyclerView recyclerView, ArrayList<View> views, int direction, int focusableMode) {
|
||||||
|
final int currentPosition = getCurrentPosition();
|
||||||
|
final View currentView = findViewByPosition(currentPosition);
|
||||||
|
if (currentView == null) return true;
|
||||||
|
if (recyclerView.hasFocus()) {
|
||||||
|
final int movement = getMovement(direction);
|
||||||
|
if (movement != DIRECTION_NO_WHERE) {
|
||||||
|
final int targetPosition = movement == DIRECTION_BACKWARD ?
|
||||||
|
currentPosition - 1 : currentPosition + 1;
|
||||||
|
ScrollHelper.smoothScrollToPosition(recyclerView, this, targetPosition);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentView.addFocusables(views, direction, focusableMode);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onFocusSearchFailed(View focused, int focusDirection, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMovement(int direction) {
|
||||||
|
if (mOrientation == VERTICAL) {
|
||||||
|
if (direction == View.FOCUS_UP) {
|
||||||
|
return mShouldReverseLayout ? DIRECTION_FORWARD : DIRECTION_BACKWARD;
|
||||||
|
} else if (direction == View.FOCUS_DOWN) {
|
||||||
|
return mShouldReverseLayout ? DIRECTION_BACKWARD : DIRECTION_FORWARD;
|
||||||
|
} else {
|
||||||
|
return DIRECTION_NO_WHERE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (direction == View.FOCUS_LEFT) {
|
||||||
|
return mShouldReverseLayout ? DIRECTION_FORWARD : DIRECTION_BACKWARD;
|
||||||
|
} else if (direction == View.FOCUS_RIGHT) {
|
||||||
|
return mShouldReverseLayout ? DIRECTION_BACKWARD : DIRECTION_FORWARD;
|
||||||
|
} else {
|
||||||
|
return DIRECTION_NO_WHERE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensureLayoutState() {
|
||||||
|
if (mOrientationHelper == null) {
|
||||||
|
mOrientationHelper = OrientationHelper.createOrientationHelper(this, mOrientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can set up your own properties here or change the exist properties like mSpaceMain and mSpaceInOther
|
||||||
|
*/
|
||||||
|
protected void setUp() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getProperty(int position) {
|
||||||
|
return mShouldReverseLayout ? position * -mInterval : position * mInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter) {
|
||||||
|
removeAllViews();
|
||||||
|
mOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scrollToPosition(int position) {
|
||||||
|
if (!mInfinite && (position < 0 || position >= getItemCount())) return;
|
||||||
|
mPendingScrollPosition = position;
|
||||||
|
mOffset = mShouldReverseLayout ? position * -mInterval : position * mInterval;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeHorizontalScrollOffset(RecyclerView.State state) {
|
||||||
|
return computeScrollOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeVerticalScrollOffset(RecyclerView.State state) {
|
||||||
|
return computeScrollOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeHorizontalScrollExtent(RecyclerView.State state) {
|
||||||
|
return computeScrollExtent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeVerticalScrollExtent(RecyclerView.State state) {
|
||||||
|
return computeScrollExtent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeHorizontalScrollRange(RecyclerView.State state) {
|
||||||
|
return computeScrollRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeVerticalScrollRange(RecyclerView.State state) {
|
||||||
|
return computeScrollRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeScrollOffset() {
|
||||||
|
if (getChildCount() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSmoothScrollbarEnabled) {
|
||||||
|
return !mShouldReverseLayout ?
|
||||||
|
getCurrentPosition() : getItemCount() - getCurrentPosition() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final float realOffset = getOffsetOfRightAdapterPosition();
|
||||||
|
return !mShouldReverseLayout ? (int) realOffset : (int) ((getItemCount() - 1) * mInterval + realOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeScrollExtent() {
|
||||||
|
if (getChildCount() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSmoothScrollbarEnabled) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) mInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeScrollRange() {
|
||||||
|
if (getChildCount() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSmoothScrollbarEnabled) {
|
||||||
|
return getItemCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) (getItemCount() * mInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
if (mOrientation == VERTICAL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return scrollBy(dx, recycler, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
if (mOrientation == HORIZONTAL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return scrollBy(dy, recycler, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int scrollBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
if (getChildCount() == 0 || dy == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ensureLayoutState();
|
||||||
|
int willScroll = dy;
|
||||||
|
|
||||||
|
float realDx = dy / getDistanceRatio();
|
||||||
|
if (Math.abs(realDx) < 0.00000001f) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
float targetOffset = mOffset + realDx;
|
||||||
|
|
||||||
|
//handle the boundary
|
||||||
|
if (!mInfinite && targetOffset < getMinOffset()) {
|
||||||
|
willScroll -= (targetOffset - getMinOffset()) * getDistanceRatio();
|
||||||
|
} else if (!mInfinite && targetOffset > getMaxOffset()) {
|
||||||
|
willScroll = (int) ((getMaxOffset() - mOffset) * getDistanceRatio());
|
||||||
|
}
|
||||||
|
|
||||||
|
realDx = willScroll / getDistanceRatio();
|
||||||
|
|
||||||
|
mOffset += realDx;
|
||||||
|
|
||||||
|
//handle recycle
|
||||||
|
layoutItems(recycler);
|
||||||
|
|
||||||
|
return willScroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void layoutItems(RecyclerView.Recycler recycler) {
|
||||||
|
detachAndScrapAttachedViews(recycler);
|
||||||
|
positionCache.clear();
|
||||||
|
|
||||||
|
final int itemCount = getItemCount();
|
||||||
|
if (itemCount == 0) return;
|
||||||
|
|
||||||
|
// make sure that current position start from 0 to 1
|
||||||
|
final int currentPos = mShouldReverseLayout ?
|
||||||
|
-getCurrentPositionOffset() : getCurrentPositionOffset();
|
||||||
|
int start = currentPos - mLeftItems;
|
||||||
|
int end = currentPos + mRightItems;
|
||||||
|
|
||||||
|
// handle max visible count
|
||||||
|
if (useMaxVisibleCount()) {
|
||||||
|
boolean isEven = mMaxVisibleItemCount % 2 == 0;
|
||||||
|
if (isEven) {
|
||||||
|
int offset = mMaxVisibleItemCount / 2;
|
||||||
|
start = currentPos - offset + 1;
|
||||||
|
end = currentPos + offset + 1;
|
||||||
|
} else {
|
||||||
|
int offset = (mMaxVisibleItemCount - 1) / 2;
|
||||||
|
start = currentPos - offset;
|
||||||
|
end = currentPos + offset + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mInfinite) {
|
||||||
|
if (start < 0) {
|
||||||
|
start = 0;
|
||||||
|
if (useMaxVisibleCount()) end = mMaxVisibleItemCount;
|
||||||
|
}
|
||||||
|
if (end > itemCount) end = itemCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
float lastOrderWeight = Float.MIN_VALUE;
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
if (useMaxVisibleCount() || !removeCondition(getProperty(i) - mOffset)) {
|
||||||
|
// start and end base on current position,
|
||||||
|
// so we need to calculate the adapter position
|
||||||
|
int adapterPosition = i;
|
||||||
|
if (i >= itemCount) {
|
||||||
|
adapterPosition %= itemCount;
|
||||||
|
} else if (i < 0) {
|
||||||
|
int delta = (-adapterPosition) % itemCount;
|
||||||
|
if (delta == 0) delta = itemCount;
|
||||||
|
adapterPosition = itemCount - delta;
|
||||||
|
}
|
||||||
|
final View scrap = recycler.getViewForPosition(adapterPosition);
|
||||||
|
measureChildWithMargins(scrap, 0, 0);
|
||||||
|
resetViewProperty(scrap);
|
||||||
|
// we need i to calculate the real offset of current view
|
||||||
|
final float targetOffset = getProperty(i) - mOffset;
|
||||||
|
layoutScrap(scrap, targetOffset);
|
||||||
|
final float orderWeight = mEnableBringCenterToFront ?
|
||||||
|
setViewElevation(scrap, targetOffset) : adapterPosition;
|
||||||
|
if (orderWeight > lastOrderWeight) {
|
||||||
|
addView(scrap);
|
||||||
|
} else {
|
||||||
|
addView(scrap, 0);
|
||||||
|
}
|
||||||
|
if (i == currentPos) currentFocusView = scrap;
|
||||||
|
lastOrderWeight = orderWeight;
|
||||||
|
positionCache.put(i, scrap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFocusView.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useMaxVisibleCount() {
|
||||||
|
return mMaxVisibleItemCount != DETERMINE_BY_MAX_AND_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean removeCondition(float targetOffset) {
|
||||||
|
return targetOffset > maxRemoveOffset() || targetOffset < minRemoveOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetViewProperty(View v) {
|
||||||
|
v.setRotation(0);
|
||||||
|
v.setRotationY(0);
|
||||||
|
v.setRotationX(0);
|
||||||
|
v.setScaleX(1f);
|
||||||
|
v.setScaleY(1f);
|
||||||
|
v.setAlpha(1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ float getMaxOffset() {
|
||||||
|
return !mShouldReverseLayout ? (getItemCount() - 1) * mInterval : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ float getMinOffset() {
|
||||||
|
return !mShouldReverseLayout ? 0 : -(getItemCount() - 1) * mInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void layoutScrap(View scrap, float targetOffset) {
|
||||||
|
final int left = calItemLeft(scrap, targetOffset);
|
||||||
|
final int top = calItemTop(scrap, targetOffset);
|
||||||
|
if (mOrientation == VERTICAL) {
|
||||||
|
layoutDecorated(scrap, mSpaceInOther + left, mSpaceMain + top,
|
||||||
|
mSpaceInOther + left + mDecoratedMeasurementInOther, mSpaceMain + top + mDecoratedMeasurement);
|
||||||
|
} else {
|
||||||
|
layoutDecorated(scrap, mSpaceMain + left, mSpaceInOther + top,
|
||||||
|
mSpaceMain + left + mDecoratedMeasurement, mSpaceInOther + top + mDecoratedMeasurementInOther);
|
||||||
|
}
|
||||||
|
setItemViewProperty(scrap, targetOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int calItemLeft(View itemView, float targetOffset) {
|
||||||
|
return mOrientation == VERTICAL ? 0 : (int) targetOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int calItemTop(View itemView, float targetOffset) {
|
||||||
|
return mOrientation == VERTICAL ? (int) targetOffset : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when the target offset reach this,
|
||||||
|
* the view will be removed and recycled in {@link #layoutItems(RecyclerView.Recycler)}
|
||||||
|
*/
|
||||||
|
protected float maxRemoveOffset() {
|
||||||
|
return mOrientationHelper.getTotalSpace() - mSpaceMain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when the target offset reach this,
|
||||||
|
* the view will be removed and recycled in {@link #layoutItems(RecyclerView.Recycler)}
|
||||||
|
*/
|
||||||
|
protected float minRemoveOffset() {
|
||||||
|
return -mDecoratedMeasurement - mOrientationHelper.getStartAfterPadding() - mSpaceMain;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float getDistanceRatio() {
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentPosition() {
|
||||||
|
if (getItemCount() == 0) return 0;
|
||||||
|
|
||||||
|
int position = getCurrentPositionOffset();
|
||||||
|
if (!mInfinite) return Math.abs(position);
|
||||||
|
|
||||||
|
position = !mShouldReverseLayout ?
|
||||||
|
//take care of position = getItemCount()
|
||||||
|
(position >= 0 ?
|
||||||
|
position % getItemCount() :
|
||||||
|
getItemCount() + position % getItemCount()) :
|
||||||
|
(position > 0 ?
|
||||||
|
getItemCount() - position % getItemCount() :
|
||||||
|
-position % getItemCount());
|
||||||
|
return position == getItemCount() ? 0 : position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View findViewByPosition(int position) {
|
||||||
|
final int itemCount = getItemCount();
|
||||||
|
if (itemCount == 0) return null;
|
||||||
|
for (int i = 0; i < positionCache.size(); i++) {
|
||||||
|
final int key = positionCache.keyAt(i);
|
||||||
|
if (key >= 0) {
|
||||||
|
if (position == key % itemCount) return positionCache.valueAt(i);
|
||||||
|
} else {
|
||||||
|
int delta = key % itemCount;
|
||||||
|
if (delta == 0) delta = -itemCount;
|
||||||
|
if (itemCount + delta == position) return positionCache.valueAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLayoutPositionOfView(View v) {
|
||||||
|
for (int i = 0; i < positionCache.size(); i++) {
|
||||||
|
int key = positionCache.keyAt(i);
|
||||||
|
View value = positionCache.get(key);
|
||||||
|
if (value == v) return key;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int getCurrentPositionOffset() {
|
||||||
|
if (mInterval == 0) return 0;
|
||||||
|
return Math.round(mOffset / mInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sometimes we need to get the right offset of matching adapter position
|
||||||
|
* cause when {@link #mInfinite} is set true, there will be no limitation of {@link #mOffset}
|
||||||
|
*/
|
||||||
|
private float getOffsetOfRightAdapterPosition() {
|
||||||
|
if (mShouldReverseLayout)
|
||||||
|
return mInfinite ?
|
||||||
|
(mOffset <= 0 ?
|
||||||
|
(mOffset % (mInterval * getItemCount())) :
|
||||||
|
(getItemCount() * -mInterval + mOffset % (mInterval * getItemCount()))) :
|
||||||
|
mOffset;
|
||||||
|
else
|
||||||
|
return mInfinite ?
|
||||||
|
(mOffset >= 0 ?
|
||||||
|
(mOffset % (mInterval * getItemCount())) :
|
||||||
|
(getItemCount() * mInterval + mOffset % (mInterval * getItemCount()))) :
|
||||||
|
mOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by {@link CenterSnapHelper} to center the current view
|
||||||
|
*
|
||||||
|
* @return the dy between center and current position
|
||||||
|
*/
|
||||||
|
public int getOffsetToCenter() {
|
||||||
|
if (mInfinite)
|
||||||
|
return (int) ((getCurrentPositionOffset() * mInterval - mOffset) * getDistanceRatio());
|
||||||
|
return (int) ((getCurrentPosition() *
|
||||||
|
(!mShouldReverseLayout ? mInterval : -mInterval) - mOffset) * getDistanceRatio());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOffsetToPosition(int position) {
|
||||||
|
if (mInfinite)
|
||||||
|
return (int) (((getCurrentPositionOffset() +
|
||||||
|
(!mShouldReverseLayout ? position - getCurrentPositionOffset() : -getCurrentPositionOffset() - position)) *
|
||||||
|
mInterval - mOffset) * getDistanceRatio());
|
||||||
|
return (int) ((position *
|
||||||
|
(!mShouldReverseLayout ? mInterval : -mInterval) - mOffset) * getDistanceRatio());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
|
||||||
|
this.onPageChangeListener = onPageChangeListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getInfinite() {
|
||||||
|
return mInfinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfinite(boolean enable) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (enable == mInfinite) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInfinite = enable;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDistanceToBottom() {
|
||||||
|
return mDistanceToBottom == INVALID_SIZE ?
|
||||||
|
(mOrientationHelper.getTotalSpaceInOther() - mDecoratedMeasurementInOther) / 2 : mDistanceToBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistanceToBottom(int mDistanceToBottom) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (this.mDistanceToBottom == mDistanceToBottom) return;
|
||||||
|
this.mDistanceToBottom = mDistanceToBottom;
|
||||||
|
removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getEnableBringCenterToFront() {
|
||||||
|
return mEnableBringCenterToFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnableBringCenterToFront(boolean bringCenterToTop) {
|
||||||
|
assertNotInLayoutOrScroll(null);
|
||||||
|
if (mEnableBringCenterToFront == bringCenterToTop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.mEnableBringCenterToFront = bringCenterToTop;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current state of the smooth scrollbar feature. It is enabled by default.
|
||||||
|
*
|
||||||
|
* @return True if smooth scrollbar is enabled, false otherwise.
|
||||||
|
* @see #setSmoothScrollbarEnabled(boolean)
|
||||||
|
*/
|
||||||
|
public boolean getSmoothScrollbarEnabled() {
|
||||||
|
return mSmoothScrollbarEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When smooth scrollbar is enabled, the position and size of the scrollbar thumb is computed
|
||||||
|
* based on the number of visible pixels in the visible items. This however assumes that all
|
||||||
|
* list items have similar or equal widths or heights (depending on list orientation).
|
||||||
|
* If you use a list in which items have different dimensions, the scrollbar will change
|
||||||
|
* appearance as the user scrolls through the list. To avoid this issue, you need to disable
|
||||||
|
* this property.
|
||||||
|
* <p>
|
||||||
|
* When smooth scrollbar is disabled, the position and size of the scrollbar thumb is based
|
||||||
|
* solely on the number of items in the adapter and the position of the visible items inside
|
||||||
|
* the adapter. This provides a stable scrollbar as the user navigates through a list of items
|
||||||
|
* with varying widths / heights.
|
||||||
|
*
|
||||||
|
* @param enabled Whether or not to enable smooth scrollbar.
|
||||||
|
* @see #setSmoothScrollbarEnabled(boolean)
|
||||||
|
*/
|
||||||
|
public void setSmoothScrollbarEnabled(boolean enabled) {
|
||||||
|
mSmoothScrollbarEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnPageChangeListener {
|
||||||
|
void onPageSelected(int position);
|
||||||
|
|
||||||
|
void onPageScrollStateChanged(int state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SavedState implements Parcelable {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
int position;
|
||||||
|
float offset;
|
||||||
|
boolean isReverseLayout;
|
||||||
|
|
||||||
|
SavedState() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SavedState(Parcel in) {
|
||||||
|
position = in.readInt();
|
||||||
|
offset = in.readFloat();
|
||||||
|
isReverseLayout = in.readInt() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SavedState(SavedState other) {
|
||||||
|
position = other.position;
|
||||||
|
offset = other.offset;
|
||||||
|
isReverseLayout = other.isReverseLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(position);
|
||||||
|
dest.writeFloat(offset);
|
||||||
|
dest.writeInt(isReverseLayout ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#E9E9E9"
|
||||||
|
android:alpha="0.8">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
||||||
|
</vector>
|
@ -0,0 +1,11 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#E9E9E9"
|
||||||
|
android:alpha="0.8">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||||
|
</vector>
|
After Width: | Height: | Size: 282 B |
After Width: | Height: | Size: 402 B |
After Width: | Height: | Size: 325 B |
After Width: | Height: | Size: 267 B |
After Width: | Height: | Size: 786 B |
After Width: | Height: | Size: 786 B |
After Width: | Height: | Size: 255 B |
After Width: | Height: | Size: 320 B |
After Width: | Height: | Size: 530 B |
After Width: | Height: | Size: 479 B |
After Width: | Height: | Size: 308 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 379 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 666 B |
After Width: | Height: | Size: 537 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 859 B |
@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/root_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/title_bar_bg_color"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/rl_left_hot_zone"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingStart="@dimen/font_20dp"
|
||||||
|
android:paddingEnd="@dimen/font_20dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_left"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/ic_back" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="@dimen/font_16dp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/rl_edit_hot_zone"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingStart="@dimen/font_20dp"
|
||||||
|
android:paddingEnd="@dimen/font_20dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_edit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:text="@string/edit"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="@dimen/font_14dp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/rl_add_hot_zone"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingStart="@dimen/font_20dp"
|
||||||
|
android:paddingEnd="@dimen/font_20dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_right"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/ic_add" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="@dimen/font_80dp"
|
||||||
|
android:layout_height="@dimen/font_80dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bg_pic_add"
|
||||||
|
android:layout_width="@dimen/font_74dp"
|
||||||
|
android:layout_height="@dimen/font_74dp"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:src="@drawable/ic_add" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="@dimen/font_80dp"
|
||||||
|
android:layout_height="@dimen/font_80dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/pic_iv"
|
||||||
|
android:layout_width="@dimen/font_74dp"
|
||||||
|
android:layout_height="@dimen/font_74dp"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:scaleType="center" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/pic_delete_iv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@+id/pic_iv"
|
||||||
|
android:layout_alignEnd="@+id/pic_iv"
|
||||||
|
android:layout_marginTop="-5dp"
|
||||||
|
android:layout_marginEnd="-5dp"
|
||||||
|
android:src="@drawable/ic_pic_delete" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_loading"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#33000000"
|
||||||
|
android:padding="@dimen/font_20dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="CommonTitleView">
|
||||||
|
<attr name="title" format="string"></attr>
|
||||||
|
<attr name="show_style" format="enum">
|
||||||
|
<enum name="left" value="1" />
|
||||||
|
<enum name="left_middle" value="2" />
|
||||||
|
<enum name="left_middle_right" value="3" />
|
||||||
|
<enum name="middle" value="4" />
|
||||||
|
<enum name="middle_right" value="5" />
|
||||||
|
<enum name="right" value="6" />
|
||||||
|
<enum name="edit" value="7" />
|
||||||
|
</attr>
|
||||||
|
<attr name="is_fixed_height" format="boolean" />
|
||||||
|
<attr name="fixed_height" format="integer" />
|
||||||
|
<attr name="drawableLeft" format="reference" />
|
||||||
|
<attr name="drawableRight" format="reference" />
|
||||||
|
<attr name="bgColor" format="reference|color" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="AutoPlayRecyclerView">
|
||||||
|
<attr name="timeInterval" format="integer" />
|
||||||
|
<attr name="direction" format="enum">
|
||||||
|
<enum name="left" value="1" />
|
||||||
|
<enum name="right" value="2" />
|
||||||
|
</attr>
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
<color name="purple_700">#FF3700B3</color>
|
||||||
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
<color name="red">#FF0000</color>
|
||||||
|
|
||||||
|
<color name="bg_delete_btn">#FF5151</color>
|
||||||
|
<color name="bg_export_btn">#FFAA60</color>
|
||||||
|
|
||||||
|
<color name="font_666">#666666</color>
|
||||||
|
<color name="font_333">#333333</color>
|
||||||
|
<color name="font_999">#999999</color>
|
||||||
|
<color name="bg_F5">#F5F5F5</color>
|
||||||
|
<color name="bg_E9">#E9E9E9</color>
|
||||||
|
|
||||||
|
<color name="title_bar_bg_color">#0786F0</color>
|
||||||
|
<color name="btn_bg_start">#3BA6FF</color>
|
||||||
|
<color name="btn_bg_end">#0786F0</color>
|
||||||
|
<color name="yellow_button_color">#FFAA61</color>
|
||||||
|
|
||||||
|
<color name="home_template_text_color">#2E69FF</color>
|
||||||
|
<color name="home_record_text_color">#FF973B</color>
|
||||||
|
|
||||||
|
<color name="color_33">#333333</color>
|
||||||
|
<color name="color_f5">#F5F5F5</color>
|
||||||
|
<color name="color_66">#666666</color>
|
||||||
|
<color name="color_99">#999999</color>
|
||||||
|
|
||||||
|
</resources>
|
@ -0,0 +1,52 @@
|
|||||||
|
<resources>
|
||||||
|
<dimen name="font_0.5dp">0.5dp</dimen>
|
||||||
|
<dimen name="font_1dp">1dp</dimen>
|
||||||
|
<dimen name="font_2dp">2dp</dimen>
|
||||||
|
<dimen name="font_3dp">3dp</dimen>
|
||||||
|
<dimen name="font_4dp">4dp</dimen>
|
||||||
|
<dimen name="font_8dp">8dp</dimen>
|
||||||
|
<dimen name="font_5dp">5dp</dimen>
|
||||||
|
<dimen name="font_6dp">6dp</dimen>
|
||||||
|
<dimen name="font_7dp">7dp</dimen>
|
||||||
|
<dimen name="font_9dp">9dp</dimen>
|
||||||
|
<dimen name="font_10dp">10dp</dimen>
|
||||||
|
<dimen name="font_11dp">11dp</dimen>
|
||||||
|
<dimen name="font_12dp">12dp</dimen>
|
||||||
|
<dimen name="font_13dp">13dp</dimen>
|
||||||
|
<dimen name="font_14dp">14dp</dimen>
|
||||||
|
<dimen name="font_15dp">15dp</dimen>
|
||||||
|
<dimen name="font_16dp">16dp</dimen>
|
||||||
|
<dimen name="font_17dp">17dp</dimen>
|
||||||
|
<dimen name="font_18dp">18dp</dimen>
|
||||||
|
<dimen name="font_19dp">19dp</dimen>
|
||||||
|
<dimen name="font_20dp">20dp</dimen>
|
||||||
|
<dimen name="font_21dp">21dp</dimen>
|
||||||
|
<dimen name="font_22dp">22dp</dimen>
|
||||||
|
<dimen name="font_23dp">23dp</dimen>
|
||||||
|
<dimen name="font_24dp">24dp</dimen>
|
||||||
|
<dimen name="font_26dp">26dp</dimen>
|
||||||
|
<dimen name="font_27dp">27dp</dimen>
|
||||||
|
<dimen name="font_28dp">28dp</dimen>
|
||||||
|
<dimen name="font_30dp">30dp</dimen>
|
||||||
|
<dimen name="font_29dp">29dp</dimen>
|
||||||
|
<dimen name="font_40dp">40dp</dimen>
|
||||||
|
<dimen name="font_42dp">42dp</dimen>
|
||||||
|
<dimen name="font_46dp">46dp</dimen>
|
||||||
|
<dimen name="font_60dp">60dp</dimen>
|
||||||
|
<dimen name="font_65dp">65dp</dimen>
|
||||||
|
<dimen name="font_70dp">70dp</dimen>
|
||||||
|
<dimen name="font_72dp">72dp</dimen>
|
||||||
|
<dimen name="font_74dp">74dp</dimen>
|
||||||
|
<dimen name="font_79dp">79dp</dimen>
|
||||||
|
<dimen name="font_80dp">80dp</dimen>
|
||||||
|
<dimen name="font_90dp">90dp</dimen>
|
||||||
|
<dimen name="font_84dp">84dp</dimen>
|
||||||
|
<dimen name="font_100dp">100dp</dimen>
|
||||||
|
<dimen name="font_115dp">115dp</dimen>
|
||||||
|
<dimen name="font_152dp">152dp</dimen>
|
||||||
|
<dimen name="font_160dp">160dp</dimen>
|
||||||
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
|
<dimen name="action_height">48dp</dimen>
|
||||||
|
<dimen name="font_size">15dp</dimen>
|
||||||
|
<dimen name="font_185dp">185dp</dimen>
|
||||||
|
</resources>
|