From 154a1136564454c5740d75b30366329309d91616 Mon Sep 17 00:00:00 2001 From: rosuh Date: Fri, 21 Aug 2020 15:47:10 +0800 Subject: [PATCH 1/2] [Update] - Modify payload usage. --- .../main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/filepicker/src/main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt b/filepicker/src/main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt index 8c214ee..fe4515a 100644 --- a/filepicker/src/main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt +++ b/filepicker/src/main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt @@ -87,12 +87,12 @@ class FileListAdapter( when (holder) { is FileListItemHolder -> { holder.itemView.findViewById(R.id.cb_list_file_picker)?.let { - it.isChecked = payloads[0] as Boolean + it.isChecked = getItem(position)?.isChecked() ?: false } } is FileListItemSingleChoiceHolder -> { holder.itemView.findViewById(R.id.rb_list_file_picker)?.let { - it.isChecked = payloads[0] as Boolean + it.isChecked = getItem(position)?.isChecked() ?: false } } } From 889f77259aadcc8b18839cab1b0a94f694383dcd Mon Sep 17 00:00:00 2001 From: rosuH Date: Wed, 16 Sep 2020 11:09:27 +0800 Subject: [PATCH 2/2] :spark: :arrow_up: [Update] - A new api for custom file types which comes with auto filter features. - Upgrade Kotlin to 1.4.10 --- build.gradle | 4 +- filepicker/build.gradle | 2 +- .../filepicker/config/DefaultFileDetector.kt | 44 +++++++++++---- .../filepicker/config/FilePickerConfig.kt | 56 +++++++++++++++++-- .../me/rosuh/filepicker/utils/FileUtils.kt | 35 +++++++----- gradle/wrapper/gradle-wrapper.properties | 4 +- sample/build.gradle | 2 +- .../java/me/rosuh/sample/SampleActivity.kt | 30 ++++------ .../main/res/layout/demo_activity_main.xml | 29 +++++++--- 9 files changed, 143 insertions(+), 63 deletions(-) diff --git a/build.gradle b/build.gradle index f04bfbe..9034dd1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version="1.3.60" + ext.kotlin_version="1.4.10" repositories { google() jcenter() @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:4.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' classpath "org.jlleitschuh.gradle:ktlint-gradle:9.1.1" diff --git a/filepicker/build.gradle b/filepicker/build.gradle index aef3e95..a06de71 100644 --- a/filepicker/build.gradle +++ b/filepicker/build.gradle @@ -44,7 +44,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlin_version}" implementation "com.android.support:appcompat-v7:${supportLibVersion}" implementation "com.android.support:recyclerview-v7:${supportLibVersion}" - implementation "com.android.support.constraint:constraint-layout:1.1.3" + implementation "com.android.support.constraint:constraint-layout:2.0.1" testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileDetector.kt b/filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileDetector.kt index 669b4bb..bacc78e 100644 --- a/filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileDetector.kt +++ b/filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileDetector.kt @@ -10,19 +10,39 @@ import me.rosuh.filepicker.filetype.* */ class DefaultFileDetector : AbstractFileDetector() { + var enableCustomTypes: Boolean = false + private set + private val allDefaultFileType: ArrayList by lazy { - val fileTypes = ArrayList() - fileTypes.add(AudioFileType()) - fileTypes.add(RasterImageFileType()) - fileTypes.add(CompressedFileType()) - fileTypes.add(DataBaseFileType()) - fileTypes.add(ExecutableFileType()) - fileTypes.add(FontFileType()) - fileTypes.add(PageLayoutFileType()) - fileTypes.add(TextFileType()) - fileTypes.add(VideoFileType()) - fileTypes.add(WebFileType()) - fileTypes + ArrayList() + } + + fun registerDefaultTypes() { + with(allDefaultFileType) { + clear() + add(AudioFileType()) + add(RasterImageFileType()) + add(CompressedFileType()) + add(DataBaseFileType()) + add(ExecutableFileType()) + add(FontFileType()) + add(PageLayoutFileType()) + add(TextFileType()) + add(VideoFileType()) + add(WebFileType()) + } + enableCustomTypes = false + } + + /** + * @author rosuh@qq.com + * @date 2020/9/16 + * save user's custom file types + */ + fun registerCustomTypes(customFileTypes: ArrayList) { + allDefaultFileType.clear() + allDefaultFileType.addAll(customFileTypes) + enableCustomTypes = true } override fun fillFileType(itemBeanImpl: FileItemBeanImpl): FileItemBeanImpl { diff --git a/filepicker/src/main/java/me/rosuh/filepicker/config/FilePickerConfig.kt b/filepicker/src/main/java/me/rosuh/filepicker/config/FilePickerConfig.kt index db5af06..b90f541 100644 --- a/filepicker/src/main/java/me/rosuh/filepicker/config/FilePickerConfig.kt +++ b/filepicker/src/main/java/me/rosuh/filepicker/config/FilePickerConfig.kt @@ -6,6 +6,7 @@ import android.support.annotation.StringRes import me.rosuh.filepicker.FilePickerActivity import me.rosuh.filepicker.R import me.rosuh.filepicker.engine.ImageEngine +import me.rosuh.filepicker.filetype.FileType /** * @@ -14,6 +15,12 @@ import me.rosuh.filepicker.engine.ImageEngine */ class FilePickerConfig(private val pickerManager: FilePickerManager) { + var isAutoFilter: Boolean = false + + private val customFileTypes: ArrayList by lazy { + ArrayList(2) + } + private val contextRes = pickerManager.contextRef!!.get()!!.resources /** @@ -77,9 +84,14 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) { /** * 自定文件类型甄别器和默认类型甄别器 */ + @Deprecated( + "Use 'register' function instead.", + ReplaceWith("registerFileType(types)"), + level = DeprecationLevel.WARNING + ) var customDetector: AbstractFileDetector? = null - private set - val defaultFileDetector: DefaultFileDetector by lazy { DefaultFileDetector() } + + val defaultFileDetector: DefaultFileDetector by lazy { DefaultFileDetector().also { it.registerDefaultTypes() } } /** * 点击操作接口,采用默认实现 @@ -140,7 +152,10 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) { } @JvmOverloads - fun storageType(volumeName: String = "", @StorageMediaType storageMediaType: String): FilePickerConfig { + fun storageType( + volumeName: String = "", + @StorageMediaType storageMediaType: String + ): FilePickerConfig { mediaStorageName = volumeName mediaStorageType = storageMediaType return this @@ -157,11 +172,19 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) { } /** + * @author rosuh@qq.com + * @date 2020/9/15 + * custom file type had upgrade to [registerFileType], which can simplify your usage. * 实现 [AbstractFileDetector] 以自定义您自己的文件类型检测器 * Custom your file detector by implementing [AbstractFileDetector] */ + @Deprecated( + "Use 'register' function instead.", + ReplaceWith("registerFileType(types)"), + level = DeprecationLevel.WARNING + ) fun customDetector(detector: AbstractFileDetector): FilePickerConfig { - customDetector = detector + this.customDetector = detector return this } @@ -227,6 +250,28 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) { this.customImageEngine = ie return this } + /** + * @author rosuh@qq.com + * @date 2020/9/15 + * 用于注册你自定义的文件类型。 + * 库将自动调用你的自定义类型里的[FileType.verify]来识别文件。如果识别成功,就会自动填充到 [me.rosuh.filepicker.bean.FileItemBeanImpl.fileType] 中 + * 如果[autoFilter]为 true,那么库将自动过滤掉不符合你自定义类型的文件。不会在结果中显示出来。 + * 如果为 false,那么就只是检测类型。不会对结果列表做修改 + * 你不需要再调用[fileType]方法,否则将默认使用[fileType] + * --- + * Pass your custom [FileType] instances list and all done! This lib would auto detect file type + * by using [FileType.verify]. + * If [autoFilter] is true, this lib will filter result by using your custom file types. + * If [autoFilter] is true, the library will automatically filter out files that do not meet your custom type. + * Will not show up in the results. * If it is false, then only the detection type. No changes to the result list + * You don't need to call [fileType] again ! + */ + fun registerFileType(types: List, autoFilter: Boolean = true): FilePickerConfig { + this.customFileTypes.addAll(types) + this.defaultFileDetector.registerCustomTypes(customFileTypes) + this.isAutoFilter = autoFilter + return this + } fun forResult(requestCode: Int) { val activity = pickerManager.contextRef?.get()!! @@ -246,16 +291,19 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) { */ @get:StorageMediaType const val STORAGE_EXTERNAL_STORAGE = "STORAGE_EXTERNAL_STORAGE" + /** * TODO 可拔插的 SD 卡 */ @get:StorageMediaType const val STORAGE_UUID_SD_CARD = "STORAGE_UUID_SD_CARD" + /** * TODO 可拔插 U 盘 */ @get:StorageMediaType const val STORAGE_UUID_USB_DRIVE = "STORAGE_UUID_USB_DRIVE" + /** * 自定义路径 */ diff --git a/filepicker/src/main/java/me/rosuh/filepicker/utils/FileUtils.kt b/filepicker/src/main/java/me/rosuh/filepicker/utils/FileUtils.kt index b1b3c7d..33153d4 100644 --- a/filepicker/src/main/java/me/rosuh/filepicker/utils/FileUtils.kt +++ b/filepicker/src/main/java/me/rosuh/filepicker/utils/FileUtils.kt @@ -8,7 +8,7 @@ import me.rosuh.filepicker.bean.FileItemBeanImpl import me.rosuh.filepicker.bean.FileNavBeanImpl import me.rosuh.filepicker.config.FilePickerConfig.Companion.STORAGE_CUSTOM_ROOT_PATH import me.rosuh.filepicker.config.FilePickerConfig.Companion.STORAGE_EXTERNAL_STORAGE -import me.rosuh.filepicker.config.FilePickerManager +import me.rosuh.filepicker.config.FilePickerManager.config import java.io.File /** @@ -24,16 +24,16 @@ class FileUtils { * 根据配置参数获取根目录文件 * @return File */ - fun getRootFile(): File { - return when (FilePickerManager.config.mediaStorageType) { + fun getRootFile():File { + return when (config.mediaStorageType) { STORAGE_EXTERNAL_STORAGE -> { File(Environment.getExternalStorageDirectory().absoluteFile.toURI()) } STORAGE_CUSTOM_ROOT_PATH -> { - if (FilePickerManager.config.customRootPath.isEmpty()) { + if (config.customRootPath.isEmpty()) { File(Environment.getExternalStorageDirectory().absoluteFile.toURI()) } else { - File(FilePickerManager.config.customRootPath) + File(config.customRootPath) } } else -> { @@ -50,10 +50,11 @@ class FileUtils { beanSubscriber: BeanSubscriber ): ArrayList { val listData: ArrayList = ArrayList() + var isDetected = false for (file in rootFile.listFiles()) { //以符号 . 开头的视为隐藏文件或隐藏文件夹,后面进行过滤 val isHiddenFile = file.name.startsWith(".") - if (!FilePickerManager.config.isShowHiddenFiles && isHiddenFile) { + if (!config.isShowHiddenFiles && isHiddenFile) { // skip hidden files continue } @@ -81,8 +82,16 @@ class FileUtils { beanSubscriber ) // 如果调用者没有实现文件类型甄别器,则使用的默认甄别器 - FilePickerManager.config.customDetector?.fillFileType(itemBean) - ?: FilePickerManager.config.defaultFileDetector.fillFileType(itemBean) + config.customDetector?.fillFileType(itemBean) + ?: config.defaultFileDetector.fillFileType(itemBean) + isDetected = itemBean.fileType != null + if (config.defaultFileDetector.enableCustomTypes + && config.isAutoFilter + && !isDetected + ) { + // enable auto filter AND using user's custom file type. Filter them. + continue + } listData.add(itemBean) } // 默认字典排序 @@ -90,7 +99,7 @@ class FileUtils { listData.sortWith(compareBy({ !it.isDir }, { it.fileName.toUpperCase() })) // 将当前列表数据暴露,以供调用者自己处理数据 // expose data list to outside caller - return FilePickerManager.config.selfFilter?.doFilter(listData) ?: listData + return config.selfFilter?.doFilter(listData) ?: listData } /** @@ -107,10 +116,10 @@ class FileUtils { // 优先级:目标设备名称 --> 自定义路径 --> 默认 SD 卡 currentDataSource.add( FileNavBeanImpl( - if (!FilePickerManager.config.mediaStorageName.isNullOrEmpty()) { - FilePickerManager.config.mediaStorageName - } else if (!FilePickerManager.config.customRootPath.isEmpty()) { - FilePickerManager.config.customRootPath + if (!config.mediaStorageName.isNullOrEmpty()) { + config.mediaStorageName + } else if (!config.customRootPath.isEmpty()) { + config.customRootPath } else { context.getString(R.string.file_picker_tv_sd_card) }, diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2bde8f..bd4d82d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Nov 27 14:17:28 CST 2019 +#Wed Sep 16 10:42:32 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/sample/build.gradle b/sample/build.gradle index 994a540..7510b7e 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -35,7 +35,7 @@ dependencies { // implementation 'com.squareup.picasso:picasso:2.5.2' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support.constraint:constraint-layout:2.0.1' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/sample/src/main/java/me/rosuh/sample/SampleActivity.kt b/sample/src/main/java/me/rosuh/sample/SampleActivity.kt index 8dbec17..7889764 100644 --- a/sample/src/main/java/me/rosuh/sample/SampleActivity.kt +++ b/sample/src/main/java/me/rosuh/sample/SampleActivity.kt @@ -22,6 +22,11 @@ import me.rosuh.filepicker.bean.FileItemBeanImpl import me.rosuh.filepicker.config.* import me.rosuh.filepicker.engine.ImageEngine import me.rosuh.filepicker.filetype.FileType +import me.rosuh.filepicker.config.AbstractFileFilter +import me.rosuh.filepicker.config.FilePickerConfig +import me.rosuh.filepicker.config.FilePickerManager +import me.rosuh.filepicker.config.SimpleItemClickListener +import me.rosuh.filepicker.filetype.AudioFileType import me.rosuh.filepicker.filetype.RasterImageFileType import me.rosuh.filepicker.utils.ScreenUtils @@ -125,7 +130,6 @@ class SampleActivity : AppCompatActivity() { } }) .skipDirWhenSelect(false) - .setTheme(R.style.FilePickerThemeReply) .forResult(FilePickerManager.REQUEST_CODE) } // 多选文件 @@ -133,7 +137,6 @@ class SampleActivity : AppCompatActivity() { FilePickerManager .from(this@SampleActivity) .setTheme(getRandomTheme()) - .setTheme(R.style.FilePickerThemeCrane) .forResult(FilePickerManager.REQUEST_CODE) } // 多选文件夹 @@ -149,7 +152,6 @@ class SampleActivity : AppCompatActivity() { } }) .skipDirWhenSelect(false) - .setTheme(R.style.FilePickerThemeShrine) .forResult(FilePickerManager.REQUEST_CODE) } // 自定义根目录 @@ -160,29 +162,17 @@ class SampleActivity : AppCompatActivity() { // 不指定名称则为导航栏将显示绝对路径 // .storageType(FilePickerConfig.STORAGE_CUSTOM_ROOT_PATH) .setCustomRootPath("/storage/emulated/0/Download") - .setTheme(R.style.FilePickerThemeReply) .forResult(FilePickerManager.REQUEST_CODE) } // 自定义文件类型 + // the new api for register your custom file type btn_custom_file_type.setOnClickListener { - FilePickerManager - .from(this@SampleActivity) - // 1. 使用自定义文件检测器来检测类型,并赋值给 [FileItemBeanImpl.fileType] 属性 - // 1. Using detector detect file's type and fill it into [FileItemBeanImpl.fileType] - .customDetector(CustomFileDetector()) - .filter(object : AbstractFileFilter() { - override fun doFilter(listData: ArrayList): ArrayList { - // 2. 接收结果列表,然后过滤出您想要的类型 - // 2. Receive result list and filter what you want - listData.removeAll { - (it.fileType !is CustomFileType) && !it.isDir - } - return listData - } - }) - .showHiddenFiles(true) + FilePickerManager.from(this@SampleActivity) + .setTheme(getRandomTheme()) + .registerFileType(arrayListOf(AudioFileType())) .forResult(FilePickerManager.REQUEST_CODE) } + findViewById