筛选和排序

This commit is contained in:
litingting 2025-09-29 18:30:36 +08:00
parent 2b8bdcb10c
commit a204314d92
83 changed files with 2409 additions and 646 deletions

View File

@ -52,4 +52,6 @@ dependencies {
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
implementation (libs.glide) implementation (libs.glide)
kapt (libs.compiler) kapt (libs.compiler)
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation ("com.google.android.material:material:1.13.0")
} }

View File

@ -13,6 +13,7 @@
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<application <application
android:name=".App"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"

View File

@ -0,0 +1,14 @@
package com.ux.video.file.filerecovery
import android.app.Application
class App: Application() {
companion object{
lateinit var mAppContext: App
}
override fun onCreate() {
super.onCreate()
mAppContext = this
}
}

View File

@ -13,7 +13,6 @@ abstract class BaseAdapter<K, T : ViewBinding>(
protected val data: MutableList<K> = mutableListOf() protected val data: MutableList<K> = mutableListOf()
fun addData(items: List<K>?) { fun addData(items: List<K>?) {
items?.let { items?.let {
val start = data.size val start = data.size

View File

@ -0,0 +1,50 @@
package com.ux.video.file.filerecovery.base
import android.content.Context
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
abstract class NewBaseAdapter<K>(
protected val mContext: Context
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
protected val data: MutableList<K> = mutableListOf()
fun addData(items: List<K>?) {
items?.let {
val start = data.size
data.addAll(it)
notifyItemRangeInserted(start, it.size)
}
}
fun setData(items: List<K>?) {
data.clear()
items?.let { data.addAll(it) }
notifyDataSetChanged()
}
override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return onCreateBinding(parent, viewType)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
onBind(holder, data[position], getItemViewType(position))
}
/**
* 子类实现根据 viewType 创建对应的 ViewHolder
*/
protected abstract fun onCreateBinding(
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder
/**
* 子类实现绑定数据
*/
protected abstract fun onBind(holder: RecyclerView.ViewHolder, item: K, viewType: Int)
}

View File

@ -24,9 +24,9 @@ class DocumentsScanResultActivity : BaseActivity<ActivityDocumentsScanResultBind
override fun initData() { override fun initData() {
super.initData() super.initData()
ScanRepository.instance.photoResults.observe(this@DocumentsScanResultActivity) { // ScanRepository.instance.photoResults.observe(this@DocumentsScanResultActivity) {
resultAdapter?.setData(it) // resultAdapter?.setData(it)
} // }
} }

View File

@ -6,6 +6,15 @@ import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseActivity import com.ux.video.file.filerecovery.base.BaseActivity
import com.ux.video.file.filerecovery.databinding.ActivityScanSelectTypeBinding import com.ux.video.file.filerecovery.databinding.ActivityScanSelectTypeBinding
import com.ux.video.file.filerecovery.result.ScanningActivity import com.ux.video.file.filerecovery.result.ScanningActivity
import com.ux.video.file.filerecovery.utils.Common.KEY_SCAN_TYPE
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_video
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video
import kotlin.properties.Delegates import kotlin.properties.Delegates
class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() { class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
@ -30,19 +39,20 @@ class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
setSelectType(type) setSelectType(type)
} }
override fun initData() { override fun initData() {
super.initData() super.initData()
binding.imageBack.setOnClickListener { finish() } binding.imageBack.setOnClickListener { finish() }
binding.scanAllFile.setOnClickListener { binding.scanAllFile.setOnClickListener {
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply { startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
putExtra(ScanningActivity.Companion.KEY_SCAN_TYPE, allType) putExtra(KEY_SCAN_TYPE, allType)
}) })
} }
binding.scanDeletedFile.setOnClickListener { binding.scanDeletedFile.setOnClickListener {
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply { startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
putExtra(ScanningActivity.Companion.KEY_SCAN_TYPE, deletedType) putExtra(KEY_SCAN_TYPE, deletedType)
}) })
} }
} }
@ -50,26 +60,26 @@ class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
private fun setSelectType(fileType: Int) { private fun setSelectType(fileType: Int) {
when (fileType) { when (fileType) {
VALUE_PHOTO -> { VALUE_PHOTO -> {
allType = ScanningActivity.Companion.VALUE_SCAN_TYPE_photo allType = VALUE_SCAN_TYPE_photo
deletedType = ScanningActivity.Companion.VALUE_SCAN_TYPE_deleted_photo deletedType = VALUE_SCAN_TYPE_deleted_photo
binding.title.text = getString(R.string.photo_title) binding.title.text = getString(R.string.photo_title)
} }
VALUE_VIDEO -> { VALUE_VIDEO -> {
allType = ScanningActivity.Companion.VALUE_SCAN_TYPE_video allType = VALUE_SCAN_TYPE_video
deletedType = ScanningActivity.Companion.VALUE_SCAN_TYPE_deleted_video deletedType = VALUE_SCAN_TYPE_deleted_video
binding.title.text = getString(R.string.video_title) binding.title.text = getString(R.string.video_title)
} }
VALUE_AUDIO -> { VALUE_AUDIO -> {
allType = ScanningActivity.Companion.VALUE_SCAN_TYPE_audio allType = VALUE_SCAN_TYPE_audio
deletedType = ScanningActivity.Companion.VALUE_SCAN_TYPE_deleted_audio deletedType = VALUE_SCAN_TYPE_deleted_audio
binding.title.text = getString(R.string.audio_title) binding.title.text = getString(R.string.audio_title)
} }
VALUE_DOCUMENT -> { VALUE_DOCUMENT -> {
allType = ScanningActivity.Companion.VALUE_SCAN_TYPE_documents allType = VALUE_SCAN_TYPE_documents
deletedType = ScanningActivity.Companion.VALUE_SCAN_TYPE_deleted_documents deletedType = VALUE_SCAN_TYPE_deleted_documents
binding.title.text = getString(R.string.document_title) binding.title.text = getString(R.string.document_title)
} }
} }

View File

@ -0,0 +1,68 @@
package com.ux.video.file.filerecovery.photo
import android.graphics.Color
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.databinding.CommonLayoutSortItemBinding
import com.ux.video.file.filerecovery.databinding.DialogSortBinding
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.DateValidatorPointForward
import java.text.SimpleDateFormat
import java.util.*
class DatePickerDialogFragment(val onClickSort: (type: Int) -> Unit) : DialogFragment() {
private lateinit var binding: DialogSortBinding
override fun onStart() {
super.onStart()
dialog?.window?.apply {
setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
setGravity(Gravity.BOTTOM)
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DialogSortBinding.inflate(inflater)
return binding.root
}
fun showDatePicker() {
// 创建日期选择器构建器
val builder = MaterialDatePicker.Builder.datePicker()
builder.setTitleText("选择日期")
// 可选:限制可选日期,比如只能选择今天之后的日期
val constraintsBuilder = CalendarConstraints.Builder()
constraintsBuilder.setValidator(DateValidatorPointForward.now()) // 今天之后
builder.setCalendarConstraints(constraintsBuilder.build())
val datePicker = builder.build()
// 显示日期选择器
datePicker.show(supportFragmentManager, "MATERIAL_DATE_PICKER")
// 监听用户选择
datePicker.addOnPositiveButtonClickListener { selection ->
// selection 是 Long 类型的时间戳UTC 毫秒)
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val dateString = sdf.format(Date(selection))
println("用户选择的日期:$dateString")
}
}
}

View File

@ -0,0 +1,128 @@
package com.ux.video.file.filerecovery.photo
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
import android.widget.RelativeLayout
import androidx.core.view.forEach
import com.ux.video.file.filerecovery.databinding.CommonLayoutFilterItemBinding
import com.ux.video.file.filerecovery.databinding.PopwindowsFilterBinding
import com.ux.video.file.filerecovery.utils.Common.setItemSelect
import com.ux.video.file.filerecovery.utils.CustomTextView
class FilterPopupWindows(
context: Context, list: Array<String>,
selectedPos: Int,
onClickConfirm: (value: String) -> Unit,
var onClickDismiss: () -> Unit
) :
PopupWindow(context) {
private val viewBinding: PopwindowsFilterBinding =
PopwindowsFilterBinding.inflate(LayoutInflater.from(context))
init {
setContentView(viewBinding.root)
width = ViewGroup.LayoutParams.MATCH_PARENT
height = ViewGroup.LayoutParams.WRAP_CONTENT
isFocusable = true
isOutsideTouchable = true
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
// 动画(可选)
// animationStyle = R.style.PopupAnimation
viewBinding.viewMask.setOnClickListener {
dismiss()
}
setData(list, selectedPos, onClickConfirm)
}
private fun setData(
list: Array<String>,
selectedPos: Int,
onClickConfirm: (value: String) -> Unit
) {
viewBinding.parentLayout.removeAllViews()
list.forEachIndexed { index, item ->
viewBinding.parentLayout.run {
addView(
CommonLayoutFilterItemBinding.inflate(
LayoutInflater.from(context),
this,
false
).apply {
textItem.text = item
if (index == selectedPos) {
textItem.isSelected = true
checkImage.isSelected = true
}
}.root
)
}
}
setMutualExclusion(onClickConfirm)
}
private fun setMutualExclusion(onClickConfirm: (value: String) -> Unit) {
viewBinding.run {
for (i in 0 until parentLayout.childCount) {
val child = parentLayout.getChildAt(i)
if (child is RelativeLayout) {
child.setOnClickListener {
for (j in 0 until parentLayout.childCount) {
val other = parentLayout.getChildAt(j)
if (other is RelativeLayout) {
setItemSelect(other, false)
}
}
setItemSelect(child, true)
for (j in 0 until child.childCount) {
val other = child.getChildAt(j)
if (other is CustomTextView) {
onClickConfirm.invoke(other.text.toString())
}
}
dismiss()
}
}
}
}
}
fun show(anchor: View, xOff: Int = 0, yOff: Int = 0) {
showAsDropDown(anchor, xOff, yOff)
viewBinding.viewMask.apply {
alpha = 0f
animate().alpha(1f).setDuration(200).start()
visibility = View.VISIBLE
}
}
override fun dismiss() {
Log.d("------------", "--------------dismiss")
viewBinding.viewMask.animate().alpha(0f).setDuration(200)
.withEndAction {
super.dismiss()
onClickDismiss.invoke()
}.start()
}
}

View File

@ -1,61 +1,107 @@
package com.ux.video.file.filerecovery.photo package com.ux.video.file.filerecovery.photo
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.ux.video.file.filerecovery.base.BaseAdapter import com.ux.video.file.filerecovery.base.BaseAdapter
import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding
import com.ux.video.file.filerecovery.utils.ExtendFunctions.addItemDecorationOnce import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx import com.ux.video.file.filerecovery.utils.ExtendFunctions.resetItemDecorationOnce
import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration
import com.ux.video.file.filerecovery.utils.ScanRepository
class PhotoDisplayDateAdapter(mContext: Context) : class PhotoDisplayDateAdapter(
mContext: Context,
var mColumns: Int,
var viewModel: ScanRepository,
var onSelectedUpdate: (updatePath: String, isAdd: Boolean) -> Unit
) :
BaseAdapter<Pair<String, List<ResultPhotosFiles>>, PhotoDisplayDateAdapterBinding>(mContext) { BaseAdapter<Pair<String, List<ResultPhotosFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
private var allSelected: Boolean? = null private var allSelected: Boolean? = null
private var columns = 3
override fun getViewBinding(parent: ViewGroup): PhotoDisplayDateAdapterBinding = override fun getViewBinding(parent: ViewGroup): PhotoDisplayDateAdapterBinding =
PhotoDisplayDateAdapterBinding.inflate( PhotoDisplayDateAdapterBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false
) )
/**
* 返回所有嵌套的数据量总数
*/
fun getTotalChildCount(): Int {
return data.sumOf { it.second.size }
}
/**
* activity页面上点击全选按钮执行
*/
fun setAllSelected(allSelect: Boolean) { fun setAllSelected(allSelect: Boolean) {
allSelected = allSelect allSelected = allSelect
data.forEach {
it.second.forEach { item ->
onSelectedUpdate(item.path.toString(),allSelect)
}
}
notifyDataSetChanged() notifyDataSetChanged()
} }
fun setColumns(int: Int){
columns = int fun resetAllValue(b: Boolean?){
allSelected = b
}
fun setColumns(int: Int) {
mColumns = int
notifyDataSetChanged() notifyDataSetChanged()
} }
@SuppressLint("SetTextI18n")
override fun bindItem( override fun bindItem(
holder: VHolder<PhotoDisplayDateAdapterBinding>, holder: VHolder<PhotoDisplayDateAdapterBinding>,
item: Pair<String, List<ResultPhotosFiles>> item: Pair<String, List<ResultPhotosFiles>>
) { ) {
holder.vb.run { holder.vb.run {
val photoDisplayDateChildAdapter = PhotoDisplayDateChildAdapter(mContext)
item.run { item.run {
allSelected?.let {
imSelectStatus.isSelected = it
photoDisplayDateChildAdapter.setAllSelected(it)
}
imSelectStatus.setOnClickListener {
it.isSelected = !it.isSelected
photoDisplayDateChildAdapter.setAllSelected(it.isSelected)
}
val (date, files) = item val (date, files) = item
val childAdapter = PhotoDisplayDateChildAdapter(
mContext,
mColumns,
viewModel
) { path, addOrRemove, isDateAllSelected ->
//点击当前Adapter某一天的全选或者子Item上的选中都会回调到这里
tvDayAllSelect.isSelected = isDateAllSelected
onSelectedUpdate(path.toString(),addOrRemove)
}.apply { setData(files) }
allSelected?.let {
childAdapter.setAllSelected(it)
}
tvDayAllSelect.setOnClickListener {
it.isSelected = !it.isSelected
childAdapter.setAllSelected(it.isSelected)
}
textDate.text = date textDate.text = date
textChildCounts.text = "(${files.size})"
recyclerChild.apply { recyclerChild.apply {
layoutManager = GridLayoutManager(context, columns) layoutManager = GridLayoutManager(context, mColumns)
val gridSpacingItemDecoration = val gridSpacingItemDecoration =
GridSpacingItemDecoration(4, 8.dpToPx(mContext), true) GridSpacingItemDecoration(mColumns, Common.itemSpacing, Common.horizontalSpacing)
addItemDecorationOnce(gridSpacingItemDecoration) Common.showLog("---------mColumns=${mColumns}")
adapter = photoDisplayDateChildAdapter.apply { setData(files) } // resetItemDecorationOnce(gridSpacingItemDecoration)
adapter = childAdapter
isNestedScrollingEnabled = false isNestedScrollingEnabled = false
} }
} }
} }
} }
} }

View File

@ -3,7 +3,11 @@ package com.ux.video.file.filerecovery.photo
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.engine.GlideException
@ -12,55 +16,151 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
import com.ux.video.file.filerecovery.base.BaseAdapter import com.ux.video.file.filerecovery.App
import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateChildAdapterBinding import com.ux.video.file.filerecovery.base.NewBaseAdapter
import com.ux.video.file.filerecovery.databinding.FileSpanCountThreeAdapterBinding
import com.ux.video.file.filerecovery.databinding.FileSpanCountTwoAdapterBinding
import com.ux.video.file.filerecovery.utils.Common import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.CustomTextView
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
import com.ux.video.file.filerecovery.utils.ScanManager import com.ux.video.file.filerecovery.utils.ScanManager
import com.ux.video.file.filerecovery.utils.ScanRepository import com.ux.video.file.filerecovery.utils.ScanRepository
import kotlin.collections.remove
class PhotoDisplayDateChildAdapter(mContext: Context) : class PhotoDisplayDateChildAdapter(
BaseAdapter<ResultPhotosFiles, PhotoDisplayDateChildAdapterBinding>(mContext) { mContext: Context,
var mColumns: Int,
private var allSelected: Boolean? = null var viewModel: ScanRepository,
override fun getViewBinding(parent: ViewGroup): PhotoDisplayDateChildAdapterBinding = /**
PhotoDisplayDateChildAdapterBinding.inflate( * 通知外层某天全选的按钮更新状态
LayoutInflater.from(parent.context), * @param updatePath 当前点击的item
parent, * @param addOrRemove 选中还是取消选中
false * @param dateAllSelected 这组数据是否全部选中某一天
) */
var onSelectedUpdate: (updatePath: String, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit
) :
NewBaseAdapter<ResultPhotosFiles>(mContext) {
fun setAllSelected(allselect: Boolean) { //日期组某一天的数据选择状态维护
allSelected = allselect val dateSelectedMap = mutableSetOf<String>()
companion object {
private const val TYPE_TWO = 2
private const val TYPE_THREE = 3
private const val TYPE_FOUR = 4
}
fun setAllSelected(isAdd: Boolean) {
data.forEach {
addOrRemove(it.path.toString(), isAdd)
}
notifyDataSetChanged() notifyDataSetChanged()
} }
override fun bindItem( override fun getItemViewType(position: Int): Int {
holder: VHolder<PhotoDisplayDateChildAdapterBinding>, return when (mColumns) {
item: ResultPhotosFiles 2 -> TYPE_TWO
3 -> TYPE_THREE
4 -> TYPE_FOUR
else -> TYPE_THREE
}
}
fun setColumns(int: Int) {
mColumns = int
notifyDataSetChanged()
}
/**
* 设置View为正方形
*/
private fun setHeight(view: View) {
val layoutParams = view.layoutParams
val screenWidth = view.context.resources.displayMetrics.widthPixels
val i = (Common.itemSpacing).dpToPx(App.mAppContext) * (mColumns - 1)
val itemSize =
(screenWidth - i - 2 * Common.horizontalSpacing.dpToPx(App.mAppContext) )/ mColumns
view.layoutParams = layoutParams.apply {
height = itemSize
}
}
override fun onCreateBinding(
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
TYPE_TWO -> TwoHolder(
FileSpanCountTwoAdapterBinding.inflate(
inflater,
parent,
false
)
)
else -> ThreeHolder(
FileSpanCountThreeAdapterBinding.inflate(
inflater,
parent,
false
)
)
}
}
override fun onBind(
holder: RecyclerView.ViewHolder,
item: ResultPhotosFiles,
viewType: Int
) { ) {
holder.vb.run { when (holder) {
item.run { is TwoHolder -> holder.vb.run {
imSelectStatus.isSelected = ScanRepository.instance.checkIsSelect(path.toString()) initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item)
allSelected?.let { }
imSelectStatus.isSelected = it
//全选按钮手动触发,需要更新 is ThreeHolder -> holder.vb.run {
updateSetList(it, path.toString()) initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item)
}
} }
imSelectStatus.setOnClickListener {
it.isSelected = !it.isSelected
updateSetList(it.isSelected, path.toString())
} }
class ThreeHolder(val vb: FileSpanCountThreeAdapterBinding) :
RecyclerView.ViewHolder(vb.root)
class TwoHolder(val vb: FileSpanCountTwoAdapterBinding) :
RecyclerView.ViewHolder(vb.root)
private fun initDateView(
rootLayout: RelativeLayout,
imageSelectStatus: ImageView,
textSize: CustomTextView,
imageThumbnail: ImageView,
item: ResultPhotosFiles
) {
item.run {
viewModel.checkIsSelect(path.toString()).let {
imageSelectStatus.isSelected = it
addOrRemove(path.toString(), it)
}
imageSelectStatus.setOnClickListener {
it.isSelected = !it.isSelected
it.isSelected.let { newStatus ->
addOrRemove(path.toString(), newStatus)
}
}
textSize.text = Common.formatFileSize(mContext, size) textSize.text = Common.formatFileSize(mContext, size)
Glide.with(mContext) Glide.with(mContext)
.load(targetFile) .load(targetFile)
.apply( .apply(
RequestOptions() RequestOptions()
.transform(CenterCrop(), RoundedCorners(15.dpToPx(mContext))) .transform(CenterCrop(), RoundedCorners(8.dpToPx(mContext)))
) )
.listener(object : RequestListener<Drawable> { .listener(object : RequestListener<Drawable> {
override fun onLoadFailed( override fun onLoadFailed(
@ -89,12 +189,20 @@ class PhotoDisplayDateChildAdapter(mContext: Context) :
}) })
.into(imageThumbnail) .into(imageThumbnail)
setHeight(rootLayout)
} }
}
} }
private fun updateSetList(boolean: Boolean, path: String) { private fun addOrRemove(path: String, boolean: Boolean) {
ScanRepository.instance.toggleSelection(boolean,path) if (boolean) {
dateSelectedMap.add(path)
} else {
dateSelectedMap.remove(path)
} }
onSelectedUpdate.invoke(path, boolean, dateSelectedMap.size == itemCount)
}
} }

View File

@ -1,14 +1,19 @@
package com.ux.video.file.filerecovery.photo package com.ux.video.file.filerecovery.photo
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.LinearLayout
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.ux.video.file.filerecovery.R import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseActivity import com.ux.video.file.filerecovery.base.BaseActivity
import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding
import com.ux.video.file.filerecovery.utils.Common import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.ExtendFunctions.addItemDecorationOnce import com.ux.video.file.filerecovery.utils.Common.setItemSelect
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterBySize import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterBySize
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterBySizeList import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterBySizeList
@ -16,6 +21,7 @@ import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterWithinMonths
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterWithinMonthsList import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterWithinMonthsList
import com.ux.video.file.filerecovery.utils.ExtendFunctions.getParcelableArrayListExtraCompat import com.ux.video.file.filerecovery.utils.ExtendFunctions.getParcelableArrayListExtraCompat
import com.ux.video.file.filerecovery.utils.ExtendFunctions.mbToBytes import com.ux.video.file.filerecovery.utils.ExtendFunctions.mbToBytes
import com.ux.video.file.filerecovery.utils.ExtendFunctions.resetItemDecorationOnce
import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration
import com.ux.video.file.filerecovery.utils.ScanManager import com.ux.video.file.filerecovery.utils.ScanManager
import com.ux.video.file.filerecovery.utils.ScanManager.copySelectedFilesAsync import com.ux.video.file.filerecovery.utils.ScanManager.copySelectedFilesAsync
@ -38,12 +44,19 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
val FILTER_SIZE_1 = 1 val FILTER_SIZE_1 = 1
val FILTER_SIZE_5 = 2 val FILTER_SIZE_5 = 2
val FILTER_SIZE_OVER_5 = 3 val FILTER_SIZE_OVER_5 = 3
val SORT_ASC_SIZE = 0
val SORT_DESC_SIZE = 1
val SORT_ASC_DATE = 2
val SORT_DESC_DATE = 3
} }
private var sortDialogFragment: SortDialogFragment? = null
private var columns = 3 private var columns = 3
private var dateAdapter: PhotoDisplayDateAdapter? = null private var dateAdapter: PhotoDisplayDateAdapter? = null
private var sizeAdapter: PhotoDisplayDateChildAdapter? = null
val selectedSet = mutableSetOf<String>() // 保存选中状态 //文件大小排序使用的适配器
private var sizeSortAdapter: PhotoDisplayDateChildAdapter? = null
//默认倒序排序 //默认倒序排序
@ -55,12 +68,26 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
//筛选大小,默认全部-1 //筛选大小,默认全部-1
private var filterSize = FILTER_SIZE_ALL private var filterSize = FILTER_SIZE_ALL
private var filterDatePopupWindows: FilterPopupWindows? = null
private var filterSizePopupWindows: FilterPopupWindows? = null
private var filterLayoutPopupWindows: FilterPopupWindows? = null
private lateinit var sortBySizeBigToSmall: List<ResultPhotosFiles> private lateinit var sortBySizeBigToSmall: List<ResultPhotosFiles>
private lateinit var sortBySizeSmallToBig: List<ResultPhotosFiles> private lateinit var sortBySizeSmallToBig: List<ResultPhotosFiles>
private lateinit var sortByDayReverse: List<Pair<String, List<ResultPhotosFiles>>> private lateinit var sortByDateReverse: List<Pair<String, List<ResultPhotosFiles>>>
private lateinit var sortedByPositive: List<Pair<String, List<ResultPhotosFiles>>> private lateinit var sortedByDatePositive: List<Pair<String, List<ResultPhotosFiles>>>
//选中的所有数据集合(实际选中)
private lateinit var allSelectedSetList: Set<String>
//选中的所有数据集合(筛选后的数据实际显示的所有选中)
private lateinit var filterSelectedSetList: Set<String>
private lateinit var mItemDecoration: GridSpacingItemDecoration
private lateinit var viewModel: ScanRepository
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoSortingBinding = override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoSortingBinding =
ActivityPhotoSortingBinding.inflate(inflater) ActivityPhotoSortingBinding.inflate(inflater)
@ -69,32 +96,57 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
val list: ArrayList<ResultPhotosFiles>? = val list: ArrayList<ResultPhotosFiles>? =
intent.getParcelableArrayListExtraCompat(KEY_PHOTO_FOLDER_FILE) intent.getParcelableArrayListExtraCompat(KEY_PHOTO_FOLDER_FILE)
mItemDecoration =
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
updateButtonCounts(0)
viewModel = ViewModelProvider(this).get(ScanRepository::class.java)
viewModel.selectedLiveData.observe(this) { selectedSet ->
allSelectedSetList = selectedSet
Common.showLog("所有数据 选中状态更新: ${selectedSet.size}")
}
viewModel.selectedDisplayLiveData.observe(this) { displaySet ->
filterSelectedSetList = displaySet
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
updateCurrentIsAllSelectStatus()
}
list?.let { list?.let {
//倒序(最近的在前面)
sortByDayReverse = Common.getSortByDayNewToOld(it) //降序(最近的在前面)
//正序(最远的在前面) sortByDateReverse = Common.getSortByDayNewToOld(it)
sortedByPositive = Common.getSortByDayOldToNew(sortByDayReverse) //升序(时间最远的在前面)
sortedByDatePositive = Common.getSortByDayOldToNew(sortByDateReverse)
sortBySizeBigToSmall = Common.getSortBySizeBigToSmall(it) sortBySizeBigToSmall = Common.getSortBySizeBigToSmall(it)
sortBySizeSmallToBig = Common.getSortBySizeSmallToBig(it) sortBySizeSmallToBig = Common.getSortBySizeSmallToBig(it)
sizeAdapter = PhotoDisplayDateChildAdapter(this@PhotoSortingActivity) sizeSortAdapter = PhotoDisplayDateChildAdapter(
dateAdapter = PhotoDisplayDateAdapter(this@PhotoSortingActivity).apply { this@PhotoSortingActivity,
setData(sortByDayReverse) columns, viewModel
) { path, isAdd, allSelected ->
// updateSelectedList(isAdd, path)
// updateCurrentIsAllSelectStatus()
viewModel.toggleSelection(isAdd, path)
}
dateAdapter =
PhotoDisplayDateAdapter(
this@PhotoSortingActivity,
columns,
viewModel
) { actionPath, isAdd ->
// updateSelectedList(isAdd, actionPath)
// updateCurrentIsAllSelectStatus()
viewModel.toggleSelection(isAdd, actionPath)
}.apply {
setData(sortByDateReverse)
} }
setDateAdapter() setDateAdapter()
setFilter() setFilter()
binding.run { binding.run {
tvRecover.setOnClickListener {
lifecycleScope.launch {
ScanRepository.instance.selectedFlow.collect { newSet ->
println("选中集合变化:$newSet")
tvSelectCounts.text = newSet.size.toString()
}
}
tvSelectCounts.setOnClickListener {
lifecycleScope.copySelectedFilesAsync( lifecycleScope.copySelectedFilesAsync(
selectedSet = ScanRepository.instance.selectedFlow.value, selectedSet = filterSelectedSetList,
folder = Common.recoveryPhotoDir, folder = Common.recoveryPhotoDir,
onProgress = { currentCounts: Int, fileName: String, success: Boolean -> onProgress = { currentCounts: Int, fileName: String, success: Boolean ->
@ -109,10 +161,10 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
} }
} }
btnDelete.setOnClickListener { tvDelete.setOnClickListener {
lifecycleScope.deleteFilesAsync( lifecycleScope.deleteFilesAsync(
selectedSet = ScanRepository.instance.selectedFlow.value, selectedSet = filterSelectedSetList,
onProgress = { currentCounts: Int, path:String, success: Boolean -> onProgress = { currentCounts: Int, path: String, success: Boolean ->
ScanManager.showLog( ScanManager.showLog(
"--------删除图片 ", "--------删除图片 ",
"----------${currentCounts} ${path}" "----------${currentCounts} ${path}"
@ -124,124 +176,163 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
} }
} }
linear.setOnCheckedChangeListener { group, checkedId -> imSort.setOnClickListener {
when (checkedId) { sortDialogFragment = sortDialogFragment ?: SortDialogFragment {
R.id.btn_date_old_to_new -> { when (it) {
SORT_ASC_DATE -> {
setDateAdapter() setDateAdapter()
dateAdapter?.setData(sortedByPositive) dateAdapter?.setData(sortedByDatePositive)
sortReverse = false sortReverse = false
} }
R.id.btn_date_new_to_old -> { SORT_DESC_DATE -> {
setDateAdapter() setDateAdapter()
dateAdapter?.setData(sortByDayReverse) dateAdapter?.setData(sortByDateReverse)
sortReverse = true sortReverse = true
} }
R.id.btn_size_big_to_small -> { SORT_DESC_SIZE -> {
setSizeAdapter() setSizeAdapter()
sizeAdapter?.setData(sortBySizeBigToSmall) sizeSortAdapter?.setData(sortBySizeBigToSmall)
sortReverse = true sortReverse = true
} }
R.id.btn_size_small_to_big -> { SORT_ASC_SIZE -> {
setSizeAdapter() setSizeAdapter()
sizeAdapter?.setData(sortBySizeSmallToBig) sizeSortAdapter?.setData(sortBySizeSmallToBig)
sortReverse = false sortReverse = false
} }
} }
}
sortDialogFragment?.show(supportFragmentManager, "")
} }
imSelectAll.setOnClickListener { //全选按钮 只对当前显示的数据有效
imSelectAll.isSelected = !imSelectAll.isSelected tvSelectAll.setOnClickListener {
sizeAdapter?.setAllSelected(imSelectAll.isSelected) it.isSelected = !it.isSelected
dateAdapter?.setAllSelected(imSelectAll.isSelected) dateAdapter?.setAllSelected(it.isSelected)
sizeSortAdapter?.setAllSelected(it.isSelected)
}
}
} }
} }
private fun updateCurrentIsAllSelectStatus() {
filterSelectedSetList.size.let {
binding.tvSelectCounts.text = it.toString()
updateButtonCounts(it)
when (binding.recyclerView.adapter) {
is PhotoDisplayDateAdapter -> {
val adapter = binding.recyclerView.adapter as PhotoDisplayDateAdapter
binding.tvSelectAll.isSelected = it == adapter.getTotalChildCount()
} }
is PhotoDisplayDateChildAdapter -> {
binding.tvSelectAll.isSelected = it == binding.recyclerView.adapter?.itemCount
}
}
}
} }
private fun setDateAdapter() { private fun setDateAdapter() {
binding.recyclerView.run { binding.recyclerView.run {
adapter = dateAdapter?.apply { setColumns(columns) } adapter = dateAdapter?.apply { setColumns(columns) }
layoutManager = LinearLayoutManager(this@PhotoSortingActivity) layoutManager = LinearLayoutManager(this@PhotoSortingActivity)
val bPx = 16.dpToPx(context)
setPadding(0, 0, 0, 0)
clipToPadding = false
} }
} }
private fun setSizeAdapter() { private fun setSizeAdapter() {
binding.recyclerView.run { binding.recyclerView.run {
adapter = sizeAdapter val aPx = 16.dpToPx(context)
val bPx = 6.dpToPx(context)
setPadding(aPx, 0, bPx, 0)
clipToPadding = false
layoutManager = GridLayoutManager(context, columns) layoutManager = GridLayoutManager(context, columns)
val gridSpacingItemDecoration = // resetItemDecorationOnce(mItemDecoration)
GridSpacingItemDecoration(4, 8.dpToPx(this@PhotoSortingActivity), true) adapter = sizeSortAdapter
addItemDecorationOnce(gridSpacingItemDecoration)
} }
} }
/** /**
* 筛选 * 筛选和布局设置
*/ */
private fun setFilter() { private fun setFilter() {
binding.linearDate.setOnCheckedChangeListener { group, checkedId -> //日期筛选
when (checkedId) { binding.run {
R.id.btn_date_all -> { filterDateLayout.setOnClickListener {
filterDate = FILTER_DATE_ALL setItemSelect(it as LinearLayout, true)
} resources.getStringArray(R.array.filter_date).let { data ->
filterDatePopupWindows = filterDatePopupWindows ?: FilterPopupWindows(
R.id.btn_date_within_1 -> { this@PhotoSortingActivity,
filterDate = FILTER_DATE_1 data,
} 0,
{ clickValue ->
R.id.btn_date_customize -> { when (clickValue) {
data[0] -> filterDate = FILTER_DATE_ALL
} data[1] -> filterDate = FILTER_DATE_1
data[2] -> filterDate = FILTER_DATE_6
data[3] -> filterDate = FILTER_DATE_24
data[4] -> {}
} }
startFilter() startFilter()
} }) {
binding.linearSize.setOnCheckedChangeListener { group, checkedId -> setItemSelect(it, false)
when (checkedId) {
R.id.btn_size_all -> {
filterSize = FILTER_SIZE_ALL
} }
R.id.btn_size_1m -> { filterDatePopupWindows?.show(it)
filterSize = FILTER_SIZE_1
} }
R.id.btn_size_5m -> {
filterSize = FILTER_SIZE_5
}
R.id.btn_size_over_5m -> {
filterSize = FILTER_SIZE_OVER_5
} }
//大小筛选
filterSizeLayout.setOnClickListener {
setItemSelect(it as LinearLayout, true)
resources.getStringArray(R.array.filter_size).let { data ->
filterSizePopupWindows = filterSizePopupWindows ?: FilterPopupWindows(
this@PhotoSortingActivity,
data,
0,
{ clickValue ->
when (clickValue) {
data[0] -> filterSize = FILTER_SIZE_ALL
data[1] -> filterSize = FILTER_SIZE_1
data[2] -> filterSize = FILTER_SIZE_5
data[3] -> filterSize = FILTER_SIZE_OVER_5
} }
startFilter() startFilter()
}) {
setItemSelect(it, false)
} }
filterSizePopupWindows?.show(it)
binding.rgLayout.setOnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.rb_columns_2 -> {
columns = 2
}
R.id.rb_columns_3 -> {
columns = 3
}
R.id.rb_columns_4 -> {
columns = 4
}
} }
}
//布局设置
filterLayoutLinearlayout.setOnClickListener {
setItemSelect(it as LinearLayout, true)
resources.getStringArray(R.array.filter_layout).let { data ->
filterLayoutPopupWindows = filterLayoutPopupWindows ?: FilterPopupWindows(
this@PhotoSortingActivity,
data,
1,
{ clickValue ->
when (clickValue) {
data[0] -> columns = 2
data[1] -> columns = 3
data[2] -> columns = 4
}
when (binding.recyclerView.adapter) { when (binding.recyclerView.adapter) {
is PhotoDisplayDateAdapter -> { is PhotoDisplayDateAdapter -> {
dateAdapter?.setColumns(columns) dateAdapter?.setColumns(columns)
@ -250,10 +341,38 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
is PhotoDisplayDateChildAdapter -> { is PhotoDisplayDateChildAdapter -> {
binding.recyclerView.layoutManager = binding.recyclerView.layoutManager =
GridLayoutManager(this@PhotoSortingActivity, columns) GridLayoutManager(this@PhotoSortingActivity, columns)
sizeSortAdapter?.setColumns(columns)
}
}
}) {
setItemSelect(it, false)
}
}
filterLayoutPopupWindows?.show(it)
}
} }
} }
/**
* 根据当前显示的实际数据选中的数量来更新按钮文字和状态
*/
private fun updateButtonCounts(selectedCounts: Int) {
binding.run {
if (selectedCounts <= 0) {
tvDelete.isEnabled = false
tvRecover.isEnabled = false
} else {
tvDelete.isEnabled = true
tvRecover.isEnabled = true
} }
tvDelete.text = getString(R.string.delete_placeholder, selectedCounts)
tvRecover.text = getString(R.string.recover_placeholder, selectedCounts)
}
} }
@ -262,33 +381,41 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
*/ */
private fun startFilter() { private fun startFilter() {
when (binding.recyclerView.adapter) { when (binding.recyclerView.adapter) {
//当前是时间排序
is PhotoDisplayDateAdapter -> { is PhotoDisplayDateAdapter -> {
val list = if (sortReverse) sortByDayReverse else sortedByPositive //确定当前排序
val list = if (sortReverse) sortByDateReverse else sortedByDatePositive
val filterSizeCovert = filterSizeCovert(filterSize) val filterSizeCovert = filterSizeCovert(filterSize)
list.filterWithinMonths(filterDate) list.filterWithinMonths(filterDate)
.filterBySize(filterSizeCovert.first, filterSizeCovert.second).let { .filterBySize(filterSizeCovert.first, filterSizeCovert.second)
dateAdapter?.setData(it) .let { currentList ->
ScanManager.showLog( //对筛选后的数据与实际选中集合对比 ,得出筛选后显示的数据中的选中数据
"---", val checkSelectListContain =
"---date-----${it.size} filterDate=${filterDate} first=${filterSizeCovert.first} second=${filterSizeCovert.second} dateAdapter=${dateAdapter}" Common.checkSelectListContainDate(currentList, allSelectedSetList)
) updateButtonCounts(checkSelectListContain.first)
} viewModel.filterResetDisplayFlow(checkSelectListContain.second)
Common.showLog( "筛选后重置 allSelectedSetList=${allSelectedSetList.size} filterSelectedSetList=${filterSelectedSetList.size} Thread=${Thread.currentThread().name}")
dateAdapter?.resetAllValue(null)
dateAdapter?.setData(currentList)
} }
}
//当前是大小排序
is PhotoDisplayDateChildAdapter -> { is PhotoDisplayDateChildAdapter -> {
val list = if (sortReverse) sortBySizeBigToSmall else sortBySizeSmallToBig val list = if (sortReverse) sortBySizeBigToSmall else sortBySizeSmallToBig
val filterSizeCovert = filterSizeCovert(filterSize) val filterSizeCovert = filterSizeCovert(filterSize)
list.filterWithinMonthsList(filterDate) list.filterWithinMonthsList(filterDate)
.filterBySizeList(filterSizeCovert.first, filterSizeCovert.second).let { .filterBySizeList(filterSizeCovert.first, filterSizeCovert.second)
sizeAdapter?.setData(it) .let { currentList ->
ScanManager.showLog( //对筛选后的数据与实际选中集合对比 ,得出筛选后显示的数据中的选中数据
"---", val checkSelectListContain =
"----size----${it.size} filterDate=${filterDate} first=${filterSizeCovert.first} second=${filterSizeCovert.second} sizeAdapter=${sizeAdapter}" Common.checkSelectListContainSize(currentList, allSelectedSetList)
) updateButtonCounts(checkSelectListContain.first)
viewModel.filterResetDisplayFlow(checkSelectListContain.second)
sizeSortAdapter?.setData(currentList)
} }
} }
} }
} }
@ -306,4 +433,5 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
} }
} }

View File

@ -11,7 +11,7 @@ data class ResultPhotosFiles(
val path: String?= null, val path: String?= null,
val size: Long, // 字节 val size: Long, // 字节
val lastModified: Long, // 时间戳 val lastModified: Long, // 时间戳
var isSelected: Boolean = false // 选中状态 // var isSelected: Boolean = false // 选中状态
): Parcelable{ ): Parcelable{
val targetFile: File? val targetFile: File?
get() = path?.let { File(it) } get() = path?.let { File(it) }

View File

@ -0,0 +1,116 @@
package com.ux.video.file.filerecovery.photo
import android.graphics.Color
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.databinding.CommonLayoutSortItemBinding
import com.ux.video.file.filerecovery.databinding.DialogSortBinding
class SortDialogFragment(val onClickSort: (type: Int) -> Unit) : DialogFragment() {
private lateinit var binding: DialogSortBinding
private var clickType = PhotoSortingActivity.SORT_DESC_DATE
private lateinit var LayoutList: List<CommonLayoutSortItemBinding>
override fun onStart() {
super.onStart()
dialog?.window?.apply {
setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
setGravity(Gravity.BOTTOM)
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DialogSortBinding.inflate(inflater)
binding.run {
LayoutList = listOf(
ascendingSizeLayout,
descendingSizeLayout,
ascendingDateLayout,
descendingDateLayout
)
setMutualExclusion(LayoutList)
resetSelectedSortType(clickType)
setIconText(
LayoutList[0],
R.drawable.icon_ascending_size,
getString(R.string.size),
getString(R.string.asc_size_describe)
)
setIconText(
LayoutList[1],
R.drawable.icon_descending_size,
getString(R.string.size),
getString(R.string.desc_size_describe)
)
setIconText(
LayoutList[2],
R.drawable.icon_ascending_date,
getString(R.string.date),
getString(R.string.asc_date_describe)
)
setIconText(
LayoutList[3],
R.drawable.icon_descending_date,
getString(R.string.date),
getString(R.string.desc_date_describe)
)
tvCancel.setOnClickListener { dismiss() }
tvOk.setOnClickListener {
onClickSort(clickType)
dismiss()
}
}
return binding.root
}
fun resetSelectedSortType(type: Int) {
LayoutList.forEachIndexed { index, item ->
item.checkImage.isSelected = index == type
}
}
private fun setIconText(
itemBinding: CommonLayoutSortItemBinding,
iconId: Int,
text: String,
subText: String
) {
itemBinding.run {
sortType.text = text
sortSubType.text = subText
icon.setImageResource(iconId)
}
}
private fun setMutualExclusion(listOf: List<CommonLayoutSortItemBinding>) {
for (i in 0 until listOf.size) {
val binding = listOf[i]
binding.root.setOnClickListener {
for (j in 0 until listOf.size) {
listOf[j].checkImage.isSelected = false
}
clickType = i
binding.checkImage.isSelected = true
}
}
}
}

View File

@ -0,0 +1,42 @@
package com.ux.video.file.filerecovery.result
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment
import com.ux.video.file.filerecovery.databinding.DialogExitBinding
import com.ux.video.file.filerecovery.databinding.DialogPermissionBinding
class ExitDialogFragment(val onClickExit: () -> Unit) : DialogFragment() {
private lateinit var binding: DialogExitBinding
override fun onStart() {
super.onStart()
dialog?.window?.apply {
setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DialogExitBinding.inflate(inflater)
binding.run {
cancel.setOnClickListener { dismiss() }
exit.setOnClickListener {
onClickExit()
dismiss()
}
}
return binding.root
}
}

View File

@ -1,5 +1,6 @@
package com.ux.video.file.filerecovery.result package com.ux.video.file.filerecovery.result
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
@ -27,15 +28,19 @@ class ScanResultAdapter(
false false
) )
@SuppressLint("SetTextI18n")
override fun bindItem( override fun bindItem(
holder: VHolder<ScanResultAdapterBinding>, holder: VHolder<ScanResultAdapterBinding>,
item: ResultPhotos item: ResultPhotos
) { ) {
holder.vb.run { holder.vb.run {
val imageViews = listOf(im1, im2, im3) val imageViews = listOf(im1, im2, im3)
item.run { item.run {
textDirNameCount.text = "$dirName(${allFiles.size})" imageViewEnter.setOnClickListener { onClickItem(allFiles) }
textDirNameCount.text = dirName
textFileCounts.text = "(${allFiles.size})"
val takeFiles = allFiles.take(3) val takeFiles = allFiles.take(3)
imageViews.forEachIndexed { index, imageView -> imageViews.forEachIndexed { index, imageView ->
if (index < takeFiles.size) { if (index < takeFiles.size) {
@ -59,7 +64,7 @@ class ScanResultAdapter(
.load(file) .load(file)
.apply( .apply(
RequestOptions() RequestOptions()
.transform(CenterCrop(), RoundedCorners(15.dpToPx(context))) .transform(CenterCrop(), RoundedCorners(8.dpToPx(context)))
) )
.into(imageView) .into(imageView)
} }

View File

@ -2,13 +2,27 @@ package com.ux.video.file.filerecovery.result
import android.content.Intent import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseActivity import com.ux.video.file.filerecovery.base.BaseActivity
import com.ux.video.file.filerecovery.databinding.ActivityScanResultDisplayBinding import com.ux.video.file.filerecovery.databinding.ActivityScanResultDisplayBinding
import com.ux.video.file.filerecovery.photo.PhotoSortingActivity import com.ux.video.file.filerecovery.photo.PhotoSortingActivity
import com.ux.video.file.filerecovery.photo.ResultPhotos import com.ux.video.file.filerecovery.photo.ResultPhotos
import com.ux.video.file.filerecovery.result.ScanningActivity import com.ux.video.file.filerecovery.result.ScanningActivity
import com.ux.video.file.filerecovery.utils.Common.KEY_SCAN_TYPE
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_video
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video
import com.ux.video.file.filerecovery.utils.ExtendFunctions.getParcelableArrayListExtraCompat import com.ux.video.file.filerecovery.utils.ExtendFunctions.getParcelableArrayListExtraCompat
import com.ux.video.file.filerecovery.utils.ScanManager
import com.ux.video.file.filerecovery.utils.ScanRepository import com.ux.video.file.filerecovery.utils.ScanRepository
/** /**
@ -16,9 +30,12 @@ import com.ux.video.file.filerecovery.utils.ScanRepository
*/ */
class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>() { class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>() {
private var scanResultAdapter: ScanResultAdapter? = null private var scanResultAdapter: ScanResultAdapter? = null
private var scanType: Int = VALUE_SCAN_TYPE_photo
private var exitDialog: ExitDialogFragment? = null
companion object { companion object {
val KEY_SCAN_RESULT = "scan_result" val KEY_SCAN_RESULT = "scan_result"
} }
override fun inflateBinding(inflater: LayoutInflater): ActivityScanResultDisplayBinding = override fun inflateBinding(inflater: LayoutInflater): ActivityScanResultDisplayBinding =
@ -28,9 +45,16 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
super.initView() super.initView()
val list: ArrayList<ResultPhotos>? = val list: ArrayList<ResultPhotos>? =
intent.getParcelableArrayListExtraCompat(KEY_SCAN_RESULT) intent.getParcelableArrayListExtraCompat(KEY_SCAN_RESULT)
scanResultAdapter = ScanResultAdapter(this@ScanResultDisplayActivity){ folderLists-> scanResultAdapter = ScanResultAdapter(this@ScanResultDisplayActivity) { folderLists ->
startActivity(Intent(this@ScanResultDisplayActivity, PhotoSortingActivity::class.java).apply { startActivity(
putParcelableArrayListExtra(PhotoSortingActivity.KEY_PHOTO_FOLDER_FILE, folderLists) Intent(
this@ScanResultDisplayActivity,
PhotoSortingActivity::class.java
).apply {
putParcelableArrayListExtra(
PhotoSortingActivity.KEY_PHOTO_FOLDER_FILE,
folderLists
)
}) })
} }
binding.recyclerResult.run { binding.recyclerResult.run {
@ -56,4 +80,50 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
// scanResultAdapter?.setData(it) // scanResultAdapter?.setData(it)
// } // }
} }
override fun initData() {
super.initData()
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
setSelectTypeTitle(scanType)
binding.imageViewBack.setOnClickListener { dealExit() }
onBackPressedDispatcher.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
dealExit()
}
})
}
private fun dealExit(){
exitDialog = exitDialog?:ExitDialogFragment(){
finish()
}
exitDialog?.show(supportFragmentManager,"")
}
private fun setSelectTypeTitle(fileType: Int) {
binding.run {
when (fileType) {
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
title.text = getString(R.string.photo_title)
}
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> {
title.text = getString(R.string.video_title)
}
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
title.text = getString(R.string.audio_title)
}
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
title.text = getString(R.string.document_title)
}
}
}
}
} }

View File

@ -11,6 +11,15 @@ import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALU
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_DOCUMENT import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_PHOTO import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_PHOTO
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_VIDEO import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_VIDEO
import com.ux.video.file.filerecovery.utils.Common.KEY_SCAN_TYPE
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_video
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video
import com.ux.video.file.filerecovery.utils.ScanManager import com.ux.video.file.filerecovery.utils.ScanManager
import com.ux.video.file.filerecovery.utils.ScanRepository import com.ux.video.file.filerecovery.utils.ScanRepository
import com.ux.video.file.filerecovery.utils.ScanState import com.ux.video.file.filerecovery.utils.ScanState
@ -21,15 +30,15 @@ import kotlinx.coroutines.launch
class ScanningActivity : BaseActivity<ActivityScanningBinding>() { class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
companion object { companion object {
val KEY_SCAN_TYPE = "scan_type" // val KEY_SCAN_TYPE = "scan_type"
val VALUE_SCAN_TYPE_photo = 0 // val VALUE_SCAN_TYPE_photo = 0
val VALUE_SCAN_TYPE_deleted_photo = 1 // val VALUE_SCAN_TYPE_deleted_photo = 1
val VALUE_SCAN_TYPE_video = 2 // val VALUE_SCAN_TYPE_video = 2
val VALUE_SCAN_TYPE_deleted_video = 3 // val VALUE_SCAN_TYPE_deleted_video = 3
val VALUE_SCAN_TYPE_audio = 4 // val VALUE_SCAN_TYPE_audio = 4
val VALUE_SCAN_TYPE_deleted_audio = 5 // val VALUE_SCAN_TYPE_deleted_audio = 5
val VALUE_SCAN_TYPE_documents = 6 // val VALUE_SCAN_TYPE_documents = 6
val VALUE_SCAN_TYPE_deleted_documents = 7 // val VALUE_SCAN_TYPE_deleted_documents = 7
} }
private var scanType: Int = VALUE_SCAN_TYPE_photo private var scanType: Int = VALUE_SCAN_TYPE_photo
@ -44,7 +53,7 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_documents -> scanAll() VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_documents -> scanAll()
VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_deleted_video, VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_deleted_documents -> scanDeleted() VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_deleted_video, VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_deleted_documents -> scanDeleted()
} }
binding.scanProgress.setCenterImage(R.drawable.ic_scan_file) binding.scanProgress.setCenterImage(R.drawable.im_photo_center_image)
binding.imageViewBack.setOnClickListener { finish() } binding.imageViewBack.setOnClickListener { finish() }
} }
@ -176,6 +185,7 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
) )
} }
finish()
} }

View File

@ -7,6 +7,7 @@ import android.graphics.BitmapFactory
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF import android.graphics.RectF
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
@ -19,7 +20,7 @@ class CircleImageProgressView @JvmOverloads constructor(
private val paintBg = Paint(Paint.ANTI_ALIAS_FLAG).apply { private val paintBg = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.STROKE style = Paint.Style.STROKE
strokeWidth = 20f strokeWidth = 20f
color = Color.parseColor("#C9DDEF") // 背景浅蓝 color = Color.parseColor("#9CC0EC") // 背景浅蓝
} }
private val paintProgress = Paint(Paint.ANTI_ALIAS_FLAG).apply { private val paintProgress = Paint(Paint.ANTI_ALIAS_FLAG).apply {
@ -57,44 +58,42 @@ class CircleImageProgressView @JvmOverloads constructor(
override fun onDraw(canvas: Canvas) { override fun onDraw(canvas: Canvas) {
super.onDraw(canvas) super.onDraw(canvas)
val stroke = paintBg.strokeWidth val stroke = paintBg.strokeWidth
val rect = RectF(stroke, stroke, width - stroke, height - stroke) val radius = (width / 2f) - (stroke / 2f)
// 背景圆环 val rect = RectF(
(width / 2f) - radius,
(height / 2f) - radius,
(width / 2f) + radius,
(height / 2f) + radius
)
// 1. 背景圆环
canvas.drawArc(rect, 0f, 360f, false, paintBg) canvas.drawArc(rect, 0f, 360f, false, paintBg)
// 中心图片
// 2. 中心图片(圆形裁剪)
centerBitmap?.let { centerBitmap?.let {
// val left = (width - it.width) / 2f val innerRadius = radius - stroke / 2f // 图片只占内圆,不盖住圆环
// val top = (height - it.height) / 2f
// canvas.drawBitmap(it, left, top, null)
// val desiredSize = width * imageScale
// val rectDst = RectF(
// (width - desiredSize) / 2f,
// (height - desiredSize) / 2f,
// (width + desiredSize) / 2f,
// (height + desiredSize) / 2f
// )
// canvas.drawBitmap(it, null, rectDst, null)
val innerRadius = (width / 2f) - stroke // 圆环内半径
val left = (width / 2f) - innerRadius val left = (width / 2f) - innerRadius
val top = (height / 2f) - innerRadius val top = (height / 2f) - innerRadius
val right = (width / 2f) + innerRadius val right = (width / 2f) + innerRadius
val bottom = (height / 2f) + innerRadius val bottom = (height / 2f) + innerRadius
val rectDst = RectF(left, top, right, bottom) val rectDst = RectF(left, top, right, bottom)
// 缩放图片填满内圆区域 val saveCount = canvas.save()
// canvas.drawBitmap(it, null, rectDst, null) val path = Path().apply {
addCircle(width / 2f, height / 2f, innerRadius, Path.Direction.CW)
}
canvas.clipPath(path)
canvas.drawBitmap(it, null, rectDst, null)
canvas.restoreToCount(saveCount)
} }
// 3. 进度圆弧
// 进度圆弧
val sweepAngle = progress * 360f / 100f val sweepAngle = progress * 360f / 100f
canvas.drawArc(rect, -90f, sweepAngle, false, paintProgress) canvas.drawArc(rect, -90f, sweepAngle, false, paintProgress)
} }
} }

View File

@ -4,19 +4,38 @@ import android.content.Context
import android.icu.text.SimpleDateFormat import android.icu.text.SimpleDateFormat
import android.icu.util.Calendar import android.icu.util.Calendar
import android.os.Environment import android.os.Environment
import android.util.Log
import android.view.ViewGroup
import com.ux.video.file.filerecovery.App
import com.ux.video.file.filerecovery.R import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import kotlin.collections.sortedBy import kotlin.collections.sortedBy
object Common { object Common {
val itemSpacing = 10
val horizontalSpacing = 16
val KEY_SCAN_TYPE = "scan_type"
val VALUE_SCAN_TYPE_photo = 0
val VALUE_SCAN_TYPE_deleted_photo = 1
val VALUE_SCAN_TYPE_video = 2
val VALUE_SCAN_TYPE_deleted_video = 3
val VALUE_SCAN_TYPE_audio = 4
val VALUE_SCAN_TYPE_deleted_audio = 5
val VALUE_SCAN_TYPE_documents = 6
val VALUE_SCAN_TYPE_deleted_documents = 7
val rootDir = Environment.getExternalStorageDirectory() val rootDir = Environment.getExternalStorageDirectory()
val dateFormat = SimpleDateFormat("MMM dd yyyy", Locale.ENGLISH) val dateFormat = SimpleDateFormat("MMMM d,yyyy", Locale.ENGLISH)
val recoveryPhotoDir = "MyAllRecovery/Photo" val recoveryPhotoDir = "MyAllRecovery/Photo"
/** /**
* 默认按照日期分类将最新的排前面 * 默认按照日期分类将最新的排前面 降序
*/ */
fun getSortByDayNewToOld(list: ArrayList<ResultPhotosFiles>): List<Pair<String, List<ResultPhotosFiles>>> { fun getSortByDayNewToOld(list: ArrayList<ResultPhotosFiles>): List<Pair<String, List<ResultPhotosFiles>>> {
@ -31,21 +50,21 @@ object Common {
} }
/** /**
* 按照日期排序 时间最早的排前面 * 按照日期排序 时间最早的排前面 升序
* *
*/ */
fun getSortByDayOldToNew(list: List<Pair<String, List<ResultPhotosFiles>>>) = fun getSortByDayOldToNew(list: List<Pair<String, List<ResultPhotosFiles>>>) =
list.sortedBy { dateFormat.parse(it.first)?.time ?: 0L } list.sortedBy { dateFormat.parse(it.first)?.time ?: 0L }
/** /**
* 按照文件大小排序将最大的排前面 * 按照文件大小排序将最大的排前面 降序
*/ */
fun getSortBySizeBigToSmall(list: ArrayList<ResultPhotosFiles>) = list.sortedByDescending { fun getSortBySizeBigToSmall(list: ArrayList<ResultPhotosFiles>) = list.sortedByDescending {
it.size it.size
} }
/** /**
* 按照文件大小排序将最大的排前面 * 按照文件大小排序将最小的排前面 升序
*/ */
fun getSortBySizeSmallToBig(list: ArrayList<ResultPhotosFiles>) = list.sortedBy { fun getSortBySizeSmallToBig(list: ArrayList<ResultPhotosFiles>) = list.sortedBy {
it.size it.size
@ -77,7 +96,7 @@ object Common {
* @param months 筛选months月之内的数据 * @param months 筛选months月之内的数据
*/ */
fun filterWithinOneMonthByDay( fun filterWithinOneMonthByDay(
grouped: List<Pair<String, List<ResultPhotosFiles>>>,months: Int grouped: List<Pair<String, List<ResultPhotosFiles>>>, months: Int
): List<Pair<String, List<ResultPhotosFiles>>> { ): List<Pair<String, List<ResultPhotosFiles>>> {
val today = Calendar.getInstance() val today = Calendar.getInstance()
val oneMonthAgo = Calendar.getInstance().apply { val oneMonthAgo = Calendar.getInstance().apply {
@ -89,10 +108,11 @@ object Common {
day != null && !day.before(oneMonthAgo.time) && !day.after(today.time) day != null && !day.before(oneMonthAgo.time) && !day.after(today.time)
} }
} }
/** /**
* @param months 筛选months月之内的数据 * @param months 筛选months月之内的数据
*/ */
fun filterWithinOneMonth(list: List<ResultPhotosFiles>,months: Int): List<ResultPhotosFiles> { fun filterWithinOneMonth(list: List<ResultPhotosFiles>, months: Int): List<ResultPhotosFiles> {
val today = Calendar.getInstance() val today = Calendar.getInstance()
val oneMonthAgo = Calendar.getInstance().apply { val oneMonthAgo = Calendar.getInstance().apply {
add(Calendar.MONTH, -months) add(Calendar.MONTH, -months)
@ -104,4 +124,55 @@ object Common {
} }
} }
/**
* 设置全部子View的选中
*/
fun setItemSelect(view: ViewGroup, boolean: Boolean) {
for (i in 0 until view.childCount) {
val child = view.getChildAt(i)
child.isSelected = boolean
}
}
/**
* @param list 筛选后的显示的数据
* @param selected 实际选中的数据集合
* @return 显示的选中数量和选中集合
*/
fun checkSelectListContainDate(
list: List<Pair<String, List<ResultPhotosFiles>>>,
selected: Set<String>
): Pair<Int, MutableSet<String>> {
val currentSelected = mutableSetOf<String>()
val totalSelectedCount = list.sumOf { pair ->
pair.second.count {
val isSelected = it.path in selected
if (isSelected) currentSelected.add(it.path.toString())
isSelected
}
}
showLog("-------totalSelectedCount = $totalSelectedCount currentSelected=${currentSelected.size}")
return totalSelectedCount to currentSelected
}
fun checkSelectListContainSize(list: List<ResultPhotosFiles>, selected: Set<String>): Pair<Int, MutableSet<String>> {
val currentSelected = mutableSetOf<String>()
val totalSelectedCount = list.count {
val isSelected = it.path in selected
if (isSelected) currentSelected.add(it.path.toString())
isSelected
}
showLog("-------totalSelectedCount 222=${totalSelectedCount}")
return totalSelectedCount to currentSelected
}
fun showLog(msg: String) {
Log.d("============", msg)
}
} }

View File

@ -17,10 +17,15 @@ class CustomTextView @JvmOverloads constructor(
private var alimama: Typeface? = null private var alimama: Typeface? = null
} }
private var selectedText: String? = null
private var normalText: String? = null
init { init {
attrs?.let { attrs?.let {
val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomTextView) val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomTextView)
val type = typedArray.getInt(R.styleable.CustomTextView_fontType, 0) val type = typedArray.getInt(R.styleable.CustomTextView_fontType, 0)
selectedText = typedArray.getString(R.styleable.CustomTextView_selected_text)
normalText = typedArray.getString(R.styleable.CustomTextView_normal_text)
typedArray.recycle() typedArray.recycle()
Typeface.create("sans-serif-light", Typeface.NORMAL) // Roboto Light Typeface.create("sans-serif-light", Typeface.NORMAL) // Roboto Light
@ -31,9 +36,10 @@ class CustomTextView @JvmOverloads constructor(
0 -> { 0 -> {
typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
} }
1 -> { 1 -> {
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
} }
2 -> { 2 -> {
@ -43,12 +49,19 @@ class CustomTextView @JvmOverloads constructor(
typeface = alimama typeface = alimama
} }
3 -> {
typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
}
else -> typeface = Typeface.DEFAULT else -> typeface = Typeface.DEFAULT
} }
} }
} }
override fun setSelected(selected: Boolean) {
super.setSelected(selected)
updateText()
}
private fun updateText() {
// Common.showLog("--updateText$isSelected selectedText=${selectedText} normalText=${normalText} text=${text}")
text = if (isSelected) selectedText ?: text else normalText ?: text
}
} }

View File

@ -29,11 +29,9 @@ object ExtendFunctions {
} }
} }
fun RecyclerView.addItemDecorationOnce(decoration: RecyclerView.ItemDecoration) { fun RecyclerView.resetItemDecorationOnce(decoration: RecyclerView.ItemDecoration) {
for (i in 0 until itemDecorationCount) { while (itemDecorationCount > 0) {
if (getItemDecorationAt(i)::class == decoration::class) { removeItemDecorationAt(0)
return // 已经有同类型,避免重复
}
} }
addItemDecoration(decoration) addItemDecoration(decoration)
} }

View File

@ -3,11 +3,19 @@ package com.ux.video.file.filerecovery.utils
import android.graphics.Rect import android.graphics.Rect
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.ux.video.file.filerecovery.App
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
/**
* @param spanCount 列数
* @param spacing 列与列之间的间距dp
* @param edgeSpacing RecyclerView 左右两边的边距dp
*/
class GridSpacingItemDecoration( class GridSpacingItemDecoration(
private val spanCount: Int, private val spanCount: Int,
private val spacing: Int, private val itemSpacing: Int,
private val includeEdge: Boolean private val edgeSpacing: Int
) : RecyclerView.ItemDecoration() { ) : RecyclerView.ItemDecoration() {
override fun getItemOffsets( override fun getItemOffsets(
@ -16,20 +24,31 @@ class GridSpacingItemDecoration(
val position = parent.getChildAdapterPosition(view) val position = parent.getChildAdapterPosition(view)
val column = position % spanCount val column = position % spanCount
if (includeEdge) { val itemSpacingPx = itemSpacing.dpToPx(App.mAppContext)
outRect.left = spacing - column * spacing / spanCount val edgePx = edgeSpacing.dpToPx(App.mAppContext)
outRect.right = (column + 1) * spacing / spanCount
when (column) {
0 -> { // 第一列
outRect.left = edgePx
outRect.right = itemSpacingPx / 2
}
spanCount - 1 -> { // 最后一列
outRect.left = itemSpacingPx / 2
outRect.right = edgePx
}
else -> { // 中间列
outRect.left = itemSpacingPx / 2
outRect.right = itemSpacingPx / 2
}
}
// 顶部间距(第一行也加)
if (position < spanCount) { if (position < spanCount) {
outRect.top = spacing outRect.top = itemSpacingPx
}
outRect.bottom = spacing
} else {
outRect.left = column * spacing / spanCount
outRect.right = spacing - (column + 1) * spacing / spanCount
if (position >= spanCount) {
outRect.top = spacing
}
} }
// 底部间距
outRect.bottom = itemSpacingPx
} }
} }

View File

@ -6,6 +6,14 @@ import android.util.Log
import com.ux.video.file.filerecovery.photo.ResultPhotos import com.ux.video.file.filerecovery.photo.ResultPhotos
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
import com.ux.video.file.filerecovery.result.ScanningActivity import com.ux.video.file.filerecovery.result.ScanningActivity
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_video
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -56,19 +64,19 @@ object ScanManager {
} else { } else {
var fileCheckBoolean: Boolean = false var fileCheckBoolean: Boolean = false
when (type) { when (type) {
ScanningActivity.VALUE_SCAN_TYPE_photo -> { VALUE_SCAN_TYPE_photo -> {
fileCheckBoolean = isFormatFile(file, IMAGE_FILE) && isValidImage(file) fileCheckBoolean = isFormatFile(file, IMAGE_FILE) && isValidImage(file)
} }
ScanningActivity.VALUE_SCAN_TYPE_video -> { VALUE_SCAN_TYPE_video -> {
fileCheckBoolean = isFormatFile(file, VIDEO_FILE) fileCheckBoolean = isFormatFile(file, VIDEO_FILE)
} }
ScanningActivity.VALUE_SCAN_TYPE_audio -> { VALUE_SCAN_TYPE_audio -> {
fileCheckBoolean = isFormatFile(file, AUDIO_FILE) fileCheckBoolean = isFormatFile(file, AUDIO_FILE)
} }
ScanningActivity.VALUE_SCAN_TYPE_documents -> { VALUE_SCAN_TYPE_documents -> {
fileCheckBoolean = file.isFile && isFormatFile(file, DOCUMENT_FILE) fileCheckBoolean = file.isFile && isFormatFile(file, DOCUMENT_FILE)
} }
} }
@ -126,20 +134,20 @@ object ScanManager {
if (insideHidden) { if (insideHidden) {
var fileCheckBoolean: Boolean = false var fileCheckBoolean: Boolean = false
when (type) { when (type) {
ScanningActivity.VALUE_SCAN_TYPE_deleted_photo -> { VALUE_SCAN_TYPE_deleted_photo -> {
fileCheckBoolean = fileCheckBoolean =
isFormatFile(file, IMAGE_FILE) && isValidImage(file) isFormatFile(file, IMAGE_FILE) && isValidImage(file)
} }
ScanningActivity.VALUE_SCAN_TYPE_deleted_video -> { VALUE_SCAN_TYPE_deleted_video -> {
fileCheckBoolean = isFormatFile(file, VIDEO_FILE) fileCheckBoolean = isFormatFile(file, VIDEO_FILE)
} }
ScanningActivity.VALUE_SCAN_TYPE_deleted_audio -> { VALUE_SCAN_TYPE_deleted_audio -> {
fileCheckBoolean = isFormatFile(file, AUDIO_FILE) fileCheckBoolean = isFormatFile(file, AUDIO_FILE)
} }
ScanningActivity.VALUE_SCAN_TYPE_deleted_documents -> { VALUE_SCAN_TYPE_deleted_documents -> {
fileCheckBoolean = file.isFile && isFormatFile(file, DOCUMENT_FILE) fileCheckBoolean = file.isFile && isFormatFile(file, DOCUMENT_FILE)
} }
} }

View File

@ -2,49 +2,78 @@ package com.ux.video.file.filerecovery.utils
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.ux.video.file.filerecovery.photo.ResultPhotos import com.ux.video.file.filerecovery.photo.ResultPhotos
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
class ScanRepository private constructor() { class ScanRepository : ViewModel() {
// private val _selectedFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
//---------扫描结果 // val selectedFlow: StateFlow<MutableSet<String>> = _selectedFlow
private val _photoResults = MutableLiveData<List<ResultPhotos>>() //
val photoResults: LiveData<List<ResultPhotos>> get() = _photoResults //
// private val _selectedDisplayFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
private val _videoResults = MutableLiveData<List<ResultPhotos>>() // val selectedDisplayFlow: StateFlow<MutableSet<String>> = _selectedDisplayFlow
val videoResults: LiveData<List<ResultPhotos>> get() = _videoResults
//----------查看指定目录里面的文件
fun setPhotoResults(data: List<ResultPhotos>) { private val _selectedLiveData = MutableLiveData<Set<String>>(emptySet())
_photoResults.value = data val selectedLiveData: LiveData<Set<String>> = _selectedLiveData
}
fun setVideoResults(data: List<ResultPhotos>) { // 当前筛选显示的选中项
_videoResults.value = data private val _selectedDisplayLiveData = MutableLiveData<Set<String>>(emptySet())
} val selectedDisplayLiveData: LiveData<Set<String>> = _selectedDisplayLiveData
private val _selectedFlow = MutableStateFlow<Set<String>>(emptySet()) fun toggleSelection(isAdd: Boolean, path: String) {
val selectedFlow: StateFlow<Set<String>> = _selectedFlow val current = _selectedLiveData.value?.toMutableSet() ?: mutableSetOf()
val currentDisplay = _selectedDisplayLiveData.value?.toMutableSet() ?: mutableSetOf()
fun toggleSelection(boolean: Boolean, path: String) { if (isAdd) {
val current = _selectedFlow.value.toMutableSet()
if (boolean) {
current.add(path) current.add(path)
ScanManager.showLog("_------", "add selected ${path}") currentDisplay.add(path)
// Common.showLog( "add selected ${path}")
} else { } else {
current.remove(path) current.remove(path)
ScanManager.showLog("_------", "remove selected ${path}") currentDisplay.remove(path)
// Common.showLog( "remove selected ${path}")
} }
_selectedFlow.value = current Common.showLog( "toggleSelection------------ _selectedDisplayFlow=${_selectedDisplayLiveData.value?.size} _selectedFlow=${_selectedLiveData.value?.size} ")
// LiveData 使用新对象赋值,保证 observer 触发
_selectedLiveData.value = current.toSet()
_selectedDisplayLiveData.value = currentDisplay.toSet()
} }
fun checkIsSelect(path: String) : Boolean{ // fun toggleSelection(isAdd: Boolean, path: String) {
val current = _selectedFlow.value.toMutableSet() // val current = _selectedFlow.value.toMutableSet()
return current.contains(path) // val currentDisplay = _selectedDisplayFlow.value.toMutableSet()
// if (isAdd) {
// current.add(path)
// currentDisplay.add(path)
// Common.showLog( "add selected ${path}")
// } else {
// current.remove(path)
// currentDisplay.remove(path)
// Common.showLog( "remove selected ${path}")
// }
// _selectedFlow.value = current
// _selectedDisplayFlow.value = currentDisplay
// }
/**
* 数据筛选后重置当前显示的选中集合
*/
fun filterResetDisplayFlow(list: MutableSet<String>){
_selectedDisplayLiveData.value = list.toSet()
Common.showLog( "筛选后重置 _selectedDisplayFlow=${_selectedDisplayLiveData.value?.size} _selectedFlow=${_selectedLiveData.value?.size} ")
}
fun checkIsSelect(path: String): Boolean {
val current = _selectedDisplayLiveData.value
return current?.contains(path) == true
} }

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_title_blue" android:state_selected="true"/>
<item android:color="@color/main_title" android:state_selected="false"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_title_blue" android:state_selected="true"/>
<item android:color="@color/switch_track_false" android:state_selected="false"/>
</selector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/main_text_blue" android:state_enabled="true"/>
<item android:color="@color/switch_track_true" android:state_enabled="false"/>
</selector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/main_text_blue" android:state_enabled="true"/>
<item android:color="@color/switch_track_true" android:state_enabled="false"/>
</selector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 开启状态 -->
<item android:color="@color/main_text_blue" android:state_checked="true"/>
<!-- 关闭状态 -->
<item android:color="@color/dividing_line_color" android:state_checked="false"/>
</selector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 开启状态 -->
<item android:color="@color/switch_track_true" android:state_checked="true"/>
<!-- 关闭状态 -->
<item android:color="@color/switch_track_false" android:state_checked="false"/>
</selector>

View File

@ -2,6 +2,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<corners android:radius="8dp"/> <corners android:radius="8dp"/>
<solid android:color="@color/dialog_btn_stoke"/> <solid android:color="@color/main_text_blue"/>
</shape> </shape>

View File

@ -2,6 +2,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<corners android:radius="8dp"/> <corners android:radius="8dp"/>
<stroke android:color="@color/dialog_btn_stoke" android:width="1dp"/> <stroke android:color="@color/main_text_blue" android:width="1dp"/>
</shape> </shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topRightRadius="8dp" android:bottomRightRadius="8dp"/>
<solid android:color="@color/main_text_blue"/>
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topRightRadius="8dp" android:bottomRightRadius="8dp"/>
<solid android:color="@color/switch_track_true"/>
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topLeftRadius="8dp" android:bottomLeftRadius="8dp"/>
<solid android:color="@color/color_bg"/>
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:bottomRightRadius="20dp" android:bottomLeftRadius="20dp"/>
<solid android:color="@color/white" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topLeftRadius="8dp" android:bottomLeftRadius="8dp"/>
<solid android:color="@color/white"/>
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topRightRadius="20dp" android:topLeftRadius="20dp" />
<solid android:color="@color/white" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="28"
android:viewportHeight="28">
<group>
<clip-path
android:pathData="M14,0L14,0A14,14 0,0 1,28 14L28,14A14,14 0,0 1,14 28L14,28A14,14 0,0 1,0 14L0,14A14,14 0,0 1,14 0z"/>
<path
android:pathData="M14,0L14,0A14,14 0,0 1,28 14L28,14A14,14 0,0 1,14 28L14,28A14,14 0,0 1,0 14L0,14A14,14 0,0 1,14 0z"
android:fillColor="#ffffff"/>
<path
android:pathData="M14,0C11.231,0 8.524,0.821 6.222,2.359C3.92,3.898 2.125,6.084 1.066,8.642C0.006,11.201 -0.271,14.016 0.269,16.731C0.809,19.447 2.143,21.942 4.101,23.899C6.058,25.857 8.553,27.191 11.269,27.731C13.984,28.271 16.799,27.994 19.358,26.934C21.916,25.875 24.102,24.08 25.641,21.778C27.179,19.476 28,16.769 28,14C28,10.287 26.525,6.726 23.899,4.1C21.274,1.475 17.713,0 14,0ZM22.925,10.15L12.425,20.65C12.118,20.869 11.752,20.991 11.375,21C11.003,20.964 10.644,20.844 10.325,20.65L4.025,14.35C3.747,14.071 3.59,13.694 3.59,13.3C3.59,12.906 3.747,12.528 4.025,12.25C4.304,11.972 4.681,11.815 5.075,11.815C5.469,11.815 5.847,11.972 6.125,12.25L11.375,17.5L20.825,8.05C21.116,7.796 21.489,7.657 21.875,7.657C22.261,7.657 22.634,7.796 22.925,8.05C23.089,8.172 23.222,8.33 23.314,8.512C23.406,8.695 23.454,8.896 23.454,9.1C23.454,9.304 23.406,9.506 23.314,9.688C23.222,9.87 23.089,10.028 22.925,10.15Z"
android:fillColor="#0014F0"/>
</group>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<group>
<clip-path
android:pathData="M14,0L14,0A14,14 0,0 1,28 14L28,14A14,14 0,0 1,14 28L14,28A14,14 0,0 1,0 14L0,14A14,14 0,0 1,14 0z"/>
<path
android:pathData="M14,0L14,0A14,14 0,0 1,28 14L28,14A14,14 0,0 1,14 28L14,28A14,14 0,0 1,0 14L0,14A14,14 0,0 1,14 0z"
android:fillColor="#ffffff"/>
<path
android:pathData="M14,0C11.231,0 8.524,0.821 6.222,2.359C3.92,3.898 2.125,6.084 1.066,8.642C0.006,11.201 -0.271,14.016 0.269,16.731C0.809,19.447 2.143,21.942 4.101,23.899C6.058,25.857 8.553,27.191 11.269,27.731C13.984,28.271 16.799,27.994 19.358,26.934C21.916,25.875 24.102,24.08 25.641,21.778C27.179,19.476 28,16.769 28,14C28,10.287 26.525,6.726 23.899,4.1C21.274,1.475 17.713,0 14,0ZM22.925,10.15L12.425,20.65C12.118,20.869 11.752,20.991 11.375,21C11.003,20.964 10.644,20.844 10.325,20.65L4.025,14.35C3.747,14.071 3.59,13.694 3.59,13.3C3.59,12.906 3.747,12.528 4.025,12.25C4.304,11.972 4.681,11.815 5.075,11.815C5.469,11.815 5.847,11.972 6.125,12.25L11.375,17.5L20.825,8.05C21.116,7.796 21.489,7.657 21.875,7.657C22.261,7.657 22.634,7.796 22.925,8.05C23.089,8.172 23.222,8.33 23.314,8.512C23.406,8.695 23.454,8.896 23.454,9.1C23.454,9.304 23.406,9.506 23.314,9.688C23.222,9.87 23.089,10.028 22.925,10.15Z"
android:fillColor="#0014F0"/>
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M512.2,64.2c-247.4,0 -448,200.6 -448,448s200.6,448 448,448 448,-200.6 448,-448 -200.6,-448 -448,-448zM709,445.6L474.4,632.4c-14.7,11.7 -35.9,9.5 -48,-4.7 -0.5,-0.3 -1,-0.6 -1.4,-1L310.4,543c-15.5,-11.3 -18.8,-33 -7.5,-48.5s33,-18.8 48.5,-7.5l101.3,74.1 213.2,-169.7c15,-11.9 36.8,-9.5 48.7,5.5 11.8,14.9 9.4,36.8 -5.6,48.7z"
android:fillColor="#13227a"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="16dp"
android:height="256dp" android:height="16dp"
android:viewportWidth="1024" android:viewportWidth="1024"
android:viewportHeight="1024"> android:viewportHeight="1024">
<path <path
android:pathData="M518,87.1c-235.3,0 -426,190.7 -426,426s190.7,426 426,426 426,-190.7 426,-426 -190.7,-426 -426,-426zM518,855.1c-188.9,0 -342.1,-153.2 -342.1,-342.1S329,170.9 518,170.9s342.1,153.2 342.1,342.1 -153.2,342.1 -342.1,342.1z" android:pathData="M518,87.1c-235.3,0 -426,190.7 -426,426s190.7,426 426,426 426,-190.7 426,-426 -190.7,-426 -426,-426zM518,855.1c-188.9,0 -342.1,-153.2 -342.1,-342.1S329,170.9 518,170.9s342.1,153.2 342.1,342.1 -153.2,342.1 -342.1,342.1z"
android:fillColor="#13227a"/> android:fillColor="@color/black"/>
</vector> </vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M518,87.1c-235.3,0 -426,190.7 -426,426s190.7,426 426,426 426,-190.7 426,-426 -190.7,-426 -426,-426zM518,855.1c-188.9,0 -342.1,-153.2 -342.1,-342.1S329,170.9 518,170.9s342.1,153.2 342.1,342.1 -153.2,342.1 -342.1,342.1z"
android:fillColor="@color/white"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,7 +1,7 @@
<?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"
android:shape="rectangle"> android:shape="rectangle">
<corners android:radius="12dp"/> <corners android:bottomRightRadius="8dp" android:bottomLeftRadius="8dp"/>
<solid android:color="@color/color_photo_size_bg"/> <solid android:color="@color/color_photo_size_bg"/>
</shape> </shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_arrow_up_blue" android:state_selected="true" />
<item android:drawable="@drawable/icon_arrow_down_gray" android:state_selected="false" />
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_checkmark_filter" android:state_selected="true" />
<item android:drawable="@android:color/transparent" android:state_selected="false" />
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_checkmark_28dp" android:state_selected="true" />
<item android:drawable="@drawable/icon_unselected_28dp" />
</selector>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_selected" android:state_selected="true" />
<item android:drawable="@drawable/icon_unselected" />
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_checkmark_16dp" android:state_selected="true" />
<item android:drawable="@drawable/icon_unselected_16dp" />
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_rectangle_blue_right_8" android:state_enabled="true" />
<item android:drawable="@drawable/bg_rectangle_d5ebff_right_8" android:state_enabled="false" />
</selector>

View File

@ -1,12 +1,211 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".photo.PhotoSortingActivity"> tools:context=".photo.PhotoSortingActivity">
<RelativeLayout
android:id="@+id/layout_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingBottom="9dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/image_view_back"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:paddingHorizontal="13dp"
android:paddingVertical="14dp"
android:src="@drawable/black_return" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_select_all"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_alignParentEnd="true"
android:gravity="center"
android:paddingHorizontal="16dp"
android:text="@string/select_all"
android:textColor="@color/color_title_blue"
android:textSize="16sp"
app:fontType="bold"
app:normal_text="@string/select_all"
app:selected_text="@string/deselect_all"
tools:ignore="RelativeOverlap" />
<LinearLayout
android:id="@+id/filter_date_layout"
android:layout_width="wrap_content"
android:layout_height="42dp"
android:layout_below="@id/tv_select_all"
android:layout_marginStart="16dp"
android:gravity="center"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/date"
android:textColor="@color/selector_black_blue"
android:textSize="16sp"
app:fontType="bold" />
<ImageView
android:layout_width="8dp"
android:layout_height="4dp"
android:layout_marginStart="8dp"
android:src="@drawable/selector_arrow_up_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/filter_size_layout"
android:layout_width="wrap_content"
android:layout_height="42dp"
android:layout_alignTop="@id/filter_date_layout"
android:layout_marginStart="20dp"
android:layout_toEndOf="@id/filter_date_layout"
android:gravity="center"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/size"
android:textColor="@color/selector_black_blue"
android:textSize="16sp"
app:fontType="bold" />
<ImageView
android:layout_width="8dp"
android:layout_height="4dp"
android:layout_marginStart="8dp"
android:src="@drawable/selector_arrow_up_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/filter_layout_linearlayout"
android:layout_width="wrap_content"
android:layout_height="42dp"
android:layout_alignTop="@id/filter_date_layout"
android:layout_marginStart="20dp"
android:layout_toEndOf="@id/filter_size_layout"
android:gravity="center"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/layout"
android:textColor="@color/selector_black_blue"
android:textSize="16sp"
app:fontType="bold" />
<ImageView
android:layout_width="8dp"
android:layout_height="4dp"
android:layout_marginStart="8dp"
android:src="@drawable/selector_arrow_up_down" />
</LinearLayout>
<ImageView
android:layout_width="47dp"
android:layout_height="16dp"
android:layout_alignTop="@id/filter_date_layout"
android:layout_alignBottom="@id/filter_date_layout"
android:layout_alignParentEnd="true"
android:layout_marginEnd="8dp"
android:id="@+id/im_sort"
android:paddingHorizontal="16dp"
android:src="@drawable/icon_sort" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_thumbnail_counts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/filter_date_layout"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:text="@string/hide_thumbnails"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_thumbnail_counts"
android:layout_alignStart="@id/tv_thumbnail_counts"
android:layout_marginTop="8dp"
android:text="@string/hide_thumbnails_describe"
android:textColor="@color/main_sub_title"
android:textSize="12sp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_hide_thumbnails"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_alignTop="@id/tv_thumbnail_counts"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
app:thumbTint="@color/selector_switch_thumb_color"
app:trackTint="@color/selector_switch_track_color" />
</RelativeLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_bg">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"
android:background="@drawable/bg_rectangle_white_left_8"
android:gravity="center"
android:text="@string/delete"
android:textColor="@color/selector_delete_button_enable"
android:textSize="16sp"
app:fontType="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/tv_recover" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_recover"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:background="@drawable/selector_recover_button_enable"
android:gravity="center"
android:text="@string/recover"
android:textColor="@color/white"
android:textSize="16sp"
app:fontType="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@id/tv_delete"
app:layout_constraintRight_toRightOf="parent" />
<TextView <TextView
android:id="@+id/tv_select_counts" android:id="@+id/tv_select_counts"
@ -14,21 +213,21 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:text="@string/app_name" /> android:text="@string/app_name"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete"
android:id="@+id/btn_delete"
android:layout_toEndOf="@id/tv_select_counts"/>
<RadioGroup <RadioGroup
android:id="@+id/rg_layout" android:id="@+id/rg_layout"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/tv_select_counts" android:layout_below="@id/tv_select_counts"
android:orientation="horizontal"> android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<RadioButton <RadioButton
android:id="@+id/rb_columns_2" android:id="@+id/rb_columns_2"
@ -55,7 +254,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/rg_layout" android:layout_below="@id/rg_layout"
android:orientation="horizontal"> android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<RadioButton <RadioButton
android:id="@+id/btn_size_all" android:id="@+id/btn_size_all"
@ -83,57 +285,42 @@
</RadioGroup> </RadioGroup>
<RadioGroup <!-- <RadioGroup-->
android:id="@+id/linear_date" <!-- android:id="@+id/linear_date"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:layout_below="@id/linear_size" <!-- android:layout_below="@id/linear_size"-->
android:orientation="horizontal"> <!-- android:orientation="horizontal">-->
<RadioButton <!-- <RadioButton-->
android:id="@+id/btn_date_all" <!-- android:id="@+id/btn_date_all"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:text="all date" /> <!-- android:text="all date" />-->
<RadioButton <!-- <RadioButton-->
android:id="@+id/btn_date_within_1" <!-- android:id="@+id/btn_date_within_1"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:text="within 1 month" /> <!-- android:text="within 1 month" />-->
<RadioButton <!-- <RadioButton-->
android:id="@+id/btn_date_customize" <!-- android:id="@+id/btn_date_customize"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content" <!-- android:layout_height="wrap_content"-->
android:text="customize" /> <!-- android:text="customize" />-->
</RadioGroup> <!-- </RadioGroup>-->
<ImageView
android:id="@+id/im_select_all"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_below="@id/linear_date"
android:padding="8dp"
android:src="@drawable/selector_icon_select" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/im_select_all"
android:layout_alignBottom="@id/im_select_all"
android:layout_toEndOf="@id/im_select_all"
android:gravity="center_vertical"
android:text="@string/select_all" />
<RadioGroup <RadioGroup
android:id="@+id/linear" android:id="@+id/linear"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/im_select_all" android:orientation="horizontal"
android:orientation="horizontal"> android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<RadioButton <RadioButton
android:id="@+id/btn_date_old_to_new" android:id="@+id/btn_date_old_to_new"
@ -160,10 +347,7 @@
android:text="big" /> android:text="big" />
</RadioGroup> </RadioGroup>
<androidx.recyclerview.widget.RecyclerView </androidx.constraintlayout.widget.ConstraintLayout>
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/linear" />
</RelativeLayout>
</LinearLayout>

View File

@ -1,47 +1,165 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".result.ScanResultDisplayActivity"> tools:context=".result.ScanResultDisplayActivity">
<TextView <RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/image_view_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingHorizontal="13dp"
android:paddingVertical="14dp"
android:src="@drawable/black_return" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_bg"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_rectangle_white_20"
android:paddingVertical="20dp">
<RelativeLayout
android:id="@+id/relativelayout_finish"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/im_finish"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_centerVertical="true"
android:src="@drawable/icon_finish" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_toEndOf="@id/im_finish"
android:text="@string/finished"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
</RelativeLayout>
<LinearLayout
android:id="@+id/layout_file_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/div_line"
app:layout_constraintTop_toBottomOf="@id/relativelayout_finish">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_all_counts" android:id="@+id/text_all_counts"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="13" /> android:text="13"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_file_type" android:id="@+id/text_file_type"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/text_all_counts" android:textSize="14sp"
android:layout_marginTop="8dp"
app:fontType="bold"
android:textColor="@color/main_sub_title"
android:text="photos" /> android:text="photos" />
</LinearLayout>
<TextView <View
android:id="@+id/div_line"
android:layout_width="1dp"
android:layout_height="18dp"
android:background="@color/dividing_line_color"
app:layout_constraintBottom_toBottomOf="@id/layout_file_counts"
app:layout_constraintLeft_toRightOf="@id/layout_file_counts"
app:layout_constraintRight_toLeftOf="@id/layout_folder_counts"
app:layout_constraintTop_toTopOf="@id/layout_file_counts" />
<LinearLayout
android:id="@+id/layout_folder_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@id/div_line"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/relativelayout_finish"
app:layout_constraintTop_toTopOf="@id/layout_file_counts">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_dir_count" android:id="@+id/text_dir_count"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="75dp" android:text="13"
android:layout_toEndOf="@id/text_all_counts" android:textColor="@color/main_title"
android:text="13" /> android:textSize="16sp"
app:fontType="bold" />
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_dir" android:id="@+id/text_dir"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/text_dir_count" android:textSize="14sp"
android:layout_alignStart="@id/text_dir_count" android:layout_marginTop="8dp"
app:fontType="bold"
android:textColor="@color/main_sub_title"
android:text="Folders" /> android:text="Folders" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_result" android:id="@+id/recycler_result"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/text_dir" android:layout_marginTop="30dp" />
android:layout_marginTop="35dp" /> </LinearLayout>
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="50dp"
android:id="@+id/relativelayout"
android:paddingHorizontal="16dp">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textColor="@color/selector_c7c7cc_blue"
android:textSize="16sp"
app:fontType="bold"
android:id="@+id/text_item"
tools:ignore="RelativeOverlap" />
<ImageView
android:layout_width="16dp"
android:layout_height="12dp"
android:id="@+id/check_image"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:src="@drawable/selector_filter_image_view" />
</RelativeLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="5dp">
<ImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_centerVertical="true"
android:src="@drawable/icon_ascending_size" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/sort_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_toEndOf="@id/icon"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/sort_sub_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/sort_type"
android:layout_alignStart="@id/sort_type"
android:layout_marginTop="2dp"
android:textColor="@color/main_sub_title"
android:textSize="12sp" />
<ImageView
android:id="@+id/check_image"
android:layout_width="16dp"
android:layout_height="12dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:src="@drawable/selector_filter_image_view" />
</RelativeLayout>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<DatePicker
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_rectangle_white_20"
android:orientation="vertical"
android:paddingHorizontal="20dp"
android:paddingVertical="30dp">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/exit_title"
android:textSize="20sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:lineSpacingExtra="2dp"
android:text="@string/exit_content"
android:textColor="@color/dialog_permission_content"
android:textSize="14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginTop="26dp"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/exit"
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_weight="1"
android:background="@drawable/bg_dialog_btn_cancel_stoke_8"
android:gravity="center"
android:text="@string/exit"
android:textColor="@color/main_text_blue"
android:textSize="14sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/cancel"
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginStart="20dp"
android:layout_weight="1"
android:background="@drawable/bg_dialog_btn_allow_solid_8"
android:gravity="center"
android:text="@string/cancel"
android:textColor="@color/white"
android:textSize="14sp"
app:fontType="bold" />
</LinearLayout>
</LinearLayout>
</FrameLayout>

View File

@ -10,7 +10,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_marginEnd="20dp" android:layout_marginEnd="20dp"
android:background="@drawable/bg_dialog_permission_white_20" android:background="@drawable/bg_rectangle_white_20"
android:orientation="vertical" android:orientation="vertical"
android:padding="20dp"> android:padding="20dp">
@ -20,7 +20,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/permission_request" android:text="@string/permission_request"
android:textSize="20sp" android:textSize="20sp"
app:fontType="medium" /> app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -56,9 +56,9 @@
android:background="@drawable/bg_dialog_btn_cancel_stoke_8" android:background="@drawable/bg_dialog_btn_cancel_stoke_8"
android:gravity="center" android:gravity="center"
android:text="@string/cancel" android:text="@string/cancel"
android:textColor="@color/dialog_btn_stoke" android:textColor="@color/main_text_blue"
android:textSize="14sp" android:textSize="14sp"
app:fontType="medium" /> app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/allow" android:id="@+id/allow"
@ -71,7 +71,7 @@
android:text="@string/allow" android:text="@string/allow"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14sp" android:textSize="14sp"
app:fontType="medium" /> app:fontType="bold" />
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_rectangle_white_top_20"
android:orientation="vertical">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:text="@string/sort_by"
android:textColor="@color/main_title"
android:textSize="20sp"
app:fontType="bold" />
<include
android:id="@+id/ascending_size_layout"
layout="@layout/common_layout_sort_item"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="@+id/descending_size_layout"
layout="@layout/common_layout_sort_item" />
<include
android:id="@+id/ascending_date_layout"
layout="@layout/common_layout_sort_item" />
<include
android:id="@+id/descending_date_layout"
layout="@layout/common_layout_sort_item" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="16dp"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:background="@drawable/bg_rectangle_f5f5fa_left_8"
android:gravity="center"
android:text="@string/cancel"
android:textColor="@color/main_text_blue"
android:textSize="16sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_ok"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:background="@drawable/bg_rectangle_blue_right_8"
android:gravity="center"
android:text="@string/ok"
android:textColor="@color/white"
android:textSize="16sp"
app:fontType="bold" />
</LinearLayout>
</LinearLayout>
</FrameLayout>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/root_layout"
android:layout_marginEnd="10dp"
android:layout_marginTop="9dp"
android:layout_width="match_parent"
android:layout_height="150dp">
<ImageView
android:id="@+id/image_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_size"
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_alignParentBottom="true"
android:layout_centerVertical="true"
android:paddingStart="6dp"
android:background="@drawable/photo_size_bg"
android:text="150kb"
android:textColor="@color/white"
android:textSize="11sp"
app:fontType="bold"
tools:ignore="RtlSymmetry" />
<ImageView
android:id="@+id/image_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="6dp"
android:paddingVertical="6dp"
android:src="@drawable/selector_icon_select_16" />
</RelativeLayout>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginTop="9dp"
android:layout_marginEnd="10dp">
<ImageView
android:id="@+id/image_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_size"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:background="@drawable/photo_size_bg"
android:gravity="center_vertical"
android:paddingStart="6dp"
android:text="150kb"
android:textColor="@color/white"
android:textSize="14sp"
app:fontType="bold" />
<ImageView
android:id="@+id/image_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="6dp"
android:paddingVertical="6dp"
android:src="@drawable/selector_icon_checkmark_28dp" />
</RelativeLayout>

View File

@ -1,30 +1,51 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_date" android:id="@+id/text_date"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textSize="19sp"
android:text="@string/app_name"
android:textStyle="bold"
android:layout_marginStart="8dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:paddingTop="21dp"
android:text="@string/app_name"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
<ImageView <com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="36dp" android:id="@+id/text_child_counts"
android:layout_height="36dp" android:layout_width="wrap_content"
android:padding="8dp" android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_toEndOf="@id/text_date"
android:paddingTop="21dp"
android:text="@string/app_name"
android:textColor="@color/main_sub_title"
android:textSize="16sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_day_all_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:id="@+id/im_select_status" android:layout_marginEnd="16dp"
android:src="@drawable/selector_icon_select" /> android:drawableStart="@drawable/selector_icon_select_16"
android:drawablePadding="4dp"
android:paddingTop="21dp"
android:text="@string/select"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_child" android:id="@+id/recycler_child"
android:layout_width="match_parent" android:layout_width="match_parent"
android:paddingStart="16dp"
android:paddingEnd="6dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/text_date" /> android:layout_below="@id/text_date" />

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp">
<ImageView
android:id="@+id/image_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/photo_size_bg">
<TextView
android:id="@+id/text_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="150kb"
android:textColor="@color/white"
android:textSize="15sp" />
</RelativeLayout>
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:padding="8dp"
android:id="@+id/im_select_status"
android:src="@drawable/selector_icon_select" />
</RelativeLayout>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/view_mask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0"
android:visibility="gone"
android:background="@color/popup_windows_mask" />
<LinearLayout
android:id="@+id/parent_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_rectangle_white_bottom_20"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>

View File

@ -5,22 +5,51 @@
android:layout_marginTop="13dp" android:layout_marginTop="13dp"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_dir_name_count" android:id="@+id/text_dir_name_count"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="44dp"
android:layout_marginStart="26dp" android:layout_marginStart="16dp"
android:textColor="@color/main_title"
app:fontType="bold"
android:textSize="16sp"
android:gravity="center"
android:text="@string/allow"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_file_counts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textColor="@color/main_sub_title"
app:fontType="bold"
android:textSize="16sp"
android:text="@string/allow"
app:layout_constraintBottom_toBottomOf="@id/text_dir_name_count"
app:layout_constraintLeft_toRightOf="@id/text_dir_name_count"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:id="@+id/image_view_enter"
app:layout_constraintEnd_toEndOf="parent"
android:paddingHorizontal="16dp"
android:paddingVertical="14dp"
app:layout_constraintTop_toTopOf="@id/text_dir_name_count"
app:layout_constraintBottom_toBottomOf="@id/text_dir_name_count"
android:src="@drawable/icon_vector"/>
<ImageView <ImageView
android:id="@+id/im1" android:id="@+id/im1"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="120dp" android:layout_height="102dp"
android:layout_below="@id/text_dir_name_count" android:layout_below="@id/text_dir_name_count"
android:layout_marginStart="10dp" android:layout_marginStart="16dp"
android:layout_marginEnd="7dp" android:layout_marginEnd="10dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:src="@mipmap/ic_launcher" android:src="@mipmap/ic_launcher"
app:layout_constraintHorizontal_weight="1" app:layout_constraintHorizontal_weight="1"
@ -33,7 +62,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_below="@id/text_dir_name_count" android:layout_below="@id/text_dir_name_count"
android:layout_marginEnd="7dp" android:layout_marginEnd="10dp"
android:src="@mipmap/ic_launcher" android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="@id/im1" app:layout_constraintBottom_toBottomOf="@id/im1"
app:layout_constraintHorizontal_weight="1" app:layout_constraintHorizontal_weight="1"
@ -46,7 +75,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_below="@id/text_dir_name_count" android:layout_below="@id/text_dir_name_count"
android:layout_marginEnd="10dp" android:layout_marginEnd="16dp"
android:src="@mipmap/ic_launcher" android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="@id/im1" app:layout_constraintBottom_toBottomOf="@id/im1"
app:layout_constraintHorizontal_weight="1" app:layout_constraintHorizontal_weight="1"

View File

@ -2,44 +2,34 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"> android:orientation="vertical">
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/app_name" android:text="@string/app_name"
android:textSize="29sp" android:textSize="29sp"
android:fontFamily="sans-serif"/> app:fontType="bold"/>
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/app_name" android:text="@string/app_name"
android:textSize="29sp" android:textSize="29sp"
android:textStyle="bold" app:fontType="bold"/>
android:fontFamily="sans-serif"/> <com.ux.video.file.filerecovery.utils.CustomTextView
<TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/app_name" android:text="@string/app_name"
android:textSize="29sp" android:textSize="29sp"
android:fontFamily="sans-serif-light"/> app:fontType="alimama"/>
<TextView <com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/app_name" android:text="@string/app_name"
android:textSize="29sp" android:textSize="29sp"
android:fontFamily="sans-serif-thin"/> app:fontType="regular"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="29sp"
android:fontFamily="sans-serif-medium"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="29sp"
android:fontFamily="sans-serif-condensed"/>

View File

@ -2,11 +2,12 @@
<resources> <resources>
<declare-styleable name="CustomTextView"> <declare-styleable name="CustomTextView">
<attr name="fontType" format="enum"> <attr name="fontType" format="enum">
<enum name="regular" value="0"/> <enum name="regular" value="0" />
<enum name="bold" value="1"/> <enum name="bold" value="1" />
<enum name="alimama" value="2"/> <enum name="alimama" value="2" />
<enum name="medium" value="3"/>
</attr> </attr>
<attr name="selected_text" format="string" />
<attr name="normal_text" format="string" />
</declare-styleable> </declare-styleable>
<declare-styleable name="CircleImageProgressView"> <declare-styleable name="CircleImageProgressView">

View File

@ -3,7 +3,7 @@
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="color_scan_select_bg">#DDF6C1</color> <color name="color_scan_select_bg">#DDF6C1</color>
<color name="color_photo_size_bg">#B1A6A6A6</color> <color name="color_photo_size_bg">#66000000</color>
<color name="main_title">#000000</color> <color name="main_title">#000000</color>
<color name="main_sub_title">#9696A2</color> <color name="main_sub_title">#9696A2</color>
@ -12,6 +12,11 @@
<color name="color_title_start_color">#198BF5</color> <color name="color_title_start_color">#198BF5</color>
<color name="color_title_end_color">#6D00F2</color> <color name="color_title_end_color">#6D00F2</color>
<color name="dialog_permission_content">#9696A2</color> <color name="dialog_permission_content">#9696A2</color>
<color name="dividing_line_color">#E5E5EA</color>
<color name="main_text_blue">#0014F0</color>
<color name="switch_track_false">#C7C7CC</color>
<color name="switch_track_true">#D5EBFF</color>
<color name="popup_windows_mask">#65000000</color>
<color name="dialog_btn_stoke">#0014F0</color>
</resources> </resources>

View File

@ -3,6 +3,8 @@
<string name="scan_all_file">Scan all files</string> <string name="scan_all_file">Scan all files</string>
<string name="scan_deleted_files">Scan deleted files</string> <string name="scan_deleted_files">Scan deleted files</string>
<string name="select_all">Select all</string> <string name="select_all">Select all</string>
<string name="select">Select</string>
<string name="deselect_all">Deselect all</string>
<string name="size_kb">%.2f KB</string> <string name="size_kb">%.2f KB</string>
@ -31,6 +33,7 @@
<string name="permission_request_promote">We will never share, upload, or send your data without your permission.</string> <string name="permission_request_promote">We will never share, upload, or send your data without your permission.</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
<string name="exit">Exit</string>
<string name="allow">Allow</string> <string name="allow">Allow</string>
<string name="scan">Scanning…</string> <string name="scan">Scanning…</string>
<string name="describe_photos">photos</string> <string name="describe_photos">photos</string>
@ -41,4 +44,41 @@
<string name="describe_delete_audios">deleted audios</string> <string name="describe_delete_audios">deleted audios</string>
<string name="describe_documents">documents</string> <string name="describe_documents">documents</string>
<string name="describe_delete_documents">deleted documents</string> <string name="describe_delete_documents">deleted documents</string>
<string name="finished">Finished!</string>
<string name="exit_title">Recoverable files are ready</string>
<string name="exit_content">If you exit,the scanning results will be discarded.Are you sure you want to exit now?</string>
<string name="date">Date</string>
<string name="size">Size</string>
<string name="layout">Layout</string>
<string name="hide_thumbnails">Hide thumbnails (%d)</string>
<string name="hide_thumbnails_describe">Thumbnails refer to photos below 256 pixels</string>
<string name="delete">Delete</string>
<string name="recover">Recover</string>
<string name="delete_placeholder">Delete (%d)</string>
<string name="recover_placeholder">Recover (%d)</string>
<string name="sort_by">Sort by</string>
<string name="asc_size_describe">(Small to large)</string>
<string name="desc_size_describe">(Large to Small)</string>
<string name="asc_date_describe">(Old to new)</string>
<string name="desc_date_describe">(New to old)</string>
<string name="ok">OK</string>
<string-array name="filter_date">
<item>All</item>
<item>within 1 month</item>
<item>within 6 month</item>
<item>within 24 month</item>
<item>Customize</item>
</string-array>
<string-array name="filter_size">
<item>All</item>
<item>0-1 M</item>
<item>1-5 M</item>
<item>>5 M</item>
</string-array>
<string-array name="filter_layout">
<item>2 columns</item>
<item>3 columns</item>
<item>4 columns</item>
</string-array>
</resources> </resources>