Commit ba032ba3 authored by wanglei's avatar wanglei

Initial commit

parent 40fc93ff
*.iml *.iml
.gradle .gradle
/local.properties /local.properties
/.idea
/.idea/caches /.idea/caches
/.idea/libraries /.idea/libraries
/.idea/modules.xml /.idea/modules.xml
......
...@@ -46,7 +46,10 @@ ...@@ -46,7 +46,10 @@
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".activity.FileManagerActivity" android:name=".activity.FileManagerActivity"
android:exported="false" /> android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<meta-data <meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION" android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
......
package com.base.easyfilemanager.activity package com.base.easyfilemanager.activity
import android.content.Context import android.content.Context
import android.graphics.Color
import android.media.MediaScannerConnection import android.media.MediaScannerConnection
import android.net.Uri import android.net.Uri
import android.os.Environment import android.os.Environment
...@@ -14,6 +15,7 @@ import com.base.easyfilemanager.adapter.FileBrowseAdapter ...@@ -14,6 +15,7 @@ import com.base.easyfilemanager.adapter.FileBrowseAdapter
import com.base.easyfilemanager.bean.FileBean import com.base.easyfilemanager.bean.FileBean
import com.base.easyfilemanager.bean.FileCategoryBean import com.base.easyfilemanager.bean.FileCategoryBean
import com.base.easyfilemanager.databinding.ActivityFileCategoryBinding import com.base.easyfilemanager.databinding.ActivityFileCategoryBinding
import com.base.easyfilemanager.helps.BarUtils
import com.base.easyfilemanager.helps.BaseActivity import com.base.easyfilemanager.helps.BaseActivity
import com.base.easyfilemanager.helps.MediaStoreEx.geFileMedia import com.base.easyfilemanager.helps.MediaStoreEx.geFileMedia
import com.base.easyfilemanager.helps.MediaStoreEx.getAudioMedia import com.base.easyfilemanager.helps.MediaStoreEx.getAudioMedia
...@@ -41,6 +43,7 @@ class FileCategoryActivity : BaseActivity<ActivityFileCategoryBinding>() { ...@@ -41,6 +43,7 @@ class FileCategoryActivity : BaseActivity<ActivityFileCategoryBinding>() {
override fun initView() { override fun initView() {
initStatusBar()
type = intent.extras?.getString("type") ?: "" type = intent.extras?.getString("type") ?: ""
binding.tvTittle.text = type binding.tvTittle.text = type
adapter = FileBrowseAdapter { size -> adapter = FileBrowseAdapter { size ->
...@@ -65,6 +68,12 @@ class FileCategoryActivity : BaseActivity<ActivityFileCategoryBinding>() { ...@@ -65,6 +68,12 @@ class FileCategoryActivity : BaseActivity<ActivityFileCategoryBinding>() {
} }
} }
private fun initStatusBar() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
}
override fun initListener() { override fun initListener() {
binding.flBack.setOnClickListener { binding.flBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
......
package com.base.easyfilemanager.activity package com.base.easyfilemanager.activity
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Environment
import android.view.View
import androidx.activity.addCallback
import androidx.core.content.FileProvider
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.base.easyfilemanager.adapter.FileManagerAdapter
import com.base.easyfilemanager.bean.FileBean
import com.base.easyfilemanager.databinding.ActivityFileManagerBinding import com.base.easyfilemanager.databinding.ActivityFileManagerBinding
import com.base.easyfilemanager.helps.BarUtils
import com.base.easyfilemanager.helps.BaseActivity import com.base.easyfilemanager.helps.BaseActivity
import com.base.easyfilemanager.helps.FileHelp.deleteDirectory
import com.base.easyfilemanager.view.AdPreparationPop
import com.base.easyfilemanager.view.FileDeleteDialog.showFileDeleteDialog
import com.base.easyfilemanager.view.SimpleFileDialog.showSimpleFileDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.File
class FileManagerActivity : BaseActivity<ActivityFileManagerBinding>() { class FileManagerActivity : BaseActivity<ActivityFileManagerBinding>() {
private var currentMode: Int = BROWSER_MODE
companion object {
const val BROWSER_MODE = 12
const val OPERATION_MODE = 13
const val CONFIRM_MODE = 18
}
override val binding: ActivityFileManagerBinding by lazy { override val binding: ActivityFileManagerBinding by lazy {
ActivityFileManagerBinding.inflate(layoutInflater) ActivityFileManagerBinding.inflate(layoutInflater)
} }
private val adapter by lazy {
FileManagerAdapter(
allSelect = {
binding.ivAll.isSelected = it
},
showEmpty = {
showEmpty(isEmpty = it, showWrite = !it)
}
)
}
override fun initView() { override fun initView() {
initStatusBar()
binding.rv.adapter = adapter
loadStorage()
}
private fun initStatusBar() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
}
override fun initListener() {
binding.ivAll.setOnClickListener {
it.isSelected = !it.isSelected
adapter.toggleSelect(it.isSelected)
}
binding.ivWrite.setOnClickListener {
operationMode()
}
binding.ivNewFile.setOnClickListener {
showSimpleFileDialog { name ->
val file = File(adapter.getCurrentDir(), name)
if (file.isFile) return@showSimpleFileDialog
if (!file.exists()) {
file.mkdirs()
adapter.notifyCurrentDir()
}
}
}
onBackPressedDispatcher.addCallback {
if (currentMode == BROWSER_MODE) {
val isRoot = adapter.beforePage()
if (isRoot) {
AdPreparationPop(this@FileManagerActivity) {
finish()
}.show()
}
}
if (currentMode == OPERATION_MODE) {
browserMode()
}
if (currentMode == CONFIRM_MODE) {
adapter.beforePage()
}
}
binding.flBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
}
private fun loadStorage() {
val root = Environment.getExternalStorageDirectory().listFiles()
val dataList = root?.map { FileBean(it.name, it.path, it.length()) } ?: listOf()
showEmpty(isEmpty = dataList.isEmpty(), showWrite = true)
adapter.setData(dataList)
} }
private fun showEmpty(isEmpty: Boolean = false, showAll: Boolean = false, showWrite: Boolean = false) {
binding.llEmpty.isVisible = isEmpty
if (isEmpty) {
binding.flAllWrite.visibility = View.GONE
} else {
binding.flAllWrite.visibility = View.VISIBLE
binding.ivAll.isVisible = showAll
binding.ivWrite.isVisible = showWrite
}
}
private fun operationMode() {
currentMode = OPERATION_MODE
binding.flConfirm.visibility = View.GONE
binding.llOperation.visibility = View.VISIBLE
adapter.changeSelect(true, canNext = false)
binding.ivAll.isSelected = false
showEmpty(showAll = true)
binding.llMove.setOnClickListener {
confirmMode("Move")
}
binding.llCopy.setOnClickListener {
confirmMode("Copy")
}
binding.llRename.setOnClickListener {
val files = adapter.getSelectData().map { File(it.path) }
if (files.size == 1) {
renameFile(files.first())
}
}
binding.llDelete.setOnClickListener {
val files = adapter.getSelectData().map { File(it.path) }
if (files.isNotEmpty()) {
showFileDeleteDialog {
lifecycleScope.launch(Dispatchers.Main) {
async {
files.forEach { if (it.isFile) it.delete() else deleteDirectory(it) }
}.await()
browserMode()
adapter.notifyCurrentDir()
}
}
}
}
}
private fun renameFile(file: File) {
val dir = file.parentFile
showSimpleFileDialog(file.name, nameAction = {
runCatching { file.renameTo(File(dir, it)) }
operationFinish()
})
}
@SuppressLint("SetTextI18n")
private fun confirmMode(operation: String) {
val selectFile = adapter.getSelectData()
if (selectFile.isEmpty())
return
currentMode = CONFIRM_MODE
binding.llOperation.visibility = View.GONE
binding.ivAll.isSelected = false
binding.ivAll.visibility = View.GONE
binding.flConfirm.visibility = View.VISIBLE
adapter.changeSelect(false, isAddCannotNext = true)
binding.tvCancel.setOnClickListener {
browserMode()
}
binding.tvConfirm.setOnClickListener {
val files = adapter.getOperationList()
val currentDir = adapter.getCurrentDir()
when (operation) {
"Move" -> {
binding.tvConfirm.text = "Motion"
moveFiles(files, currentDir, ::operationFinish)
}
"Copy" -> {
binding.tvConfirm.text = "Paste"
copyFiles(files, currentDir, ::operationFinish)
}
}
}
}
private fun moveFiles(
files: List<File>, currentDir: File,
finish: () -> Unit
) = lifecycleScope.launch(Dispatchers.IO) {
runCatching {
files.forEach {
it.copyRecursively(File(currentDir, it.name), true)
it.deleteRecursively()
}
}
finish.invoke()
}
fun copyFiles(
files: List<File>, currentDir: File,
finish: () -> Unit
) = lifecycleScope.launch(Dispatchers.IO) {
runCatching {
files.forEach {
it.copyRecursively(File(currentDir, it.name), true)
}
}
finish.invoke()
}
private fun operationFinish() = lifecycleScope.launch(Dispatchers.Main) {
browserMode()
adapter.notifyCurrentDir()
}
private fun browserMode() {
currentMode = BROWSER_MODE
binding.ivAll.visibility = View.GONE
binding.ivWrite.visibility = View.VISIBLE
adapter.changeSelect(false, isRemoveCannotNext = true)
binding.llOperation.visibility = View.GONE
binding.flConfirm.visibility = View.GONE
}
} }
\ No newline at end of file
package com.base.easyfilemanager.activity package com.base.easyfilemanager.activity
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import com.base.easyfilemanager.databinding.ActivityMainBinding import com.base.easyfilemanager.databinding.ActivityMainBinding
import com.base.easyfilemanager.helps.BarUtils
import com.base.easyfilemanager.helps.BaseActivity import com.base.easyfilemanager.helps.BaseActivity
import com.base.easyfilemanager.helps.MediaStoreEx.updateMediaStore import com.base.easyfilemanager.helps.MediaStoreEx.updateMediaStore
...@@ -17,5 +19,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() { ...@@ -17,5 +19,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun initView() { override fun initView() {
updateMediaStore() updateMediaStore()
initStatusBar()
}
private fun initStatusBar() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
} }
} }
\ No newline at end of file
package com.base.easyfilemanager.adapter
import android.annotation.SuppressLint
import android.os.Environment
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.easyfilemanager.R
import com.base.easyfilemanager.bean.FileBean
import com.base.easyfilemanager.bean.FileBean.Companion.isApk
import com.base.easyfilemanager.bean.FileBean.Companion.isAudio
import com.base.easyfilemanager.bean.FileBean.Companion.isDir
import com.base.easyfilemanager.bean.FileBean.Companion.isDocument
import com.base.easyfilemanager.bean.FileBean.Companion.isImage
import com.base.easyfilemanager.bean.FileBean.Companion.isVideo
import com.base.easyfilemanager.bean.FileBean.Companion.isZip
import com.base.easyfilemanager.databinding.ItemFileManagerListBinding
import com.base.easyfilemanager.helps.KotlinExt.toFormatSize
import com.base.easyfilemanager.helps.XmlEx.inflate
import com.bumptech.glide.Glide
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
@SuppressLint("NotifyDataSetChanged")
class FileManagerAdapter(
private val allSelect: (select: Boolean) -> Unit,
private val showEmpty: ((isShow: Boolean) -> Unit)? = null
) : RecyclerView.Adapter<FileManagerAdapter.GGGG>() {
private val TAG = "FileManagerAdapter"
private var showSelect: Boolean = false
private var currentDir = Environment.getExternalStorageDirectory()
private val cannotNextFiles = arrayListOf<File>()
private var canNext: Boolean = true
private val fileList = arrayListOf<FileBean>()
inner class GGGG(view: View) : ViewHolder(view) {
val binding = ItemFileManagerListBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GGGG {
return GGGG(R.layout.item_file_manager_list.inflate(parent))
}
override fun getItemCount(): Int {
return fileList.size
}
override fun onBindViewHolder(holder: GGGG, position: Int) {
}
private fun bindIcon(data: FileBean, iv: ImageView) {
val file = File(data.path)
when {
isDir(file) -> iv.setImageResource(R.mipmap.dir)
isImage(file) or isVideo(file) -> {
Glide.with(iv.context)
.load(data.path)
.centerCrop()
.into(iv)
}
isAudio(file) -> iv.setImageResource(R.mipmap.audio)
isZip(file) -> iv.setImageResource(R.mipmap.zip)
isApk(file) -> iv.setImageResource(R.mipmap.apk)
isDocument(file) -> iv.setImageResource(R.mipmap.file)
else -> iv.setImageResource(R.mipmap.file)
}
}
override fun onBindViewHolder(holder: GGGG, position: Int, payloads: MutableList<Any>) {
val data = fileList[position]
val context = holder.binding.root.context
if (payloads.isEmpty()) {
bindIcon(data, holder.binding.iv)
holder.binding.tvName.text = data.name
val file = File(data.path)
val timeE = SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).format(file.lastModified())
if (file.isFile) {
val sizeF = file.length().toFormatSize()
holder.binding.tvInfo.text = "$timeE $sizeF"
} else {
val count = file.list()?.size ?: 0
holder.binding.tvInfo.text = "$timeE $count items"
}
//================================是否显示选中按钮逻辑==================================
if (showSelect) {
val drawable = ContextCompat.getDrawable(context, R.drawable.bg_selected)
holder.binding.ivSelector.isSelected = data.isSelect
holder.binding.ivSelector.isVisible = true
holder.binding.ivSelector.setImageDrawable(drawable)
holder.binding.ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
holder.binding.ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "sdada")
allSelect.invoke(fileList.all { it.isSelect })
}
} else {
val drawable = ContextCompat.getDrawable(context, R.mipmap.jiantou_b)
holder.binding.ivSelector.setImageDrawable(drawable)
holder.binding.ivSelector.isVisible = file.isDirectory
holder.binding.ivSelector.setOnClickListener { }
}
//============================选中目录无法再进入子目录逻辑==============================
holder.binding.root.setOnClickListener {
if (!cannotNextFiles.contains(file) && file.isDirectory && canNext)
nextPage(file)
}
if (cannotNextFiles.contains(file) && file.isDirectory) {
val color = ContextCompat.getColor(context, R.color.color_6e6e6e)
holder.binding.llItem.setBackgroundColor(color)
} else {
val color = ContextCompat.getColor(context, R.color.white)
holder.binding.llItem.setBackgroundColor(color)
}
} else {
holder.binding.root.setOnClickListener {
holder.binding.ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
private fun nextPage(file: File) {
currentDir = file
val files = currentDir.listFiles()
val data = files?.map { FileBean(it.name, it.path, it.length()) } ?: listOf()
setData(data, isEmpty = { showEmpty?.invoke(it) })
}
fun getCurrentDir(): File {
return currentDir
}
fun notifyCurrentDir() {
val files = currentDir.listFiles()
// files?.sortByDescending { it.lastModified() }
val data = files?.map { FileBean(it.name, it.path, it.length()) } ?: listOf()
setData(data, isEmpty = { showEmpty?.invoke(it) })
}
fun changeSelect(
isSelect: Boolean,
isAddCannotNext: Boolean = false,
isRemoveCannotNext: Boolean = false,
canNext: Boolean = true,
) {
showSelect = isSelect
if (isAddCannotNext) {
cannotNextFiles.addAll(getSelectData().map { File(it.path) })
}
if (isRemoveCannotNext) {
cannotNextFiles.clear()
}
this.canNext = canNext
notifyDataSetChanged()
}
fun getSelectData(): List<FileBean> {
return fileList.filter { it.isSelect }
}
/**
*@param 是否是根目录
*/
fun beforePage(): Boolean {
return if (currentDir.absoluteFile == Environment.getExternalStorageDirectory().absoluteFile) {
true
} else {
currentDir = currentDir.parentFile
val files = currentDir.listFiles()
val data = files?.map { FileBean(it.name, it.path, it.length()) } ?: listOf()
setData(data, isEmpty = { showEmpty?.invoke(it) })
false
}
}
fun setData(data: List<FileBean>, isEmpty: ((flag: Boolean) -> Unit)? = null) {
fileList.clear()
fileList.addAll(data)
notifyDataSetChanged()
isEmpty?.invoke(fileList.isEmpty())
}
fun getOperationList(): ArrayList<File> {
return cannotNextFiles
}
fun toggleSelect(select: Boolean) {
fileList.forEach { fileBean ->
fileBean.isSelect = select
}
notifyDataSetChanged()
}
}
\ No newline at end of file
...@@ -17,23 +17,68 @@ data class FileBean( ...@@ -17,23 +17,68 @@ data class FileBean(
fun isImage() = !isDir && type in listOf("png", "jpg", "gif") fun isImage() = !isDir && type in listOf("png", "jpg", "gif")
fun isVideo() = !isDir && type in listOf("mp4") fun isVideo() = !isDir && type in listOf("mp4")
fun isAudio() = !isDir && type in listOf("mp3") fun isAudio() = !isDir && type in listOf("mp3")
fun isLargeFile() = !isDir && size >= 10 * 1024 * 1024
fun isZip() = !isDir && type in listOf("zip", "tar", "7z") fun isZip() = !isDir && type in listOf("zip", "tar", "7z")
fun isApk() = !isDir && type in listOf("apk") fun isApk() = !isDir && type in listOf("apk")
fun isDoc() = !isDir && type in listOf("pdf", "doc", "docx", "xls", "ppt", "txt")
fun isDocx() = !isDir && type in listOf("docx") companion object {
fun isPdf() = !isDir && type in listOf("pdf") fun isDir(file: File): Boolean {
fun isXls() = !isDir && type in listOf("xls", "xlsx") return file.isDirectory
fun isTxt() = !isDir && type in listOf("txt") }
fun isPpt() = !isDir && type in listOf("ppt")
fun isOther() = !isImage() && !isVideo() && !isAudio() && !isZip() && !isApk() fun isEmptyFile(file: File): Boolean {
fun isJunk() = !isDir && type in listOf("tmp", "cache", "temp") return file.isFile && file.length() == 0L
}
fun isImage(file: File): Boolean {
return file.name.contains(".jpg") or
file.name.contains(".png") or
file.name.contains(".gif")
}
fun isVideo(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 isAudio(file: File): Boolean {
return file.name.contains(".mp3") or
file.name.contains(".aac") or
file.name.contains(".ogg") or
file.name.contains(".m4a") or
file.name.contains(".aac")
}
fun isLargeFile(file: File): Boolean {
return file.length() >= 10 * 1024 * 1024
}
fun isZip(file: File): Boolean {
return file.name.contains(".zip")
}
fun isApk(file: File): Boolean {
return file.name.contains(".apk")
}
fun isDocument(file: File): Boolean {
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")
}
}
} }
\ No newline at end of file
...@@ -10,6 +10,7 @@ import androidx.recyclerview.widget.GridLayoutManager ...@@ -10,6 +10,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
import com.base.easyfilemanager.R import com.base.easyfilemanager.R
import com.base.easyfilemanager.activity.FileCategoryActivity import com.base.easyfilemanager.activity.FileCategoryActivity
import com.base.easyfilemanager.activity.FileManagerActivity
import com.base.easyfilemanager.activity.MainActivity import com.base.easyfilemanager.activity.MainActivity
import com.base.easyfilemanager.adapter.FileCategoryAdapter import com.base.easyfilemanager.adapter.FileCategoryAdapter
import com.base.easyfilemanager.bean.FileCategoryBean import com.base.easyfilemanager.bean.FileCategoryBean
...@@ -76,6 +77,23 @@ class FileCategoryFragment : BaseFragment<FragmentFileCategoryBinding>() { ...@@ -76,6 +77,23 @@ class FileCategoryFragment : BaseFragment<FragmentFileCategoryBinding>() {
binding.rvCategory.adapter = categoryAdapter binding.rvCategory.adapter = categoryAdapter
categoryAdapter.setData(categoryList) categoryAdapter.setData(categoryList)
recentAdapter = FileCategoryAdapter(FileCategoryAdapter.MODE_RECENT, ::itemClick)
binding.rvRecent.adapter = recentAdapter
if (requireContext().checkStorePermission()) {
refreshRecent()
}
val total = totalSize().toFormatSize().split(" ")
binding.tvTotal.text = total[0]
binding.tvTotalUnit.text = total[1]
val used = (totalSize() - availableSize()).toFormatSize().split(" ")
binding.tvUsed.text = used[0]
binding.tvUsedUnit.text = used[1]
}
override fun setListener() {
binding.tvAuthorization.setOnClickListener { binding.tvAuthorization.setOnClickListener {
requireContext().showGerPermission(deny = {}, allow = { requireContext().showGerPermission(deny = {}, allow = {
val launcher = (requireActivity() as MainActivity).launcher val launcher = (requireActivity() as MainActivity).launcher
...@@ -96,21 +114,20 @@ class FileCategoryFragment : BaseFragment<FragmentFileCategoryBinding>() { ...@@ -96,21 +114,20 @@ class FileCategoryFragment : BaseFragment<FragmentFileCategoryBinding>() {
binding.llAll.setOnClickListener { binding.llAll.setOnClickListener {
itemClick(FileCategoryBean.Image) itemClick(FileCategoryBean.Image)
} }
binding.flManager.setOnClickListener {
recentAdapter = FileCategoryAdapter(FileCategoryAdapter.MODE_RECENT, ::itemClick) if (requireContext().checkStorePermission()) {
binding.rvRecent.adapter = recentAdapter startActivity(Intent(requireContext(), FileManagerActivity::class.java))
} else {
if (requireContext().checkStorePermission()) { requireContext().showGerPermission(
refreshRecent() "Our application needs to manager your files Before you authorize, we need to confirm with you:",
deny = {},
allow = {
startActivity(Intent(requireContext(), FileManagerActivity::class.java))
}
)
}
} }
val total = totalSize().toFormatSize().split(" ")
binding.tvTotal.text = total[0]
binding.tvTotalUnit.text = total[1]
val used = (totalSize() - availableSize()).toFormatSize().split(" ")
binding.tvUsed.text = used[0]
binding.tvUsedUnit.text = used[1]
} }
private fun itemClick(key: String) { private fun itemClick(key: String) {
......
package com.base.easyfilemanager.helps package com.base.easyfilemanager.helps
import android.os.Environment
import android.util.Log
import java.io.File import java.io.File
import java.util.LinkedList
import java.util.Stack
class FileHelp {
object FileHelp {
private val TAG = "FileHelp"
fun deleteDirectory(dir: File): Boolean {
val stackFiles = Stack<File>()
stackFiles.push(dir)
while (stackFiles.size > 0) {
val currentFile = stackFiles.peek()
val subFiles = currentFile.listFiles()
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
}
} }
\ No newline at end of file
...@@ -13,6 +13,7 @@ object DialogViews { ...@@ -13,6 +13,7 @@ object DialogViews {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun Context.showGerPermission( fun Context.showGerPermission(
tittle: String? = null,
deny: ((view: Dialog) -> Unit)? = null, deny: ((view: Dialog) -> Unit)? = null,
allow: ((view: Dialog) -> Unit)? = null allow: ((view: Dialog) -> Unit)? = null
): Dialog { ): Dialog {
...@@ -39,6 +40,8 @@ object DialogViews { ...@@ -39,6 +40,8 @@ object DialogViews {
// .create() // .create()
binding.idTvTt.text = binding.idTvTt.text =
"Our application needs to access your files to find media file Before you authorize, we need to confirm with you:" "Our application needs to access your files to find media file Before you authorize, we need to confirm with you:"
tittle?.let { binding.idTvTt.text = it }
binding.idFullLottie.imageAssetsFolder = "permission_finger/images/" binding.idFullLottie.imageAssetsFolder = "permission_finger/images/"
binding.idFullLottie.setAnimation("permission_finger/data.json") binding.idFullLottie.setAnimation("permission_finger/data.json")
binding.idFullLottie.playAnimation() binding.idFullLottie.playAnimation()
......
package com.base.easyfilemanager.view
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.base.easyfilemanager.R
import com.base.easyfilemanager.databinding.DialogFileNewRenameBinding
object SimpleFileDialog {
fun Context.showSimpleFileDialog(
name: String = "",
nameAction: (name: String) -> Unit
): AlertDialog {
val binding = DialogFileNewRenameBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.setCanceledOnTouchOutside(false)
dialog.show()
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_280)
lp?.height = ViewGroup.LayoutParams.WRAP_CONTENT
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
if (name.isNotEmpty()) {
binding.edit.setText(name)
}
binding.tvSure.setOnClickListener {
val text = binding.edit.text.toString()
if (text.isEmpty() or text.isBlank()) {
return@setOnClickListener
}
nameAction.invoke(text)
dialog.dismiss()
}
binding.ivCancel.setOnClickListener {
dialog.dismiss()
}
return dialog
}
}
\ No newline at end of file
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
android:id="@+id/cl_action_bar" android:id="@+id/cl_action_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="60dp"
android:layout_marginTop="36dp"
android:background="@color/white" android:background="@color/white"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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: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=".activity.FileManagerActivity"> android:orientation="vertical">
</androidx.constraintlayout.widget.ConstraintLayout> <FrameLayout
\ No newline at end of file android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="36dp">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="10dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_vertical"
android:src="@mipmap/fanhui"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="INTERNAL STORAGE"
android:textColor="#FF333333"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<FrameLayout
android:id="@+id/fl_all_write"
android:layout_width="65dp"
android:layout_height="match_parent"
android:layout_gravity="end">
<ImageView
android:id="@+id/iv_all"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="20dp"
android:src="@drawable/bg_selected"
android:visibility="gone"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_write"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="20dp"
android:src="@mipmap/sldo_089"
android:visibility="gone"
tools:ignore="ContentDescription" />
</FrameLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:ignore="NestedWeights">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:ignore="NestedWeights" />
<ImageView
android:id="@+id/iv_new_file"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="end|bottom"
android:layout_marginEnd="28dp"
android:layout_marginBottom="50dp"
android:src="@mipmap/dkis_58959"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/ll_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="150dp"
android:orientation="vertical"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="200dp"
android:layout_height="192dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/sda_887965"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:text="The folder is empty"
android:textColor="#FF333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/ll_operation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
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="DisableBaselineAlignment">
<LinearLayout
android:id="@+id/ll_move"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables,UselessParent">
<ImageView
android:id="@+id/iv_move"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/sfad_6959"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="4dp"
android:text="Move"
android:textColor="#FF333333"
android:textSize="12sp"
tools:ignore="HardcodedText,SmallSp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_copy"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables,UselessParent">
<ImageView
android:id="@+id/iv_copy"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/wsd_69859"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="4dp"
android:text="Copy"
android:textColor="#FF333333"
android:textSize="12sp"
tools:ignore="HardcodedText,SmallSp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_delete"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables,UselessParent">
<ImageView
android:id="@+id/iv_delete"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/delete"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="4dp"
android:text="Delete"
android:textColor="#FF333333"
android:textSize="12sp"
tools:ignore="HardcodedText,SmallSp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_rename"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables,UselessParent">
<ImageView
android:id="@+id/iv_rename"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/rename"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="4dp"
android:text="Rename"
android:textColor="#FF333333"
android:textSize="12sp"
tools:ignore="HardcodedText,SmallSp" />
</LinearLayout>
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/fl_confirm"
android:layout_width="match_parent"
android:layout_height="75dp"
android:visibility="gone">
<com.noober.background.view.BLTextView
android:id="@+id/tv_cancel"
android:layout_width="140dp"
android:layout_height="40dp"
android:gravity="center"
android:text="Cancel"
android:textColor="#FF999999"
android:textSize="17sp"
android:textStyle="bold"
app:bl_corners_radius="8dp"
app:bl_solid_color="#FFF5F5F5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_confirm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_confirm"
android:layout_width="140dp"
android:layout_height="40dp"
android:gravity="center"
android:text="Motion"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold"
app:bl_corners_radius="8dp"
app:bl_solid_color="@color/theme_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_cancel"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</LinearLayout>
\ 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="270dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardCornerRadius="12dp">
<ImageView
android:id="@+id/iv_cancel"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end"
android:layout_margin="5dp"
android:src="@mipmap/sok_298"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="New Folder"
android:textColor="#FF333333"
android:textSize="17sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="25dp"
android:layout_marginTop="40dp"
android:backgroundTint="#FFF5F5F5"
android:gravity="center_horizontal"
android:hint="Please enter a new name"
android:importantForAutofill="no"
android:singleLine="true"
android:textColor="#FF333333"
android:textSize="14sp"
tools:ignore="HardcodedText,TextFields" />
<com.noober.background.view.BLTextView
android:id="@+id/tv_sure"
android:layout_width="230dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="20dp"
android:gravity="center"
android:text="Sure"
android:textColor="#FFFFFFFF"
android:textSize="17sp"
app:bl_corners_radius="8dp"
app:bl_solid_color="#FF333333"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<FrameLayout <FrameLayout
android:id="@+id/fl_yuan" android:id="@+id/fl_manager"
android:layout_width="146dp" android:layout_width="146dp"
android:layout_height="146dp" android:layout_height="146dp"
android:layout_margin="20dp" android:layout_margin="20dp"
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<TextView <TextView
android:id="@+id/tv_manager"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
...@@ -61,7 +60,7 @@ ...@@ -61,7 +60,7 @@
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@id/ll_used" app:layout_constraintBottom_toTopOf="@id/ll_used"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/fl_yuan" app:layout_constraintStart_toEndOf="@id/fl_manager"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<LinearLayout <LinearLayout
...@@ -117,7 +116,7 @@ ...@@ -117,7 +116,7 @@
android:orientation="vertical" android:orientation="vertical"
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/fl_yuan" app:layout_constraintStart_toEndOf="@id/fl_manager"
app:layout_constraintTop_toBottomOf="@id/ll_total"> app:layout_constraintTop_toBottomOf="@id/ll_total">
<LinearLayout <LinearLayout
...@@ -242,7 +241,7 @@ ...@@ -242,7 +241,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:src="@mipmap/jianotu" android:src="@mipmap/jiantou_s"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
</LinearLayout> </LinearLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="12dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="Image"
android:textColor="#FF333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="January 5, 2024 2 itmes"
android:textColor="#FF999999"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:src="@drawable/bg_selected"
tools:ignore="ContentDescription" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="40dp"
android:layout_marginTop="13dp"
android:background="#FFF4F4F4" />
</LinearLayout>
\ No newline at end of file
...@@ -4,4 +4,5 @@ ...@@ -4,4 +4,5 @@
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="theme_color">#8F5CE4</color> <color name="theme_color">#8F5CE4</color>
<color name="color_f04949">#f04949</color> <color name="color_f04949">#f04949</color>
<color name="color_6e6e6e">#6e6e6e</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_310">310dp</dimen> <dimen name="dp_310">310dp</dimen>
<dimen name="dp_280">280dp</dimen>
</resources> </resources>
\ No newline at end of file
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