Commit 951d7815 authored by wanglei's avatar wanglei

...

parent aa77a6b2
...@@ -84,6 +84,8 @@ dependencies { ...@@ -84,6 +84,8 @@ dependencies {
implementation("com.github.angcyo.DslTablayout:TabLayout:3.5.5") implementation("com.github.angcyo.DslTablayout:TabLayout:3.5.5")
implementation("com.github.angcyo.DslTablayout:ViewPager2Delegate:3.5.5") implementation("com.github.angcyo.DslTablayout:ViewPager2Delegate:3.5.5")
implementation("com.airbnb.android:lottie:6.4.0") implementation("com.airbnb.android:lottie:6.4.0")
implementation("com.github.pokercc:ExpandableRecyclerView:0.9.3")
//mlkit //mlkit
implementation("com.google.android.gms:play-services-mlkit-document-scanner:16.0.0-beta1") implementation("com.google.android.gms:play-services-mlkit-document-scanner:16.0.0-beta1")
......
package com.base.pdfviewerscannerwhite.bean
import android.animation.ValueAnimator
import android.graphics.drawable.Drawable
data class ParentBean(
val icon: Int = 0,
val tittle: String = "",
val childItem: List<ChildBean> = arrayListOf(),
) {
var playAnimation: Boolean = true
var isExpand: Boolean = true
var isSelect: Boolean = true
var finished: Boolean = false
var rotateValueAnimator: ValueAnimator? = null
}
data class ChildBean(
val icon: Int = 0,
val path: String = "",
) {
var playAnimation: Boolean = true
var apkIcon: Drawable? = null
var isSelect: Boolean = true
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.cleanjunk
import android.animation.ValueAnimator
import android.graphics.Color
import android.view.animation.LinearInterpolator
import android.widget.Toast
import androidx.activity.addCallback
import androidx.core.animation.doOnEnd
import androidx.core.view.updatePadding
import com.base.pdfviewerscannerwhite.ads.admob.AdmobInterstitialUtils
import com.base.pdfviewerscannerwhite.databinding.ActivityLayoutCleanupingBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.utils.AppPreferences
import com.base.pdfviewerscannerwhite.utils.BarUtils
import com.base.pdfviewerscannerwhite.utils.updateMediaStore
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import java.io.File
import kotlin.random.Random
/**
* 实际清理页面
*/
class CleaningActivity : BaseActivity<ActivityLayoutCleanupingBinding>() {
override val binding: ActivityLayoutCleanupingBinding by lazy {
ActivityLayoutCleanupingBinding.inflate(layoutInflater)
}
private val intentSize by lazy {
intent.getLongExtra("size", -1)
}
private val listPath by lazy {
intent.getStringArrayExtra("list") ?: arrayOf()
}
override fun initView() {
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
MainScope().launch(Dispatchers.IO) {
try {
listPath.forEach {
val file = File(it)
runCatching { file.deleteRecursively() }
}
updateMediaStore(listPath)
} catch (_: Exception) {
} finally {
}
}
playAnm()
}
override fun initListener() {
onBackPressedDispatcher.addCallback {
Toast.makeText(this@CleaningActivity, "wait a moment", Toast.LENGTH_SHORT).show()
}
}
private fun playAnm() {
ValueAnimator.ofFloat(0f, 360f).run {
duration = 1000
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
interpolator = LinearInterpolator()
addUpdateListener {
binding.idYuan.rotation = it.animatedValue as Float
}
start()
}
ValueAnimator.ofInt(0, 100).run {
duration = Random.nextLong(7000, 8000)
interpolator = LinearInterpolator()
addUpdateListener {
binding.idTvJd.text = "${it.animatedValue as Int}"
}
doOnEnd {
val isCleanEndAdSp = AppPreferences.getInstance().getString("isCleanEndAdSp", "1").toInt()
if (isCleanEndAdSp == 1) {
AdmobInterstitialUtils.showInterstitialAd(this@CleaningActivity) {
// startActivity(
// Intent(this@com.base.pdfviewerscannerwhite.ui.cleanjunk.CleaningActivity, ResultActivity::class.java).putExtra("from", JUNK_CLEANER)
// .putExtra("clean_size", intentSize)
// )
finish()
}
} else {
// startActivity(
// Intent(this@com.base.pdfviewerscannerwhite.ui.cleanjunk.CleaningActivity, ResultActivity::class.java).putExtra("from", JUNK_CLEANER)
// .putExtra("clean_size", intentSize)
// )
finish()
}
}
start()
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.cleanjunk
import android.annotation.SuppressLint
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.ParentBean
import com.base.pdfviewerscannerwhite.databinding.ItemJunkChildBinding
import com.base.pdfviewerscannerwhite.databinding.ItemJunkParentBinding
import com.base.pdfviewerscannerwhite.utils.KotlinExt.toFormatSize
import com.base.pdfviewerscannerwhite.utils.XmlEx.inflate
import pokercc.android.expandablerecyclerview.ExpandableAdapter
import java.io.File
class JunkExpandAdapter(private val selectAction: (size: Long) -> Unit) : ExpandableAdapter<ExpandableAdapter.ViewHolder>() {
private val beanList = arrayListOf<ParentBean>()
override fun getChildCount(groupPosition: Int): Int {
return beanList[groupPosition].childItem.size
}
override fun getGroupCount(): Int {
return beanList.size
}
override fun onCreateChildViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(R.layout.item_junk_child.inflate(viewGroup))
}
override fun onCreateGroupViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(R.layout.item_junk_parent.inflate(viewGroup))
}
override fun onBindChildViewHolder(holder: ViewHolder, groupPosition: Int, childPosition: Int, payloads: List<Any>) {
val binding = ItemJunkChildBinding.bind(holder.itemView)
val parentBean = beanList[groupPosition]
val childBeanList = parentBean.childItem
val childBean = childBeanList[childPosition]
if (payloads.isEmpty()) {
if (childBean.apkIcon == null) binding.iv.setImageResource(childBean.icon) else binding.iv.setImageDrawable(childBean.apkIcon)
val file = File(childBean.path)
binding.tvName.text = file.name
binding.tvSize.text = file.length().toFormatSize()
binding.ivSelector.isSelected = childBean.isSelect
binding.root.setOnClickListener {
childBean.isSelect = !childBean.isSelect
notifyChildChange(groupPosition, childPosition, "aaa")
val allSelect = childBeanList.all { it.isSelect }
if (parentBean.isSelect != allSelect) {
parentBean.isSelect = allSelect
notifyGroupChange(groupPosition, "aa")
}
selectChange()
}
if (childBean.playAnimation) {
val slideInFromRight = AnimationUtils.loadAnimation(holder.itemView.context, R.anim.slide_in_from_right)
binding.root.startAnimation(slideInFromRight)
childBean.playAnimation = false
}
} else {
binding.ivSelector.isSelected = childBean.isSelect
}
}
@SuppressLint("NotifyDataSetChanged")
override fun onBindGroupViewHolder(holder: ViewHolder, groupPosition: Int, expand: Boolean, payloads: List<Any>) {
val binding = ItemJunkParentBinding.bind(holder.itemView)
val bean = beanList[groupPosition]
bean.isExpand = expand
if (bean.isExpand) {
binding.ivExpand.setImageResource(R.mipmap.zhankai)
} else {
binding.ivExpand.setImageResource(R.mipmap.shouqi)
}
if (payloads.isEmpty()) {
binding.tvName.text = bean.tittle
val size = bean.childItem.sumOf { File(it.path).length() }
binding.tvSize.text = size.toFormatSize()
binding.flExpand.setOnClickListener {
bean.isExpand = !bean.isExpand
notifyGroupChange(groupPosition, "aa")
if (bean.isExpand) {
expandGroup(groupPosition, true)
} else {
collapseGroup(groupPosition, true)
}
}
binding.ivSelector.isSelected = bean.isSelect
binding.flSelector.setOnClickListener {
bean.isSelect = !bean.isSelect
bean.childItem.forEach { it.isSelect = bean.isSelect }
notifyDataSetChanged()
selectChange()
}
if (bean.playAnimation) {
val slideInFromRight = AnimationUtils.loadAnimation(holder.itemView.context, R.anim.slide_in_from_right)
binding.root.startAnimation(slideInFromRight)
bean.playAnimation = false
}
} else {
binding.ivSelector.isSelected = bean.isSelect
}
}
override fun onGroupViewHolderExpandChange(holder: ViewHolder, groupPosition: Int, animDuration: Long, expand: Boolean) {}
@SuppressLint("NotifyDataSetChanged")
fun addData(list: List<ParentBean>, clear: Boolean = true) {
if (clear) {
beanList.clear()
}
beanList.addAll(list)
notifyDataSetChanged()
}
private fun selectChange() {
val size = beanList.flatMap { it.childItem }.filter { it.isSelect }.sumOf { bean -> File(bean.path).length() }
selectAction.invoke(size)
}
fun getChoosePath(): List<String> {
return beanList.flatMap { it.childItem }.filter { it.isSelect }.map { it.path }
}
}
package com.base.pdfviewerscannerwhite.ui.cleanjunk
import android.animation.ValueAnimator
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.view.animation.LinearInterpolator
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.ParentBean
import com.base.pdfviewerscannerwhite.databinding.ItemJunkParentScanBinding
import com.base.pdfviewerscannerwhite.utils.XmlEx.inflate
class JunkScanAdapter : RecyclerView.Adapter<JunkScanAdapter.ParentViewHolder>() {
private val beanList = arrayListOf<ParentBean>()
inner class ParentViewHolder(view: View) : RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ParentViewHolder {
return ParentViewHolder(R.layout.item_junk_parent_scan.inflate(parent))
}
override fun getItemCount(): Int {
return beanList.size
}
override fun onBindViewHolder(holder: ParentViewHolder, position: Int) {
val bean = beanList[position]
val context = holder.itemView.context
val binding = ItemJunkParentScanBinding.bind(holder.itemView)
binding.ivIcon.setImageResource(bean.icon)
binding.tvTitle.text = bean.tittle
if (bean.playAnimation) {
val slideInFromRight = AnimationUtils.loadAnimation(holder.itemView.context, R.anim.slide_in_from_right)
binding.ll.startAnimation(slideInFromRight)
bean.playAnimation = false
}
if (bean.finished) {
binding.ivRotate.rotation = 0f
binding.ivRotate.setImageDrawable(ContextCompat.getDrawable(context, R.mipmap.xuan))
bean.rotateValueAnimator?.cancel()
bean.rotateValueAnimator = null
} else {
bean.rotateValueAnimator = ValueAnimator.ofFloat(0f, 360f).apply {
duration = 1000
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
interpolator = LinearInterpolator()
addUpdateListener {
binding.ivRotate.rotation = it.animatedValue as Float
}
start()
}
}
}
fun addData(bean: ParentBean, position: Int) {
beanList.add(bean)
notifyItemChanged(position)
}
fun setFinishScan(position: Int) {
val bean = beanList[position]
bean.finished = true
notifyItemChanged(position)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.cleanjunk
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Environment
import android.view.View
import androidx.activity.addCallback
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.ads.admob.AdmobInterstitialUtils
import com.base.pdfviewerscannerwhite.bean.ChildBean
import com.base.pdfviewerscannerwhite.bean.ParentBean
import com.base.pdfviewerscannerwhite.databinding.ActivityScanJunkBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.helper.MyApplication
import com.base.pdfviewerscannerwhite.utils.AppPreferences
import com.base.pdfviewerscannerwhite.utils.BarUtils
import com.base.pdfviewerscannerwhite.utils.FileHelp.getFileFolder
import com.base.pdfviewerscannerwhite.utils.KotlinExt.toFormatSize
import com.base.pdfviewerscannerwhite.utils.PermissionUtils.checkStorePermission
import com.base.pdfviewerscannerwhite.utils.queryFiles
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.io.File
import kotlin.random.Random
class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {
private lateinit var junkScanAdapter: JunkScanAdapter
private lateinit var junkExpandAdapter: JunkExpandAdapter
override val binding: ActivityScanJunkBinding by lazy {
ActivityScanJunkBinding.inflate(layoutInflater)
}
private val mPathFlow = MutableSharedFlow<String>(
replay = 5,//当新的订阅者Collect时,发送几个已经发送过的数据给它
extraBufferCapacity = 5,//减去replay,MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity
onBufferOverflow = BufferOverflow.DROP_OLDEST//缓存策略,三种 丢掉最新值、丢掉最旧值和挂起
)
private val pathFlow: SharedFlow<String> = mPathFlow
private var cleanSize: Long = 0L
@SuppressLint("SetTextI18n")
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
// binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
junkScanAdapter = JunkScanAdapter()
binding.rv.adapter = junkScanAdapter
junkExpandAdapter = JunkExpandAdapter { size ->
cleanSize = size
if (size > 0) {
binding.tvBtn.text = "Clean up ${size.toFormatSize()}"
} else {
binding.tvBtn.text = "Got it"
}
}
binding.rvEx.adapter = junkExpandAdapter
lifecycleScope.launch(Dispatchers.Main) {
pathFlow.collectLatest {
binding.tvPath.text = it
}
}
//record last use junk clean function time
AppPreferences.getInstance().put("last_use_junk_clean", System.currentTimeMillis())
beginScan()
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
AdmobInterstitialUtils.showInterstitialAd(this@ScanJunkActivity, false) {
finishToMain()
}
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.tvBtn.setOnClickListener {
if (binding.tvBtn.text == "Got it") {
// startActivity(Intent(this, ResultActivity::class.java).apply {
// putExtra("from", ConstObject.JUNK_CLEANER)
// })
// finish()
} else {
startActivity(Intent(this, CleaningActivity::class.java).apply {
val list = junkExpandAdapter.getChoosePath()
putExtra("list", list.toTypedArray())
putExtra("size", cleanSize)
})
finish()
}
}
}
@SuppressLint("SetTextI18n")
private fun beginScan() = lifecycleScope.launch(Dispatchers.Main) {
var size = 0L
junkScanAdapter.addData(ParentBean(R.mipmap.x_residual, "Residual File"), 0)
delay(Random.nextLong(500, 1500))
junkScanAdapter.addData(ParentBean(R.mipmap.x_useless, "Useless installation package"), 1)
delay(Random.nextLong(500, 1500))
junkScanAdapter.addData(ParentBean(R.mipmap.x_temp, "Temp Files"), 2)
delay(Random.nextLong(500, 1500))
junkScanAdapter.addData(ParentBean(R.mipmap.x_residual, "Log Files"), 3)
val emptyFolder = arrayListOf<File>()
arrayOf(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC),
).forEach { dir ->
val list = getFileFolder(mPathFlow, dir, filter = { it.listFiles().isNullOrEmpty() }).await()
emptyFolder.addAll(list)
}
size = emptyFolder.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(0)
val apkList = queryFiles(this@ScanJunkActivity, ".apk", mPathFlow).await()
size += apkList.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(1)
val tempList = queryFiles(this@ScanJunkActivity, ".temp", mPathFlow).await()
size += tempList.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(2)
val logList = queryFiles(this@ScanJunkActivity, ".log", mPathFlow).await()
size += logList.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(3)
delay(Random.nextLong(500, 1000))
binding.rv.visibility = View.GONE
binding.rvEx.visibility = View.VISIBLE
// if (emptyFolder.isNotEmpty()) {
val childList1 = emptyFolder.map { ChildBean(R.mipmap.d_reseiual, it.absolutePath) }
val emptyParent = ParentBean(tittle = "Residual File", childItem = childList1)
junkExpandAdapter.addData(listOf(emptyParent), false)
junkExpandAdapter.expandAllGroup()
// }
if (apkList.isNotEmpty()) {
val childList2 = apkList.map {
ChildBean(R.mipmap.d_useless, it.absolutePath).apply { apkIcon = getApkDrawable(it.absolutePath) }
}
val apkParent = ParentBean(tittle = "Useless installation package", childItem = childList2)
junkExpandAdapter.addData(listOf(apkParent), false)
junkExpandAdapter.expandAllGroup()
}
if (tempList.isNotEmpty()) {
val childList3 = tempList.map { ChildBean(R.mipmap.d_temp, it.absolutePath) }
val tempParent = ParentBean(tittle = "Temp Files", childItem = childList3)
junkExpandAdapter.addData(listOf(tempParent), false)
junkExpandAdapter.expandAllGroup()
}
if (logList.isNotEmpty()) {
val childList4 = logList.map { ChildBean(R.mipmap.d_log, it.absolutePath) }
val logParent = ParentBean(tittle = "Log Files", childItem = childList4)
junkExpandAdapter.addData(listOf(logParent), false)
junkExpandAdapter.expandAllGroup()
}
binding.progressBar.visibility = View.GONE
binding.clTop.setBackgroundResource(R.mipmap.hong_bg)
binding.tvPath.visibility = View.GONE
binding.tvBtn.isEnabled = true
binding.tvBtn.setTextColor(ContextCompat.getColor(this@ScanJunkActivity, R.color.white))
cleanSize = size
if (size > 0) {
binding.tvBtn.text = "Clean up ${size.toFormatSize()}"
} else {
binding.tvBtn.text = "Got it"
}
}
private fun setSize(size: Long) {
val split = size.toFormatSize().split(" ")
binding.tvSize.text = split[0]
binding.tvUnit.text = split[1]
}
private fun getApkDrawable(apkPath: String): Drawable? {
val packageInfo = packageManager.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES)
if (packageInfo != null) {
val applicationInfo = packageInfo.applicationInfo
return packageManager.getApplicationIcon(applicationInfo)
}
return null
}
companion object {
fun fastGetJunkSize(context: Context = MyApplication.context): Long {
if (!context.checkStorePermission()) {
return 0
}
var size = 0L
val emptyFolder = arrayListOf<File>()
arrayOf(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC),
).forEach { dir ->
val list = getFileFolder(dir, filter = { it.listFiles().isNullOrEmpty() })
emptyFolder.addAll(list)
}
size = emptyFolder.sumOf { it.length() }
val apkList = queryFiles(context, ".apk")
size += apkList.sumOf { it.length() }
val tempList = queryFiles(context, ".apk")
size += tempList.sumOf { it.length() }
val logList = queryFiles(context, ".apk")
size += logList.sumOf { it.length() }
return size
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.utils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableSharedFlow
import java.io.File
import java.util.LinkedList
object FileHelp {
fun CoroutineScope.getFileFolder(
flow: MutableSharedFlow<String>? = null,
file: File,
filter: (file: File) -> Boolean
) = async(Dispatchers.IO) {
val set = HashSet<File>()
//添加第一层文件到链表
val linkList = LinkedList<File>()
val fileList = file.listFiles()
fileList?.forEach {
if (it.isDirectory) {
flow?.emit(it.absolutePath)
linkList.add(it)
if (filter.invoke(it)) {
set.add(it)
}
}
}
//链表取文件
var tempFile: File
while (!linkList.isEmpty()) {
tempFile = linkList.removeFirst()
val tempFileList = tempFile.listFiles()
tempFileList?.forEach {
if (it.isDirectory) {
flow?.emit(it.absolutePath)
linkList.add(it)
if (filter.invoke(it)) {
set.add(it)
}
}
}
}
set.toList()
}
fun getFileFolder(
file: File,
filter: (file: File) -> Boolean
): List<File> {
val set = HashSet<File>()
//添加第一层文件到链表
val linkList = LinkedList<File>()
val fileList = file.listFiles()
fileList?.forEach {
if (it.isDirectory) {
linkList.add(it)
if (filter.invoke(it)) {
set.add(it)
}
}
}
//链表取文件
var tempFile: File
while (!linkList.isEmpty()) {
tempFile = linkList.removeFirst()
val tempFileList = tempFile.listFiles()
tempFileList?.forEach {
if (it.isDirectory) {
linkList.add(it)
if (filter.invoke(it)) {
set.add(it)
}
}
}
}
return set.toList()
}
}
\ No newline at end of file
...@@ -126,274 +126,274 @@ fun Context.getMediaFile(selectionArgs: Array<String>? = null): ArrayList<MediaB ...@@ -126,274 +126,274 @@ fun Context.getMediaFile(selectionArgs: Array<String>? = null): ArrayList<MediaB
} }
@SuppressLint("Range") //@SuppressLint("Range")
fun Context.getMediaPhotoCountSize(): Pair<Int, Long> { //fun Context.getMediaPhotoCountSize(): Pair<Int, Long> {
var count = 0 // var count = 0
var totalSize = 0L // var totalSize = 0L
runCatching { // runCatching {
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI // val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.SIZE) // val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.SIZE)
//
// 执行查询 // // 执行查询
val cursor = contentResolver.query(uri, projection, null, null, null) // val cursor = contentResolver.query(uri, projection, null, null, null)
//
// 检查cursor是否包含数据 // // 检查cursor是否包含数据
count = cursor?.count ?: 0 // count = cursor?.count ?: 0
while (cursor?.moveToNext() == true) { // while (cursor?.moveToNext() == true) {
totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE)) // totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
} // }
// 关闭cursor // // 关闭cursor
cursor?.close() // cursor?.close()
} // }
//
//
return Pair(count, totalSize) // return Pair(count, totalSize)
} //}
fun Context.getMediaPhoto(): List<MediaBean> { //fun Context.getMediaPhoto(): List<MediaBean> {
//
val list = arrayListOf<MediaBean>() // val list = arrayListOf<MediaBean>()
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI // val baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA) // val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA)
//
// 执行查询 // // 执行查询
var cursor: Cursor? = null // var cursor: Cursor? = null
//
try { // try {
cursor = contentResolver.query(baseUri, projection, null, null, null) // cursor = contentResolver.query(baseUri, projection, null, null, null)
//
if (cursor != null) { // if (cursor != null) {
while (cursor.moveToNext()) { // while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)) // val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
val uri = Uri.withAppendedPath(baseUri, id.toString()) // val uri = Uri.withAppendedPath(baseUri, id.toString())
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)) // val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
list.add(MediaBean(path = path, uri = uri, mimeType = "image/*")) // list.add(MediaBean(path = path, uri = uri, mimeType = "image/*"))
} // }
} // }
} catch (e: Exception) { // } catch (e: Exception) {
//
} finally { // } finally {
cursor?.close() // cursor?.close()
} // }
//
return list // return list
} //}
fun Context.getMediaVideo(): List<MediaBean> { //fun Context.getMediaVideo(): List<MediaBean> {
//
val list = arrayListOf<MediaBean>() // val list = arrayListOf<MediaBean>()
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val baseUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI // val baseUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA, MediaStore.Video.Media.MIME_TYPE) // val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA, MediaStore.Video.Media.MIME_TYPE)
//
// 执行查询 // // 执行查询
var cursor: Cursor? = null // var cursor: Cursor? = null
//
try { // try {
cursor = contentResolver.query(baseUri, projection, null, null, null) // cursor = contentResolver.query(baseUri, projection, null, null, null)
//
if (cursor != null) { // if (cursor != null) {
while (cursor.moveToNext()) { // while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)) // val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
val uri = Uri.withAppendedPath(baseUri, id.toString()) // val uri = Uri.withAppendedPath(baseUri, id.toString())
LogEx.logDebug(TAG, "getMediaVideo uri=$uri") // LogEx.logDebug(TAG, "getMediaVideo uri=$uri")
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)) // val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE)) // val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE))
list.add(MediaBean(path = path, uri = uri, mimeType = mimeType)) // list.add(MediaBean(path = path, uri = uri, mimeType = mimeType))
} // }
} // }
} catch (e: Exception) { // } catch (e: Exception) {
//
} finally { // } finally {
cursor?.close() // cursor?.close()
} // }
//
return list // return list
} //}
fun Context.getMediaAudio(): List<MediaBean> { //fun Context.getMediaAudio(): List<MediaBean> {
//
val list = arrayListOf<MediaBean>() // val list = arrayListOf<MediaBean>()
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val baseUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI // val baseUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.MIME_TYPE) // val projection = arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.MIME_TYPE)
//
// 执行查询 // // 执行查询
var cursor: Cursor? = null // var cursor: Cursor? = null
//
try { // try {
cursor = contentResolver.query(baseUri, projection, null, null, null) // cursor = contentResolver.query(baseUri, projection, null, null, null)
//
if (cursor != null) { // if (cursor != null) {
while (cursor.moveToNext()) { // while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)) // val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
val uri = Uri.withAppendedPath(baseUri, id.toString()) // val uri = Uri.withAppendedPath(baseUri, id.toString())
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)) // val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE)) // val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE))
list.add(MediaBean(path = path, uri = uri, mimeType = mimeType)) // list.add(MediaBean(path = path, uri = uri, mimeType = mimeType))
} // }
} // }
} catch (e: Exception) { // } catch (e: Exception) {
//
} finally { // } finally {
cursor?.close() // cursor?.close()
} // }
//
return list // return list
} //}
@SuppressLint("Range") //@SuppressLint("Range")
fun Context.getMediaVideoCountSize(): Pair<Int, Long> { //fun Context.getMediaVideoCountSize(): Pair<Int, Long> {
//
var count = 0 // var count = 0
var totalSize: Long = 0 // var totalSize: Long = 0
//
runCatching { // runCatching {
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI // val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.SIZE) // val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.SIZE)
//
// 执行查询 // // 执行查询
val cursor = contentResolver.query(uri, projection, null, null, null) // val cursor = contentResolver.query(uri, projection, null, null, null)
//
// 检查cursor是否包含数据 // // 检查cursor是否包含数据
count = cursor?.count ?: 0 // count = cursor?.count ?: 0
while (cursor?.moveToNext() == true) { // while (cursor?.moveToNext() == true) {
totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE)) // totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
} // }
// 关闭cursor // // 关闭cursor
cursor?.close() // cursor?.close()
} // }
return Pair(count, totalSize) // return Pair(count, totalSize)
} //}
@SuppressLint("Range") //@SuppressLint("Range")
fun Context.getMediaAudioCountSize(): Pair<Int, Long> { //fun Context.getMediaAudioCountSize(): Pair<Int, Long> {
var count = 0 // var count = 0
var totalSize: Long = 0 // var totalSize: Long = 0
runCatching { // runCatching {
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI // val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf( // val projection = arrayOf(
MediaStore.Audio.Media._ID, // MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.SIZE, // MediaStore.Audio.Media.SIZE,
) // )
//
// 执行查询 // // 执行查询
val cursor = contentResolver.query(uri, projection, null, null, null) // val cursor = contentResolver.query(uri, projection, null, null, null)
//
// 检查cursor是否包含数据 // // 检查cursor是否包含数据
count = cursor?.count ?: 0 // count = cursor?.count ?: 0
while (cursor?.moveToNext() == true) { // while (cursor?.moveToNext() == true) {
totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)) // totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE))
} // }
//
// 关闭cursor // // 关闭cursor
cursor?.close() // cursor?.close()
} // }
return Pair(count, totalSize) // return Pair(count, totalSize)
} //}
fun Context.getMediaDocumentCountSize(): Int { //fun Context.getMediaDocumentCountSize(): Int {
var count = 0 // var count = 0
runCatching { // runCatching {
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
val mimeTypeSelectionArgs = arrayOf( // val mimeTypeSelectionArgs = arrayOf(
MIME_TYPE_PDF, // MIME_TYPE_PDF,
MIME_TYPE_DOC, // MIME_TYPE_DOC,
MIME_TYPE_DOCX, // MIME_TYPE_DOCX,
MIME_TYPE_XLS, // MIME_TYPE_XLS,
MIME_TYPE_XLSX, // MIME_TYPE_XLSX,
MIME_TYPE_PPT, // MIME_TYPE_PPT,
MIME_TYPE_PPTX, // MIME_TYPE_PPTX,
) // )
val mimeTypeSelection = // val mimeTypeSelection =
"${MediaStore.Files.FileColumns.MIME_TYPE} IN (" + mimeTypeSelectionArgs.joinToString(",") { "?" } + ")" // "${MediaStore.Files.FileColumns.MIME_TYPE} IN (" + mimeTypeSelectionArgs.joinToString(",") { "?" } + ")"
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val uri = MediaStore.Files.getContentUri("external") // val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(MediaStore.Files.FileColumns._ID) // val projection = arrayOf(MediaStore.Files.FileColumns._ID)
//
// 执行查询 // // 执行查询
val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null) // val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)
//
// 检查cursor是否包含数据 // // 检查cursor是否包含数据
count = cursor?.count ?: 0 // count = cursor?.count ?: 0
//
// 关闭cursor // // 关闭cursor
cursor?.close() // cursor?.close()
} // }
return count // return count
} //}
fun Context.getMediaApkCountSize(): Int { //fun Context.getMediaApkCountSize(): Int {
var count = 0 // var count = 0
runCatching { // runCatching {
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
val mimeTypeSelectionArgs = arrayOf( // val mimeTypeSelectionArgs = arrayOf(
MIME_TYPE_APK // MIME_TYPE_APK
) // )
val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?" // val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val uri = MediaStore.Files.getContentUri("external") // val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(MediaStore.Files.FileColumns._ID) // val projection = arrayOf(MediaStore.Files.FileColumns._ID)
//
// 执行查询 // // 执行查询
val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null) // val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)
//
// 检查cursor是否包含数据 // // 检查cursor是否包含数据
count = cursor?.count ?: 0 // count = cursor?.count ?: 0
//
// 关闭cursor // // 关闭cursor
cursor?.close() // cursor?.close()
} // }
return count // return count
} //}
fun Context.getMediaZipCountSize(): Int { //fun Context.getMediaZipCountSize(): Int {
var count = 0 // var count = 0
runCatching { // runCatching {
val contentResolver = this.contentResolver // val contentResolver = this.contentResolver
//
val mimeTypeSelectionArgs = arrayOf( // val mimeTypeSelectionArgs = arrayOf(
MIME_TYPE_ZIP // MIME_TYPE_ZIP
) // )
val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?" // val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
//
// 定义查询的Uri和列 // // 定义查询的Uri和列
val uri = MediaStore.Files.getContentUri("external") // val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(MediaStore.Files.FileColumns._ID) // val projection = arrayOf(MediaStore.Files.FileColumns._ID)
//
// 执行查询 // // 执行查询
val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null) // val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)
//
// 检查cursor是否包含数据 // // 检查cursor是否包含数据
count = cursor?.count ?: 0 // count = cursor?.count ?: 0
//
// 关闭cursor // // 关闭cursor
cursor?.close() // cursor?.close()
} // }
return count // return count
} //}
private fun getFileTypeSelection(fileSuffix: String): String { private fun getFileTypeSelection(fileSuffix: String): String {
return (MediaStore.Files.FileColumns.MEDIA_TYPE + "=" return (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
...@@ -451,22 +451,22 @@ fun queryFiles(context: Context, fileSuffix: String): MutableList<File> { ...@@ -451,22 +451,22 @@ fun queryFiles(context: Context, fileSuffix: String): MutableList<File> {
return fileList return fileList
} }
fun getFileNameFromUri(context: Context, uri: Uri): String { //fun getFileNameFromUri(context: Context, uri: Uri): String {
var displayName = "" // var displayName = ""
if (DocumentsContract.isDocumentUri(context, uri)) { // if (DocumentsContract.isDocumentUri(context, uri)) {
val projection = arrayOf(OpenableColumns.DISPLAY_NAME) // val projection = arrayOf(OpenableColumns.DISPLAY_NAME)
var cursor: Cursor? = null // var cursor: Cursor? = null
try { // try {
cursor = context.contentResolver.query(uri, projection, null, null, null) // cursor = context.contentResolver.query(uri, projection, null, null, null)
val column_index = cursor!!.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME) // val column_index = cursor!!.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
if (cursor.moveToFirst()) { // if (cursor.moveToFirst()) {
displayName = cursor.getString(column_index) // displayName = cursor.getString(column_index)
} // }
} catch (e: java.lang.Exception) { // } catch (e: java.lang.Exception) {
e.printStackTrace() // e.printStackTrace()
} finally { // } finally {
cursor?.close() // cursor?.close()
} // }
} // }
return displayName // return displayName
} //}
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="800"
android:fillAfter="true"
android:fromXDelta="100%p"
android:startOffset="0"
android:toXDelta="0" />
</set>
\ 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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="169dp"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/id_bottom_content"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/id_yuan"
android:layout_width="229dp"
android:layout_height="229dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/qingliz" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="124dp"
android:layout_height="124dp"
android:layout_gravity="center"
android:src="@mipmap/qingliyuan" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<TextView
android:id="@+id/id_tv_jd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@color/white"
android:textSize="48sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="%"
android:textColor="@color/white"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</androidx.appcompat.widget.LinearLayoutCompat>
</FrameLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/id_bottom_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="150dp"
android:text="Wait a moment..."
android:textColor="#666666"
android:textSize="16sp"
tools:ignore="HardcodedText" />
</androidx.appcompat.widget.LinearLayoutCompat>
</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=".ui.activity.cleanjunk.ScanJunkActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@mipmap/lan_bg"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/b_fanhui"
tools:ignore="ContentDescription,MissingPrefix" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="Clean Junk"
android:textColor="@color/white"
android:textSize="19sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:text="0"
android:textColor="@color/white"
android:textSize="54sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll"
app:layout_constraintVertical_bias="0.3"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_size" />
<ProgressBar
android:id="@+id/progress_bar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="16dp"
android:indeterminate="true"
android:indeterminateTint="@color/white"
android:indeterminateTintMode="src_atop"
app:layout_constraintBottom_toTopOf="@id/tv_path" />
<TextView
android:id="@+id/tv_path"
android:layout_width="match_parent"
android:layout_height="35dp"
android:background="#1A000000"
android:ellipsize="middle"
android:gravity="center_vertical"
android:paddingHorizontal="15dp"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
tools:ignore="RtlSymmetry"
tools:layout_editor_absoluteX="0dp"
tools:text="Scan in progress:/storage/emulated/0/qitu/download" />
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/tv_btn"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<pokercc.android.expandablerecyclerview.ExpandableRecyclerView
android:id="@+id/rv_ex"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</FrameLayout>
<TextView
android:id="@+id/tv_btn"
android:layout_width="338dp"
android:layout_height="50dp"
android:layout_marginBottom="30dp"
android:background="@drawable/bg_clean_btn"
android:enabled="false"
android:gravity="center"
android:text="Scan in progress"
android:textColor="#AEAEB0"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="10dp">
<ImageView
android:id="@+id/iv"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginVertical="6dp"
tools:ignore="ContentDescription"
tools:src="@mipmap/d_reseiual" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="8dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="14sp"
tools:text="Ali Webpage ads" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="Suggestion: Clean up"
android:textColor="#999999"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="#FF8523"
android:textSize="14sp"
tools:text="12.72 MB" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="16dp"
android:src="@drawable/bg_circle_selector"
tools:ignore="ContentDescription" />
</LinearLayout>
\ 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="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_expand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:padding="10dp">
<ImageView
android:id="@+id/iv_expand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/zhankai"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="8dp"
android:layout_weight="1"
android:textColor="@color/black"
android:textSize="15sp"
tools:text="Residual File" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="#FF8523"
android:textSize="14sp"
tools:text="12.72 MB" />
<FrameLayout
android:id="@+id/fl_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
android:padding="10dp">
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/bg_circle_selector"
tools:ignore="ContentDescription" />
</FrameLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#E5E6EB"
app:layout_constraintBottom_toBottomOf="parent" />
</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="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="8dp">
<ImageView
android:id="@+id/iv_rotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/jiazai"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/ll"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_rotate"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="12dp"
tools:ignore="ContentDescription"
tools:src="@mipmap/d_reseiual" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="11dp"
android:text="Residual File"
android:textColor="@color/black"
android:textSize="15sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="1px"
android:background="#E5E6EB"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/ll" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment