Commit bf2a6d39 authored by wanglei's avatar wanglei

Initial commit

parent 90804b8b
...@@ -48,6 +48,8 @@ dependencies { ...@@ -48,6 +48,8 @@ dependencies {
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.coil) implementation(libs.coil)
implementation(libs.coil.video)
implementation(libs.coil.gif)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
......
...@@ -19,10 +19,14 @@ ...@@ -19,10 +19,14 @@
android:theme="@style/Theme.SolarMasterAce" android:theme="@style/Theme.SolarMasterAce"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".filebrowser.FileBrowserActivity" android:name=".internalstorage.InternalStorageActivity"
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".dupfile.DupImageActivity" android:name=".filedetails.FileDetailActivity"
android:exported="false"
android:launchMode="singleTop" />
<activity
android:name=".filebrowser.FileBrowserActivity"
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
......
...@@ -5,4 +5,11 @@ import com.zxhy.solarmasterace.data.FileBean ...@@ -5,4 +5,11 @@ import com.zxhy.solarmasterace.data.FileBean
interface AdapterCommonDataFunction { interface AdapterCommonDataFunction {
abstract fun setData(data: List<FileBean>) abstract fun setData(data: List<FileBean>)
abstract fun addData(data: List<FileBean>)
abstract fun addDataFinish(data: List<FileBean>)
abstract fun clearData()
abstract fun removeData(data: List<FileBean>)
abstract fun getSelectData(): List<FileBean>
abstract fun toggleSelect(select: Boolean)
} }
\ No newline at end of file
package com.zxhy.solarmasterace.adapter
import android.annotation.SuppressLint
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.zxhy.solarmasterace.data.FileBean
abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(),
AdapterCommonDataFunction {
protected val fileList = arrayListOf<FileBean>()
private var firstRefresh = true
@SuppressLint("NotifyDataSetChanged")
override fun setData(data: List<FileBean>) {
fileList.clear()
fileList.addAll(data)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
override fun addData(data: List<FileBean>) {
fileList.addAll(data)
if (firstRefresh) {
notifyDataSetChanged()
firstRefresh = false
}
}
@SuppressLint("NotifyDataSetChanged")
override fun addDataFinish(data: List<FileBean>) {
fileList.addAll(data)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
override fun clearData() {
if (fileList.size == 0) return
fileList.clear()
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
override fun removeData(data: List<FileBean>) {
data.forEach {
val index = fileList.indexOf(it)
if (index != -1) {
fileList.removeAt(index)
notifyItemRemoved(index)
}
}
}
override fun getSelectData(): List<FileBean> {
return fileList.filter { it.isSelect }
}
override fun getItemCount(): Int {
return fileList.size
}
@SuppressLint("NotifyDataSetChanged")
override fun toggleSelect(select: Boolean) {
fileList.mapIndexed { index, fileBean ->
if (fileBean.isSelect != select) {
fileBean.isSelect = select
notifyItemChanged(index, "单条刷新")
}
}
}
}
\ No newline at end of file
...@@ -2,8 +2,28 @@ package com.zxhy.solarmasterace.adapter ...@@ -2,8 +2,28 @@ package com.zxhy.solarmasterace.adapter
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.zxhy.solarmasterace.databinding.ItemCardDupImageBinding
import com.zxhy.solarmasterace.databinding.ItemCardImage85Binding import com.zxhy.solarmasterace.databinding.ItemCardImage85Binding
import com.zxhy.solarmasterace.databinding.ItemCardImageSelector100Binding
import com.zxhy.solarmasterace.databinding.ItemCardImageSelector85Binding
import com.zxhy.solarmasterace.databinding.ItemCardLargeFileBinding
class ItemImage85ViewHolder(view: View) : RecyclerView.ViewHolder(view) { class ItemCardImage85ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemCardImage85Binding.bind(view) val binding = ItemCardImage85Binding.bind(view)
} }
\ No newline at end of file
class ItemCardImageSelect85ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemCardImageSelector85Binding.bind(view)
}
class ItemCardImageSelect100ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemCardImageSelector100Binding.bind(view)
}
class ItemCardDupImageViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemCardDupImageBinding.bind(view)
}
class ItemCardLargeFileViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemCardLargeFileBinding.bind(view)
}
package com.zxhy.solarmasterace.data
data class DupFileBean(
val md5: String = "",
var dupData: List<FileBean> = listOf(),
var isSelect: Boolean = false
)
package com.zxhy.solarmasterace.data package com.zxhy.solarmasterace.data
import android.content.Context
import android.net.Uri import android.net.Uri
import android.text.format.Formatter
import android.widget.ImageView
import coil.load
import com.zxhy.solarmasterace.R import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.quicktools.ColiVideoEx
import java.io.File import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
data class FileBean( data class FileBean(
val id: Long = 0L,
val name: String = "", val name: String = "",
val path: String = "", val path: String = "",
val uri: Uri = Uri.EMPTY, val uri: Uri = Uri.EMPTY,
...@@ -38,7 +46,7 @@ data class FileBean( ...@@ -38,7 +46,7 @@ data class FileBean(
} }
fun isAudio(): Boolean { fun isAudio(): Boolean {
return name.contains(".mp3") or name.contains(".avi") return name.contains(".mp3") or name.contains(".wave") or name.contains(".ogg")
} }
fun isApk(): Boolean { fun isApk(): Boolean {
...@@ -78,4 +86,96 @@ data class FileBean( ...@@ -78,4 +86,96 @@ data class FileBean(
fun isDocument(): Boolean { fun isDocument(): Boolean {
return isWord() or isExcel() or isPPt() or isPdf() or isTxt() return isWord() or isExcel() or isPPt() or isPdf() or isTxt()
} }
fun sizeFormat(context: Context): String? {
return Formatter.formatFileSize(context, size)
}
fun bindIconImage(image: ImageView) {
if (isImage()) {
image.load(file())
} else if (isVideo()) {
image.load(file(), ColiVideoEx.videoLoader(image.context))
} else if (isAudio()) {
image.setImageResource(R.mipmap.fasd_87985)
} else if (isApk()) {
image.setImageResource(R.mipmap.faad_8795)
} else if (isZip()) {
image.setImageResource(R.mipmap.fas_87895)
} else if (isLogFile()) {
image.setImageResource(R.mipmap.fzzx_65987)
} else if (isWord()) {
image.setImageResource(R.mipmap.wrf_58997)
} else if (isExcel()) {
image.setImageResource(R.mipmap.ex_289897)
} else if (isPPt()) {
image.setImageResource(R.mipmap.fas_87895)
} else if (isPdf()) {
image.setImageResource(R.mipmap.zc_8979855556)
} else if (isTxt()) {
image.setImageResource(R.mipmap.fdg_87985)
} else {
image.setImageResource(R.mipmap.ff_0985)
}
}
}
fun File.isImage(): Boolean {
return name.contains(".jpg") or name.contains(".png") or name.contains(".gif")
}
fun File.isVideo(): Boolean {
return name.contains(".mp4") or name.contains(".avi")
}
fun File.isAudio(): Boolean {
return name.contains(".mp3") or name.contains(".wave") or name.contains(".ogg")
}
fun File.isApk(): Boolean {
return name.contains(".apk")
}
fun File.isZip(): Boolean {
return name.contains(".zip") or name.contains(".rar")
}
fun File.isLogFile(): Boolean {
return name.contains("log") or name.contains("Log")
}
fun File.isWord(): Boolean {
return name.contains(".doc") or name.contains(".docx")
}
fun File.isExcel(): Boolean {
return name.contains(".xls") or name.contains(".xlsx")
}
fun File.isPPt(): Boolean {
return name.contains(".ppt") or name.contains(".pptx")
}
fun File.isPdf(): Boolean {
return name.contains(".pdf")
} }
fun File.isTxt(): Boolean {
return name.contains(".txt")
}
fun File.isDocument(): Boolean {
return isWord() or isExcel() or isPPt() or isPdf() or isTxt()
}
fun File.toFileBean(): FileBean {
val timeE = SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).format(lastModified())
return FileBean(
name = name,
path = absolutePath,
size = length(),
time = timeE
)
}
package com.zxhy.solarmasterace.filebrowser
import android.view.ViewGroup
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.adapter.CommonAdapter
import com.zxhy.solarmasterace.adapter.ItemCardLargeFileViewHolder
import com.zxhy.solarmasterace.quicktools.inflate
class CardFileAdapter(
private val selectClick: (flag: Boolean) -> Unit
) : CommonAdapter<ItemCardLargeFileViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemCardLargeFileViewHolder {
return ItemCardLargeFileViewHolder(R.layout.item_card_large_file.inflate(parent))
}
override fun onBindViewHolder(holder: ItemCardLargeFileViewHolder, position: Int) {
}
override fun onBindViewHolder(
holder: ItemCardLargeFileViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val data = fileList[position]
val context = holder.binding.root.context
if (payloads.isEmpty()) {
holder.binding.apply {
data.bindIconImage(ivIcon)
tvName.text = data.name
tvSize.text = data.sizeFormat(context)
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
notifyItemChanged(position, "单条刷新")
val flag = fileList.all { it.isSelect }
selectClick.invoke(flag)
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.filebrowser
import android.annotation.SuppressLint
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.adapter.CommonAdapter
import com.zxhy.solarmasterace.adapter.ItemCardDupImageViewHolder
import com.zxhy.solarmasterace.adapter.ItemCardImageSelect85ViewHolder
import com.zxhy.solarmasterace.data.DupFileBean
import com.zxhy.solarmasterace.quicktools.inflate
import java.io.File
class DupImageAdapter(
private val selectClick: (flag: Boolean) -> Unit
) : RecyclerView.Adapter<ItemCardDupImageViewHolder>() {
private val dupFileList = arrayListOf<DupFileBean>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemCardDupImageViewHolder {
return ItemCardDupImageViewHolder(R.layout.item_card_dup_image.inflate(parent))
}
override fun getItemCount(): Int {
return dupFileList.size
}
override fun onBindViewHolder(holder: ItemCardDupImageViewHolder, position: Int) {
// val data = dupFileList[position]
// holder.binding.apply {
// val adapter = ImageAdapter()
// rv.adapter = adapter
// adapter.setData(data.dupData)
// iv.isSelected = data.isSelect
// iv.setOnClickListener {
// data.isSelect = !data.isSelect
// notifyItemChanged(position, "单条刷新")
// }
// }
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(
holder: ItemCardDupImageViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val data = dupFileList[position]
if (payloads.isEmpty()) {
holder.binding.apply {
tvTip.text = "${data.dupData.size} items"
val adapter = ImageAdapter {
ivSelector.isSelected = it
data.isSelect = it
val flag = dupFileList.all { dupFileBean -> dupFileBean.isSelect }
selectClick.invoke(flag)
}
rv.adapter = adapter
adapter.setData(data.dupData)
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !it.isSelected
notifyItemChanged(position, "单条刷新")
val flag = dupFileList.all { dupFileBean -> dupFileBean.isSelect }
selectClick.invoke(flag)
adapter.toggleSelect(data.isSelect)
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
@SuppressLint("NotifyDataSetChanged")
fun setData(data: List<DupFileBean>) {
dupFileList.clear()
dupFileList.addAll(data)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun toggleSelect(select: Boolean) {
dupFileList.map {
it.isSelect = select
it.dupData.map { fileBean -> fileBean.isSelect = select }
}
notifyDataSetChanged()
}
fun getSelectFile(): ArrayList<File> {
val fileList = arrayListOf<File>()
dupFileList.map {
it.dupData.map { fileBean ->
if (it.isSelect) {
fileList.add(File(fileBean.path))
}
}
}
return fileList
}
private inner class ImageAdapter(
val selectClick: (flag: Boolean) -> Unit
) : CommonAdapter<ItemCardImageSelect85ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ItemCardImageSelect85ViewHolder {
return ItemCardImageSelect85ViewHolder(
R.layout.item_card_image_selector_85.inflate(parent)
)
}
override fun onBindViewHolder(holder: ItemCardImageSelect85ViewHolder, position: Int) {}
override fun onBindViewHolder(
holder: ItemCardImageSelect85ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val data = fileList[position]
if (payloads.isEmpty()) {
holder.binding.apply {
iv.load(data.path)
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
notifyItemChanged(position, "单条刷新")
val flag = fileList.all { it.isSelect }
selectClick.invoke(flag)
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
}
super.onBindViewHolder(holder, position, payloads)
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.filebrowser package com.zxhy.solarmasterace.filebrowser
import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.view.View
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
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 androidx.recyclerview.widget.GridLayoutManager
import com.zxhy.solarmasterace.R import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.databinding.ActivityFileBrowserBinding import com.zxhy.solarmasterace.databinding.ActivityFileBrowserBinding
import com.zxhy.solarmasterace.quicktools.apkFile
import com.zxhy.solarmasterace.quicktools.audioFile
import com.zxhy.solarmasterace.quicktools.deleteFiles
import com.zxhy.solarmasterace.quicktools.documentFile
import com.zxhy.solarmasterace.quicktools.dupImage
import com.zxhy.solarmasterace.quicktools.emptyFile
import com.zxhy.solarmasterace.quicktools.excelFile
import com.zxhy.solarmasterace.quicktools.imageFile
import com.zxhy.solarmasterace.quicktools.largeFile
import com.zxhy.solarmasterace.quicktools.logFile
import com.zxhy.solarmasterace.quicktools.pdfFile
import com.zxhy.solarmasterace.quicktools.pptFile
import com.zxhy.solarmasterace.quicktools.txtFile
import com.zxhy.solarmasterace.quicktools.videoFile
import com.zxhy.solarmasterace.quicktools.wordFile
import com.zxhy.solarmasterace.quicktools.zipFile
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
class FileBrowserActivity : AppCompatActivity() { class FileBrowserActivity : AppCompatActivity() {
private lateinit var binding: ActivityFileBrowserBinding private lateinit var binding: ActivityFileBrowserBinding
private var title: String = "title"
private lateinit var dupImageAdapter: DupImageAdapter
private lateinit var cardFileAdapter: CardFileAdapter
private lateinit var fileGridAdapter: FileGridAdapter
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
...@@ -19,7 +49,490 @@ class FileBrowserActivity : AppCompatActivity() { ...@@ -19,7 +49,490 @@ class FileBrowserActivity : AppCompatActivity() {
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets insets
}
title = intent.extras?.getString("tittle") ?: ""
binding.tvTittle.text = title
binding.clArrow.setOnClickListener {
finish()
}
when (title) {
"Duplicate picture" -> dupImageMode()
"Scan large files" -> largeFileMode()
"Scan empty file" -> emptyFileMode()
"Image" -> imageMode()
"Video" -> videoMode()
"Audio" -> audioMode()
"Apk" -> apkMode()
"Zip" -> zipMode()
"Log file" -> logFileMode()
"Word" -> wordMode()
"Excel" -> excelMode()
"PPT" -> pptMode()
"PDF" -> pdfMode()
"TXT" -> txtMode()
"Documents" -> documentMode()
}
}
private fun documentMode() {
cardUi()
loadDocumentFile()
}
private fun loadDocumentFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
documentFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun txtMode() {
cardUi()
loadTxtFile()
}
private fun loadTxtFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
txtFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun pdfMode() {
cardUi()
loadPdfFile()
}
private fun loadPdfFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
pdfFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun pptMode() {
cardUi()
loadPptFile()
}
@SuppressLint("SetTextI18n")
private fun loadPptFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
pptFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
fun gridUi() {
binding.tvTip1.visibility = View.VISIBLE
binding.tvTip2.visibility = View.GONE
fileGridAdapter = FileGridAdapter {
binding.ivAll.isSelected = it
}
binding.ivAll.setOnClickListener {
it.isSelected = !it.isSelected
fileGridAdapter.toggleSelect(it.isSelected)
}
binding.rv.visibility = View.INVISIBLE
binding.rvWarp.visibility = View.VISIBLE
binding.rvWarp.layoutManager = GridLayoutManager(this, 3)
binding.rvWarp.adapter = fileGridAdapter
binding.tvDelete.background =
ContextCompat.getDrawable(this, R.drawable.bg_ff5c67e5_corners)
binding.tvDelete.text = "删除"
binding.tvDelete.setTextColor(ContextCompat.getColor(this, R.color.white))
binding.tvDelete.setOnClickListener {
deleteGridUiFile(fileGridAdapter.getSelectData())
}
}
fun cardUi() {
binding.tvTip1.visibility = View.VISIBLE
binding.tvTip2.visibility = View.INVISIBLE
cardFileAdapter = CardFileAdapter {
binding.ivAll.isSelected = it
}
binding.rv.adapter = cardFileAdapter
binding.ivAll.setOnClickListener {
it.isSelected = !it.isSelected
cardFileAdapter.toggleSelect(it.isSelected)
}
binding.tvDelete.background =
ContextCompat.getDrawable(this, R.drawable.bg_ff5c67e5_corners)
binding.tvDelete.text = "删除"
binding.tvDelete.setTextColor(ContextCompat.getColor(this, R.color.white))
binding.tvDelete.setOnClickListener {
deleteCardFile(cardFileAdapter.getSelectData())
}
}
private fun excelMode() {
cardUi()
loadExcelFile()
}
@SuppressLint("SetTextI18n")
private fun loadExcelFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
excelFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun wordMode() {
cardUi()
loadWordFile()
}
private fun logFileMode() {
cardUi()
loadLogFile()
}
private fun zipMode() {
cardUi()
loadZipFile()
}
private fun apkMode() {
cardUi()
loadApkFile()
}
private fun audioMode() {
cardUi()
loadAudioFile()
}
private fun videoMode() {
gridUi()
loadVideoFile()
}
private fun imageMode() {
cardUi()
loadImageFile()
}
@SuppressLint("SetTextI18n")
private fun loadWordFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
wordFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadImageFile() {
fileGridAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
imageFile(
onDo = { data ->
launch(Dispatchers.Main) {
fileGridAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
fileGridAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadVideoFile() {
fileGridAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
videoFile(
onDo = { data ->
launch(Dispatchers.Main) {
fileGridAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
fileGridAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun largeFileMode() {
binding.tvTip1.visibility = View.VISIBLE
binding.tvTip2.visibility = View.VISIBLE
cardFileAdapter = CardFileAdapter {
binding.ivAll.isSelected = it
} }
binding.rv.adapter = cardFileAdapter
binding.ivAll.setOnClickListener {
it.isSelected = !it.isSelected
cardFileAdapter.toggleSelect(it.isSelected)
}
binding.tvDelete.background =
ContextCompat.getDrawable(this, R.drawable.bg_ff5c67e5_corners)
binding.tvDelete.text = "删除"
binding.tvDelete.setTextColor(ContextCompat.getColor(this, R.color.white))
binding.tvDelete.setOnClickListener {
deleteCardFile(cardFileAdapter.getSelectData())
}
loadLargeFile()
}
private fun deleteCardFile(files: List<FileBean>) = lifecycleScope.launch(Dispatchers.Main) {
asyDeleteFiles(files).await()
cardFileAdapter.removeData(files)
binding.ivAll.isSelected = false
cardFileAdapter.toggleSelect(false)
} }
private fun deleteGridUiFile(files: List<FileBean>) = lifecycleScope.launch(Dispatchers.Main) {
asyDeleteFiles(files).await()
fileGridAdapter.removeData(files)
binding.ivAll.isSelected = false
fileGridAdapter.toggleSelect(false)
}
private fun asyDeleteFiles(files: List<FileBean>) = lifecycleScope.async(Dispatchers.IO) {
deleteFiles(files.map { it.file() })
}
@SuppressLint("SetTextI18n")
private fun loadLargeFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
largeFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadAudioFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
audioFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadApkFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
apkFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadZipFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
zipFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadLogFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
logFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun emptyFileMode() {
cardUi()
loadEmptyFile()
}
@SuppressLint("SetTextI18n")
private fun loadEmptyFile() {
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
emptyFile(
onDo = { data ->
launch(Dispatchers.Main) {
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
}
}
)
}
}
private fun dupImageMode() {
binding.tvTip1.visibility = View.GONE
binding.tvTip2.visibility = View.GONE
binding.llAll.setOnClickListener {
it.isSelected = !it.isSelected
dupImageAdapter.toggleSelect(it.isSelected)
}
dupImageAdapter = DupImageAdapter {
binding.ivAll.isSelected = it
}
binding.rv.adapter = dupImageAdapter
binding.tvDelete.background =
ContextCompat.getDrawable(this, R.drawable.bg_ff5c67e5_corners)
binding.tvDelete.text = "删除"
binding.tvDelete.setTextColor(ContextCompat.getColor(this, R.color.white))
binding.tvDelete.setOnClickListener {
val files = dupImageAdapter.getSelectFile()
lifecycleScope.launch(Dispatchers.IO) {
deleteFiles(files)
loadDupImage()
}
}
loadDupImage()
}
private fun loadDupImage() {
lifecycleScope.launch(Dispatchers.IO) {
val data = dupImage()
launch(Dispatchers.Main) {
dupImageAdapter.setData(data)
binding.ivAll.isSelected = false
}
}
}
} }
\ No newline at end of file
package com.zxhy.solarmasterace.filebrowser
import android.view.View
import android.view.ViewGroup
import coil.load
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.adapter.CommonAdapter
import com.zxhy.solarmasterace.adapter.ItemCardImageSelect100ViewHolder
import com.zxhy.solarmasterace.quicktools.ColiVideoEx
import com.zxhy.solarmasterace.quicktools.inflate
class FileGridAdapter(
private val selectClick: (flag: Boolean) -> Unit
) : CommonAdapter<ItemCardImageSelect100ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ItemCardImageSelect100ViewHolder {
return ItemCardImageSelect100ViewHolder(R.layout.item_card_image_selector_100.inflate(parent))
}
override fun onBindViewHolder(holder: ItemCardImageSelect100ViewHolder, position: Int) {
}
override fun onBindViewHolder(
holder: ItemCardImageSelect100ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val data = fileList[position]
val context = holder.binding.root.context
if (payloads.isEmpty()) {
holder.binding.apply {
if (data.isImage()) {
iv.load(data.file())
ivCamera.visibility = View.GONE
} else if (data.isVideo()) {
iv.load(data.file(), ColiVideoEx.videoLoader(context))
ivCamera.visibility = View.VISIBLE
}
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
notifyItemChanged(position, "单条刷新")
val flag = fileList.all { it.isSelect }
selectClick.invoke(flag)
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.filedetails
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.solarmasterace.R
import com.zxhy.solarmasterace.databinding.ActivityFileDetailBinding
class FileDetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityFileDetailBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityFileDetailBinding.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
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.internalstorage
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.solarmasterace.R
import com.zxhy.solarmasterace.databinding.ActivityInternalStorageBinding
class InternalStorageActivity : AppCompatActivity() {
private lateinit var binding: ActivityInternalStorageBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityInternalStorageBinding.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
}
}
}
\ No newline at end of file
...@@ -8,12 +8,14 @@ import android.view.LayoutInflater ...@@ -8,12 +8,14 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.navigation.fragment.findNavController
import com.zxhy.solarmasterace.R import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.databinding.FragmentManagerBinding import com.zxhy.solarmasterace.databinding.FragmentManagerBinding
import com.zxhy.solarmasterace.quicktools.getMountInfoList import com.zxhy.solarmasterace.quicktools.getMountInfoList
import java.math.BigDecimal import java.math.BigDecimal
class ManagerFragment : Fragment() { class ManagerFragment : Fragment() {
private lateinit var binding: FragmentManagerBinding private lateinit var binding: FragmentManagerBinding
private lateinit var context: Context private lateinit var context: Context
...@@ -52,7 +54,7 @@ class ManagerFragment : Fragment() { ...@@ -52,7 +54,7 @@ class ManagerFragment : Fragment() {
categoryMode() categoryMode()
} }
fun categoryMode() { private fun categoryMode() {
binding.apply { binding.apply {
val txtColo1 = ContextCompat.getColor(context, R.color.white) val txtColo1 = ContextCompat.getColor(context, R.color.white)
val txtColo2 = ContextCompat.getColor(context, R.color.color_FF5C67E5) val txtColo2 = ContextCompat.getColor(context, R.color.color_FF5C67E5)
...@@ -70,12 +72,38 @@ class ManagerFragment : Fragment() { ...@@ -70,12 +72,38 @@ class ManagerFragment : Fragment() {
clFile.visibility = View.VISIBLE clFile.visibility = View.VISIBLE
clDocuments.visibility = View.GONE clDocuments.visibility = View.GONE
llImage.setOnClickListener {
nav("Image")
}
llVideo.setOnClickListener {
nav("Video")
}
llAudio.setOnClickListener {
nav("Audio")
}
llApk.setOnClickListener {
nav("Apk")
}
llZip.setOnClickListener {
nav("Zip")
}
llLogFile.setOnClickListener {
nav("Log file")
}
} }
} }
fun documentsMode() { private fun nav(tittle: String) {
val bundle = Bundle().apply {
putString("tittle", tittle)
}
findNavController().navigate(R.id.fileBrowserActivity, bundle)
}
private fun documentsMode() {
binding.apply { binding.apply {
val txtColo1 = ContextCompat.getColor(context, R.color.white) val txtColo1 = ContextCompat.getColor(context, R.color.white)
val txtColo2 = ContextCompat.getColor(context, R.color.color_FF5C67E5) val txtColo2 = ContextCompat.getColor(context, R.color.color_FF5C67E5)
...@@ -93,6 +121,25 @@ class ManagerFragment : Fragment() { ...@@ -93,6 +121,25 @@ class ManagerFragment : Fragment() {
clFile.visibility = View.GONE clFile.visibility = View.GONE
clDocuments.visibility = View.VISIBLE clDocuments.visibility = View.VISIBLE
llWord.setOnClickListener {
nav("Word")
}
llExcel.setOnClickListener {
nav("Excel")
}
llPpt.setOnClickListener {
nav("PPT")
}
llPdf.setOnClickListener {
nav("PDF")
}
llTxt.setOnClickListener {
nav("TXT")
}
llAllDoc.setOnClickListener {
nav("Documents")
}
} }
} }
......
package com.zxhy.solarmasterace.quicktools
import android.content.Context
import coil.ImageLoader
import coil.decode.VideoFrameDecoder
object ColiVideoEx {
fun videoLoader(context: Context): ImageLoader {
val imageLoader = ImageLoader.Builder(context)
.components {
add(VideoFrameDecoder.Factory())
}.build()
return imageLoader
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.quicktools
import android.os.Environment
import com.zxhy.solarmasterace.data.DupFileBean
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.data.isApk
import com.zxhy.solarmasterace.data.isAudio
import com.zxhy.solarmasterace.data.isDocument
import com.zxhy.solarmasterace.data.isExcel
import com.zxhy.solarmasterace.data.isImage
import com.zxhy.solarmasterace.data.isLogFile
import com.zxhy.solarmasterace.data.isPPt
import com.zxhy.solarmasterace.data.isPdf
import com.zxhy.solarmasterace.data.isTxt
import com.zxhy.solarmasterace.data.isVideo
import com.zxhy.solarmasterace.data.isWord
import com.zxhy.solarmasterace.data.isZip
import com.zxhy.solarmasterace.data.toFileBean
import java.io.File
import java.util.Stack
fun dupImage(): List<DupFileBean> {
val rootDir = Environment.getExternalStorageDirectory()
val list = FileHelper.recursiveTraverseFolder(rootDir)
val dupMap = HashMap<String, ArrayList<File>>()
list.map {
if (it.isImage()) {
val md5 = it.digestMd5().byteArrayToHexString()
val dupList = dupMap[md5]
if (dupList == null) {
val newList = arrayListOf<File>()
dupMap[md5] = newList
newList.add(it)
} else {
dupList.add(it)
}
}
}
val dupList = dupMap.filter { it.value.size > 1 }
.map { map ->
DupFileBean(
md5 = map.key,
dupData = map.value.map { file ->
FileBean(
name = file.name,
path = file.absolutePath
)
}
)
}
return dupList
}
fun largeFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.length() > 10 * 1024 * 1024) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun audioFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isAudio()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun apkFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isApk()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun zipFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isZip()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun logFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isLogFile()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun documentFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isDocument()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun txtFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isTxt()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun pdfFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isPdf()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun pptFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isPPt()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun excelFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isExcel()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun wordFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isWord()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun emptyFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.length() == 0L) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun imageFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isImage()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun videoFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isVideo()) {
tempList.add(it.toFileBean())
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
tempList.clear()
}
}
}
onFinish?.invoke(tempList, count)
}
fun deleteFiles(files: List<File>) {
try {
files.map {
if (it.exists()) it.delete()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
//删除文件夹
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
package com.zxhy.solarmasterace.quicktools
import android.os.Environment
import android.util.Log
import java.io.File
import java.util.LinkedList
object FileHelper {
//key:directory path
//value:directory sublist
private val fileMap = HashMap<String, Array<File>?>()
//递归遍历
//只返回文件,不返回目录
//递归返回是所有递归执行完后返回的,所以该方法没意义了
fun recursiveTraverseFolder(
folder: File,
onDo: ((file: File) -> Unit)? = null
): ArrayList<File> {
val fileList = arrayListOf<File>()
folder.listFiles()?.forEach {
if (it.isDirectory) {
fileList.addAll(recursiveTraverseFolder(it) { file -> onDo?.invoke(file) })
} else {
fileList.add(it)
onDo?.invoke(it)
}
}
return fileList
}
//LinkedLis方式遍历
fun linkedLisTraverseFolder(folder: File, onDo: ((file: File) -> Unit)?) {
//添加第一层文件到链表
val linkList = LinkedList<File>()
val fileList = folder.listFiles()
fileList?.forEach {
if (it.isDirectory) {
linkList.add(it)
}else{
onDo?.invoke(it)
}
}
//链表取文件
var tempFile: File
while (!linkList.isEmpty()) {
tempFile = linkList.removeFirst()
val tempFileList = tempFile.listFiles()
tempFileList?.forEach {
if (it.isDirectory) {
linkList.add(it)
} else {
onDo?.invoke(it)
}
}
}
}
fun traverseFolderMap(folder: File) {
folder.listFiles()?.forEach {
if (it.isDirectory) {
fileMap[it.absolutePath] = it.listFiles()
traverseFolderMap(it)
}
}
}
private fun iniFileMap() {
val rootDir = Environment.getExternalStorageDirectory()
traverseFolderMap(rootDir)
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.quicktools
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
//根据加密类型获取具体的值
fun File.digestMd5(): ByteArray {
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.solarmasterace.tools package com.zxhy.solarmasterace.tools
import android.annotation.SuppressLint
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.Adapter
import coil.load import coil.load
import coil.transform.CircleCropTransformation
import coil.transform.RoundedCornersTransformation import coil.transform.RoundedCornersTransformation
import coil.transform.Transformation
import com.zxhy.solarmasterace.R import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.adapter.AdapterCommonDataFunction import com.zxhy.solarmasterace.adapter.CommonAdapter
import com.zxhy.solarmasterace.adapter.ItemImage85ViewHolder import com.zxhy.solarmasterace.adapter.ItemCardImage85ViewHolder
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.quicktools.inflate import com.zxhy.solarmasterace.quicktools.inflate
class RecentImageAdapter() : Adapter<ItemImage85ViewHolder>(), AdapterCommonDataFunction { class RecentImageAdapter() : CommonAdapter<ItemCardImage85ViewHolder>() {
private val fileList = arrayListOf<FileBean>() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemCardImage85ViewHolder {
return ItemCardImage85ViewHolder(R.layout.item_card_image_85.inflate(parent))
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemImage85ViewHolder {
return ItemImage85ViewHolder(R.layout.item_card_image_85.inflate(parent))
}
override fun getItemCount(): Int {
return fileList.size
} }
override fun onBindViewHolder(holder: ItemImage85ViewHolder, position: Int) { override fun onBindViewHolder(holder: ItemCardImage85ViewHolder, position: Int) {
val data = fileList[position] val data = fileList[position]
holder.binding.apply { holder.binding.apply {
iv.load(data.uri) { iv.load(data.uri) {
transformations(RoundedCornersTransformation()) transformations(RoundedCornersTransformation())
} }
} }
}
@SuppressLint("NotifyDataSetChanged")
override fun setData(data: List<FileBean>) {
fileList.clear()
fileList.addAll(data)
notifyDataSetChanged()
} }
} }
\ No newline at end of file
package com.zxhy.solarmasterace.tools package com.zxhy.solarmasterace.tools
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
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.zxhy.solarmasterace.R import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.databinding.FragmentToolsBinding import com.zxhy.solarmasterace.databinding.FragmentToolsBinding
import com.zxhy.solarmasterace.quicktools.recentImage import com.zxhy.solarmasterace.quicktools.recentImage
...@@ -40,6 +42,25 @@ class ToolsFragment : Fragment() { ...@@ -40,6 +42,25 @@ class ToolsFragment : Fragment() {
context = requireContext() context = requireContext()
imageAdapter = RecentImageAdapter() imageAdapter = RecentImageAdapter()
binding.rv.adapter = imageAdapter binding.rv.adapter = imageAdapter
binding.cardDupImage.setOnClickListener {
val bundle = Bundle().apply {
putString("tittle", "Duplicate picture")
}
findNavController().navigate(R.id.fileBrowserActivity, bundle)
}
binding.cardLargeImage.setOnClickListener {
val bundle = Bundle().apply {
putString("tittle", "Scan large files")
}
findNavController().navigate(R.id.fileBrowserActivity, bundle)
}
binding.cardEmptyFile.setOnClickListener {
val bundle = Bundle().apply {
putString("tittle", "Scan empty file")
}
findNavController().navigate(R.id.fileBrowserActivity, bundle)
}
loadRecentImage() loadRecentImage()
} }
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF5C67E5" />
<corners
android:bottomLeftRadius="25dp"
android:bottomRightRadius="25dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF5C67E5" /> <solid android:color="#FF5C67E5" />
<corners <corners android:radius="25dp" />
android:bottomLeftRadius="25dp"
android:bottomRightRadius="25dp" />
</shape> </shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFE7E7E7" />
<corners android:radius="20dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/rwr_89726" android:state_selected="true" />
<item android:drawable="@mipmap/sd_56987" android:state_selected="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFF4F4F4" />
<corners android:radius="8dp" />
</shape>
\ No newline at end of file
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
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"
android:background="#FFF4F4F4"
tools:context=".filebrowser.FileBrowserActivity"> tools:context=".filebrowser.FileBrowserActivity">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top" android:id="@+id/cl_top"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
app:layout_constraintBottom_toTopOf="@id/tv_tip1"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
...@@ -52,7 +54,8 @@ ...@@ -52,7 +54,8 @@
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
...@@ -65,6 +68,7 @@ ...@@ -65,6 +68,7 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageView <ImageView
android:id="@+id/iv_all"
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"
...@@ -80,8 +84,9 @@ ...@@ -80,8 +84,9 @@
android:id="@+id/tv_tip1" android:id="@+id/tv_tip1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:text="3 items" android:text="0 items"
android:textColor="#FF666666" android:textColor="#FF666666"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/rv" app:layout_constraintBottom_toTopOf="@id/rv"
...@@ -97,30 +102,52 @@ ...@@ -97,30 +102,52 @@
android:text="Files larger than 10MB" android:text="Files larger than 10MB"
android:textColor="#FF666666" android:textColor="#FF666666"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/rv" app:layout_constraintBottom_toBottomOf="@id/tv_tip1"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top" app:layout_constraintTop_toTopOf="@id/tv_tip1"
tools:ignore="HardcodedText,RtlHardcoded" /> tools:ignore="HardcodedText,RtlHardcoded" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv" android:id="@+id/rv"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/tv_delete"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tip1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_warp"
android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginTop="30dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="4dp"
android:background="@drawable/bg_rv_card"
android:overScrollMode="never"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/tv_delete" app:layout_constraintBottom_toTopOf="@id/tv_delete"
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/cl_top" /> app:layout_constraintTop_toBottomOf="@id/tv_tip1" />
<TextView <TextView
android:id="@+id/tv_delete" android:id="@+id/tv_delete"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginHorizontal="56dp" android:layout_marginHorizontal="56dp"
android:layout_marginBottom="54dp" android:layout_marginTop="12dp"
android:layout_marginBottom="40dp"
android:gravity="center"
android:textSize="17sp"
android:textStyle="bold"
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" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".filedetails.FileDetailActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/cl_arrow"
android:layout_width="60dp"
android:layout_height="36dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:src="@mipmap/df_0011"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Image"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/iv"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_marginTop="24dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Name:"
android:textColor="#ff666666"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/iv"
app:layout_constraintTop_toBottomOf="@id/iv"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Name:"
android:textColor="#ff666666"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/iv"
app:layout_constraintTop_toBottomOf="@id/tv_name"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_Position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Name:"
android:textColor="#ff666666"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/iv"
app:layout_constraintTop_toBottomOf="@id/tv_size"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".internalstorage.InternalStorageActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/cl_arrow"
android:layout_width="60dp"
android:layout_height="36dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:src="@mipmap/df_0011"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Internal storage"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<LinearLayout
android:id="@+id/ll_all"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_write"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp"
android:src="@mipmap/dsad_6985"
tools:ignore="ContentDescription" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/cl_operation"
app:layout_constraintTop_toBottomOf="@id/cl_top">
</androidx.recyclerview.widget.RecyclerView>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginEnd="-24dp"
android:layout_marginBottom="40dp"
android:src="@mipmap/ds_787845"
app:layout_constraintBottom_toTopOf="@id/cl_operation"
app:layout_constraintRight_toRightOf="@id/cl_operation"
tools:ignore="ContentDescription" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_operation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="50dp"
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toTopOf="@id/cl_confirm"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/rv">
<ImageView
android:id="@+id/iv_move"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@mipmap/sdlo_58789"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/iv_copy"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="Move"
android:textColor="#333333"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@id/iv_move"
app:layout_constraintRight_toRightOf="@id/iv_move"
app:layout_constraintTop_toBottomOf="@id/iv_move"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_copy"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@mipmap/dssd_3859789"
app:layout_constraintLeft_toRightOf="@id/iv_move"
app:layout_constraintRight_toLeftOf="@id/iv_share"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="Copy"
android:textColor="#333333"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@id/iv_copy"
app:layout_constraintRight_toRightOf="@id/iv_copy"
app:layout_constraintTop_toBottomOf="@id/iv_copy"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_share"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@mipmap/slo_578956"
app:layout_constraintLeft_toRightOf="@id/iv_copy"
app:layout_constraintRight_toLeftOf="@id/iv_more"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="Share"
android:textColor="#333333"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@id/iv_share"
app:layout_constraintRight_toRightOf="@id/iv_share"
app:layout_constraintTop_toBottomOf="@id/iv_share"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_more"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@mipmap/ewt_39878"
app:layout_constraintLeft_toRightOf="@id/iv_share"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="More"
android:textColor="#333333"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@id/iv_more"
app:layout_constraintRight_toRightOf="@id/iv_more"
app:layout_constraintTop_toBottomOf="@id/iv_more"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="57dp"
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_operation">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="122dp"
android:layout_height="40dp"
android:background="@drawable/bg_ffe7e7e7_corners"
android:gravity="center"
android:text="Cancel"
android:textColor="#999999"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_define"
android:layout_width="122dp"
android:layout_height="40dp"
android:background="@drawable/bg_ff5c67e5_corners"
android:gravity="center"
android:text="Motion"
android:textColor="#ffffff"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
android:id="@+id/cl_top" android:id="@+id/cl_top"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="350dp" android:layout_height="350dp"
android:background="@drawable/bg_ff5c67e5_corners" android:background="@drawable/bg_ff5c67e5_blf_corners"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
...@@ -83,13 +83,15 @@ ...@@ -83,13 +83,15 @@
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:id="@+id/card_category" android:id="@+id/card_category"
android:layout_width="171dp" android:layout_width="0dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginBottom="-25dp" android:layout_marginBottom="-25dp"
app:cardCornerRadius="8dp" app:cardCornerRadius="8dp"
app:layout_constraintBottom_toBottomOf="@id/cl_top" app:layout_constraintBottom_toBottomOf="@id/cl_top"
app:layout_constraintLeft_toLeftOf="parent"> app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/card_documents">
<ImageView <ImageView
android:id="@+id/iv_category" android:id="@+id/iv_category"
...@@ -114,14 +116,17 @@ ...@@ -114,14 +116,17 @@
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:id="@+id/card_documents" android:id="@+id/card_documents"
android:layout_width="171dp" android:layout_width="0dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_marginLeft="4dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="-25dp" android:layout_marginBottom="-25dp"
app:cardBackgroundColor="#FFFFFFFF" app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="8dp" app:cardCornerRadius="8dp"
app:cardElevation="5dp" app:cardElevation="5dp"
app:layout_constraintBottom_toBottomOf="@id/cl_top" app:layout_constraintBottom_toBottomOf="@id/cl_top"
app:layout_constraintLeft_toRightOf="@id/card_category"
app:layout_constraintRight_toRightOf="parent"> app:layout_constraintRight_toRightOf="parent">
<ImageView <ImageView
...@@ -522,7 +527,7 @@ ...@@ -522,7 +527,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="Log file" android:text="All"
android:textColor="#FF333333" android:textColor="#FF333333"
android:textSize="12sp" android:textSize="12sp"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<TextView
android:id="@+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:textColor="#FF666666"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/card"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="109dp"
app:cardBackgroundColor="#FFFFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tip">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/iv_selector"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginRight="17dp"
android:src="@drawable/bg_circle_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/rv"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription,RtlHardcoded" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
android:id="@+id/iv" android:id="@+id/iv"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="centerCrop" /> android:scaleType="centerCrop"
tools:ignore="ImageContrastCheck" />
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
<?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="100dp"
android:layout_height="100dp"
android:layout_margin="8dp"
app:cardCornerRadius="8dp"
tools:ignore="ContentDescription">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:ignore="ImageContrastCheck" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="right"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:src="@drawable/bg_image_circle_selector"
tools:ignore="RtlHardcoded" />
<ImageView
android:id="@+id/iv_camera"
android:layout_width="28dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:src="@mipmap/ols_877895" />
</androidx.cardview.widget.CardView>
<?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="85dp"
android:layout_height="85dp"
android:layout_margin="8dp"
app:cardCornerRadius="8dp"
tools:ignore="ContentDescription">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:ignore="ImageContrastCheck" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="right"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:src="@drawable/bg_image_circle_selector"
tools:ignore="RtlHardcoded" />
</androidx.cardview.widget.CardView>
<?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="match_parent"
android:layout_height="64dp"
android:layout_margin="8dp"
app:cardCornerRadius="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription,InvalidId" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="@id/iv_icon"
app:layout_constraintLeft_toRightOf="@id/iv_icon"
app:layout_constraintRight_toLeftOf="@id/iv_selector"
app:layout_constraintTop_toTopOf="@id/iv_icon">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:singleLine="true"
android:textColor="#FF333333"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="#FF999999"
android:textSize="13sp" />
</LinearLayout>
<ImageView
android:id="@+id/iv_selector"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginEnd="16dp"
android:src="@drawable/bg_circle_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
...@@ -22,5 +22,13 @@ ...@@ -22,5 +22,13 @@
<action <action
android:id="@+id/action_toolsFragment_to_managerFragment" android:id="@+id/action_toolsFragment_to_managerFragment"
app:destination="@id/managerFragment" /> app:destination="@id/managerFragment" />
<action
android:id="@+id/action_toolsFragment_to_fileBrowserActivity"
app:destination="@id/fileBrowserActivity" />
</fragment> </fragment>
<activity
android:id="@+id/fileBrowserActivity"
android:name="com.zxhy.solarmasterace.filebrowser.FileBrowserActivity"
android:label="activity_file_browser"
tools:layout="@layout/activity_file_browser" />
</navigation> </navigation>
\ No newline at end of file
...@@ -25,6 +25,8 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const ...@@ -25,6 +25,8 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const
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" }
coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" } coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
coil-video = { group = "io.coil-kt", name = "coil-video", version.ref = "coil" }
coil-gif = { group = "io.coil-kt", name = "coil-gif", version.ref = "coil" }
[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