增加删除中和恢复中弹窗

This commit is contained in:
litingting 2025-10-10 15:44:34 +08:00
parent 0dd66d6c96
commit d610ef5d53
29 changed files with 901 additions and 74 deletions

View File

@ -24,6 +24,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.FileRecovery"
tools:targetApi="31">
<activity
android:name=".photo.PhotoInfoActivity"
android:exported="false" />
<activity
android:name=".photo.PhotoSortingActivity"
android:exported="false" />
@ -39,6 +42,9 @@
<activity
android:name=".documents.DocumentsScanResultActivity"
android:exported="false" />
<activity
android:name=".success.RecoverySuccessActivity"
android:exported="false" />
<activity
android:name=".main.MainActivity"
android:exported="true">

View File

@ -0,0 +1,83 @@
package com.ux.video.file.filerecovery.base
import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Bundle
import android.os.CountDownTimer
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.databinding.DialogRecoveringBinding
abstract class BaseIngDialogFragment(var total: Int, var complete: () -> Unit) : DialogFragment() {
private lateinit var binding: DialogRecoveringBinding
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 = DialogRecoveringBinding.inflate(inflater)
initUi(binding)
binding.run {
if (total < 20) {
val defaultTimer = 2000L
object : CountDownTimer(defaultTimer, 200) {
override fun onFinish() {
progressBar.progress = 100
complete.invoke()
}
override fun onTick(millisUntilFinished: Long) {
var progressPercentage = ((100 * millisUntilFinished) / defaultTimer)
val i = (100 - progressPercentage).toInt()
progressBar.progress = i
}
}.start()
}
}
return binding.root
}
protected abstract fun initUi(binding: DialogRecoveringBinding)
@SuppressLint("SetTextI18n")
fun updateProgress(number: Int) {
binding.tvRecoverNumber.text = "${number}/"
if (total < 20) {
return
}
val progress = if (total > 20) {
(number * 100f / total).toInt()
} else {
0
}
binding.progressBar.progress = progress
if (progress == 100) {
complete.invoke()
}
}
}

View File

@ -42,27 +42,5 @@ class DatePickerDialogFragment(val onClickSort: (type: Int) -> Unit) : DialogFra
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,24 @@
package com.ux.video.file.filerecovery.photo
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseIngDialogFragment
import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding
/**
* 删除中弹窗
*/
class DeletingDialogFragment(total: Int, complete:()-> Unit) : BaseIngDialogFragment(total,complete) {
override fun initUi(binding: DialogRecoveringBinding) {
binding.run {
relativeLayout.setBackgroundResource(R.drawable.bg_rectangle_fdad00_top_20)
tvType.text = getString(R.string.deleting)
tvContent.text = getString(R.string.delete_content)
tvTotal.text = total.toString()
}
}
}

View File

@ -8,7 +8,6 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.ux.video.file.filerecovery.base.BaseAdapter
import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding
import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.ExtendFunctions.resetItemDecorationOnce
import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration
import com.ux.video.file.filerecovery.utils.ScanRepository
@ -16,7 +15,8 @@ class PhotoDisplayDateAdapter(
mContext: Context,
var mColumns: Int,
var viewModel: ScanRepository,
var onSelectedUpdate: (updatePath: String, isAdd: Boolean) -> Unit
var onSelectedUpdate: (updatePath: String, isAdd: Boolean) -> Unit,
var clickItem:(item:ResultPhotosFiles)-> Unit
) :
BaseAdapter<Pair<String, List<ResultPhotosFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
@ -46,6 +46,7 @@ class PhotoDisplayDateAdapter(
}
}
notifyDataSetChanged()
allSelected = null
}
fun resetAllValue(b: Boolean?){
@ -72,12 +73,12 @@ class PhotoDisplayDateAdapter(
val childAdapter = PhotoDisplayDateChildAdapter(
mContext,
mColumns,
viewModel
) { path, addOrRemove, isDateAllSelected ->
viewModel,
{ path, addOrRemove, isDateAllSelected ->
//点击当前Adapter某一天的全选或者子Item上的选中都会回调到这里
tvDayAllSelect.isSelected = isDateAllSelected
onSelectedUpdate(path.toString(),addOrRemove)
}.apply { setData(files) }
},clickItem).apply { setData(files) }
allSelected?.let {
childAdapter.setAllSelected(it)

View File

@ -36,7 +36,8 @@ class PhotoDisplayDateChildAdapter(
* @param addOrRemove 选中还是取消选中
* @param dateAllSelected 这组数据是否全部选中某一天
*/
var onSelectedUpdate: (updatePath: String, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit
var onSelectedUpdate: (updatePath: String, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit,
var clickItem:(item:ResultPhotosFiles)-> Unit
) :
NewBaseAdapter<ResultPhotosFiles>(mContext) {
@ -189,6 +190,7 @@ class PhotoDisplayDateChildAdapter(
})
.into(imageThumbnail)
rootLayout.setOnClickListener { clickItem(item) }
setHeight(rootLayout)
}

View File

@ -0,0 +1,92 @@
package com.ux.video.file.filerecovery.photo
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseActivity
import com.ux.video.file.filerecovery.databinding.ActivityPhotoInfoBinding
import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding
import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
import com.ux.video.file.filerecovery.utils.ScanManager
class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
companion object {
val KEY_CLICK_ITEM = "click_item"
}
private var myData: ResultPhotosFiles? = null
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoInfoBinding =
ActivityPhotoInfoBinding.inflate(inflater)
override fun initView() {
super.initView()
myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(KEY_CLICK_ITEM, ResultPhotosFiles::class.java)
} else {
@Suppress("DEPRECATION")
intent.getParcelableExtra("MY_KEY")
}
binding.run {
myData?.let {
tvName.text = it.name
tvPath.text = it.path
tvDate.text = Common.getFormatDate(it.lastModified)
tvResolution.text = it.resolution
Glide.with(this@PhotoInfoActivity)
.load(it.targetFile)
.apply(
RequestOptions()
.transform(
CenterCrop(),
RoundedCorners(8.dpToPx(this@PhotoInfoActivity))
)
)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: com.bumptech.glide.request.target.Target<Drawable?>,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: Drawable,
model: Any,
target: Target<Drawable?>?,
dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
return false
}
})
.into(image)
}
}
}
}

View File

@ -1,5 +1,6 @@
package com.ux.video.file.filerecovery.photo
import android.content.Intent
import android.view.LayoutInflater
import android.widget.LinearLayout
import androidx.activity.viewModels
@ -9,9 +10,13 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.DateValidatorPointForward
import com.google.android.material.datepicker.MaterialDatePicker
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseActivity
import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding
import com.ux.video.file.filerecovery.success.RecoverySuccessActivity
import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.Common.setItemSelect
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
@ -28,6 +33,9 @@ import com.ux.video.file.filerecovery.utils.ScanManager.copySelectedFilesAsync
import com.ux.video.file.filerecovery.utils.ScanManager.deleteFilesAsync
import com.ux.video.file.filerecovery.utils.ScanRepository
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
@ -58,6 +66,10 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
//文件大小排序使用的适配器
private var sizeSortAdapter: PhotoDisplayDateChildAdapter? = null
private var dialogRecovering: RecoveringDialogFragment? = null
private var dialogDeleting: DeletingDialogFragment? = null
//默认倒序排序
private var sortReverse = true
@ -112,6 +124,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
updateCurrentIsAllSelectStatus()
}
binding.imageViewBack.setOnClickListener { finish() }
list?.let {
//降序(最近的在前面)
@ -123,21 +136,34 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
sizeSortAdapter = PhotoDisplayDateChildAdapter(
this@PhotoSortingActivity,
columns, viewModel
) { path, isAdd, allSelected ->
// updateSelectedList(isAdd, path)
// updateCurrentIsAllSelectStatus()
columns, viewModel,
{ path, isAdd, allSelected ->
viewModel.toggleSelection(isAdd, path)
}) { item ->
startActivity(
Intent(
this@PhotoSortingActivity,
PhotoInfoActivity::class.java
).apply {
putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item)
})
}
dateAdapter =
PhotoDisplayDateAdapter(
this@PhotoSortingActivity,
columns,
viewModel
) { actionPath, isAdd ->
// updateSelectedList(isAdd, actionPath)
// updateCurrentIsAllSelectStatus()
viewModel,
{ actionPath, isAdd ->
viewModel.toggleSelection(isAdd, actionPath)
}) { item ->
startActivity(
Intent(
this@PhotoSortingActivity,
PhotoInfoActivity::class.java
).apply {
putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item)
})
}.apply {
setData(sortByDateReverse)
}
@ -145,23 +171,25 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
setFilter()
binding.run {
tvRecover.setOnClickListener {
showRecoveringDialog()
lifecycleScope.copySelectedFilesAsync(
selectedSet = filterSelectedSetList,
folder = Common.recoveryPhotoDir,
onProgress = { currentCounts: Int, fileName: String, success: Boolean ->
ScanManager.showLog(
"--------恢复图片 ",
"----------${currentCounts} ${fileName}"
)
dialogRecovering?.updateProgress(currentCounts)
}) { counts ->
dialogRecovering?.updateProgress(counts)
ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}")
}
}
tvDelete.setOnClickListener {
showDeletingDialog()
lifecycleScope.deleteFilesAsync(
selectedSet = filterSelectedSetList,
onProgress = { currentCounts: Int, path: String, success: Boolean ->
@ -169,9 +197,9 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
"--------删除图片 ",
"----------${currentCounts} ${path}"
)
dialogDeleting?.updateProgress(currentCounts)
}) { counts ->
dialogDeleting?.updateProgress(counts)
ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}")
}
@ -281,7 +309,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
data[1] -> filterDate = FILTER_DATE_1
data[2] -> filterDate = FILTER_DATE_6
data[3] -> filterDate = FILTER_DATE_24
data[4] -> {}
data[4] -> showDatePicker()
}
startFilter()
}) {
@ -433,5 +461,48 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
}
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")
}
}
private fun showRecoveringDialog() {
dialogRecovering = dialogRecovering ?: RecoveringDialogFragment(filterSelectedSetList.size){
complete()
}
dialogRecovering?.show(supportFragmentManager, "")
}
private fun showDeletingDialog() {
dialogDeleting = dialogDeleting ?: DeletingDialogFragment(filterSelectedSetList.size){
complete()
}
dialogDeleting?.show(supportFragmentManager, "")
}
private fun complete() {
dialogDeleting?.dismiss()
dialogRecovering?.dismiss()
startActivity(Intent(this@PhotoSortingActivity, RecoverySuccessActivity::class.java))
}
}

View File

@ -0,0 +1,22 @@
package com.ux.video.file.filerecovery.photo
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseIngDialogFragment
import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding
/**
* 恢复中弹窗
*/
class RecoveringDialogFragment(total: Int, complete:()-> Unit) : BaseIngDialogFragment(total,complete) {
override fun initUi(binding: DialogRecoveringBinding) {
binding.run {
relativeLayout.setBackgroundResource(R.drawable.bg_rectangle_0048fd_top_20)
tvType.text = getString(R.string.recovering)
tvContent.text = getString(R.string.recovering_content)
tvTotal.text = total.toString()
}
}
}

View File

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

View File

@ -0,0 +1,50 @@
package com.ux.video.file.filerecovery.success
import android.content.Intent
import android.os.Environment
import android.view.LayoutInflater
import androidx.lifecycle.lifecycleScope
import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseActivity
import com.ux.video.file.filerecovery.databinding.ActivityRecoverOrDeletedSuccessBinding
import com.ux.video.file.filerecovery.databinding.ActivityScanningBinding
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_AUDIO
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_VIDEO
import com.ux.video.file.filerecovery.result.ScanResultDisplayActivity
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.ScanRepository
import com.ux.video.file.filerecovery.utils.ScanState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBinding>() {
companion object {
// val KEY_SCAN_TYPE = "scan_type"
}
private var scanType: Int = VALUE_SCAN_TYPE_photo
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoverOrDeletedSuccessBinding =
ActivityRecoverOrDeletedSuccessBinding.inflate(inflater)
override fun initData() {
super.initData()
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
binding.imageViewBack.setOnClickListener { finish() }
}
}

View File

@ -172,6 +172,10 @@ object Common {
return totalSelectedCount to currentSelected
}
fun getFormatDate(time: Long): String{
return dateFormat.format(Date(time))
}
fun showLog(msg: String) {
Log.d("============", msg)
}

View File

@ -100,15 +100,24 @@ object ScanManager {
name = file.name,
path = file.absolutePath,
size = file.length(),
lastModified = file.lastModified()
lastModified = file.lastModified(),
resolution = getImageSize(file).run {
"$first*$second"
}
)
}
ResultPhotos(dir, ArrayList(resultPhotosFilesList))
}
emit(ScanState.Complete(ArrayList(map)))
}
private fun getImageSize(file: File): Pair<Int, Int> {
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(file.absolutePath, options)
val width = options.outWidth
val height = options.outHeight
return Pair(width, height)
}
/**
* 递归扫描隐藏目录下的有效图片(删除的图片)
@ -172,7 +181,10 @@ object ScanManager {
name = file.name,
path = file.absolutePath,
size = file.length(),
lastModified = file.lastModified()
lastModified = file.lastModified(),
resolution = getImageSize(file).run {
"$first*$second"
}
)
}
ResultPhotos(dir, ArrayList(resultPhotosFilesList))

View File

@ -1,5 +1,6 @@
package com.ux.video.file.filerecovery.utils
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@ -32,33 +33,18 @@ class ScanRepository : ViewModel() {
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}")
}
Common.showLog( "toggleSelection------------ _selectedDisplayFlow=${_selectedDisplayLiveData.value?.size} _selectedFlow=${_selectedLiveData.value?.size} ")
// LiveData 使用新对象赋值,保证 observer 触发
_selectedLiveData.value = current.toSet()
_selectedDisplayLiveData.value = currentDisplay.toSet()
Log.d("CallTrace", Log.getStackTraceString(Exception("Call trace")))
}
// fun toggleSelection(isAdd: Boolean, path: String) {
// val current = _selectedFlow.value.toMutableSet()
// 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
// }
/**
* 数据筛选后重置当前显示的选中集合

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/dialog_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="20dp" android:topLeftRadius="20dp" />
<solid android:color="@color/dialog_progress_color" />
</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:radius="8dp"/>
<solid android:color="@color/dialog_shape_delete"/>
</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/dialog_shape_delete" />
</shape>

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 背景 -->
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/dialog_shape"/>
<corners android:topLeftRadius="20dp" android:topRightRadius="20dp"/>
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape android:shape="rectangle">
<solid android:color="@color/dialog_progress_color"/>
<corners android:topLeftRadius="20dp" android:topRightRadius="20dp"/>
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".photo.PhotoInfoActivity">
<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>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="20dp"
android:background="@drawable/bg_rectangle_white_20"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="320dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name"
android:textColor="@color/main_sub_title"
android:textSize="14sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:gravity="end"
android:textColor="@color/main_title"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="11dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/path"
android:textColor="@color/main_sub_title"
android:textSize="14sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:gravity="end"
android:textColor="@color/main_title"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="11dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.ux.video.file.filerecovery.utils.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/resolution"
android:textColor="@color/main_sub_title"
android:textSize="14sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_resolution"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:gravity="end"
android:textColor="@color/main_title"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="11dp"
android:gravity="center_vertical"
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/main_sub_title"
android:textSize="14sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:gravity="end"
android:textColor="@color/main_title"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<include layout="@layout/common_bottom_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="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="21dp"-->
<!-- android:background="@drawable/bg_rectangle_white_left_8"-->
<!-- android:gravity="center"-->
<!-- android:text="@string/delete"-->
<!-- android:textColor="@color/main_text_blue"-->
<!-- 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="21dp"-->
<!-- android:background="@drawable/bg_rectangle_blue_right_8"-->
<!-- 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" />-->
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@ -0,0 +1,105 @@
<?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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_bg"
android:orientation="vertical"
tools:context=".result.ScanningActivity">
<RelativeLayout
android:id="@+id/top_layout"
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>
<ImageView
android:id="@+id/image_center"
android:layout_width="212dp"
android:layout_height="212dp"
android:layout_below="@id/top_layout"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:src="@drawable/image_recover_success" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/image_center"
android:layout_centerHorizontal="true"
android:layout_marginTop="46dp"
android:textColor="@color/main_text_blue"
android:textSize="48sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_file_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/tv_number"
android:layout_marginStart="6dp"
android:layout_toEndOf="@id/tv_number"
android:textColor="@color/main_sub_title"
android:textSize="16sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_describe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_number"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:textColor="@color/main_sub_title"
android:textSize="20sp"
app:fontType="bold" />
<include
layout="@layout/common_bottom_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_continue"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="21dp"
android:layout_marginHorizontal="16dp"
android:layout_alignParentBottom="true"
android:visibility="gone"
android:background="@drawable/bg_rectangle_fdad00_8"
android:gravity="center"
android:text="@string/text_continue"
android:textColor="@color/white"
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" />
</RelativeLayout>

View File

@ -8,8 +8,6 @@
android:background="@color/white"
android:orientation="vertical"
tools:context=".result.ScanResultDisplayActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<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="21dp"
android:background="@drawable/bg_rectangle_white_left_8"
android:gravity="center"
android:text="@string/delete"
android:textColor="@color/main_text_blue"
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="21dp"
android:background="@drawable/bg_rectangle_blue_right_8"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,81 @@
<?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">
<RelativeLayout
android:id="@+id/relative_layout"
android:layout_width="match_parent"
android:layout_height="280dp"
android:background="@drawable/bg_rectangle_0048fd_top_20">
<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:max="100"
android:progress="1"
android:progressDrawable="@drawable/top_round_progress" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_recover_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp"
android:text="0/"
android:textColor="@color/white"
android:textSize="34sp"
app:fontType="alimama" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/tv_recover_number"
android:layout_marginTop="30dp"
android:layout_marginBottom="5dp"
android:layout_toEndOf="@id/tv_recover_number"
android:text="1"
android:textColor="@color/white"
android:textSize="16sp"
app:fontType="alimama" />
<ProgressBar
android:id="@+id/circle_progress"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_below="@id/tv_recover_number"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:indeterminateTint="@color/white" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/circle_progress"
android:layout_alignBottom="@id/circle_progress"
android:layout_marginStart="7dp"
android:layout_toEndOf="@id/circle_progress"
android:text="@string/recovering"
android:textColor="@color/white"
android:textSize="20sp"
app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/circle_progress"
android:layout_alignStart="@id/circle_progress"
android:layout_marginTop="7dp"
android:text="@string/recovering_content"
android:textColor="@color/white"
android:textSize="12sp"
app:fontType="bold" />
</RelativeLayout>
</FrameLayout>

View File

@ -18,5 +18,8 @@
<color name="switch_track_false">#C7C7CC</color>
<color name="switch_track_true">#D5EBFF</color>
<color name="popup_windows_mask">#65000000</color>
<color name="dialog_shape">#0048FD</color>
<color name="dialog_shape_delete">#fdad00</color>
<color name="dialog_progress_color">#6BFFFFFF</color>
</resources>

View File

@ -62,6 +62,17 @@
<string name="asc_date_describe">(Old to new)</string>
<string name="desc_date_describe">(New to old)</string>
<string name="ok">OK</string>
<string name="name">Name</string>
<string name="path">Path</string>
<string name="resolution">Resolution</string>
<string name="recovering">Recovering...</string>
<string name="recovering_content">It may take a few seconds to recover the file(s), please
wait..</string>
<string name="deleting">Deleting...</string>
<string name="delete_content">It may take a few seconds to delete the file(s), please wait..</string>
<string name="recovered_success">Recovered successfully!</string>
<string name="deleted_success">Deleted successfully!</string>
<string name="text_continue">Continue</string>
<string-array name="filter_date">
<item>All</item>