Commit bdd01dc6 authored by wanglei's avatar wanglei

feat:白包版本完成

parent 90804b8b
...@@ -3,7 +3,20 @@ ...@@ -3,7 +3,20 @@
<component name="deploymentTargetDropDown"> <component name="deploymentTargetDropDown">
<value> <value>
<entry key="app"> <entry key="app">
<State /> <State>
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="3426369207001D6" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-03-21T08:35:33.717775700Z" />
</State>
</entry> </entry>
</value> </value>
</component> </component>
......
...@@ -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,15 @@ ...@@ -19,10 +19,15 @@
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:launchMode="singleTop"
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.ItemCardFileBinding
import com.zxhy.solarmasterace.databinding.ItemCardImage85Binding import com.zxhy.solarmasterace.databinding.ItemCardImage85Binding
import com.zxhy.solarmasterace.databinding.ItemCardImageSelector100Binding
import com.zxhy.solarmasterace.databinding.ItemCardImageSelector85Binding
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 ItemCardFileViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemCardFileBinding.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.util.Log
import android.widget.ImageView
import coil.dispose
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 +48,7 @@ data class FileBean( ...@@ -38,7 +48,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 +88,99 @@ data class FileBean( ...@@ -78,4 +88,99 @@ 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) {
image.dispose()
if (isDir()) {
image.setImageResource(R.mipmap.dsjjd_698987)
} else 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.zczxc_699887)
}
}
}
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.dialog
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.databinding.DialogFolderDetailBinding
import com.zxhy.solarmasterace.databinding.DialogFolderNameBinding
fun Context.showFolderDialog(
fileName: String = "",
tittle: String = "",
newFolder: ((name: String) -> Unit)? = null,
reName: ((name: String) -> Unit)? = null,
) {
val binding = DialogFolderNameBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.show()
dialog.setCanceledOnTouchOutside(false)
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_271)
lp?.height = this.resources.getDimensionPixelOffset(R.dimen.dp_181)
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
binding.ivCancel.setOnClickListener {
dialog.dismiss()
}
binding.etName.setText(fileName)
binding.tvSure.setOnClickListener {
val name = binding.etName.text.toString()
if (name.isEmpty() or name.isBlank()) return@setOnClickListener
when (tittle) {
"New Folder" -> {
newFolder?.invoke(name)
}
"Rename" -> {
reName?.invoke(name)
}
}
dialog.dismiss()
}
}
@SuppressLint("SetTextI18n")
fun Context.showFolderDetailDialog(
context: Context,
fileBean: FileBean,
) {
val binding = DialogFolderDetailBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.show()
dialog.setCanceledOnTouchOutside(false)
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_271)
lp?.height = ViewGroup.LayoutParams.WRAP_CONTENT
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
fileBean.bindIconImage(binding.ivFile)
binding.tvName.text = fileBean.name
binding.tvSub.text = fileBean.file().list()?.size.toString() + " items"
binding.tvTime.text = "Time:" + fileBean.time
binding.tvSize.text = "Size:" + fileBean.sizeFormat(context)
binding.tvPosition.text = fileBean.path
binding.tvCancel.setOnClickListener {
dialog.dismiss()
}
}
package com.zxhy.solarmasterace.dialog
import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import androidx.appcompat.app.AlertDialog
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.databinding.DialogLoadingBinding
fun Context.showLoadingDialog(): Dialog {
val binding = DialogLoadingBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.show()
dialog.setCanceledOnTouchOutside(false)
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_210)
lp?.height = this.resources.getDimensionPixelOffset(R.dimen.dp_170)
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
// 添加旋转动画
val rotateAnimation = RotateAnimation(
0f, 360f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
)
rotateAnimation.duration = 1000
rotateAnimation.interpolator = LinearInterpolator()
rotateAnimation.repeatCount = Animation.INFINITE
binding.ivLoading.startAnimation(rotateAnimation)
return dialog
}
\ No newline at end of file
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.ItemCardFileViewHolder
import com.zxhy.solarmasterace.quicktools.inflate
class CardFileAdapter(
private val selectClick: (flag: Boolean) -> Unit
) : CommonAdapter<ItemCardFileViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemCardFileViewHolder {
return ItemCardFileViewHolder(R.layout.item_card_file.inflate(parent))
}
override fun onBindViewHolder(holder: ItemCardFileViewHolder, position: Int) {
}
override fun onBindViewHolder(
holder: ItemCardFileViewHolder,
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
tvInfo.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,
private val itemClick: ((path: String) -> Unit)? = null
) : 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.forEach {
it.dupData.forEach { fileBean ->
if (fileBean.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)
iv.setOnClickListener {
itemClick?.invoke(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.content.Intent
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.dialog.showLoadingDialog
import com.zxhy.solarmasterace.filedetails.FileDetailActivity
import com.zxhy.solarmasterace.permission.requestStoreFollow
import com.zxhy.solarmasterace.quicktools.ActivityLauncher
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.storePermissionCheck
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
private lateinit var activityLauncher: ActivityLauncher
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
activityLauncher = ActivityLauncher(this)
binding = ActivityFileBrowserBinding.inflate(layoutInflater) binding = ActivityFileBrowserBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
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()
}
if (storePermissionCheck()) {
showBrowser()
} else {
isPermissionSet(true)
}
}
private fun showBrowser() {
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() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
documentFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
private fun txtMode() {
cardUi()
loadTxtFile()
}
private fun loadTxtFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
txtFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
private fun pdfMode() {
cardUi()
loadPdfFile()
}
private fun loadPdfFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
pdfFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
private fun pptMode() {
cardUi()
loadPptFile()
}
@SuppressLint("SetTextI18n")
private fun loadPptFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
pptFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
fun gridUi() {
binding.tvTip1.visibility = View.VISIBLE
binding.tvTip2.visibility = View.GONE
fileGridAdapter = FileGridAdapter(
selectClick = {
binding.ivAll.isSelected = it
},
itemClick = { path ->
startActivity(Intent(this, FileDetailActivity::class.java).apply {
putExtra("Path", path)
})
}
)
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() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
excelFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
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() {
gridUi()
loadImageFile()
}
@SuppressLint("SetTextI18n")
private fun loadWordFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
wordFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadImageFile() {
val dialog = showLoadingDialog()
fileGridAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
imageFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadVideoFile() {
val dialog = showLoadingDialog()
fileGridAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
videoFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
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() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
largeFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadAudioFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
audioFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadApkFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
apkFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadZipFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
zipFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadLogFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
logFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
private fun emptyFileMode() {
cardUi()
loadEmptyFile()
}
@SuppressLint("SetTextI18n")
private fun loadEmptyFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
emptyFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
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(
selectClick = { binding.ivAll.isSelected = it },
itemClick = { path ->
startActivity(Intent(this, FileDetailActivity::class.java).apply {
putExtra("Path", path)
})
}
)
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.Main) {
async {
deleteFiles(files)
}.await()
loadDupImage()
}
}
loadDupImage()
}
private fun loadDupImage() {
val dialog = showLoadingDialog()
lifecycleScope.launch(Dispatchers.IO) {
val data = dupImage()
launch(Dispatchers.Main) {
dialog.dismiss()
dupImageAdapter.setData(data)
binding.ivAll.isSelected = false
showEmptyUi()
}
}
}
private fun showEmptyUi() {
var show = false
if (this::dupImageAdapter.isInitialized) {
show = dupImageAdapter.itemCount == 0
}
if (this::cardFileAdapter.isInitialized) {
show = cardFileAdapter.itemCount == 0
}
if (this::fileGridAdapter.isInitialized) {
show = fileGridAdapter.itemCount == 0
}
if (show) {
binding.rv.visibility = View.INVISIBLE
binding.ivEmpty.visibility = View.VISIBLE
binding.llAll.visibility = View.INVISIBLE
binding.tvDelete.visibility = View.INVISIBLE
} else {
binding.rv.visibility = View.VISIBLE
binding.ivEmpty.visibility = View.INVISIBLE
binding.llAll.visibility = View.VISIBLE
binding.tvDelete.visibility = View.VISIBLE
}
}
override fun onDestroy() {
super.onDestroy()
finish()
}
override fun onRestart() {
super.onRestart()
if (storePermissionCheck()) {
isPermissionSet(false)
showBrowser()
}
}
private fun isPermissionSet(show: Boolean) {
if (show) {
binding.clPermission.visibility = View.VISIBLE
binding.clContent.visibility = View.INVISIBLE
binding.llAll.visibility = View.INVISIBLE
binding.tvSet.setOnClickListener {
requestStoreFollow(activityLauncher,
disAgreeAction = {
}, agreeAction = {
showBrowser()
})
}
} else {
binding.clPermission.visibility = View.GONE
binding.clContent.visibility = View.VISIBLE
binding.llAll.visibility = View.VISIBLE
} }
} }
} }
\ 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,
private val itemClick: ((path: String) -> Unit)? = null
) : 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
iv.setOnClickListener {
itemClick?.invoke(data.path)
}
} else if (data.isVideo()) {
iv.load(data.file(), ColiVideoEx.videoLoader(context))
ivCamera.visibility = View.VISIBLE
iv.setOnClickListener { }
}
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.annotation.SuppressLint
import android.os.Bundle
import android.text.format.Formatter
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import coil.load
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.databinding.ActivityFileDetailBinding
import java.io.File
class FileDetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityFileDetailBinding
@SuppressLint("SetTextI18n")
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
}
val path = intent.extras?.getString("Path") ?: ""
val file = File(path)
if (file.exists()) {
binding.iv.load(path)
binding.tvName.text = "Name:" + file.name
binding.tvSize.text = "Size:" + Formatter.formatFileSize(this, file.length())
binding.tvPosition.text = "Position:" + file.absoluteFile
}
binding.clArrow.setOnClickListener {
finish()
}
binding.tvDelete.setOnClickListener {
if (file.exists()) {
file.delete()
}
finish()
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.internalstorage
import android.annotation.SuppressLint
import android.os.Environment
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.adapter.CommonAdapter
import com.zxhy.solarmasterace.adapter.ItemCardFileViewHolder
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.data.toFileBean
import com.zxhy.solarmasterace.quicktools.inflate
import java.io.File
class FileDirectoryAdapter(
private val selectClick: (flag: Boolean) -> Unit,
private val showEmpty: (flag: Boolean) -> Unit,
) : CommonAdapter<ItemCardFileViewHolder>() {
private var currentDir = Environment.getExternalStorageDirectory()
private var isSelectMode = false
private var pageTurn = true
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemCardFileViewHolder {
return ItemCardFileViewHolder(R.layout.item_card_file.inflate(parent))
}
override fun onBindViewHolder(holder: ItemCardFileViewHolder, position: Int) {
}
fun setPageTurn(flag: Boolean) {
pageTurn = flag
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(
holder: ItemCardFileViewHolder,
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
if (data.isDir()) {
tvInfo.text = data.time + " ${data.file().listFiles()?.size ?: 0} items"
} else {
tvInfo.text = data.time + " ${data.sizeFormat(context)}"
}
if (isSelectMode) {
ivSelector.visibility = View.VISIBLE
} else {
ivSelector.visibility = View.INVISIBLE
}
ivSelector.isSelected = data.isSelect
ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
notifyItemChanged(position, "单条刷新")
val flag = fileList.all { it.isSelect }
selectClick.invoke(flag)
}
root.setOnClickListener {
if (!pageTurn) return@setOnClickListener
nextPage(data)
}
}
} else {
holder.binding.apply {
ivSelector.isSelected = data.isSelect
}
super.onBindViewHolder(holder, position, payloads)
}
}
private fun nextPage(data: FileBean) {
if (data.isDir()) {
currentDir = data.file()
val list = data.file().listFiles()?.toList()?.map { it.toFileBean() } ?: listOf()
setData(list)
if (list.isEmpty()) showEmpty(true) else showEmpty(false)
}
}
@SuppressLint("NotifyDataSetChanged")
fun showSelect(flag: Boolean) {
isSelectMode = flag
notifyDataSetChanged()
}
/**
* @return 是否是根目录
*/
fun beforePage(): Boolean {
return if (currentDir == Environment.getExternalStorageDirectory().absoluteFile) {
true
} else {
val parentDir = currentDir.parentFile ?: File("")
val files = parentDir.listFiles()?.toList()?.map { it.toFileBean() } ?: listOf()
setData(files)
currentDir = parentDir
if (files.isEmpty()) showEmpty(true) else showEmpty(false)
false
}
}
fun notifyCurrentDir() {
val data = currentDir.listFiles()?.map { it.toFileBean() } ?: listOf()
setData(data)
if (data.isEmpty()) showEmpty(true) else showEmpty(false)
}
fun getCurrentDir(): File? {
return currentDir
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.internalstorage
import android.os.Bundle
import android.os.Environment
import android.view.KeyEvent
import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.data.toFileBean
import com.zxhy.solarmasterace.databinding.ActivityInternalStorageBinding
import com.zxhy.solarmasterace.dialog.showFolderDetailDialog
import com.zxhy.solarmasterace.dialog.showFolderDialog
import com.zxhy.solarmasterace.permission.requestStoreFollow
import com.zxhy.solarmasterace.popupwindow.showPopupMoreOperation
import com.zxhy.solarmasterace.quicktools.ActivityLauncher
import com.zxhy.solarmasterace.quicktools.FileHelper
import com.zxhy.solarmasterace.quicktools.storePermissionCheck
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
class InternalStorageActivity : AppCompatActivity() {
private lateinit var binding: ActivityInternalStorageBinding
private lateinit var fileDirectoryAdapter: FileDirectoryAdapter
private val MODE_BROWSE = 0
private val MODE_SELECT = 1
private val MODE_SELECTED_OPERATION = 2
private val MODE_LOCK = -1
private var currentMode = MODE_BROWSE //0普通浏览模式 1可选模式 2选中操作模式 -1无权限锁功能模式
private lateinit var activityLauncher: ActivityLauncher
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
activityLauncher = ActivityLauncher(this)
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
}
if (storePermissionCheck()) {
showContent()
} else {
isPermissionSet(true)
}
binding.clArrow.setOnClickListener {
val flag = fileDirectoryAdapter.beforePage()
if (flag)
finish()
}
}
private fun showContent() {
isPermissionSet(false)
fileDirectoryAdapter = FileDirectoryAdapter(
selectClick = { binding.ivAll.isSelected = it }, showEmpty = { flag ->
if (flag) {
binding.rv.visibility = View.INVISIBLE
binding.ivEmpty.visibility = View.VISIBLE
} else {
binding.rv.visibility = View.VISIBLE
binding.ivEmpty.visibility = View.INVISIBLE
}
}
)
binding.rv.adapter = fileDirectoryAdapter
initData()
switchBrowseMode()
}
private fun switchBrowseMode() {
currentMode = MODE_BROWSE
binding.ivAdd.visibility = View.VISIBLE
fileDirectoryAdapter.toggleSelect(false)
fileDirectoryAdapter.showSelect(false)
fileDirectoryAdapter.setPageTurn(true)
binding.llAll.visibility = View.GONE
binding.ivWrite.visibility = View.VISIBLE
binding.ivWrite.setOnClickListener {
showFolderDialog(tittle = "New Folder", newFolder = { name ->
val dir = fileDirectoryAdapter.getCurrentDir()
val file = File(dir, name)
if (!file.exists()) {
file.mkdir()
}
fileDirectoryAdapter.notifyCurrentDir()
})
}
binding.ivAdd.setOnClickListener {
switchSelectMode()
}
binding.ivMore.setOnClickListener {
val fileBeanList = fileDirectoryAdapter.getSelectData()
val fileList = fileBeanList.map { it.file() }
val size = fileList.size
if (size == 0) return@setOnClickListener
showPopupMoreOperation(
this, binding.clOperation, size,
renameAction = {
val reNameFile = fileList.first()
showFolderDialog(reNameFile.name, "Rename", reName = { name ->
reNameFile.renameTo(File(reNameFile.parentFile, name))
fileDirectoryAdapter.notifyCurrentDir()
showCardTip("success renamed!")
switchBrowseMode()
})
},
detailAction = {
showFolderDetailDialog(this, fileBeanList.first())
},
shareAction = {}
)
}
binding.clOperation.visibility = View.GONE
binding.clConfirm.visibility = View.GONE
}
private fun switchSelectMode() {
currentMode = MODE_SELECT
binding.ivAdd.visibility = View.GONE
binding.llAll.isSelected = false
fileDirectoryAdapter.toggleSelect(false)
fileDirectoryAdapter.showSelect(true)
fileDirectoryAdapter.setPageTurn(false)
binding.llAll.visibility = View.VISIBLE
binding.ivWrite.visibility = View.GONE
binding.llAll.setOnClickListener {
it.isSelected = !it.isSelected
fileDirectoryAdapter.toggleSelect(it.isSelected)
}
binding.clOperation.visibility = View.VISIBLE
binding.clConfirm.visibility = View.GONE
binding.ivDelete.setOnClickListener {
val files = fileDirectoryAdapter.getSelectData().map { it.file() }
deleteFiles(files) {
showCardTip("Successfully deleted!")
}
}
binding.ivMove.setOnClickListener {
val moveFile = arrayListOf<File>()
fileDirectoryAdapter.getSelectData().map { moveFile.add(it.file()) }
switchSelectedOperationMode("Motion", moveFile)
}
binding.ivCopy.setOnClickListener {
val copyFile = arrayListOf<File>()
fileDirectoryAdapter.getSelectData().map { copyFile.add(it.file()) }
switchSelectedOperationMode("Copy", copyFile)
}
}
private fun showCardTip(tips: String) = lifecycleScope.launch(Dispatchers.Main) {
binding.tvTip.text = tips
binding.cardSuccess.visibility = View.VISIBLE
delay(1000)
binding.cardSuccess.visibility = View.INVISIBLE
}
private fun switchSelectedOperationMode(function: String, files: List<File>) {
currentMode = MODE_SELECTED_OPERATION
binding.ivAll.isSelected = false
fileDirectoryAdapter.toggleSelect(false)
fileDirectoryAdapter.showSelect(false)
fileDirectoryAdapter.setPageTurn(true)
binding.clOperation.visibility = View.GONE
binding.clConfirm.visibility = View.VISIBLE
binding.tvDefine.text = function
when (function) {
"Motion" -> {
binding.tvDefine.setOnClickListener {
moveFiles(files) {
showCardTip("Successfully moved!")
switchBrowseMode()
}
}
}
"Copy" -> {
binding.tvDefine.setOnClickListener {
copyFiles(files) {
showCardTip("Successfully copied!")
switchBrowseMode()
}
}
}
}
binding.tvCancel.setOnClickListener {
switchBrowseMode()
}
}
private fun copyFiles(files: List<File>, finish: (() -> Unit)? = null) =
lifecycleScope.launch(Dispatchers.Main) {
async {
val dir = fileDirectoryAdapter.getCurrentDir() ?: File("")
files.forEach {
if (it.isFile) {
it.copyTo(File(dir, it.name))
} else {
FileHelper.copyDirectory(it, File(dir, it.name))
}
}
}.await()
fileDirectoryAdapter.notifyCurrentDir()
finish?.invoke()
}
private fun moveFiles(files: List<File>, finish: (() -> Unit)? = null) =
lifecycleScope.launch(Dispatchers.Main) {
async(Dispatchers.IO) {
val dir = fileDirectoryAdapter.getCurrentDir() ?: File("")
files.map {
if (it.isFile) {
it.copyTo(File(dir, it.name))
it.delete()
} else {
FileHelper.copyDirectory(it, File(dir, it.name))
FileHelper.deleteDirectory(it)
}
}
}.await()
fileDirectoryAdapter.notifyCurrentDir()
finish?.invoke()
}
private fun deleteFiles(files: List<File>, finish: (() -> Unit)? = null) =
lifecycleScope.launch(Dispatchers.Main) {
async(Dispatchers.IO) {
files.map {
try {
if (it.isFile) it.delete() else FileHelper.deleteDirectory(it)
} catch (e: Exception) {
e.printStackTrace()
}
}
}.await()
fileDirectoryAdapter.notifyCurrentDir()
finish?.invoke()
}
private fun initData() {
val root = Environment.getExternalStorageDirectory()
val list = root.listFiles()?.map { it.toFileBean() } ?: listOf()
fileDirectoryAdapter.setData(list)
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
when (currentMode) {
MODE_BROWSE -> {
val flag = fileDirectoryAdapter.beforePage()
return if (flag) super.dispatchKeyEvent(event) else false
}
MODE_SELECT -> {
switchBrowseMode()
return false
}
MODE_SELECTED_OPERATION -> {
val flag = fileDirectoryAdapter.beforePage()
return if (flag) super.dispatchKeyEvent(event) else false
}
}
}
return super.dispatchKeyEvent(event)
}
private fun isPermissionSet(show: Boolean) {
if (show) {
binding.clPermission.visibility = View.VISIBLE
binding.clContent.visibility = View.GONE
binding.llTools.visibility = View.GONE
binding.tvSet.setOnClickListener {
requestStoreFollow(activityLauncher,
disAgreeAction = {
}, agreeAction = {
showContent()
})
}
} else {
binding.clPermission.visibility = View.GONE
binding.clContent.visibility = View.VISIBLE
binding.llTools.visibility = View.VISIBLE
}
}
}
...@@ -2,18 +2,22 @@ package com.zxhy.solarmasterace.manager ...@@ -2,18 +2,22 @@ package com.zxhy.solarmasterace.manager
import android.annotation.SuppressLint import android.annotation.SuppressLint
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.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.internalstorage.InternalStorageActivity
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
...@@ -49,10 +53,13 @@ class ManagerFragment : Fragment() { ...@@ -49,10 +53,13 @@ class ManagerFragment : Fragment() {
binding.cardDocuments.setOnClickListener { binding.cardDocuments.setOnClickListener {
documentsMode() documentsMode()
} }
binding.ivCircle.setOnClickListener {
startActivity(Intent(context, InternalStorageActivity::class.java))
}
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 +77,38 @@ class ManagerFragment : Fragment() { ...@@ -70,12 +77,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 +126,25 @@ class ManagerFragment : Fragment() { ...@@ -93,6 +126,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.popupwindow
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.PopupWindow
import androidx.core.content.ContextCompat
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.databinding.PopupwindowMoreOperationBinding
@SuppressLint("ClickableViewAccessibility")
fun showPopupMoreOperation(
activity: Activity,
arcView: View,
size: Int = 0,
renameAction: (() -> Unit)? = null,
detailAction: (() -> Unit)? = null,
shareAction: (() -> Unit)? = null
) {
var yOff = 0
var height = 0
val popupWindowView = activity.layoutInflater.inflate(R.layout.popupwindow_more_operation, null)
val popupBinding = PopupwindowMoreOperationBinding.bind(popupWindowView)
if (size == 1) {
yOff = activity.resources.getDimensionPixelSize(R.dimen.dp_175)
height = activity.resources.getDimensionPixelSize(R.dimen.dp_112)
} else {
popupBinding.llRename.visibility = View.GONE
popupBinding.llDetails.visibility = View.GONE
yOff = activity.resources.getDimensionPixelSize(R.dimen.dp_100)
height = activity.resources.getDimensionPixelSize(R.dimen.dp_46)
}
val width =
activity.resources.getDimensionPixelSize(R.dimen.dp_108)
val popupWindow = PopupWindow(popupWindowView, width, height, true)
popupWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
popupWindow.isOutsideTouchable = true
popupWindow.isTouchable = true
popupBinding.apply {
llRename.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
tvRename.setTextColor(ContextCompat.getColor(activity, R.color.color_FF333333))
ivRename.setImageResource(R.mipmap.dsd_7886)
}
MotionEvent.ACTION_UP -> {
tvRename.setTextColor(ContextCompat.getColor(activity, R.color.color_FF999999))
ivRename.setImageDrawable(null)
}
else -> {}
}
false
}
llRename.setOnClickListener {
tvRename.setTextColor(ContextCompat.getColor(activity, R.color.color_FF333333))
ivRename.setImageResource(R.mipmap.dsd_7886)
popupWindow.dismiss()
renameAction?.invoke()
}
llDetails.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
tvDetails.setTextColor(ContextCompat.getColor(activity, R.color.color_FF333333))
ivDetails.setImageResource(R.mipmap.dsd_7886)
}
MotionEvent.ACTION_UP -> {
tvDetails.setTextColor(ContextCompat.getColor(activity, R.color.color_FF999999))
ivDetails.setImageDrawable(null)
}
else -> {}
}
false
}
llDetails.setOnClickListener {
tvDetails.setTextColor(ContextCompat.getColor(activity, R.color.color_FF333333))
ivDetails.setImageResource(R.mipmap.dsd_7886)
popupWindow.dismiss()
detailAction?.invoke()
}
llShare.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
tvShare.setTextColor(ContextCompat.getColor(activity, R.color.color_FF333333))
ivShare.setImageResource(R.mipmap.dsd_7886)
}
MotionEvent.ACTION_UP -> {
tvShare.setTextColor(ContextCompat.getColor(activity, R.color.color_FF999999))
ivShare.setImageDrawable(null)
}
else -> {}
}
false
}
llShare.setOnClickListener {
tvShare.setTextColor(ContextCompat.getColor(activity, R.color.color_FF333333))
ivShare.setImageResource(R.mipmap.dsd_7886)
popupWindow.dismiss()
shareAction?.invoke()
}
popupWindow.showAsDropDown(arcView, (arcView.width * 0.75).toInt(), -yOff)
}
}
\ No newline at end of file
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()
}
}
package com.zxhy.solarmasterace.quicktools
import android.os.Environment
import android.util.Log
import java.io.File
import java.util.LinkedList
import java.util.Stack
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)
}
//删除文件夹
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
}
/**
* 复制文件夹
* @param source 原文件夹
* @param target 目标文件夹
*/
fun copyDirectory(source: File, target: File) {
if (source.isDirectory) {
if (!target.exists()) target.mkdir()
source.list()?.map { sub ->
copyDirectory(File(source, sub), File(target, sub))
}
} else {
source.copyTo(target)
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.quicktools
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
/**
* Uri获取File
*/
/**
* 根据Uri获取File路径
*/
fun getFilePathByUri(context: Context, uri: Uri): String? {
var path: String? = null
// 以 file:// 开头的
if (ContentResolver.SCHEME_FILE == uri.scheme) {
path = uri.path
return path
}
// 以 content:// 开头的,比如 content://media/extenral/images/media/17766
if (ContentResolver.SCHEME_CONTENT == uri.scheme) {
val cursor = context.contentResolver.query(
uri,
arrayOf(MediaStore.Images.Media.DATA),
null,
null,
null
)
if (cursor != null) {
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
if (columnIndex > -1) {
path = cursor.getString(columnIndex)
}
}
cursor.close()
}
return path
}
// 4.4及之后的 是以 content:// 开头的,比如 content://com.android.providers.media.documents/document/image%3A235700
if (ContentResolver.SCHEME_CONTENT == uri.scheme) {
if (DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
// ExternalStorageProvider
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
path = Environment.getExternalStorageDirectory().toString() + "/" + split[1]
return path
}
} else if (isDownloadsDocument(uri)) {
// DownloadsProvider
val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)
)
path = getDataColumn(context, contentUri, null, null)
return path
} else if (isMediaDocument(uri)) {
// MediaProvider
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
var contentUri: Uri? = null
when (type) {
"image" -> {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
"video" -> {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
"audio" -> {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
}
val selection = "_id=?"
val selectionArgs = arrayOf(split[1])
path = getDataColumn(context, contentUri, selection, selectionArgs)
return path
}
}
}
return null
}
/**
* 通过 MediaStore Uri获取值,或者其他基于 ContentProviders 的 Uri
*/
fun getDataColumn(
context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?
): String? {
var cursor: Cursor? = null
val column = "_data"
val projection = arrayOf(column)
try {
cursor = context.contentResolver.query(
uri!!, projection, selection, selectionArgs, null
)
if (cursor != null && cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndexOrThrow(column)
return cursor.getString(columnIndex)
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
return null
}
fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
// Whether the Uri authority is DownloadsProvider.
fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
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.quicktools
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Environment
import androidx.core.content.ContextCompat
//Android 13以后,读写权限无法弹出系统弹窗,分化为Manifest.permission.READ_MEDIA_*权限
//Android 11以后,Manifest.permission.READ_EXTERNAL_STORAGE 授予后还需授予 额外储存管理权限 ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
//Android 11以下使用Manifest.permission.READ_EXTERNAL_STORAGE
fun Context.storePermissionCheck(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {//Android 13以后
return Environment.isExternalStorageManager()
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {//Android 11以后
val flag1 = Environment.isExternalStorageManager()
val flag2 = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
).all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
return flag1 or flag2
} else { //Android 11以下,Android 6以上
return arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
).all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.tools package com.zxhy.solarmasterace.tools
import android.annotation.SuppressLint import android.net.Uri
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.getFilePathByUri
import com.zxhy.solarmasterace.quicktools.inflate import com.zxhy.solarmasterace.quicktools.inflate
class RecentImageAdapter() : Adapter<ItemImage85ViewHolder>(), AdapterCommonDataFunction { class RecentImageAdapter(
val clickItem: ((uri: Uri) -> Unit)? = null
) : 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())
}
iv.setOnClickListener {
clickItem?.invoke(data.uri)
} }
} }
}
@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.filedetails.FileDetailActivity
import com.zxhy.solarmasterace.quicktools.getFilePathByUri
import com.zxhy.solarmasterace.quicktools.recentImage import com.zxhy.solarmasterace.quicktools.recentImage
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File
class ToolsFragment : Fragment() { class ToolsFragment : Fragment() {
...@@ -38,8 +44,46 @@ class ToolsFragment : Fragment() { ...@@ -38,8 +44,46 @@ class ToolsFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
context = requireContext() context = requireContext()
imageAdapter = RecentImageAdapter() imageAdapter = RecentImageAdapter { uri ->
lifecycleScope.launch(Dispatchers.Main) {
var path = ""
async(Dispatchers.IO) {
path = getFilePathByUri(context, uri) ?: ""
}.await()
if (File(path).exists()) {
startActivity(Intent(context, FileDetailActivity::class.java).apply {
putExtra("Path", path)
})
}
}
}
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()
}
override fun onResume() {
super.onResume()
loadRecentImage() loadRecentImage()
} }
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF333333" />
<corners android:radius="20dp" />
</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="#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"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFF2F2F2" />
<corners android:radius="4dp" />
</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="#FFFFFFFF" />
<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/cl_content"
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"
...@@ -76,51 +80,150 @@ ...@@ -76,51 +80,150 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<TextView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/tv_tip1" android:id="@+id/cl_content"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="3 items"
android:textColor="#FF666666"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/rv"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top"
tools:ignore="HardcodedText,RtlHardcoded" />
<TextView
android:id="@+id/tv_tip2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:text="Files larger than 10MB"
android:textColor="#FF666666"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/rv"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top"
tools:ignore="HardcodedText,RtlHardcoded" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginTop="30dp" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
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/cl_top">
<TextView <TextView
android:id="@+id/tv_delete" android:id="@+id/tv_tip1"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="40dp" android:layout_height="wrap_content"
android:layout_marginHorizontal="56dp" android:layout_marginVertical="4dp"
android:layout_marginBottom="54dp" android:layout_marginLeft="16dp"
android:text="0 items"
android:textColor="#FF666666"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/rv"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText,RtlHardcoded" />
<TextView
android:id="@+id/tv_tip2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:text="Files larger than 10MB"
android:textColor="#FF666666"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@id/tv_tip1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_tip1"
tools:ignore="HardcodedText,RtlHardcoded" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
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_marginTop="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_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tip1" />
<TextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginHorizontal="56dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="40dp"
android:gravity="center"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/rv" />
<ImageView
android:id="@+id/iv_empty"
android:layout_width="223dp"
android:layout_height="230dp"
android:src="@mipmap/dzd_7895"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_permission"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@id/cl_top">
app:layout_constraintRight_toRightOf="parent" />
<ImageView
android:id="@+id/iv_lock"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@mipmap/dsd_487954"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_permission_tip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="66dp"
android:layout_marginTop="20dp"
android:text="There are no permissions We need to get permission to read all files."
android:textColor="#999999"
android:textSize="17sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_lock"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_set"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginHorizontal="55dp"
android:layout_marginTop="20dp"
android:background="@drawable/bg_ff5c67e5_corners"
android:gravity="center"
android:text="Set"
android:textColor="#FFFFFF"
android:textSize="17sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_permission_tip"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</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="0dp"
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_constraintRight_toRightOf="@id/iv"
app:layout_constraintTop_toBottomOf="@id/iv"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_size"
android:layout_width="0dp"
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_constraintRight_toRightOf="@+id/iv"
app:layout_constraintTop_toBottomOf="@id/tv_name"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_Position"
android:layout_width="0dp"
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_constraintRight_toRightOf="@+id/iv"
app:layout_constraintTop_toBottomOf="@id/tv_size"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginHorizontal="56dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="40dp"
android:background="@drawable/bg_ff5c67e5_corners"
android:gravity="center"
android:text="Delete"
android:textColor="#FFFFFFFF"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
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"
android:background="#FFF4F4F4"
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_tools"
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_marginHorizontal="16dp"
android:src="@mipmap/dsad_6985"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/ll_all"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="4dp"
android:text="All"
android:textColor="#FF999999"
android:textSize="14sp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_all"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp"
android:src="@drawable/bg_circle_selector"
tools:ignore="ContentDescription" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_content"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/cl_operation"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<ImageView
android:id="@+id/iv_add"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginEnd="28dp"
android:src="@mipmap/ds_787845"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.85"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_empty"
android:layout_width="223dp"
android:layout_height="230dp"
android:src="@mipmap/dzd_7895"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3"
tools:ignore="ContentDescription" />
<androidx.cardview.widget.CardView
android:id="@+id/card_success"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:visibility="gone"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="17dp"
android:src="@mipmap/wuio_8975"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="46dp"
android:layout_marginEnd="20dp"
android:text="Successfully deleted!"
android:textColor="#FF333333"
android:textSize="14sp"
tools:ignore="HardcodedText,RtlHardcoded" />
</androidx.cardview.widget.CardView>
<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_delete"
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_delete"
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="Delete"
android:textColor="#333333"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@id/iv_delete"
app:layout_constraintRight_toRightOf="@id/iv_delete"
app:layout_constraintTop_toBottomOf="@id/iv_delete"
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_delete"
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>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_permission"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<ImageView
android:id="@+id/iv_lock"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@mipmap/dsd_487954"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_permission_tip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="66dp"
android:layout_marginTop="20dp"
android:text="There are no permissions We need to get permission to read all files."
android:textColor="#999999"
android:textSize="17sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_lock"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_set"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginHorizontal="55dp"
android:layout_marginTop="20dp"
android:background="@drawable/bg_ff5c67e5_corners"
android:gravity="center"
android:text="Set"
android:textColor="#FFFFFF"
android:textSize="17sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_permission_tip"
tools:ignore="HardcodedText" />
</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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<androidx.cardview.widget.CardView
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_file"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription,RtlHardcoded" />
<TextView
android:id="@+id/tv_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="5 items"
android:textColor="#FF666666"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@id/iv_file"
app:layout_constraintLeft_toRightOf="@id/iv_file"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:text="Video"
android:textColor="#FF333333"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintLeft_toRightOf="@id/iv_file"
app:layout_constraintTop_toTopOf="@id/iv_file"
tools:ignore="HardcodedText,RtlHardcoded" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Time:"
android:textColor="#FF999999"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/iv_file"
app:layout_constraintTop_toBottomOf="@id/iv_file"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="20MB"
android:textColor="#FF999999"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/iv_file"
app:layout_constraintTop_toBottomOf="@id/tv_time"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_position"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="20dp"
android:text="Position:"
android:textColor="#FF999999"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/iv_file"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_size"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_cancel"
android:layout_width="210dp"
android:layout_height="40dp"
android:layout_marginVertical="8dp"
android:background="@drawable/bg_ff333333_corners"
android:gravity="center"
android:text="I know."
android:textColor="#FFFFFFFF"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_position"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</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:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="266dp"
android:layout_height="176dp"
android:layout_margin="5dp"
app:cardCornerRadius="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="New Folder"
android:textColor="#FF333333"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_cancel"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_margin="5dp"
android:src="@mipmap/dasi_895601"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription,ImageContrastCheck" />
<EditText
android:id="@+id/et_name"
android:layout_width="200dp"
android:layout_height="32dp"
android:background="@drawable/bg_fff2f2f2_corners"
android:gravity="center"
android:hint="Please enter a new name"
android:singleLine="true"
android:textColor="#FF999999"
android:textColorHint="#FF999999"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.45"
tools:ignore="Autofill,HardcodedText,LabelFor,TextFields,TouchTargetSizeCheck,TextContrastCheck" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="210dp"
android:layout_height="40dp"
android:layout_marginBottom="16dp"
android:background="@drawable/bg_ff333333_corners"
android:gravity="center"
android:text="Sure"
android:textColor="#FFFFFFFF"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</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:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="160dp"
android:layout_margin="5dp"
app:cardBackgroundColor="#323232"
app:cardCornerRadius="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_loading"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_gravity="center"
android:layout_marginTop="48dp"
android:src="@drawable/icon_loading"
app:layout_constraintLeft_toLeftOf="parent"
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="12dp"
android:text="loading..."
android:textColor="#ffffff"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_loading"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</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
<?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_info"
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
...@@ -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.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="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="106dp"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardElevation="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_rename"
android:layout_width="match_parent"
android:layout_height="36dp"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_rename"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@null"
android:paddingStart="12dp"
android:text="Rename"
android:textColor="#FF999999"
android:textSize="16sp"
tools:ignore="HardcodedText,RtlSymmetry" />
<ImageView
android:id="@+id/iv_rename"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="3dp"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:clickable="true"
android:focusable="true"
android:id="@+id/ll_Details"
android:layout_width="match_parent"
android:layout_height="36dp"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_Details"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingStart="12dp"
android:text="Details"
android:textColor="#FF999999"
android:textSize="16sp"
tools:ignore="HardcodedText,RtlSymmetry" />
<ImageView
android:id="@+id/iv_details"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="3dp"
tools:ignore="ContentDescription,RtlHardcoded" />
</LinearLayout>
<LinearLayout
android:clickable="true"
android:focusable="true"
android:id="@+id/ll_share"
android:layout_width="match_parent"
android:layout_height="36dp"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_share"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingStart="12dp"
android:text="Share"
android:textColor="#FF999999"
android:textSize="16sp"
tools:ignore="HardcodedText,RtlSymmetry" />
<ImageView
android:id="@+id/iv_share"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="3dp"
tools:ignore="ContentDescription,RtlHardcoded" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
\ 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
...@@ -4,4 +4,6 @@ ...@@ -4,4 +4,6 @@
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="color_FF5C67E5">#FF5C67E5</color> <color name="color_FF5C67E5">#FF5C67E5</color>
<color name="color_FF4CE0AB">#FF4CE0AB</color> <color name="color_FF4CE0AB">#FF4CE0AB</color>
<color name="color_FF333333">#FF333333</color>
<color name="color_FF999999">#FF999999</color>
</resources> </resources>
\ No newline at end of file
...@@ -2,4 +2,16 @@ ...@@ -2,4 +2,16 @@
<resources> <resources>
<dimen name="dp_24">24dp</dimen> <dimen name="dp_24">24dp</dimen>
<dimen name="dp_48">48dp</dimen> <dimen name="dp_48">48dp</dimen>
<dimen name="dp_271">271dp</dimen>
<dimen name="dp_181">181dp</dimen>
<dimen name="dp_90">90dp</dimen>
<dimen name="dp_46">46dp</dimen>
<dimen name="dp_118">118dp</dimen>
<dimen name="dp_108">108dp</dimen>
<dimen name="dp_112">112dp</dimen>
<dimen name="dp_100">100dp</dimen>
<dimen name="dp_160">160dp</dimen>
<dimen name="dp_175">175dp</dimen>
<dimen name="dp_210">210dp</dimen>
<dimen name="dp_170">170dp</dimen>
</resources> </resources>
\ 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