Commit a34aa488 authored by wanglei's avatar wanglei Committed by wanglei

完善代码

parent 484a940f
...@@ -52,4 +52,5 @@ dependencies { ...@@ -52,4 +52,5 @@ dependencies {
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
implementation(libs.androidx.navigation.fragment.ktx) implementation(libs.androidx.navigation.fragment.ktx)
implementation(libs.androidx.navigation.ui.ktx) implementation(libs.androidx.navigation.ui.ktx)
implementation(libs.glide)
} }
\ No newline at end of file
...@@ -22,22 +22,29 @@ ...@@ -22,22 +22,29 @@
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".kokoInternalstorage.KoInternalkoActivity" android:name=".kokoInternalstorage.KoInternalkoActivity"
android:exported="false" /> android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".kokodup.KoDupFilekoActivity" android:name=".kokodup.KoDupFilekoActivity"
android:exported="false" /> android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".kokolistfile.KoListFilekoActivity" android:name=".kokolistfile.KoListFilekoActivity"
android:exported="false" android:exported="false"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".gridfile.KoGridFilekoActivity" android:name=".kokogridfile.KoGridFilekoActivity"
android:exported="false" /> android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".KokoLaunchActivity" android:name=".KokoLaunchActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait"> android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
...@@ -47,7 +54,8 @@ ...@@ -47,7 +54,8 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait" /> android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
</application> </application>
</manifest> </manifest>
\ No newline at end of file
package com.zxhy.fastfilemanagerpro
import android.content.Context
import android.os.Environment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.koFileDatako
import com.zxhy.fastfilemanagerpro.kokotools.HelperTraverse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.io.File
import java.util.Stack
import kotlin.reflect.KFunction1
abstract class CommonViewModel : ViewModel() {
/**
* 只删除文件列表
*/
fun deleteFiles(files: List<File>, finishAction: () -> Unit) =
viewModelScope.launch(Dispatchers.IO) {
runCatching {
files.forEach {
if (it.exists()) {
it.delete()
}
}
}
finishAction.invoke()
}
fun deleteFileOrDir(files: List<File>, finishAction: () -> Unit) =
viewModelScope.launch(Dispatchers.IO) {
runCatching {
files.forEach {
if (it.exists()) {
if (it.isFile) it.delete() else deleteDirectory(it)
}
}
}
finishAction.invoke()
}
/**
*删除文件夹
*/
fun deleteDirectory(dir: File): Boolean {
val stackFiles = Stack<File>()
stackFiles.push(dir)
while (stackFiles.size > 0) {
val currentFile = stackFiles.peek()
val subFiles = currentFile.listFiles()
if (subFiles != null) {
for (i in subFiles.indices) {
if (subFiles[i].isFile) {
if (!subFiles[i].delete()) {
return false
}
} else {
stackFiles.push(subFiles[i])
}
}
}
if (currentFile === stackFiles.peek()) {
if (!currentFile.delete()) {
return false
}
stackFiles.pop()
}
}
return true
}
/**
* 复制文件夹
* @param source 原文件夹
* @param target 目标文件夹
*/
fun copyDirectory(source: File, target: File) {
try {
if (source.isDirectory) {
if (!target.exists()) target.mkdir()
source.list()?.map { sub ->
copyDirectory(File(source, sub), File(target, sub))
}
} else {
source.copyTo(target, overwrite = true)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
fun loadFile(
context: Context,
filter: (file: File) -> Boolean,
onDo: (list: List<KoFileDatako>) -> Unit,
onFinish: (list: List<KoFileDatako>) -> Unit
) {
viewModelScope.launch(Dispatchers.IO) {
val root = Environment.getExternalStorageDirectory()
val resultList = arrayListOf<KoFileDatako>()
var firstSend = false
HelperTraverse.linkedLisTraverseFolder(root) { file ->
if (filter(file)) {
resultList.add(file.koFileDatako(context))
if (resultList.size == 20 && !firstSend) {
onDo.invoke(resultList)
resultList.clear()
firstSend = true
}
}
}
onFinish.invoke(resultList)
}
}
fun loadAllFile(
context: Context,
filter: (file: File) -> Boolean,
onFinish: (list: List<KoFileDatako>) -> Unit
) {
viewModelScope.launch(Dispatchers.IO) {
val root = Environment.getExternalStorageDirectory()
val resultList = arrayListOf<KoFileDatako>()
HelperTraverse.linkedLisTraverseFolder(root) { file ->
if (filter(file)) {
resultList.add(file.koFileDatako(context))
}
}
onFinish.invoke(resultList)
}
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro
import android.app.Application
import com.bumptech.glide.annotation.GlideModule
@GlideModule
class GlideApp : Application() {
}
\ No newline at end of file
...@@ -5,6 +5,7 @@ import android.view.MenuItem ...@@ -5,6 +5,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.AdapterView import android.widget.AdapterView
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.annotation.ColorRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
...@@ -13,12 +14,17 @@ import androidx.navigation.findNavController ...@@ -13,12 +14,17 @@ import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import com.google.android.material.navigation.NavigationBarView import com.google.android.material.navigation.NavigationBarView
import com.zxhy.fastfilemanagerpro.databinding.ActivityMainBinding import com.zxhy.fastfilemanagerpro.databinding.ActivityMainBinding
import com.zxhy.fastfilemanagerpro.kokotools.ActivityLauncher
import com.zxhy.fastfilemanagerpro.kokotools.permission.PermissionCheck.storePermissionCheck
import com.zxhy.fastfilemanagerpro.kokotools.permission.StorePermissionEx.requestStoreFollow
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private lateinit var activityLauncher: ActivityLauncher
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
activityLauncher = ActivityLauncher(this)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
...@@ -77,5 +83,18 @@ class MainActivity : AppCompatActivity() { ...@@ -77,5 +83,18 @@ class MainActivity : AppCompatActivity() {
return true return true
} }
}) })
if (!storePermissionCheck()) {
requestStoreFollow(activityLauncher,
disAgreeAction = {
},
agreeAction = {
})
}
}
fun setSystemBarColor(@ColorRes colorRes: Int) {
// color_b3000000 权限窗口颜色
window.statusBarColor = ContextCompat.getColor(this, colorRes)
} }
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.gridfile
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ActivityKoGridFilekoBinding
class KoGridFilekoActivity : AppCompatActivity() {
private lateinit var binding: ActivityKoGridFilekoBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityKoGridFilekoBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
}
companion object {
const val IMAGE_FILE = "Image file"
const val VIDEO_FILE = "Video file"
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokoInternalstorage
import android.annotation.SuppressLint
import android.content.Context
import android.os.Environment
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ItemKokoListFileBinding
import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.koFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.loadImageIcon
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate
import java.io.File
class KoInternalkoAdapter(
private val context: Context,
private val allSelect: (flag: Boolean) -> Unit,
private val pageCount: ((count: Int) -> Unit)? = null
) : CommonAdapter<KoInternalkoAdapter.KoInternalkoViewHolder>() {
private var selectMode = false
private var currentDir = Environment.getExternalStorageDirectory()
private var cannotFiles = arrayListOf<String>()
private var canPage = true
fun setCanPage(canPage: Boolean) {
this.canPage = canPage
}
fun getCurrentDir(): File {
return currentDir
}
@SuppressLint("NotifyDataSetChanged")
fun showSelectMode(show: Boolean) {
selectMode = show
notifyDataSetChanged()
}
class KoInternalkoViewHolder(view: View) : ViewHolder(view) {
val binding = ItemKokoListFileBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): KoInternalkoViewHolder {
return KoInternalkoViewHolder(R.layout.item_koko_list_file.inflate(parent))
}
override fun onBindViewHolder(holder: KoInternalkoViewHolder, position: Int) {
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(
holder: KoInternalkoViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val context = holder.binding.root.context
val data = fileList[position]
if (payloads.isEmpty()) {
holder.binding.apply {
data.loadImageIcon(context, ivIcon)
if (cannotFiles.contains(data.toFile().absolutePath)) {
root.setBackgroundColor(ContextCompat.getColor(context, R.color.color_606060))
root.setOnClickListener { }
} else {
root.setBackgroundColor(ContextCompat.getColor(context, R.color.color_ffffff))
root.setOnClickListener {
if (canPage) {
pageNext(context, data)
}
}
}
tvName.text = data.name
tvInfo.text = "${data.timeE} ${data.sizeF}"
if (selectMode) {
ivSelector.visibility = View.VISIBLE
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "局部刷洗")
allSelect.invoke(fileList.all { it.isSelect })
}
} else {
ivSelector.visibility = View.GONE
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
private fun pageNext(context: Context, data: KoFileDatako) {
val list = data.toFile().listFiles()?.map { it.koFileDatako(context) } ?: listOf()
setData(list)
currentDir = data.toFile()
pageCount?.invoke(list.size)
}
/**
* @return 是否是根目录
*/
fun pageBefore(): Boolean {
return if (currentDir.absolutePath == Environment.getExternalStorageDirectory().absolutePath) {
true
} else {
val parentDir = currentDir.parentFile ?: File("")
if (parentDir.exists()) {
val data = parentDir.listFiles()?.map { it.koFileDatako(context) } ?: listOf()
setData(data)
currentDir = parentDir
pageCount?.invoke(data.size)
}
false
}
}
fun notifyCurrentDir() {
val data = currentDir.listFiles()?.map { it.koFileDatako(context) } ?: listOf()
setData(data)
pageCount?.invoke(itemCount)
}
@SuppressLint("NotifyDataSetChanged")
fun setCannotDir(dirs: List<File>) {
cannotFiles.addAll(dirs.map { it.absolutePath })
notifyDataSetChanged()
}
fun clearCannotDir() {
cannotFiles.clear()
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokoInternalstorage
import android.content.IntentSender.OnFinished
import androidx.lifecycle.viewModelScope
import com.zxhy.fastfilemanagerpro.CommonViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
class KoInternalkoViewModel : CommonViewModel() {
fun renameFile(selectFile: File, newName: String, result: () -> Unit) {
runCatching {
val flag = selectFile.renameTo(File(selectFile.parentFile, newName))
if (flag) {
result.invoke()
}
}
}
fun copyFiles(files: List<File>, destDir: File, result: () -> Unit) =
viewModelScope.launch(Dispatchers.IO) {
runCatching {
files.map {
if (it.isFile) {
it.copyTo(File(destDir, it.name), overwrite = true)
} else {
copyDirectory(it, File(destDir, it.name))
}
}
}
result.invoke()
}
fun moveFiles(files: List<File>, destDir: File, result: () -> Unit) =
viewModelScope.launch(Dispatchers.IO) {
runCatching {
files.map {
if (it.isFile) {
it.copyTo(File(destDir, it.name), overwrite = true)
it.delete()
} else {
copyDirectory(it, File(destDir, it.name))
deleteDirectory(it)
}
}
}
result.invoke()
}
}
\ No newline at end of file
...@@ -3,13 +3,13 @@ package com.zxhy.fastfilemanagerpro.kokoadapter ...@@ -3,13 +3,13 @@ package com.zxhy.fastfilemanagerpro.kokoadapter
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
interface AdapterCommonDataFunction { interface AdapterCommonDataFunction<T> {
abstract fun setData(data: List<KoFileDatako>) abstract fun setData(data: List<T>)
abstract fun addData(data: List<KoFileDatako>) abstract fun addData(data: List<T>)
abstract fun clearData() abstract fun clearData()
abstract fun removeData(data: List<KoFileDatako>) abstract fun removeData(data: List<T>)
abstract fun getSelectData(): List<KoFileDatako> abstract fun getSelectData(): List<T>
abstract fun toggleSelect(select: Boolean) abstract fun toggleSelect(select: Boolean)
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokoadapter package com.zxhy.fastfilemanagerpro.kokoadapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.util.Log
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(), abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(),
AdapterCommonDataFunction { AdapterCommonDataFunction<KoFileDatako> {
protected val fileList = arrayListOf<KoFileDatako>() protected val fileList = arrayListOf<KoFileDatako>()
private var firstRefresh = true private var firstRefresh = true
...@@ -53,9 +54,8 @@ abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(), ...@@ -53,9 +54,8 @@ abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(),
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
override fun toggleSelect(select: Boolean) { override fun toggleSelect(select: Boolean) {
fileList.forEach { fileList.forEach { fileBean ->
fileBean -> fileBean.isSelect = select
fileBean.isSelect=select
} }
notifyDataSetChanged() notifyDataSetChanged()
} }
......
package com.zxhy.fastfilemanagerpro.kokodata package com.zxhy.fastfilemanagerpro.kokodata
import android.content.Context import android.content.Context
import android.net.Uri
import android.text.format.Formatter import android.text.format.Formatter
import android.widget.ImageView
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokotools.GlideHelper.loadImageView
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
data class KoFileDatako( data class KoFileDatako(
var name: String, var name: String = "",
var path: String, var path: String = "",
var uri: Uri = Uri.EMPTY,
val timeE: String = "", val timeE: String = "",
var isSelect: Boolean = false, var isSelect: Boolean = false,
val sizeF: String = "" val sizeF: String = ""
) { ) {
companion object { companion object {
fun KoFileDatako.loadImageIcon(context: Context, imageView: ImageView) {
when {
isImage() or isVideo() -> imageView.loadImageView(context, toFile())
isAudio() -> imageView.setImageResource(R.mipmap.zd_8871110)
isLog() -> imageView.setImageResource(R.mipmap.zd_001123)
isZip() -> imageView.setImageResource(R.mipmap.eqwe_878979)
isApk() -> imageView.setImageResource(R.mipmap.eqwe_88599)
isDocuments() -> imageView.setImageResource(R.mipmap.qwe_889989)
toFile().isDirectory -> imageView.setImageResource(R.mipmap.dd_89896330)
else -> imageView.setImageResource(R.mipmap.qwe_889989111)
}
}
fun KoFileDatako.isImage(): Boolean {
return name.contains(".jpg") or name.contains(".png") or name.contains(".gif")
}
fun KoFileDatako.isAudio(): Boolean {
return name.contains(".mp3") or
name.contains(".aac") or
name.contains(".ogg") or
name.contains(".aac")
}
fun KoFileDatako.isLog(): Boolean {
return name.contains("log") or name.contains("Log")
}
fun KoFileDatako.isZip(): Boolean {
return name.contains(".zip") or name.contains(".7z")
}
fun KoFileDatako.isApk(): Boolean {
return name.contains(".zip") or name.contains(".7z")
}
fun KoFileDatako.isDocuments(): Boolean {
return name.contains(".doc") or
name.contains(".docx") or
name.contains(".ppt") or
name.contains(".pptx") or
name.contains(".xls") or
name.contains(".xlsx") or
name.contains(".txt") or
name.contains(".pdf")
}
fun KoFileDatako.isVideo(): Boolean {
return name.contains(".mp4") or
name.contains(".avi") or
name.contains(".flv") or
name.contains(".rmvb") or
name.contains(".mkv")
}
fun KoFileDatako.toFile(): File { fun KoFileDatako.toFile(): File {
return File(path) return File(path)
} }
......
package com.zxhy.fastfilemanagerpro.kokodialog
import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.DialogKokoFileNameBinding
import java.io.File
object FileNameDialog {
fun Context.showFileNameDialog(
file: File,
sureAction: (name: String) -> Unit
): Dialog {
val binding = DialogKokoFileNameBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.show()
dialog.setCanceledOnTouchOutside(false)
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_260)
lp?.height = this.resources.getDimensionPixelOffset(R.dimen.dp_190)
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
binding.apply {
edit.setText(file.name.toString())
tvSure.setOnClickListener {
runCatching {
if (!edit.text.isNullOrEmpty()) {
dialog.dismiss()
sureAction.invoke(edit.text.toString())
}
}
}
ivDelete.setOnClickListener {
dialog.dismiss()
}
}
return dialog
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokodialog
import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import androidx.appcompat.app.AlertDialog
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.DialogKokoLoadingBinding
object LoadingDialog {
fun Context.showLoadingDialog(): Dialog {
val binding = DialogKokoLoadingBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.show()
dialog.setCanceledOnTouchOutside(false)
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_260)
lp?.height = this.resources.getDimensionPixelOffset(R.dimen.dp_190)
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
// 添加旋转动画
val rotateAnimation = RotateAnimation(
0f, 360f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
)
rotateAnimation.duration = 1500
rotateAnimation.interpolator = LinearInterpolator()
rotateAnimation.repeatCount = Animation.INFINITE
binding.ivLoading.startAnimation(rotateAnimation)
return dialog
}
}
...@@ -4,6 +4,7 @@ import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako ...@@ -4,6 +4,7 @@ import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
class KoDupFileDatako( class KoDupFileDatako(
val md5: String, val md5: String,
val dups: List<KoFileDatako> val dups: ArrayList<KoFileDatako>,
var isSelect: Boolean = false,
) { ) {
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokodup package com.zxhy.fastfilemanagerpro.kokodup
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.View
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.zxhy.fastfilemanagerpro.R import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ActivityKoDupFilekoBinding import com.zxhy.fastfilemanagerpro.databinding.ActivityKoDupFilekoBinding
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokodialog.LoadingDialog.showLoadingDialog
import com.zxhy.fastfilemanagerpro.kokotools.ActivityLauncher
import com.zxhy.fastfilemanagerpro.kokotools.permission.PermissionCheck.storePermissionCheck
import com.zxhy.fastfilemanagerpro.kokotools.permission.StorePermissionEx.requestStoreFollow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class KoDupFilekoActivity : AppCompatActivity() { class KoDupFilekoActivity : AppCompatActivity() {
private lateinit var binding: ActivityKoDupFilekoBinding private lateinit var binding: ActivityKoDupFilekoBinding
private val viewModel: KoDupFilekoViewModel by viewModels() private val viewModel: KoDupFilekoViewModel by viewModels()
private lateinit var context: Context private lateinit var context: Context
private lateinit var adapter: KoDupFilekoAdapter private lateinit var adapter: KoDupFilekoAdapter
private lateinit var activityLauncher: ActivityLauncher
private var tittle: String = ""
private var dialog: Dialog? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
activityLauncher = ActivityLauncher(this)
context = this context = this
binding = ActivityKoDupFilekoBinding.inflate(layoutInflater) binding = ActivityKoDupFilekoBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
...@@ -27,27 +44,122 @@ class KoDupFilekoActivity : AppCompatActivity() { ...@@ -27,27 +44,122 @@ class KoDupFilekoActivity : AppCompatActivity() {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets insets
} }
adapter = KoDupFilekoAdapter {
binding.ivAllSelector.isSelected = it
enableDelete()
}
binding.llAll.setOnClickListener {
it.isSelected = !it.isSelected
adapter.toggleSelect(it.isSelected)
enableDelete()
}
binding.rv.adapter = adapter
tittle = intent.extras?.getString("Tittle") ?: ""
binding.tvTittle.text = tittle
if (storePermissionCheck()) {
showPermissionSet(false)
loadListFile()
} else {
showPermissionSet(true)
}
}
private fun loadListFile() {
dialog = showLoadingDialog()
when (tittle) {
DUP_IMAGE -> viewModel.loadDupImage(context, ::onFinishList)
DUP_FILE -> viewModel.loadDupFile(context, ::onFinishList)
}
} }
@SuppressLint("SetTextI18n")
private fun onFinishList(list: List<KoDupFileDatako>) =
lifecycleScope.launch(Dispatchers.Main) {
adapter.setData(list)
showEmptyList()
enableDelete()
binding.tvItems.text = "total:${adapter.itemCount} items"
dialog?.dismiss()
}
fun enableDelete(enable: Boolean) {
binding.tvDelete.isEnabled = enable //region 公共ui逻辑
private fun showEmptyList() {
if (adapter.itemCount == 0) {
binding.clEmpty.visibility = View.VISIBLE
binding.clShowContent.visibility = View.GONE
binding.llAll.visibility = View.GONE
} else {
binding.clEmpty.visibility = View.GONE
binding.clShowContent.visibility = View.VISIBLE
binding.llAll.visibility = View.VISIBLE
}
}
if (enable) { private fun enableDelete() {
val selectSubData = adapter.getSelectSubData()
if (selectSubData.isEmpty()) {
binding.tvDelete.isEnabled = false
binding.tvDelete.background =
ContextCompat.getDrawable(context, R.drawable.bg_fff4f4f4_corners)
binding.tvDelete.setTextColor(ContextCompat.getColor(context, R.color.color_999999))
} else {
binding.tvDelete.isEnabled = true
binding.tvDelete.background = binding.tvDelete.background =
ContextCompat.getDrawable(context, R.drawable.bg_ffff6767_corners) ContextCompat.getDrawable(context, R.drawable.bg_ffff6767_corners)
binding.tvDelete.setTextColor(ContextCompat.getColor(context, R.color.white)) binding.tvDelete.setTextColor(ContextCompat.getColor(context, R.color.white))
binding.tvDelete.setOnClickListener { binding.tvDelete.setOnClickListener {
deleteFiles(selectSubData)
}
}
}
fun showOperationResult() = lifecycleScope.launch(Dispatchers.Main) {
binding.llResult.visibility = View.VISIBLE
delay(500)
binding.llResult.visibility = View.GONE
}
fun showPermissionSet(show: Boolean) {
if (show) {
binding.clContent.visibility = View.GONE
binding.clPermissionSet.visibility = View.VISIBLE
window.statusBarColor = ContextCompat.getColor(context, R.color.color_b3000000)
binding.tvSet.setOnClickListener {
requestStoreFollow(activityLauncher, disAgreeAction = {
showPermissionSet(true)
}, agreeAction = {
showPermissionSet(false)
loadListFile()
})
} }
} else { } else {
binding.tvDelete.background = binding.clContent.visibility = View.VISIBLE
ContextCompat.getDrawable(context, R.drawable.bg_fff4f4f4_corners) binding.clPermissionSet.visibility = View.GONE
binding.tvDelete.setTextColor(ContextCompat.getColor(context, R.color.color_999999)) window.statusBarColor = ContextCompat.getColor(context, R.color.white)
} }
}
private fun deleteFiles(selectSubData: List<KoFileDatako>) {
val files = selectSubData.map { it.toFile() }
viewModel.deleteFiles(files) {
lifecycleScope.launch(Dispatchers.Main) {
showOperationResult()
adapter.removeSubData(selectSubData)
showEmptyList()
enableDelete()
}
}
}
//endregion
companion object {
const val DUP_IMAGE = "Scan for duplicate pictures"
const val DUP_FILE = "Scan for duplicate files"
} }
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokodup package com.zxhy.fastfilemanagerpro.kokodup
import android.annotation.SuppressLint
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
...@@ -7,10 +8,19 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder ...@@ -7,10 +8,19 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.zxhy.fastfilemanagerpro.R import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ItemKokoDupFileBinding import com.zxhy.fastfilemanagerpro.databinding.ItemKokoDupFileBinding
import com.zxhy.fastfilemanagerpro.databinding.ItemKokoDupImageBinding import com.zxhy.fastfilemanagerpro.databinding.ItemKokoDupImageBinding
import com.zxhy.fastfilemanagerpro.kokoadapter.AdapterCommonDataFunction
import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.loadImageIcon
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokotools.GlideHelper.loadImageView
import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate
class KoDupFilekoAdapter : RecyclerView.Adapter<KoDupFilekoAdapter.KoDupFilekoViewHolder>() { @SuppressLint("NotifyDataSetChanged")
class KoDupFilekoAdapter(
private val allSelect: (flag: Boolean) -> Unit
) : RecyclerView.Adapter<KoDupFilekoAdapter.KoDupFilekoViewHolder>(),
AdapterCommonDataFunction<KoDupFileDatako> {
private var dupFileList = arrayListOf<KoDupFileDatako>() private var dupFileList = arrayListOf<KoDupFileDatako>()
...@@ -29,20 +39,103 @@ class KoDupFilekoAdapter : RecyclerView.Adapter<KoDupFilekoAdapter.KoDupFilekoVi ...@@ -29,20 +39,103 @@ class KoDupFilekoAdapter : RecyclerView.Adapter<KoDupFilekoAdapter.KoDupFilekoVi
override fun onBindViewHolder(holder: KoDupFilekoViewHolder, position: Int) { override fun onBindViewHolder(holder: KoDupFilekoViewHolder, position: Int) {
} }
@SuppressLint("SetTextI18n")
override fun onBindViewHolder( override fun onBindViewHolder(
holder: KoDupFilekoViewHolder, holder: KoDupFilekoViewHolder,
position: Int, position: Int,
payloads: MutableList<Any> payloads: MutableList<Any>
) { ) {
val context = holder.binding.root.context val context = holder.binding.root.context
val data = dupFileList[position]
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
holder.binding.apply {
val adapter = DupImageAdapter {
data.isSelect = it
notifyItemChanged(position, "局部刷洗")
allSelect.invoke(dupFileList.all { it.isSelect })
}
rv.adapter = adapter
adapter.setData(data.dups)
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "局部刷洗")
adapter.toggleSelect(data.isSelect)
allSelect.invoke(dupFileList.all { it.isSelect })
}
tvItems.text = "${data.dups.size} items"
}
} else { } else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads) super.onBindViewHolder(holder, position, payloads)
} }
} }
inner class DupImageAdapter : CommonAdapter<DupImageAdapter.DupImageViewHolder>() { override fun setData(data: List<KoDupFileDatako>) {
dupFileList.clear()
dupFileList.addAll(data)
notifyDataSetChanged()
}
override fun addData(data: List<KoDupFileDatako>) {
dupFileList.addAll(data)
notifyDataSetChanged()
}
override fun clearData() {
if (dupFileList.size == 0) return
dupFileList.clear()
notifyDataSetChanged()
}
override fun getSelectData(): List<KoDupFileDatako> {
return dupFileList.filter { it.isSelect }
}
fun getSelectDupData(): List<KoDupFileDatako> {
return dupFileList.filter { it.isSelect }
}
fun getSelectSubData(): List<KoFileDatako> {
return dupFileList.flatMap { it.dups }.filter { it.isSelect }
}
override fun toggleSelect(select: Boolean) {
dupFileList.forEach { fileBean ->
fileBean.isSelect = select
fileBean.dups.forEach { koFileDatako ->
koFileDatako.isSelect = select
}
}
notifyDataSetChanged()
}
override fun removeData(data: List<KoDupFileDatako>) {
data.forEach {
val index = dupFileList.indexOf(it)
if (index != -1) {
dupFileList.removeAt(index)
notifyItemRemoved(index)
}
}
}
fun removeSubData(data: List<KoFileDatako>) {
dupFileList.forEach { koDupFileDatako ->
data.forEach { koFileDatako ->
koDupFileDatako.dups.remove(koFileDatako)
}
}
val removedList = dupFileList.filter { it.dups.size > 1 }
setData(removedList)
}
inner class DupImageAdapter(
private val allSelect: (flag: Boolean) -> Unit
) : CommonAdapter<DupImageAdapter.DupImageViewHolder>() {
inner class DupImageViewHolder(view: View) : ViewHolder(view) { inner class DupImageViewHolder(view: View) : ViewHolder(view) {
val binding = ItemKokoDupImageBinding.bind(view) val binding = ItemKokoDupImageBinding.bind(view)
} }
...@@ -54,17 +147,35 @@ class KoDupFilekoAdapter : RecyclerView.Adapter<KoDupFilekoAdapter.KoDupFilekoVi ...@@ -54,17 +147,35 @@ class KoDupFilekoAdapter : RecyclerView.Adapter<KoDupFilekoAdapter.KoDupFilekoVi
override fun onBindViewHolder(holder: DupImageViewHolder, position: Int) { override fun onBindViewHolder(holder: DupImageViewHolder, position: Int) {
} }
@SuppressLint("SetTextI18n")
override fun onBindViewHolder( override fun onBindViewHolder(
holder: DupImageViewHolder, holder: DupImageViewHolder,
position: Int, position: Int,
payloads: MutableList<Any> payloads: MutableList<Any>
) { ) {
val content = holder.binding.root.context val content = holder.binding.root.context
val data = fileList[position]
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
holder.binding.apply {
data.loadImageIcon(content, iv)
tvName.text = data.name
tvInfo.text = "${data.timeE} ${data.sizeF}"
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "局部刷洗")
allSelect.invoke(fileList.all { it.isSelect })
}
}
} else { } else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads) super.onBindViewHolder(holder, position, payloads)
} }
} }
} }
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokodup package com.zxhy.fastfilemanagerpro.kokodup
import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.zxhy.fastfilemanagerpro.CommonViewModel
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokotools.Md5Ex.byteArrayToHexString
import com.zxhy.fastfilemanagerpro.kokotools.Md5Ex.digestMd5
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
class KoDupFilekoViewModel : CommonViewModel() {
fun isImageFilter(file: File): Boolean {
return file.name.contains(".jpg") or
file.name.contains(".gif") or
file.name.contains(".png")
}
fun isDupFileFilter(file: File): Boolean {
return file.length() > 0
}
fun loadDupImage(
context: Context,
onFinish: (list: List<KoDupFileDatako>) -> Unit
) = viewModelScope.launch(Dispatchers.IO) {
loadAllFile(context, ::isImageFilter) { list ->
onFinish.invoke(calculateDup(list))
}
}
fun loadDupFile(
context: Context,
onFinish: (list: List<KoDupFileDatako>) -> Unit
) = viewModelScope.launch(Dispatchers.IO) {
loadAllFile(context, ::isDupFileFilter) { list ->
onFinish.invoke(calculateDup(list))
}
}
private fun calculateDup(data: List<KoFileDatako>): List<KoDupFileDatako> {
val dupMap = HashMap<String, ArrayList<KoFileDatako>>()
data.forEach {
val md5 = it.toFile().digestMd5().byteArrayToHexString()
val dupList = dupMap[md5]
if (dupList == null) {
val newList = arrayListOf<KoFileDatako>()
dupMap[md5] = newList
newList.add(it)
} else {
dupList.add(it)
}
}
val dupList = dupMap.filter { it.value.size > 1 }
.map { map ->
KoDupFileDatako(md5 = map.key, dups = map.value)
}
return dupList
}
class KoDupFilekoViewModel : ViewModel() {
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokogridfile
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ItemKokoGridFileBinding
import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.isImage
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.isVideo
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokotools.GlideHelper.loadImageView
import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate
class KoFileGridkoAdapter(
private val allSelect: (flag: Boolean) -> Unit
) : CommonAdapter<KoFileGridkoAdapter.KoFileGridkoViewHolder>() {
inner class KoFileGridkoViewHolder(view: View) : ViewHolder(view) {
val binding = ItemKokoGridFileBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): KoFileGridkoViewHolder {
return KoFileGridkoViewHolder(R.layout.item_koko_grid_file.inflate(parent))
}
override fun onBindViewHolder(holder: KoFileGridkoViewHolder, position: Int) {
}
override fun onBindViewHolder(
holder: KoFileGridkoViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val context = holder.binding.root.context
val data = fileList[position]
if (payloads.isEmpty()) {
holder.binding.apply {
ivIcon.loadImageView(context, data.toFile())
if (data.isImage()) {
ivCamera.visibility = View.GONE
}
if (data.isVideo()) {
ivCamera.visibility = View.VISIBLE
}
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "局部刷新")
allSelect.invoke(fileList.all { it.isSelect })
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokogridfile
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ActivityKoGridFilekoBinding
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokodialog.LoadingDialog.showLoadingDialog
import com.zxhy.fastfilemanagerpro.kokotools.ActivityLauncher
import com.zxhy.fastfilemanagerpro.kokotools.permission.PermissionCheck.storePermissionCheck
import com.zxhy.fastfilemanagerpro.kokotools.permission.StorePermissionEx.requestStoreFollow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class KoGridFilekoActivity : AppCompatActivity() {
private lateinit var binding: ActivityKoGridFilekoBinding
private val viewModel: KoGridFilekoViewModel by viewModels()
private lateinit var activityLauncher: ActivityLauncher
private var tittle = ""
private lateinit var adapter: KoFileGridkoAdapter
private lateinit var context: Context
private var dialog: Dialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
context = this
activityLauncher = ActivityLauncher(this)
binding = ActivityKoGridFilekoBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
tittle = intent.extras?.getString("Tittle") ?: ""
binding.tvTittle.text = tittle
adapter = KoFileGridkoAdapter {
binding.ivAllSelector.isSelected = it
enableDelete()
}
binding.rv.adapter = adapter
binding.ivAllSelector.setOnClickListener {
it.isSelected = !it.isSelected
adapter.toggleSelect(it.isSelected)
enableDelete()
}
binding.ivBack.setOnClickListener {
finish()
}
if (storePermissionCheck()) {
showPermissionSet(false)
loadListFile()
} else {
showPermissionSet(true)
}
}
//region
fun showOperationResult() = lifecycleScope.launch(Dispatchers.Main) {
binding.llResult.visibility = View.VISIBLE
delay(500)
binding.llResult.visibility = View.GONE
}
fun showPermissionSet(show: Boolean) {
if (show) {
binding.clContent.visibility = View.GONE
binding.clPermissionSet.visibility = View.VISIBLE
window.statusBarColor = ContextCompat.getColor(context, R.color.color_b3000000)
binding.tvSet.setOnClickListener {
requestStoreFollow(activityLauncher, disAgreeAction = {
showPermissionSet(true)
}, agreeAction = {
showPermissionSet(false)
loadListFile()
})
}
} else {
binding.clContent.visibility = View.VISIBLE
binding.clPermissionSet.visibility = View.GONE
window.statusBarColor = ContextCompat.getColor(context, R.color.white)
}
}
fun enableDelete() {
val enable = adapter.getSelectData().isNotEmpty()
binding.tvDelete.isEnabled = enable
if (enable) {
binding.tvDelete.background =
ContextCompat.getDrawable(context, R.drawable.bg_ffff6767_corners)
binding.tvDelete.setTextColor(ContextCompat.getColor(context, R.color.white))
binding.tvDelete.setOnClickListener {
deleteFiles()
}
} else {
binding.tvDelete.background =
ContextCompat.getDrawable(context, R.drawable.bg_fff4f4f4_corners)
binding.tvDelete.setTextColor(ContextCompat.getColor(context, R.color.color_999999))
binding.tvDelete.setOnClickListener {}
}
}
private fun deleteFiles() {
val selectData = adapter.getSelectData()
val files = selectData.map { it.toFile() }
viewModel.deleteFiles(files) {
lifecycleScope.launch(Dispatchers.Main) {
showOperationResult()
adapter.removeData(selectData)
showEmptyList()
enableDelete()
}
}
}
private fun showEmptyList() {
if (adapter.itemCount == 0) {
binding.clEmpty.visibility = View.VISIBLE
binding.clShowContent.visibility = View.GONE
binding.llAll.visibility = View.GONE
} else {
binding.clEmpty.visibility = View.GONE
binding.clShowContent.visibility = View.VISIBLE
binding.llAll.visibility = View.VISIBLE
}
}
private fun onDoList(list: List<KoFileDatako>) = lifecycleScope.launch(Dispatchers.Main) {
adapter.setData(list)
}
@SuppressLint("SetTextI18n")
private fun onFinishList(list: List<KoFileDatako>) = lifecycleScope.launch(Dispatchers.Main) {
adapter.setData(list)
showEmptyList()
enableDelete()
binding.tvItems.text = "total:${adapter.itemCount} items"
dialog?.dismiss()
}
//endregion
private fun loadListFile() {
dialog = showLoadingDialog()
when (tittle) {
IMAGE_FILE -> viewModel.loadImageFile(context, ::onDoList, ::onFinishList)
VIDEO_FILE -> viewModel.loadVideoFile(context, ::onDoList, ::onFinishList)
}
}
companion object {
const val IMAGE_FILE = "Image file"
const val VIDEO_FILE = "Video file"
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokogridfile
import android.content.Context
import com.zxhy.fastfilemanagerpro.CommonViewModel
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import java.io.File
class KoGridFilekoViewModel : CommonViewModel() {
fun isImageFilter(file: File): Boolean {
return file.name.contains(".jpg") or
file.name.contains(".png") or
file.name.contains(".gif")
}
fun isVideoFilter(file: File): Boolean {
return file.name.contains(".mp4") or
file.name.contains(".avi") or
file.name.contains(".flv") or
file.name.contains(".rmvb") or
file.name.contains(".mkv")
}
fun loadImageFile(
context: Context,
onDo: (list: List<KoFileDatako>) -> Unit,
onFinish: (list: List<KoFileDatako>) -> Unit
) {
loadFile(context, filter = (::isImageFilter),
onDo = { list ->
onDo.invoke(list)
},
onFinish = { list ->
onFinish.invoke(list)
}
)
}
fun loadVideoFile(
context: Context,
onDo: (list: List<KoFileDatako>) -> Unit,
onFinish: (list: List<KoFileDatako>) -> Unit
) {
loadFile(context, filter = (::isVideoFilter),
onDo = { list ->
onDo.invoke(list)
},
onFinish = { list ->
onFinish.invoke(list)
}
)
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokohome package com.zxhy.fastfilemanagerpro.kokohome
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
...@@ -9,6 +10,9 @@ import android.view.ViewGroup ...@@ -9,6 +10,9 @@ import android.view.ViewGroup
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.zxhy.fastfilemanagerpro.R import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.FragmentKoHomekoBinding import com.zxhy.fastfilemanagerpro.databinding.FragmentKoHomekoBinding
import com.zxhy.fastfilemanagerpro.kokoInternalstorage.KoInternalkoActivity
import com.zxhy.fastfilemanagerpro.kokodup.KoDupFilekoActivity.Companion.DUP_FILE
import com.zxhy.fastfilemanagerpro.kokodup.KoDupFilekoActivity.Companion.DUP_IMAGE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.EMPTY_FILE import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.EMPTY_FILE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.LARGE_FILE import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.LARGE_FILE
import com.zxhy.fastfilemanagerpro.kokotools.DiskHelper import com.zxhy.fastfilemanagerpro.kokotools.DiskHelper
...@@ -50,10 +54,19 @@ class KoHomekoFragment : Fragment() { ...@@ -50,10 +54,19 @@ class KoHomekoFragment : Fragment() {
findNavController().navigate(R.id.koListFilekoActivity, bundle) findNavController().navigate(R.id.koListFilekoActivity, bundle)
} }
binding.tvScanDupImage.setOnClickListener { binding.tvScanDupImage.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", DUP_IMAGE)
}
findNavController().navigate(R.id.koDupFilekoActivity, bundle)
} }
binding.tvScanDupFiles.setOnClickListener { binding.tvScanDupFiles.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", DUP_FILE)
}
findNavController().navigate(R.id.koDupFilekoActivity, bundle)
}
binding.flStorage.setOnClickListener {
startActivity(Intent(context, KoInternalkoActivity::class.java))
} }
} }
......
package com.zxhy.fastfilemanagerpro.kokolistfile package com.zxhy.fastfilemanagerpro.kokolistfile
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
...@@ -15,6 +16,7 @@ import com.zxhy.fastfilemanagerpro.R ...@@ -15,6 +16,7 @@ import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ActivityKoListFilekoBinding import com.zxhy.fastfilemanagerpro.databinding.ActivityKoListFilekoBinding
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.toFile
import com.zxhy.fastfilemanagerpro.kokodialog.LoadingDialog.showLoadingDialog
import com.zxhy.fastfilemanagerpro.kokotools.ActivityLauncher import com.zxhy.fastfilemanagerpro.kokotools.ActivityLauncher
import com.zxhy.fastfilemanagerpro.kokotools.permission.PermissionCheck.storePermissionCheck import com.zxhy.fastfilemanagerpro.kokotools.permission.PermissionCheck.storePermissionCheck
import com.zxhy.fastfilemanagerpro.kokotools.permission.StorePermissionEx.requestStoreFollow import com.zxhy.fastfilemanagerpro.kokotools.permission.StorePermissionEx.requestStoreFollow
...@@ -30,6 +32,7 @@ class KoListFilekoActivity : AppCompatActivity() { ...@@ -30,6 +32,7 @@ class KoListFilekoActivity : AppCompatActivity() {
private lateinit var adapter: KoListFilekoAdapter private lateinit var adapter: KoListFilekoAdapter
private var tittle = "" private var tittle = ""
private lateinit var context: Context private lateinit var context: Context
private var dialog: Dialog? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -79,6 +82,7 @@ class KoListFilekoActivity : AppCompatActivity() { ...@@ -79,6 +82,7 @@ class KoListFilekoActivity : AppCompatActivity() {
if (show) { if (show) {
binding.clContent.visibility = View.GONE binding.clContent.visibility = View.GONE
binding.clPermissionSet.visibility = View.VISIBLE binding.clPermissionSet.visibility = View.VISIBLE
window.statusBarColor = ContextCompat.getColor(context, R.color.color_b3000000)
binding.tvSet.setOnClickListener { binding.tvSet.setOnClickListener {
requestStoreFollow(activityLauncher, disAgreeAction = { requestStoreFollow(activityLauncher, disAgreeAction = {
showPermissionSet(true) showPermissionSet(true)
...@@ -90,11 +94,13 @@ class KoListFilekoActivity : AppCompatActivity() { ...@@ -90,11 +94,13 @@ class KoListFilekoActivity : AppCompatActivity() {
} else { } else {
binding.clContent.visibility = View.VISIBLE binding.clContent.visibility = View.VISIBLE
binding.clPermissionSet.visibility = View.GONE binding.clPermissionSet.visibility = View.GONE
window.statusBarColor = ContextCompat.getColor(context, R.color.white)
} }
} }
private fun loadListFile() { private fun loadListFile() {
dialog = showLoadingDialog()
when (tittle) { when (tittle) {
EMPTY_FILE -> viewModel.loadEmptyFile(context, ::onDoList, ::onFinishList) EMPTY_FILE -> viewModel.loadEmptyFile(context, ::onDoList, ::onFinishList)
LARGE_FILE -> viewModel.loadLargeFile(context, ::onDoList, ::onFinishList) LARGE_FILE -> viewModel.loadLargeFile(context, ::onDoList, ::onFinishList)
...@@ -148,7 +154,8 @@ class KoListFilekoActivity : AppCompatActivity() { ...@@ -148,7 +154,8 @@ class KoListFilekoActivity : AppCompatActivity() {
adapter.setData(list) adapter.setData(list)
showEmptyList() showEmptyList()
enableDelete() enableDelete()
binding.tvTittle.text = "total:${adapter.itemCount} items" binding.tvItems.text = "total:${adapter.itemCount} items"
dialog?.dismiss()
} }
......
...@@ -8,13 +8,13 @@ import com.zxhy.fastfilemanagerpro.R ...@@ -8,13 +8,13 @@ import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ActivityKoListFilekoBinding import com.zxhy.fastfilemanagerpro.databinding.ActivityKoListFilekoBinding
import com.zxhy.fastfilemanagerpro.databinding.ItemKokoListFileBinding import com.zxhy.fastfilemanagerpro.databinding.ItemKokoListFileBinding
import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.loadImageIcon
import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate
class KoListFilekoAdapter( class KoListFilekoAdapter(
private val allSelect: (flag: Boolean) -> Unit private val allSelect: (flag: Boolean) -> Unit
) : CommonAdapter<KoListFilekoAdapter.ItemKokoListFileViewHolder>() { ) : CommonAdapter<KoListFilekoAdapter.ItemKokoListFileViewHolder>() {
inner class ItemKokoListFileViewHolder(view: View) : ViewHolder(view) { inner class ItemKokoListFileViewHolder(view: View) : ViewHolder(view) {
val binding = ItemKokoListFileBinding.bind(view) val binding = ItemKokoListFileBinding.bind(view)
} }
...@@ -37,11 +37,13 @@ class KoListFilekoAdapter( ...@@ -37,11 +37,13 @@ class KoListFilekoAdapter(
val data = fileList[position] val data = fileList[position]
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
holder.binding.apply { holder.binding.apply {
data.loadImageIcon(context, ivIcon)
tvName.text = data.name tvName.text = data.name
tvInfo.text = "${data.timeE} ${data.sizeF}" tvInfo.text = "${data.timeE} ${data.sizeF}"
ivSelector.isSelected = data.isSelect ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener { ivSelector.setOnClickListener {
data.isSelect = !data.isSelect data.isSelect = !data.isSelect
ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "局部刷洗") notifyItemChanged(position, "局部刷洗")
allSelect.invoke(fileList.all { it.isSelect }) allSelect.invoke(fileList.all { it.isSelect })
} }
......
...@@ -4,6 +4,7 @@ import android.content.Context ...@@ -4,6 +4,7 @@ import android.content.Context
import android.os.Environment import android.os.Environment
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.zxhy.fastfilemanagerpro.CommonViewModel
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.koFileDatako import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako.Companion.koFileDatako
import com.zxhy.fastfilemanagerpro.kokotools.HelperTraverse.linkedLisTraverseFolder import com.zxhy.fastfilemanagerpro.kokotools.HelperTraverse.linkedLisTraverseFolder
...@@ -13,7 +14,7 @@ import kotlinx.coroutines.launch ...@@ -13,7 +14,7 @@ import kotlinx.coroutines.launch
import java.io.File import java.io.File
import kotlin.reflect.KFunction1 import kotlin.reflect.KFunction1
class KoListFilekoViewModel : ViewModel() { class KoListFilekoViewModel : CommonViewModel() {
fun isEmptyFilter(file: File): Boolean { fun isEmptyFilter(file: File): Boolean {
...@@ -25,23 +26,33 @@ class KoListFilekoViewModel : ViewModel() { ...@@ -25,23 +26,33 @@ class KoListFilekoViewModel : ViewModel() {
} }
fun isAudioFilter(file: File): Boolean { fun isAudioFilter(file: File): Boolean {
return file.length() >= 10 * 1024 * 1024L return file.name.contains(".mp3") or
file.name.contains(".aac") or
file.name.contains(".ogg") or
file.name.contains(".aac")
} }
fun isLogFilter(file: File): Boolean { fun isLogFilter(file: File): Boolean {
return file.length() >= 10 * 1024 * 1024L return file.name.contains("log") or file.name.contains("Log")
} }
fun isZipFilter(file: File): Boolean { fun isZipFilter(file: File): Boolean {
return file.length() >= 10 * 1024 * 1024L return file.name.contains(".zip") or file.name.contains(".7z")
} }
fun isApkFilter(file: File): Boolean { fun isApkFilter(file: File): Boolean {
return file.length() >= 10 * 1024 * 1024L return file.name.contains(".apk")
} }
fun isDocumentsFilter(file: File): Boolean { fun isDocumentsFilter(file: File): Boolean {
return file.length() >= 10 * 1024 * 1024L return file.name.contains(".doc") or
file.name.contains(".docx") or
file.name.contains(".ppt") or
file.name.contains(".pptx") or
file.name.contains(".xls") or
file.name.contains(".xlsx") or
file.name.contains(".txt") or
file.name.contains(".pdf")
} }
fun loadEmptyFile( fun loadEmptyFile(
...@@ -150,45 +161,4 @@ class KoListFilekoViewModel : ViewModel() { ...@@ -150,45 +161,4 @@ class KoListFilekoViewModel : ViewModel() {
) )
} }
private fun loadFile(
context: Context,
filter: (file: File) -> Boolean,
onDo: (list: List<KoFileDatako>) -> Unit,
onFinish: (list: List<KoFileDatako>) -> Unit
) {
viewModelScope.launch(Dispatchers.IO) {
val root = Environment.getExternalStorageDirectory()
val resultList = arrayListOf<KoFileDatako>()
var firstSend = false
linkedLisTraverseFolder(root) { file ->
if (filter(file)) {
resultList.add(file.koFileDatako(context))
if (resultList.size == 20 && !firstSend) {
onDo.invoke(resultList)
resultList.clear()
firstSend = true
}
}
}
onFinish.invoke(resultList)
}
}
fun deleteFiles(files: List<File>, finishAction: () -> Unit) =
viewModelScope.launch(Dispatchers.IO) {
runCatching {
files.forEach {
if (it.exists()) {
it.delete()
}
}
}
finishAction.invoke()
}
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokomanager package com.zxhy.fastfilemanagerpro.kokomanager
import android.content.Context
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.zxhy.fastfilemanagerpro.R import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.FragmentKoManagerkoBinding import com.zxhy.fastfilemanagerpro.databinding.FragmentKoManagerkoBinding
import com.zxhy.fastfilemanagerpro.kokogridfile.KoGridFilekoActivity.Companion.IMAGE_FILE
import com.zxhy.fastfilemanagerpro.kokogridfile.KoGridFilekoActivity.Companion.VIDEO_FILE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.APK_FILE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.AUDIO_FILE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.DOCUMENTS_FILE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.LOG_FILE
import com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity.Companion.ZIP_FILE
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class KoManagerkoFragment : Fragment() { class KoManagerkoFragment : Fragment() {
private lateinit var binding: FragmentKoManagerkoBinding private lateinit var binding: FragmentKoManagerkoBinding
private val viewModel: KoManagerkoViewModel by viewModels()
private lateinit var context: Context
private lateinit var adapter: KoRecentkoAdapter
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -27,10 +43,57 @@ class KoManagerkoFragment : Fragment() { ...@@ -27,10 +43,57 @@ class KoManagerkoFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
} context = requireContext()
binding.llImage.setOnClickListener {
companion object{ val bundle = Bundle().apply {
putString("Tittle", IMAGE_FILE)
}
findNavController().navigate(R.id.koGridFilekoActivity, bundle)
}
binding.llVideo.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", VIDEO_FILE)
}
findNavController().navigate(R.id.koGridFilekoActivity, bundle)
}
binding.llAudio.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", AUDIO_FILE)
}
findNavController().navigate(R.id.koListFilekoActivity, bundle)
}
binding.llLogFile.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", LOG_FILE)
}
findNavController().navigate(R.id.koListFilekoActivity, bundle)
}
binding.llZip.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", ZIP_FILE)
}
findNavController().navigate(R.id.koListFilekoActivity, bundle)
}
binding.llApk.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", APK_FILE)
}
findNavController().navigate(R.id.koListFilekoActivity, bundle)
}
binding.llDocuments.setOnClickListener {
val bundle = Bundle().apply {
putString("Tittle", DOCUMENTS_FILE)
}
findNavController().navigate(R.id.koListFilekoActivity, bundle)
}
adapter = KoRecentkoAdapter()
binding.rvRecent.adapter = adapter
viewModel.loadRecentImageVideo(context) {
lifecycleScope.launch(Dispatchers.Main) {
adapter.setData(it)
}
}
} }
} }
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokomanager
import android.content.Context
import androidx.lifecycle.viewModelScope
import com.zxhy.fastfilemanagerpro.CommonViewModel
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
import com.zxhy.fastfilemanagerpro.kokotools.MediaStoreEx.recentImage
import com.zxhy.fastfilemanagerpro.kokotools.MediaStoreEx.recentVideo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class KoManagerkoViewModel : CommonViewModel() {
fun loadRecentImageVideo(
context: Context,
result: (list: ArrayList<KoFileDatako>) -> Unit
) = viewModelScope.launch(Dispatchers.IO) {
val imageList = recentImage(context).map { KoFileDatako(uri = it) }
val videoList = recentVideo(context).map { KoFileDatako(uri = it) }
val list= arrayListOf<KoFileDatako>()
list.addAll(imageList)
list.addAll(videoList)
result.invoke(list)
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokomanager
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.zxhy.fastfilemanagerpro.R
import com.zxhy.fastfilemanagerpro.databinding.ItemKokoImageBinding
import com.zxhy.fastfilemanagerpro.kokoadapter.CommonAdapter
import com.zxhy.fastfilemanagerpro.kokotools.GlideHelper.loadImageView
import com.zxhy.fastfilemanagerpro.kokotools.XmlEx.inflate
class KoRecentkoAdapter : CommonAdapter<KoRecentkoAdapter.KoRecentkoViewHolder>() {
inner class KoRecentkoViewHolder(view: View) : ViewHolder(view) {
val binding = ItemKokoImageBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): KoRecentkoViewHolder {
return KoRecentkoViewHolder(R.layout.item_koko_image.inflate(parent))
}
override fun onBindViewHolder(holder: KoRecentkoViewHolder, position: Int) {
val context = holder.binding.root.context
val data = fileList[position]
holder.binding.apply {
iv.loadImageView(context, data.uri)
}
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokotools
import android.content.Context
import android.net.Uri
import android.widget.ImageView
import com.bumptech.glide.Glide
import java.io.File
object GlideHelper {
fun ImageView.loadImageView(context: Context, file: File) {
Glide.with(context).load(file).centerCrop().into(this)
}
fun ImageView.loadImageView(context: Context, uri: Uri) {
Glide.with(context).load(uri).centerCrop().into(this)
}
}
\ No newline at end of file
package com.zxhy.fastfilemanagerpro.kokotools
import android.util.Log
import java.io.File
import java.nio.channels.FileChannel
import java.security.MessageDigest
//生成、查看文件的MD5、SHA1、SHA2、SHA3值
//https://blog.csdn.net/COCO56/article/details/106161207
object Md5Ex {
fun File.digestMd5(): ByteArray {
if (length() > Integer.MAX_VALUE) {
return "${name.length} $name".toByteArray()
}
val byteBuffer = inputStream().channel.map(FileChannel.MapMode.READ_ONLY, 0, length())
val digest = MessageDigest.getInstance("MD5")
digest.update(byteBuffer)
return digest.digest()
}
private const val HEXES = "0123456789ABCDEF"
/**
* ByteArray转Hex码
*/
fun ByteArray.byteArrayToHexString(): String {
val hex = StringBuilder(2 * this.size)
for (element in this) {
val high = element.toInt().and(0xFF).shr(4)
val low = element.toInt().and(0x0F)
hex.append(HEXES[high]).append(HEXES[low])
}
return hex.toString()
}
}
package com.zxhy.fastfilemanagerpro.kokotools
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.MediaStore
import com.zxhy.fastfilemanagerpro.kokodata.KoFileDatako
object MediaStoreEx {
fun recentImage(context: Context): ArrayList<Uri> {
val list = arrayListOf<Uri>()
var cursor: Cursor? = null
// 查询照片的Uri和字段
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME)
//DESC 降列
//ASC 升序
val sortOrder = MediaStore.Images.ImageColumns._ID + " DESC"
try {
// 执行查询
cursor = context.contentResolver.query(uri, projection, null, null, sortOrder)
// 遍历结果
if (cursor != null && cursor.moveToFirst()) {
do {
val id =
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
list.add(ContentUris.withAppendedId(uri, id))
if (list.size == 10) {
break
}
} while (cursor.moveToNext())
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
return list
}
fun recentVideo(context: Context): ArrayList<Uri> {
val list = arrayListOf<Uri>()
var cursor: Cursor? = null
// 查询照片的Uri和字段
val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME)
//DESC 降列
//ASC 升序
val sortOrder = MediaStore.Video.VideoColumns._ID + " DESC"
try {
// 执行查询
cursor = context.contentResolver.query(uri, projection, null, null, sortOrder)
// 遍历结果
if (cursor != null && cursor.moveToFirst()) {
do {
val id =
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
list.add(ContentUris.withAppendedId(uri, id))
if (list.size == 10) {
break
}
} while (cursor.moveToNext())
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
return list
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/dda_026336" android:state_selected="false" />
<item android:drawable="@mipmap/d_998989" android:state_selected="true" />
</selector>
\ No newline at end of file
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:visibility="gone"
android:id="@+id/ll_all" android:id="@+id/ll_all"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
...@@ -118,16 +119,19 @@ ...@@ -118,16 +119,19 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageView <ImageView
android:id="@+id/iv_all_selector"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginEnd="5dp" android:layout_marginEnd="12dp"
android:src="@drawable/bg_file_selector" android:src="@drawable/bg_file_selector"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription,ImageContrastCheck" />
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="0dp" android:layout_width="0dp"
android:overScrollMode="never"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginVertical="8dp" android:layout_marginVertical="8dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
...@@ -136,6 +140,7 @@ ...@@ -136,6 +140,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_items" /> app:layout_constraintTop_toBottomOf="@id/tv_items" />
<TextView <TextView
android:id="@+id/tv_delete" android:id="@+id/tv_delete"
android:layout_width="278dp" android:layout_width="278dp"
...@@ -149,14 +154,17 @@ ...@@ -149,14 +154,17 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/rv"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:id="@+id/ll_result"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/bg_000000_corners" android:background="@drawable/bg_000000_corners"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingVertical="8dp" android:paddingVertical="8dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
...@@ -222,6 +230,7 @@ ...@@ -222,6 +230,7 @@
app:layout_constraintTop_toBottomOf="@id/iv_lock" /> app:layout_constraintTop_toBottomOf="@id/iv_lock" />
<TextView <TextView
android:id="@+id/tv_set"
android:layout_width="270dp" android:layout_width="270dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".gridfile.KoGridFilekoActivity"> tools:context=".kokogridfile.KoGridFilekoActivity">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_action_bar" android:id="@+id/cl_action_bar"
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables">
<ImageView <ImageView
android:id="@+id/iv_back"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
...@@ -82,8 +83,7 @@ ...@@ -82,8 +83,7 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_show_content" android:id="@+id/cl_show_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:visibility="gone">
<TextView <TextView
android:id="@+id/tv_items" android:id="@+id/tv_items"
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="20dp" android:layout_marginEnd="20dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/tv_items" app:layout_constraintBottom_toBottomOf="@id/tv_items"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_items" app:layout_constraintTop_toTopOf="@id/tv_items"
...@@ -118,6 +119,7 @@ ...@@ -118,6 +119,7 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageView <ImageView
android:id="@+id/iv_all_selector"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
...@@ -127,14 +129,19 @@ ...@@ -127,14 +129,19 @@
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp" android:id="@+id/rv"
android:overScrollMode="never"
android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginVertical="8dp" android:layout_marginVertical="8dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/tv_delete"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_items" /> app:layout_constraintTop_toBottomOf="@id/tv_items"
app:layout_constraintVertical_bias="0.0"
app:spanCount="4" />
<TextView <TextView
android:id="@+id/tv_delete" android:id="@+id/tv_delete"
...@@ -151,6 +158,41 @@ ...@@ -151,6 +158,41 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<LinearLayout
android:id="@+id/ll_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_000000_corners"
android:orientation="horizontal"
android:paddingVertical="8dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="8dp"
android:src="@mipmap/dd_899900"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_operation_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:singleLine="true"
android:text="Delete successful!"
android:textColor="#FFFFFF"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
...@@ -188,6 +230,7 @@ ...@@ -188,6 +230,7 @@
app:layout_constraintTop_toBottomOf="@id/iv_lock" /> app:layout_constraintTop_toBottomOf="@id/iv_lock" />
<TextView <TextView
android:id="@+id/tv_set"
android:layout_width="270dp" android:layout_width="270dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_margin="5dp" android:layout_margin="5dp"
android:text="Tittle List Files" android:text="Internal storage"
android:textColor="#FF333333" android:textColor="#FF333333"
android:textSize="17sp" android:textSize="17sp"
android:textStyle="bold" android:textStyle="bold"
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
android:id="@+id/cl_content" android:id="@+id/cl_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_action_bar"> app:layout_constraintTop_toBottomOf="@id/cl_action_bar">
...@@ -99,7 +98,7 @@ ...@@ -99,7 +98,7 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:id="@+id/ll_all" android:id="@+id/ll_edit_select"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="20dp" android:layout_marginEnd="20dp"
...@@ -109,21 +108,36 @@ ...@@ -109,21 +108,36 @@
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables">
<TextView <TextView
android:id="@+id/tv_all"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="5dp"
android:text="All" android:text="All"
android:textColor="#FF666666" android:textColor="#FF666666"
android:textSize="15sp" android:textSize="15sp"
android:visibility="gone"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageView <ImageView
android:id="@+id/iv_all_selector"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:src="@drawable/bg_file_selector" android:src="@drawable/bg_file_selector"
android:visibility="gone"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Edit"
android:textColor="#FF666666"
android:textSize="15sp"
tools:ignore="HardcodedText" />
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
...@@ -131,6 +145,7 @@ ...@@ -131,6 +145,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginVertical="8dp" android:layout_marginVertical="8dp"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/cl_operation" app:layout_constraintBottom_toTopOf="@id/cl_operation"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
...@@ -176,11 +191,11 @@ ...@@ -176,11 +191,11 @@
android:id="@+id/cl_operation" android:id="@+id/cl_operation"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="83dp" android:layout_height="83dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/rv"> app:layout_constraintTop_toBottomOf="@id/rv">
<LinearLayout <LinearLayout
android:id="@+id/ll_operation"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp" android:layout_marginHorizontal="20dp"
...@@ -192,6 +207,7 @@ ...@@ -192,6 +207,7 @@
tools:ignore="DisableBaselineAlignment"> tools:ignore="DisableBaselineAlignment">
<LinearLayout <LinearLayout
android:id="@+id/ll_share"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
...@@ -218,6 +234,7 @@ ...@@ -218,6 +234,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_rename"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
...@@ -244,6 +261,7 @@ ...@@ -244,6 +261,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_delete"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
...@@ -270,6 +288,7 @@ ...@@ -270,6 +288,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_copy"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
...@@ -296,6 +315,7 @@ ...@@ -296,6 +315,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_move"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
...@@ -323,6 +343,70 @@ ...@@ -323,6 +343,70 @@
</LinearLayout> </LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_operation_confirm"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ImageView
android:id="@+id/iv_selected_icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="20dp"
android:src="@mipmap/dzd_87897891231"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_confirm_items"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="0 items"
android:textColor="#FF666666"
android:textSize="13dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_selected_icon"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText,SpUsage" />
<TextView
android:id="@+id/tv_confirm"
android:layout_width="77dp"
android:layout_height="28dp"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_ffff6767_corners"
android:gravity="center"
android:text="Move"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_cancel"
android:layout_width="77dp"
android:layout_height="28dp"
android:layout_marginEnd="24dp"
android:background="@drawable/bg_fff4f4f4_corners"
android:gravity="center"
android:text="Cancel"
android:textColor="#FF999999"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_confirm"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
...@@ -334,7 +418,8 @@ ...@@ -334,7 +418,8 @@
android:id="@+id/cl_permission_set" android:id="@+id/cl_permission_set"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#B3000000"> android:background="#B3000000"
android:visibility="gone">
<ImageView <ImageView
android:id="@+id/iv_lock" android:id="@+id/iv_lock"
......
...@@ -131,6 +131,7 @@ ...@@ -131,6 +131,7 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv" android:id="@+id/rv"
android:layout_width="0dp" android:layout_width="0dp"
android:overScrollMode="never"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginVertical="8dp" android:layout_marginVertical="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
...@@ -187,6 +188,7 @@ ...@@ -187,6 +188,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/rv"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="8dp">
<ImageView
android:layout_width="270dp"
android:layout_height="176dp"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="Rename"
android:textColor="#FF333333"
android:textSize="17sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_delete"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end"
android:layout_margin="6dp"
android:src="@mipmap/dd_0203060"
tools:ignore="ContentDescription" />
<EditText
android:id="@+id/edit"
android:layout_width="222dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="55dp"
android:backgroundTint="#FFE6E6E6"
android:gravity="center"
android:hint="Please enter"
android:textColor="#FF999999"
android:textColorHint="#FF999999"
android:textSize="14sp"
tools:ignore="Autofill,HardcodedText,TextFields" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="238dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="16dp"
android:background="@drawable/bg_494949_corners"
android:gravity="center"
android:text="Sure"
android:textColor="#FFFAF6E9"
android:textSize="15sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardBackgroundColor="#323232"
app:cardCornerRadius="10dp">
<ImageView
android:layout_width="250dp"
android:layout_height="180dp"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_loading"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:src="@drawable/loading"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.cardview.widget.CardView>
\ No newline at end of file
...@@ -35,8 +35,12 @@ ...@@ -35,8 +35,12 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recent" android:id="@+id/rv_recent"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="80dp" android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:orientation="horizontal"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_recent" /> app:layout_constraintTop_toBottomOf="@id/tv_recent" />
...@@ -64,6 +68,7 @@ ...@@ -64,6 +68,7 @@
app:layout_constraintTop_toBottomOf="@id/tv_Folder"> app:layout_constraintTop_toBottomOf="@id/tv_Folder">
<LinearLayout <LinearLayout
android:id="@+id/ll_image"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_gravity="start"
...@@ -89,6 +94,7 @@ ...@@ -89,6 +94,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_video"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
...@@ -114,6 +120,7 @@ ...@@ -114,6 +120,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_audio"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end" android:layout_gravity="end"
...@@ -150,6 +157,7 @@ ...@@ -150,6 +157,7 @@
app:layout_constraintTop_toBottomOf="@id/fl_1"> app:layout_constraintTop_toBottomOf="@id/fl_1">
<LinearLayout <LinearLayout
android:id="@+id/ll_log_file"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_gravity="start"
...@@ -175,6 +183,7 @@ ...@@ -175,6 +183,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_zip"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
...@@ -200,6 +209,7 @@ ...@@ -200,6 +209,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_apk"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end" android:layout_gravity="end"
...@@ -230,18 +240,18 @@ ...@@ -230,18 +240,18 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_gravity="start"
android:layout_marginTop="20dp"
android:layout_marginStart="-10dp" android:layout_marginStart="-10dp"
android:layout_marginTop="20dp"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintStart_toStartOf="@id/fl_2" app:layout_constraintStart_toStartOf="@id/fl_2"
app:layout_constraintTop_toBottomOf="@id/fl_2" app:layout_constraintTop_toBottomOf="@id/fl_2"
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables">
<ImageView <ImageView
android:src="@mipmap/qwe_889989"
android:layout_width="45dp" android:layout_width="45dp"
android:layout_height="45dp" android:layout_height="45dp"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:src="@mipmap/qwe_889989"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<TextView <TextView
......
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
app:cardCornerRadius="8dp"
app:cardElevation="5dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -14,7 +18,8 @@ ...@@ -14,7 +18,8 @@
android:id="@+id/tv_items" android:id="@+id/tv_items"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="12dp" android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="2 items" android:text="2 items"
android:textColor="#666666" android:textColor="#666666"
android:textSize="15sp" android:textSize="15sp"
...@@ -24,10 +29,11 @@ ...@@ -24,10 +29,11 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageView <ImageView
android:src="@drawable/bg_file_selector" android:id="@+id/iv_selector"
android:layout_width="16dp" android:layout_width="24dp"
android:layout_height="16dp" android:layout_height="24dp"
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:src="@drawable/bg_file_selector"
app:layout_constraintBottom_toBottomOf="@id/tv_items" app:layout_constraintBottom_toBottomOf="@id/tv_items"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_items" app:layout_constraintTop_toTopOf="@id/tv_items"
...@@ -37,6 +43,7 @@ ...@@ -37,6 +43,7 @@
android:id="@+id/rv" android:id="@+id/rv"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_items" /> app:layout_constraintTop_toBottomOf="@id/tv_items" />
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_margin="12dp">
<ImageView <ImageView
android:id="@+id/iv" android:id="@+id/iv"
...@@ -48,10 +49,12 @@ ...@@ -48,10 +49,12 @@
<ImageView <ImageView
android:id="@+id/iv_selector" android:id="@+id/iv_selector"
android:layout_width="16dp" android:layout_width="24dp"
android:layout_height="16dp" android:layout_height="24dp"
android:src="@drawable/bg_file_selector"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ll"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="70dp"
android:layout_margin="8dp"
android:layout_height="70dp"
app:cardCornerRadius="8dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_camera"
android:layout_width="20dp"
android:layout_height="16dp"
android:layout_gravity="center"
android:src="@mipmap/cc_87897"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="end|bottom"
android:layout_margin="4dp"
android:src="@drawable/bg_grid_file_selector"
tools:ignore="ContentDescription" />
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_margin="5dp"
app:cardCornerRadius="8dp">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</androidx.cardview.widget.CardView>
\ No newline at end of file
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
<action <action
android:id="@+id/action_koManagerkoFragment_to_koHomekoFragment" android:id="@+id/action_koManagerkoFragment_to_koHomekoFragment"
app:destination="@id/koHomekoFragment" /> app:destination="@id/koHomekoFragment" />
<action
android:id="@+id/action_koManagerkoFragment_to_koGridFilekoActivity"
app:destination="@id/koGridFilekoActivity" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/koHomekoFragment" android:id="@+id/koHomekoFragment"
...@@ -25,10 +28,23 @@ ...@@ -25,10 +28,23 @@
<action <action
android:id="@+id/action_koHomekoFragment_to_koListFilekoActivity" android:id="@+id/action_koHomekoFragment_to_koListFilekoActivity"
app:destination="@id/koListFilekoActivity" /> app:destination="@id/koListFilekoActivity" />
<action
android:id="@+id/action_koHomekoFragment_to_koDupFilekoActivity"
app:destination="@id/koDupFilekoActivity" />
</fragment> </fragment>
<activity <activity
android:id="@+id/koListFilekoActivity" android:id="@+id/koListFilekoActivity"
android:name="com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity" android:name="com.zxhy.fastfilemanagerpro.kokolistfile.KoListFilekoActivity"
android:label="activity_ko_list_fileko" android:label="activity_ko_list_fileko"
tools:layout="@layout/activity_ko_list_fileko" /> tools:layout="@layout/activity_ko_list_fileko" />
<activity
android:id="@+id/koGridFilekoActivity"
android:name="com.zxhy.fastfilemanagerpro.kokogridfile.KoGridFilekoActivity"
android:label="activity_ko_grid_fileko"
tools:layout="@layout/activity_ko_grid_fileko" />
<activity
android:id="@+id/koDupFilekoActivity"
android:name="com.zxhy.fastfilemanagerpro.kokodup.KoDupFilekoActivity"
android:label="activity_ko_dup_fileko"
tools:layout="@layout/activity_ko_dup_fileko" />
</navigation> </navigation>
\ No newline at end of file
...@@ -3,4 +3,8 @@ ...@@ -3,4 +3,8 @@
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="color_999999">#999999</color> <color name="color_999999">#999999</color>
<color name="color_fff4f4f4">#FFF4F4F4</color>
<color name="color_ffffff">#FFFFFF</color>
<color name="color_606060">#606060</color>
<color name="color_b3000000">#B3000000</color>
</resources> </resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="dp_24">24dp</dimen> <dimen name="dp_24">24dp</dimen>
<dimen name="dp_250">250dp</dimen>
<dimen name="dp_180">180dp</dimen>
<dimen name="dp_260">260dp</dimen>
<dimen name="dp_190">190dp</dimen>
</resources> </resources>
\ No newline at end of file
...@@ -13,6 +13,7 @@ activityKtx = "1.6.2" ...@@ -13,6 +13,7 @@ activityKtx = "1.6.2"
fragmentKtx = "1.6.2" fragmentKtx = "1.6.2"
navigationFragmentKtx = "2.7.7" navigationFragmentKtx = "2.7.7"
navigationUiKtx = "2.7.7" navigationUiKtx = "2.7.7"
glide = "4.16.0"
[libraries] [libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
...@@ -27,6 +28,7 @@ androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", ve ...@@ -27,6 +28,7 @@ androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", ve
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigationFragmentKtx" } androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigationFragmentKtx" }
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" } androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" }
glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
[plugins] [plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" } androidApplication = { id = "com.android.application", version.ref = "agp" }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment