Skip to content

Commit 7687193

Browse files
authored
Merge pull request #89 from rosuH/dev
Improved custom file type.
2 parents 8733b6e + 889f772 commit 7687193

10 files changed

Lines changed: 145 additions & 65 deletions

File tree

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
ext.kotlin_version="1.3.60"
4+
ext.kotlin_version="1.4.10"
55
repositories {
66
google()
77
jcenter()
@@ -10,7 +10,7 @@ buildscript {
1010
}
1111
}
1212
dependencies {
13-
classpath 'com.android.tools.build:gradle:3.2.1'
13+
classpath 'com.android.tools.build:gradle:4.0.1'
1414
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1515
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
1616
classpath "org.jlleitschuh.gradle:ktlint-gradle:9.1.1"

filepicker/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ dependencies {
4444
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlin_version}"
4545
implementation "com.android.support:appcompat-v7:${supportLibVersion}"
4646
implementation "com.android.support:recyclerview-v7:${supportLibVersion}"
47-
implementation "com.android.support.constraint:constraint-layout:1.1.3"
47+
implementation "com.android.support.constraint:constraint-layout:2.0.1"
4848
testImplementation 'junit:junit:4.12'
4949
androidTestImplementation 'com.android.support.test:runner:1.0.2'
5050
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

filepicker/src/main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ class FileListAdapter(
8787
when (holder) {
8888
is FileListItemHolder -> {
8989
holder.itemView.findViewById<CheckBox>(R.id.cb_list_file_picker)?.let {
90-
it.isChecked = payloads[0] as Boolean
90+
it.isChecked = getItem(position)?.isChecked() ?: false
9191
}
9292
}
9393
is FileListItemSingleChoiceHolder -> {
9494
holder.itemView.findViewById<RadioButton>(R.id.rb_list_file_picker)?.let {
95-
it.isChecked = payloads[0] as Boolean
95+
it.isChecked = getItem(position)?.isChecked() ?: false
9696
}
9797
}
9898
}

filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileDetector.kt

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,39 @@ import me.rosuh.filepicker.filetype.*
1010
*/
1111
class DefaultFileDetector : AbstractFileDetector() {
1212

13+
var enableCustomTypes: Boolean = false
14+
private set
15+
1316
private val allDefaultFileType: ArrayList<FileType> by lazy {
14-
val fileTypes = ArrayList<FileType>()
15-
fileTypes.add(AudioFileType())
16-
fileTypes.add(RasterImageFileType())
17-
fileTypes.add(CompressedFileType())
18-
fileTypes.add(DataBaseFileType())
19-
fileTypes.add(ExecutableFileType())
20-
fileTypes.add(FontFileType())
21-
fileTypes.add(PageLayoutFileType())
22-
fileTypes.add(TextFileType())
23-
fileTypes.add(VideoFileType())
24-
fileTypes.add(WebFileType())
25-
fileTypes
17+
ArrayList<FileType>()
18+
}
19+
20+
fun registerDefaultTypes() {
21+
with(allDefaultFileType) {
22+
clear()
23+
add(AudioFileType())
24+
add(RasterImageFileType())
25+
add(CompressedFileType())
26+
add(DataBaseFileType())
27+
add(ExecutableFileType())
28+
add(FontFileType())
29+
add(PageLayoutFileType())
30+
add(TextFileType())
31+
add(VideoFileType())
32+
add(WebFileType())
33+
}
34+
enableCustomTypes = false
35+
}
36+
37+
/**
38+
* @author rosuh@qq.com
39+
* @date 2020/9/16
40+
* save user's custom file types
41+
*/
42+
fun registerCustomTypes(customFileTypes: ArrayList<FileType>) {
43+
allDefaultFileType.clear()
44+
allDefaultFileType.addAll(customFileTypes)
45+
enableCustomTypes = true
2646
}
2747

2848
override fun fillFileType(itemBeanImpl: FileItemBeanImpl): FileItemBeanImpl {

filepicker/src/main/java/me/rosuh/filepicker/config/FilePickerConfig.kt

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.support.annotation.StringRes
66
import me.rosuh.filepicker.FilePickerActivity
77
import me.rosuh.filepicker.R
88
import me.rosuh.filepicker.engine.ImageEngine
9+
import me.rosuh.filepicker.filetype.FileType
910

1011
/**
1112
*
@@ -14,6 +15,12 @@ import me.rosuh.filepicker.engine.ImageEngine
1415
*/
1516
class FilePickerConfig(private val pickerManager: FilePickerManager) {
1617

18+
var isAutoFilter: Boolean = false
19+
20+
private val customFileTypes: ArrayList<FileType> by lazy {
21+
ArrayList<FileType>(2)
22+
}
23+
1724
private val contextRes = pickerManager.contextRef!!.get()!!.resources
1825

1926
/**
@@ -77,9 +84,14 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
7784
/**
7885
* 自定文件类型甄别器和默认类型甄别器
7986
*/
87+
@Deprecated(
88+
"Use 'register' function instead.",
89+
ReplaceWith("registerFileType(types)"),
90+
level = DeprecationLevel.WARNING
91+
)
8092
var customDetector: AbstractFileDetector? = null
81-
private set
82-
val defaultFileDetector: DefaultFileDetector by lazy { DefaultFileDetector() }
93+
94+
val defaultFileDetector: DefaultFileDetector by lazy { DefaultFileDetector().also { it.registerDefaultTypes() } }
8395

8496
/**
8597
* 点击操作接口,采用默认实现
@@ -140,7 +152,10 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
140152
}
141153

142154
@JvmOverloads
143-
fun storageType(volumeName: String = "", @StorageMediaType storageMediaType: String): FilePickerConfig {
155+
fun storageType(
156+
volumeName: String = "",
157+
@StorageMediaType storageMediaType: String
158+
): FilePickerConfig {
144159
mediaStorageName = volumeName
145160
mediaStorageType = storageMediaType
146161
return this
@@ -157,11 +172,19 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
157172
}
158173

159174
/**
175+
* @author rosuh@qq.com
176+
* @date 2020/9/15
177+
* custom file type had upgrade to [registerFileType], which can simplify your usage.
160178
* 实现 [AbstractFileDetector] 以自定义您自己的文件类型检测器
161179
* Custom your file detector by implementing [AbstractFileDetector]
162180
*/
181+
@Deprecated(
182+
"Use 'register' function instead.",
183+
ReplaceWith("registerFileType(types)"),
184+
level = DeprecationLevel.WARNING
185+
)
163186
fun customDetector(detector: AbstractFileDetector): FilePickerConfig {
164-
customDetector = detector
187+
this.customDetector = detector
165188
return this
166189
}
167190

@@ -227,6 +250,28 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
227250
this.customImageEngine = ie
228251
return this
229252
}
253+
/**
254+
* @author rosuh@qq.com
255+
* @date 2020/9/15
256+
* 用于注册你自定义的文件类型。
257+
* 库将自动调用你的自定义类型里的[FileType.verify]来识别文件。如果识别成功,就会自动填充到 [me.rosuh.filepicker.bean.FileItemBeanImpl.fileType] 中
258+
* 如果[autoFilter]为 true,那么库将自动过滤掉不符合你自定义类型的文件。不会在结果中显示出来。
259+
* 如果为 false,那么就只是检测类型。不会对结果列表做修改
260+
* 你不需要再调用[fileType]方法,否则将默认使用[fileType]
261+
* ---
262+
* Pass your custom [FileType] instances list and all done! This lib would auto detect file type
263+
* by using [FileType.verify].
264+
* If [autoFilter] is true, this lib will filter result by using your custom file types.
265+
* If [autoFilter] is true, the library will automatically filter out files that do not meet your custom type.
266+
* Will not show up in the results. * If it is false, then only the detection type. No changes to the result list
267+
* You don't need to call [fileType] again !
268+
*/
269+
fun registerFileType(types: List<FileType>, autoFilter: Boolean = true): FilePickerConfig {
270+
this.customFileTypes.addAll(types)
271+
this.defaultFileDetector.registerCustomTypes(customFileTypes)
272+
this.isAutoFilter = autoFilter
273+
return this
274+
}
230275

231276
fun forResult(requestCode: Int) {
232277
val activity = pickerManager.contextRef?.get()!!
@@ -246,16 +291,19 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
246291
*/
247292
@get:StorageMediaType
248293
const val STORAGE_EXTERNAL_STORAGE = "STORAGE_EXTERNAL_STORAGE"
294+
249295
/**
250296
* TODO 可拔插的 SD 卡
251297
*/
252298
@get:StorageMediaType
253299
const val STORAGE_UUID_SD_CARD = "STORAGE_UUID_SD_CARD"
300+
254301
/**
255302
* TODO 可拔插 U 盘
256303
*/
257304
@get:StorageMediaType
258305
const val STORAGE_UUID_USB_DRIVE = "STORAGE_UUID_USB_DRIVE"
306+
259307
/**
260308
* 自定义路径
261309
*/

filepicker/src/main/java/me/rosuh/filepicker/utils/FileUtils.kt

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import me.rosuh.filepicker.bean.FileItemBeanImpl
88
import me.rosuh.filepicker.bean.FileNavBeanImpl
99
import me.rosuh.filepicker.config.FilePickerConfig.Companion.STORAGE_CUSTOM_ROOT_PATH
1010
import me.rosuh.filepicker.config.FilePickerConfig.Companion.STORAGE_EXTERNAL_STORAGE
11-
import me.rosuh.filepicker.config.FilePickerManager
11+
import me.rosuh.filepicker.config.FilePickerManager.config
1212
import java.io.File
1313

1414
/**
@@ -24,16 +24,16 @@ class FileUtils {
2424
* 根据配置参数获取根目录文件
2525
* @return File
2626
*/
27-
fun getRootFile(): File {
28-
return when (FilePickerManager.config.mediaStorageType) {
27+
fun getRootFile():File {
28+
return when (config.mediaStorageType) {
2929
STORAGE_EXTERNAL_STORAGE -> {
3030
File(Environment.getExternalStorageDirectory().absoluteFile.toURI())
3131
}
3232
STORAGE_CUSTOM_ROOT_PATH -> {
33-
if (FilePickerManager.config.customRootPath.isEmpty()) {
33+
if (config.customRootPath.isEmpty()) {
3434
File(Environment.getExternalStorageDirectory().absoluteFile.toURI())
3535
} else {
36-
File(FilePickerManager.config.customRootPath)
36+
File(config.customRootPath)
3737
}
3838
}
3939
else -> {
@@ -50,10 +50,11 @@ class FileUtils {
5050
beanSubscriber: BeanSubscriber
5151
): ArrayList<FileItemBeanImpl> {
5252
val listData: ArrayList<FileItemBeanImpl> = ArrayList()
53+
var isDetected = false
5354
for (file in rootFile.listFiles()) {
5455
//以符号 . 开头的视为隐藏文件或隐藏文件夹,后面进行过滤
5556
val isHiddenFile = file.name.startsWith(".")
56-
if (!FilePickerManager.config.isShowHiddenFiles && isHiddenFile) {
57+
if (!config.isShowHiddenFiles && isHiddenFile) {
5758
// skip hidden files
5859
continue
5960
}
@@ -81,16 +82,24 @@ class FileUtils {
8182
beanSubscriber
8283
)
8384
// 如果调用者没有实现文件类型甄别器,则使用的默认甄别器
84-
FilePickerManager.config.customDetector?.fillFileType(itemBean)
85-
?: FilePickerManager.config.defaultFileDetector.fillFileType(itemBean)
85+
config.customDetector?.fillFileType(itemBean)
86+
?: config.defaultFileDetector.fillFileType(itemBean)
87+
isDetected = itemBean.fileType != null
88+
if (config.defaultFileDetector.enableCustomTypes
89+
&& config.isAutoFilter
90+
&& !isDetected
91+
) {
92+
// enable auto filter AND using user's custom file type. Filter them.
93+
continue
94+
}
8695
listData.add(itemBean)
8796
}
8897
// 默认字典排序
8998
// Default sort by alphabet
9099
listData.sortWith(compareBy({ !it.isDir }, { it.fileName.toUpperCase() }))
91100
// 将当前列表数据暴露,以供调用者自己处理数据
92101
// expose data list to outside caller
93-
return FilePickerManager.config.selfFilter?.doFilter(listData) ?: listData
102+
return config.selfFilter?.doFilter(listData) ?: listData
94103
}
95104

96105
/**
@@ -107,10 +116,10 @@ class FileUtils {
107116
// 优先级:目标设备名称 --> 自定义路径 --> 默认 SD 卡
108117
currentDataSource.add(
109118
FileNavBeanImpl(
110-
if (!FilePickerManager.config.mediaStorageName.isNullOrEmpty()) {
111-
FilePickerManager.config.mediaStorageName
112-
} else if (!FilePickerManager.config.customRootPath.isEmpty()) {
113-
FilePickerManager.config.customRootPath
119+
if (!config.mediaStorageName.isNullOrEmpty()) {
120+
config.mediaStorageName
121+
} else if (!config.customRootPath.isEmpty()) {
122+
config.customRootPath
114123
} else {
115124
context.getString(R.string.file_picker_tv_sd_card)
116125
},
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Wed Nov 27 14:17:28 CST 2019
1+
#Wed Sep 16 10:42:32 CST 2020
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

sample/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dependencies {
3535
// implementation 'com.squareup.picasso:picasso:2.5.2'
3636
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
3737
implementation 'com.android.support:appcompat-v7:28.0.0'
38-
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
38+
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
3939
testImplementation 'junit:junit:4.12'
4040
androidTestImplementation 'com.android.support.test:runner:1.0.2'
4141
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

sample/src/main/java/me/rosuh/sample/SampleActivity.kt

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ import me.rosuh.filepicker.bean.FileItemBeanImpl
2222
import me.rosuh.filepicker.config.*
2323
import me.rosuh.filepicker.engine.ImageEngine
2424
import me.rosuh.filepicker.filetype.FileType
25+
import me.rosuh.filepicker.config.AbstractFileFilter
26+
import me.rosuh.filepicker.config.FilePickerConfig
27+
import me.rosuh.filepicker.config.FilePickerManager
28+
import me.rosuh.filepicker.config.SimpleItemClickListener
29+
import me.rosuh.filepicker.filetype.AudioFileType
2530
import me.rosuh.filepicker.filetype.RasterImageFileType
2631
import me.rosuh.filepicker.utils.ScreenUtils
2732

@@ -125,15 +130,13 @@ class SampleActivity : AppCompatActivity() {
125130
}
126131
})
127132
.skipDirWhenSelect(false)
128-
.setTheme(R.style.FilePickerThemeReply)
129133
.forResult(FilePickerManager.REQUEST_CODE)
130134
}
131135
// 多选文件
132136
btn_multi_file.setOnClickListener {
133137
FilePickerManager
134138
.from(this@SampleActivity)
135139
.setTheme(getRandomTheme())
136-
.setTheme(R.style.FilePickerThemeCrane)
137140
.forResult(FilePickerManager.REQUEST_CODE)
138141
}
139142
// 多选文件夹
@@ -149,7 +152,6 @@ class SampleActivity : AppCompatActivity() {
149152
}
150153
})
151154
.skipDirWhenSelect(false)
152-
.setTheme(R.style.FilePickerThemeShrine)
153155
.forResult(FilePickerManager.REQUEST_CODE)
154156
}
155157
// 自定义根目录
@@ -160,29 +162,17 @@ class SampleActivity : AppCompatActivity() {
160162
// 不指定名称则为导航栏将显示绝对路径
161163
// .storageType(FilePickerConfig.STORAGE_CUSTOM_ROOT_PATH)
162164
.setCustomRootPath("/storage/emulated/0/Download")
163-
.setTheme(R.style.FilePickerThemeReply)
164165
.forResult(FilePickerManager.REQUEST_CODE)
165166
}
166167
// 自定义文件类型
168+
// the new api for register your custom file type
167169
btn_custom_file_type.setOnClickListener {
168-
FilePickerManager
169-
.from(this@SampleActivity)
170-
// 1. 使用自定义文件检测器来检测类型,并赋值给 [FileItemBeanImpl.fileType] 属性
171-
// 1. Using detector detect file's type and fill it into [FileItemBeanImpl.fileType]
172-
.customDetector(CustomFileDetector())
173-
.filter(object : AbstractFileFilter() {
174-
override fun doFilter(listData: ArrayList<FileItemBeanImpl>): ArrayList<FileItemBeanImpl> {
175-
// 2. 接收结果列表,然后过滤出您想要的类型
176-
// 2. Receive result list and filter what you want
177-
listData.removeAll {
178-
(it.fileType !is CustomFileType) && !it.isDir
179-
}
180-
return listData
181-
}
182-
})
183-
.showHiddenFiles(true)
170+
FilePickerManager.from(this@SampleActivity)
171+
.setTheme(getRandomTheme())
172+
.registerFileType(arrayListOf(AudioFileType()))
184173
.forResult(FilePickerManager.REQUEST_CODE)
185174
}
175+
186176
findViewById<Button>(R.id.btn_show_in_fragment).setOnClickListener {
187177
SampleFragment.show(supportFragmentManager, "SampleFragment")
188178
}

0 commit comments

Comments
 (0)