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>
|