恢复的文件整体UI

This commit is contained in:
litingting 2025-11-05 13:39:09 +08:00
parent b62abaec37
commit b069402b22
30 changed files with 534 additions and 93 deletions

View File

@ -1,6 +1,7 @@
package com.ux.video.file.filerecovery.recovery package com.ux.video.file.filerecovery.recovery
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
@ -11,33 +12,54 @@ import com.ux.video.file.filerecovery.databinding.ActivityRecoveryBinding
import com.ux.video.file.filerecovery.db.ObjectBoxManager import com.ux.video.file.filerecovery.db.ObjectBoxManager
import com.ux.video.file.filerecovery.recovery.ui.MyViewPage2Adapter import com.ux.video.file.filerecovery.recovery.ui.MyViewPage2Adapter
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoFragment import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoFragment
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoViewModel
import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.CustomTextView import com.ux.video.file.filerecovery.utils.CustomTextView
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() { class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoveryBinding = ActivityRecoveryBinding.inflate(inflater) val sharedViewModel: RecoveryPhotoViewModel by viewModels()
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoveryBinding =
ActivityRecoveryBinding.inflate(inflater)
override fun initView() { override fun initView() {
super.initView() super.initView()
binding.run { binding.run {
val fragments = listOf(
viewPage2.adapter = MyViewPage2Adapter(this@RecoveryActivity,listOf(RecoveryPhotoFragment(),RecoveryPhotoFragment(),RecoveryPhotoFragment(),RecoveryPhotoFragment())) RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_PHOTO),
TabLayoutMediator(tabLayout,viewPage2){tab,position-> RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_VIDEO),
val tabView = LayoutInflater.from(this@RecoveryActivity).inflate(R.layout.tab_layout_item, null) RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_AUDIO),
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_DOCUMENTS)
)
viewPage2.adapter = MyViewPage2Adapter(this@RecoveryActivity, fragments)
TabLayoutMediator(tabLayout, viewPage2) { tab, position ->
val tabView = LayoutInflater.from(this@RecoveryActivity)
.inflate(R.layout.tab_layout_item, null)
val tvTitle = tabView.findViewById<CustomTextView>(R.id.tab_item_title) val tvTitle = tabView.findViewById<CustomTextView>(R.id.tab_item_title)
val tvCount = tabView.findViewById<CustomTextView>(R.id.tab_item_count) val tvCount = tabView.findViewById<CustomTextView>(R.id.tab_item_count)
tvCount.text = getString(R.string.text_counts, 0) tvCount.text = getString(R.string.text_counts, 0)
when(position){ when (position) {
0->{tvTitle.text = getString(R.string.text_photos)} 0 -> {
1->{tvTitle.text = getString(R.string.text_videos)} tvTitle.text = getString(R.string.text_photos)
2->{tvTitle.text = getString(R.string.text_audios)} }
3->{tvTitle.text = getString(R.string.text_documents)}
1 -> {
tvTitle.text = getString(R.string.text_videos)
}
2 -> {
tvTitle.text = getString(R.string.text_audios)
}
3 -> {
tvTitle.text = getString(R.string.text_documents)
}
} }
tab.customView = tabView tab.customView = tabView
}.attach() }.attach()
tabLayout.addOnTabSelectedListener(object :OnTabSelectedListener{ tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) { override fun onTabSelected(tab: TabLayout.Tab?) {
} }
@ -57,16 +79,28 @@ class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
override fun initData() { override fun initData() {
super.initData() super.initData()
lifecycleScope.launch{ binding.imageBack.setOnClickListener {
val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(0) finish()
val recoveryFileVideo = ObjectBoxManager.queryRecoveryFileAsync(1) }
val recoveryFileAudio = ObjectBoxManager.queryRecoveryFileAsync(2) lifecycleScope.launch {
val recoveryFileDocuments = ObjectBoxManager.queryRecoveryFileAsync(3) val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_PHOTO)
sharedViewModel.setPhotosRecoveredFiles(recoveryFilePhoto)
val recoveryFileVideo = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_VIDEO)
sharedViewModel.setVideosRecoveredFiles(recoveryFileVideo)
val recoveryFileAudio = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_AUDIO)
sharedViewModel.setAudiosRecoveredFiles(recoveryFileAudio)
val recoveryFileDocuments =
ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_DOCUMENTS)
sharedViewModel.setDocumentsRecoveredFiles(recoveryFileDocuments)
binding.tabLayout.run { binding.tabLayout.run {
getTabAt(0)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text = getString(R.string.text_counts,recoveryFilePhoto.size) getTabAt(0)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
getTabAt(1)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text = getString(R.string.text_counts,recoveryFileVideo.size) getString(R.string.text_counts, recoveryFilePhoto.size)
getTabAt(2)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text = getString(R.string.text_counts,recoveryFileAudio.size) getTabAt(1)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
getTabAt(3)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text = getString(R.string.text_counts,recoveryFileDocuments.size) getString(R.string.text_counts, recoveryFileVideo.size)
getTabAt(2)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
getString(R.string.text_counts, recoveryFileAudio.size)
getTabAt(3)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
getString(R.string.text_counts, recoveryFileDocuments.size)
} }
} }
} }

View File

@ -1,32 +1,192 @@
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
import androidx.fragment.app.viewModels
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ux.video.file.filerecovery.R import com.ux.video.file.filerecovery.R
import com.ux.video.file.filerecovery.base.BaseFragment import com.ux.video.file.filerecovery.base.BaseFragment
import com.ux.video.file.filerecovery.databinding.FragmentRecoveryPhotoBinding import com.ux.video.file.filerecovery.databinding.FragmentRecoveryPhotoBinding
import com.ux.video.file.filerecovery.db.ResultDataFiles
import com.ux.video.file.filerecovery.sort.PhotoDisplayDateAdapter
import com.ux.video.file.filerecovery.sort.PhotoDisplayDateChildAdapter
import com.ux.video.file.filerecovery.utils.Common
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
class RecoveryPhotoFragment : BaseFragment<FragmentRecoveryPhotoBinding>() { class RecoveryPhotoFragment : BaseFragment<FragmentRecoveryPhotoBinding>() {
companion object { companion object {
fun newInstance() = RecoveryPhotoFragment() private const val ARG_FILE_TYPE = "arg_file_type"
fun newInstance(fileType: Int): RecoveryPhotoFragment {
val fragment = RecoveryPhotoFragment()
val args = Bundle().apply {
putInt(ARG_FILE_TYPE, fileType)
}
fragment.arguments = args
return fragment
}
} }
private val viewModel: RecoveryPhotoViewModel by viewModels() // 0-3 photo\video\audio\documents
private var fileType: Int = Common.FILE_TYPE_PHOTO
override fun initBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRecoveryPhotoBinding = private lateinit var mAdapter: PhotoDisplayDateChildAdapter
private var selectedList: List<ResultDataFiles>? = null
private val sharedViewModel: RecoveryPhotoViewModel by activityViewModels()
override fun initBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentRecoveryPhotoBinding =
FragmentRecoveryPhotoBinding.inflate(inflater, container, false) FragmentRecoveryPhotoBinding.inflate(inflater, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
fileType = arguments?.getInt(ARG_FILE_TYPE) ?: Common.FILE_TYPE_PHOTO
binding.run {
when (fileType) {
Common.FILE_TYPE_PHOTO -> {
layoutEmpty.tvScan.text = getString(R.string.scan_photos)
sharedViewModel.photoFiles.observe(viewLifecycleOwner) {
initViewVisible(it)
setRecoveredData(it, Common.VALUE_SCAN_TYPE_photo)
}
}
Common.FILE_TYPE_VIDEO -> {
layoutEmpty.tvScan.text = getString(R.string.scan_videos)
sharedViewModel.videoFiles.observe(viewLifecycleOwner) {
initViewVisible(it)
setRecoveredData(it, Common.VALUE_SCAN_TYPE_video)
}
}
Common.FILE_TYPE_AUDIO -> {
layoutEmpty.tvScan.text = getString(R.string.scan_audios)
sharedViewModel.audioFiles.observe(viewLifecycleOwner) {
initViewVisible(it)
setRecoveredData(it, Common.VALUE_SCAN_TYPE_audio)
}
}
Common.FILE_TYPE_DOCUMENTS -> {
layoutEmpty.tvScan.text = getString(R.string.scan_documents)
sharedViewModel.documentsFiles.observe(viewLifecycleOwner) {
initViewVisible(it)
setRecoveredData(it, Common.VALUE_SCAN_TYPE_documents)
}
}
}
}
sharedViewModel.selectedLiveData.observe(viewLifecycleOwner) { displaySet ->
selectedList = displaySet.toList()
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
selectedList?.let {
updateSelectStatus(it.size)
}
}
initClick()
} }
private fun initViewVisible(list: List<ResultDataFiles>) {
binding.run {
recyclerView.isVisible = list.isNotEmpty()
layoutEmpty.relativeEmptyMain.isVisible = !list.isNotEmpty()
layoutBottom.run {
bottomMainLayout.isVisible = list.isNotEmpty()
// tvRight.text = getString(R.string.share)
}
tvAllSelect.isVisible = list.isNotEmpty()
}
}
private fun updateSelectStatus(selectedCounts: Int) {
binding.run {
selectedCounts.let {
tvAllSelect.isSelected = it == mAdapter.itemCount
if (it <= 0) {
layoutBottom.tvLeft.isEnabled = false
layoutBottom.tvRight.isEnabled = false
} else {
layoutBottom.tvLeft.isEnabled = true
layoutBottom.tvRight.isEnabled = true
}
layoutBottom.tvLeft.text = getString(R.string.delete_placeholder, it)
layoutBottom.tvRight.text = getString(R.string.share_placeholder, it)
}
}
}
private fun setRecoveredData(list: List<ResultDataFiles>, scanTye: Int) {
mAdapter = PhotoDisplayDateChildAdapter(
mContext = requireContext(),
scanType = scanTye,
mColumns = 2,
viewModel = sharedViewModel,
onSelectedUpdate = { resultPhotosFiles, isAdd, allSelected ->
sharedViewModel.toggleSelection(isAdd, resultPhotosFiles)
},
hideThumbnailsUpdate = { hide ->
}) { item ->
}.apply {
setData(list)
}
updateSelectStatus(0)
binding.recyclerView.run {
adapter = mAdapter
when (scanTye) {
Common.VALUE_SCAN_TYPE_photo, Common.VALUE_SCAN_TYPE_video -> {
layoutManager = GridLayoutManager(requireContext(), 2)
val bPx = 6.dpToPx(context)
val aPx = 16.dpToPx(context)
val bottom = 75.dpToPx(context)
setPadding(aPx, 0, bPx, bottom)
}
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_documents -> {
layoutManager = LinearLayoutManager(requireContext())
val bPx = 6.dpToPx(context)
val aPx = 16.dpToPx(context)
val bottom = 75.dpToPx(context)
setPadding(aPx, 0, bPx, bottom)
}
}
}
}
private fun initClick() {
binding.tvAllSelect.setOnClickListener {
it.isSelected = !it.isSelected
mAdapter.setAllSelected(it.isSelected)
}
}
} }

View File

@ -1,7 +1,54 @@
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.ux.video.file.filerecovery.db.ResultDataFiles
import com.ux.video.file.filerecovery.utils.Common
class RecoveryPhotoViewModel : ViewModel() { class RecoveryPhotoViewModel : ViewModel() {
private val _photoFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
val photoFiles: LiveData<List<ResultDataFiles>> = _photoFiles
private val _videoFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
val videoFiles: LiveData< List<ResultDataFiles>> = _videoFiles
private val _audioFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
val audioFiles: LiveData< List<ResultDataFiles>> = _audioFiles
private val _documentsFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
val documentsFiles: LiveData< List<ResultDataFiles>> = _documentsFiles
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
val selectedLiveData: LiveData<Set<ResultDataFiles>> = _selectedLiveData
fun setPhotosRecoveredFiles(photos:List<ResultDataFiles>){
_photoFiles.value = photos
}
fun setVideosRecoveredFiles(videos:List<ResultDataFiles>){
_videoFiles.value = videos
}
fun setAudiosRecoveredFiles(audios:List<ResultDataFiles>){
_audioFiles.value = audios
}
fun setDocumentsRecoveredFiles(documents:List<ResultDataFiles>){
_documentsFiles.value = documents
}
fun toggleSelection(isAdd: Boolean, resultDataFiles: ResultDataFiles) {
val current = _selectedLiveData.value?.toMutableSet() ?: mutableSetOf()
resultDataFiles.let {
if (isAdd) {
current.add(it)
} else {
current.remove(it)
}
}
_selectedLiveData.value = current.toSet()
}
fun checkIsSelect(resultDataFiles: ResultDataFiles): Boolean {
val current = _selectedLiveData.value
return current?.contains(resultDataFiles) == true
}
} }

View File

@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.lifecycle.ViewModel
import androidx.recyclerview.widget.RecyclerView 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
@ -24,6 +25,7 @@ import com.ux.video.file.filerecovery.databinding.FileSpanCountTwoAdapterBinding
import com.ux.video.file.filerecovery.databinding.OneAudioItemBinding import com.ux.video.file.filerecovery.databinding.OneAudioItemBinding
import com.ux.video.file.filerecovery.databinding.OneDocumentsItemBinding import com.ux.video.file.filerecovery.databinding.OneDocumentsItemBinding
import com.ux.video.file.filerecovery.db.ResultDataFiles import com.ux.video.file.filerecovery.db.ResultDataFiles
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoViewModel
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.CustomTextView
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
@ -34,7 +36,7 @@ class PhotoDisplayDateChildAdapter(
mContext: Context, mContext: Context,
var scanType: Int, var scanType: Int,
var mColumns: Int, var mColumns: Int,
var viewModel: ScanRepository, var viewModel: ViewModel? = null,
/** /**
* 通知外层某天全选的按钮更新状态 * 通知外层某天全选的按钮更新状态
* @param updatePath 当前点击的item * @param updatePath 当前点击的item
@ -173,7 +175,7 @@ class PhotoDisplayDateChildAdapter(
it.textDuration.text = Common.formatDuration(duration) it.textDuration.text = Common.formatDuration(duration)
it.textSize.text = sizeString it.textSize.text = sizeString
initAudioDocuments(it.imageSelect,this) initAudioDocuments(it.imageSelect, this)
// viewModel.checkIsSelect(this).let { isSelected -> // viewModel.checkIsSelect(this).let { isSelected ->
// it.imageSelect.isSelected = isSelected // it.imageSelect.isSelected = isSelected
// addOrRemove(this, isSelected) // addOrRemove(this, isSelected)
@ -198,11 +200,11 @@ class PhotoDisplayDateChildAdapter(
it.textName.text = name it.textName.text = name
it.textDate.text = Common.getItemMonthDay(lastModified) it.textDate.text = Common.getItemMonthDay(lastModified)
it.textSize.text = sizeString it.textSize.text = sizeString
targetFile?.let { file-> targetFile?.let { file ->
it.imageIcon.setImageResource(Common.getFileIconRes(file)) it.imageIcon.setImageResource(Common.getFileIconRes(file))
} }
initAudioDocuments(it.imageSelect,this) initAudioDocuments(it.imageSelect, this)
it.constraintLayout.setOnClickListener { it.constraintLayout.setOnClickListener {
clickItem(this) clickItem(this)
@ -230,11 +232,21 @@ class PhotoDisplayDateChildAdapter(
RecyclerView.ViewHolder(vb.root) RecyclerView.ViewHolder(vb.root)
private fun initAudioDocuments(imageSelect: ImageView,item: ResultDataFiles){ private fun initAudioDocuments(imageSelect: ImageView, item: ResultDataFiles) {
viewModel.checkIsSelect(item).let { isSelected ->
imageSelect.isSelected = isSelected viewModel?.let {
addOrRemove(item, isSelected) if (it is ScanRepository) {
it.checkIsSelect(item)
} else {
it as RecoveryPhotoViewModel
it.checkIsSelect(item)
}.let { isSelected ->
imageSelect.isSelected = isSelected == true
addOrRemove(item, isSelected == true)
}
} }
imageSelect.setOnClickListener { imageSelect.setOnClickListener {
it.isSelected = !it.isSelected it.isSelected = !it.isSelected
it.isSelected.let { newStatus -> it.isSelected.let { newStatus ->
@ -242,6 +254,7 @@ class PhotoDisplayDateChildAdapter(
} }
} }
} }
private fun initDateView( private fun initDateView(
rootLayout: RelativeLayout, rootLayout: RelativeLayout,
imageSelectStatus: ImageView, imageSelectStatus: ImageView,
@ -251,7 +264,7 @@ class PhotoDisplayDateChildAdapter(
imageType: ImageView imageType: ImageView
) { ) {
item.run { item.run {
initAudioDocuments(imageSelectStatus,this) initAudioDocuments(imageSelectStatus, this)
// viewModel.checkIsSelect(this).let { // viewModel.checkIsSelect(this).let {
// imageSelectStatus.isSelected = it // imageSelectStatus.isSelected = it
// addOrRemove(this, it) // addOrRemove(this, it)

View File

@ -131,7 +131,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
mItemDecoration = mItemDecoration =
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing) GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
updateButtonCounts(0) updateButtonCounts(0)
viewModel = ViewModelProvider(this).get(ScanRepository::class.java) viewModel = ViewModelProvider(this)[ScanRepository::class.java]
viewModel.selectedLiveData.observe(this) { selectedSet -> viewModel.selectedLiveData.observe(this) { selectedSet ->
allSelectedSetList = selectedSet allSelectedSetList = selectedSet

View File

@ -112,7 +112,7 @@ object RecoverOrDeleteManager {
if (success){ if (success){
ScanManager.showLog("--------删除图片 ", "----------${currentCounts} ${path}") ScanManager.showLog("--------删除图片 ", "----------${currentCounts} ${path}")
dialogDeleting?.updateProgress(currentCounts) dialogDeleting?.updateProgress(currentCounts)
ObjectBoxManager.deleteRecoveryFile(data)
} }
}) { counts -> }) { counts ->

View File

@ -35,6 +35,12 @@ object Common {
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
val FILE_TYPE_PHOTO = 0
val FILE_TYPE_VIDEO = 1
val FILE_TYPE_AUDIO = 2
val FILE_TYPE_DOCUMENTS = 3
val rootDir = Environment.getExternalStorageDirectory() val rootDir = Environment.getExternalStorageDirectory()
val dateFormat = SimpleDateFormat("MMMM d,yyyy", Locale.ENGLISH) val dateFormat = SimpleDateFormat("MMMM d,yyyy", Locale.ENGLISH)

View File

@ -114,8 +114,8 @@ object ScanManager {
file.length() file.length()
), ),
lastModified = file.lastModified(), lastModified = file.lastModified(),
resolution = getResolution(type,file), resolution = getResolution(type, file),
fileType = getFileType(type) fileType = getFileType(type)
) )
} }
ResultData(dir, ArrayList(resultDataFilesList)) ResultData(dir, ArrayList(resultDataFilesList))
@ -220,8 +220,8 @@ object ScanManager {
file.length() file.length()
), ),
lastModified = file.lastModified(), lastModified = file.lastModified(),
resolution = getResolution(type,file), resolution = getResolution(type, file),
fileType = getFileType(type) fileType = getFileType(type)
) )
} }
@ -233,15 +233,16 @@ object ScanManager {
private fun getFileType(scanType: Int): Int { private fun getFileType(scanType: Int): Int {
return when (scanType) { return when (scanType) {
VALUE_SCAN_TYPE_deleted_photo -> 0 VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> 0
VALUE_SCAN_TYPE_deleted_video -> 1 VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> 1
VALUE_SCAN_TYPE_deleted_audio -> 2
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> 2
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> 3
else -> 3 else -> 3
} }
} }
private fun getFileSizeByMediaStore(context: Context, file: File): Long { private fun getFileSizeByMediaStore(context: Context, file: File): Long {
val uri = Uri.fromFile(file) val uri = Uri.fromFile(file)
context.contentResolver.query(uri, arrayOf(OpenableColumns.SIZE), null, null, null) context.contentResolver.query(uri, arrayOf(OpenableColumns.SIZE), null, null, null)
@ -254,8 +255,8 @@ object ScanManager {
return file.length() // fallback return file.length() // fallback
} }
private fun getResolution(type: Int,file: File): String { private fun getResolution(type: Int, file: File): String {
return when (type) { return when (type) {
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> { VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
getImageSize(file).run { getImageSize(file).run {
"$first*$second" "$first*$second"
@ -303,7 +304,7 @@ object ScanManager {
selectedSet: Set<ResultDataFiles>, selectedSet: Set<ResultDataFiles>,
rootDir: File = Common.rootDir, rootDir: File = Common.rootDir,
folder: String, folder: String,
onProgress: (currentCounts: Int, data:ResultDataFiles,fileName: String, success: Boolean) -> Unit, onProgress: (currentCounts: Int, data: ResultDataFiles, fileName: String, success: Boolean) -> Unit,
onComplete: (currentCounts: Int) -> Unit onComplete: (currentCounts: Int) -> Unit
) { ) {
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
@ -324,7 +325,7 @@ object ScanManager {
success = true success = true
recoveryCount++ recoveryCount++
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
onProgress(index + 1,resultPhotosFiles, srcFile.name, success) onProgress(index + 1, resultPhotosFiles, srcFile.name, success)
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@ -346,7 +347,7 @@ object ScanManager {
*/ */
fun CoroutineScope.deleteFilesAsync( fun CoroutineScope.deleteFilesAsync(
selectedSet: Set<ResultDataFiles>, selectedSet: Set<ResultDataFiles>,
onProgress: (currentCounts: Int, data:ResultDataFiles,fileName: String, success: Boolean) -> Unit, onProgress: (currentCounts: Int, data: ResultDataFiles, fileName: String, success: Boolean) -> Unit,
onComplete: (currentCounts: Int) -> Unit onComplete: (currentCounts: Int) -> Unit
) { ) {
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
@ -358,10 +359,10 @@ object ScanManager {
deletedCount++ deletedCount++
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
onProgress(index + 1, resultPhotosFiles,file.name, true) onProgress(index + 1, resultPhotosFiles, file.name, true)
} }
} catch (e: Exception) { } catch (e: Exception) {
onProgress(index + 1,resultPhotosFiles, resultPhotosFiles.path!!, false) onProgress(index + 1, resultPhotosFiles, resultPhotosFiles.path!!, false)
} }
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
@ -372,6 +373,4 @@ object ScanManager {
} }
} }

View File

@ -56,7 +56,7 @@ class ScanRepository : ViewModel() {
/** /**
* 删除操作完成过后对选中集合进行更新 * 删除操作完成过后对选中集合进行更新(批量删除)
*/ */
fun afterDeleted(){ fun afterDeleted(){
val selected = _selectedLiveData.value.orEmpty().toMutableSet() val selected = _selectedLiveData.value.orEmpty().toMutableSet()
@ -69,7 +69,7 @@ class ScanRepository : ViewModel() {
} }
/** /**
* 详情页删除完毕移除删除掉的数据 * 详情页删除完毕移除删除掉的数据(单个删除)
*/ */
fun afterSingleDeleted(deletedItem:ResultDataFiles){ fun afterSingleDeleted(deletedItem:ResultDataFiles){
val selected = _selectedLiveData.value.orEmpty().toMutableSet() val selected = _selectedLiveData.value.orEmpty().toMutableSet()

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
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

@ -5,5 +5,5 @@
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="@color/black"/> android:fillColor="@color/white"/>
</vector> </vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
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/main_sub_title"/>
</vector>

View File

@ -5,5 +5,5 @@
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="@color/black"/> android:fillColor="@color/white"/>
</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/black"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
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/black"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

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_24dp" android:state_selected="true" />
<item android:drawable="@drawable/icon_unselected_24dp" />
</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_black_16dp" />
</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_24dp" android:state_selected="true" />
<item android:drawable="@drawable/icon_unselected_black_24dp" />
</selector>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/color_title_blue"/>
<corners android:radius="10dp"/>
<size android:height="4dp" android:width="18dp"/>
</shape>

View File

@ -2,7 +2,7 @@
<LinearLayout 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/container" 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:background="@color/white"
@ -34,20 +34,54 @@
app:fontType="bold" /> app:fontType="bold" />
</RelativeLayout> </RelativeLayout>
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="66dp"
app:tabIndicatorHeight="4dp"
app:tabMaxWidth="18dp"
app:tabMode="fixed"
app:tabGravity="fill"
android:id="@+id/tab_layout"
app:tabIndicatorColor="@color/color_title_blue"
app:tabIndicatorGravity="center"
app:tabBackground="@color/white"/>
<androidx.viewpager2.widget.ViewPager2 <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/view_page2" android:layout_height="match_parent"
android:layout_height="match_parent"/> android:background="@color/color_bg"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="66dp"
app:tabBackground="@color/white"
app:tabGravity="fill"
app:tabIndicator="@drawable/tab_indicator"
app:tabIndicatorGravity="bottom"
app:tabMode="fixed" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="22dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_warning"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginEnd="10dp"
android:src="@drawable/icon_warining" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text_warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/warning"
android:textColor="@color/main_sub_title"
android:textSize="14sp" />
</LinearLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_page2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -2,6 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/bottom_main_layout"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.ux.video.file.filerecovery.utils.CustomTextView <com.ux.video.file.filerecovery.utils.CustomTextView
@ -13,7 +14,7 @@
android:background="@drawable/bg_rectangle_white_left_8" android:background="@drawable/bg_rectangle_white_left_8"
android:gravity="center" android:gravity="center"
android:text="@string/delete" android:text="@string/delete"
android:textColor="@color/main_text_blue" android:textColor="@color/selector_delete_button_enable"
android:textSize="16sp" android:textSize="16sp"
app:fontType="bold" app:fontType="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -27,7 +28,7 @@
android:layout_height="50dp" android:layout_height="50dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="21dp" android:layout_marginBottom="21dp"
android:background="@drawable/bg_rectangle_blue_right_8" android:background="@drawable/selector_recover_button_enable"
android:gravity="center" android:gravity="center"
android:text="@string/recover" android:text="@string/recover"
android:textColor="@color/white" android:textColor="@color/white"

View File

@ -1,20 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout 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"
android:id="@+id/recovery_photo" android:id="@+id/recovery_photo"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context=".ui.recoveryphoto.RecoveryPhotoFragment">
<TextView <RelativeLayout
android:id="@+id/message" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:text="RecoveryPhotoFragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<include
android:id="@+id/layout_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/layout_empty_recovered_files" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_all_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableStart="@drawable/selector_icon_select_black_24"
android:drawablePadding="4dp"
android:paddingTop="21dp"
android:text="@string/select_all"
android:layout_marginStart="16dp"
android:textColor="@color/main_title"
android:textSize="16sp"
app:fontType="bold" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:id="@+id/recycler_view"
android:layout_below="@id/tv_all_select"
android:layout_height="match_parent" />
<include
android:id="@+id/layout_bottom"
layout="@layout/common_bottom_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</FrameLayout>

View File

@ -0,0 +1,41 @@
<?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="match_parent"
android:id="@+id/relative_empty_main">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="180dp"
android:layout_marginTop="150dp"
android:src="@drawable/image_empty_recovered_files" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/image"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:text="@string/no_files"
android:textColor="@color/main_sub_title"
android:textSize="14sp" />
<com.ux.video.file.filerecovery.utils.CustomTextView
android:id="@+id/tv_scan"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@id/text"
android:layout_centerHorizontal="true"
android:layout_marginHorizontal="50dp"
android:layout_marginTop="30dp"
android:background="@drawable/bg_dialog_btn_cancel_stoke_8"
android:gravity="center"
android:text="@string/scan_photos"
android:textColor="@color/main_text_blue"
android:textSize="16sp"
app:fontType="bold" />
</RelativeLayout>

View File

@ -11,7 +11,7 @@
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
android:src="@drawable/selector_icon_checkmark_28dp" android:src="@drawable/selector_icon_checkmark_24dp_9696a2"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View File

@ -10,7 +10,7 @@
android:id="@+id/image_select" android:id="@+id/image_select"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:src="@drawable/selector_icon_checkmark_28dp" android:src="@drawable/selector_icon_checkmark_24dp_9696a2"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View File

@ -33,7 +33,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:drawableStart="@drawable/selector_icon_select_16" android:drawableStart="@drawable/selector_icon_select_black_16"
android:drawablePadding="4dp" android:drawablePadding="4dp"
android:paddingTop="21dp" android:paddingTop="21dp"
android:text="@string/select" android:text="@string/select"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
@ -11,7 +11,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/selector_recovery_file_tab_layout_title" android:textColor="@color/selector_recovery_file_tab_layout_title"
android:textSize="16sp" android:textSize="15sp"
android:gravity="center"
app:fontType="bold" /> app:fontType="bold" />
<com.ux.video.file.filerecovery.utils.CustomTextView <com.ux.video.file.filerecovery.utils.CustomTextView

View File

@ -88,6 +88,15 @@ wait..</string>
<string name="search">Search</string> <string name="search">Search</string>
<string name="recovered_files">Recovered files</string> <string name="recovered_files">Recovered files</string>
<string name="text_counts">(%d)</string> <string name="text_counts">(%d)</string>
<string name="warning">Please do not uninstall the File Recovery -
All Recovery to avoid file loss.</string>
<string name="no_files">No files have been recovered yet~</string>
<string name="scan_photos">Scan photos</string>
<string name="scan_videos">Scan videos</string>
<string name="scan_audios">Scan audios</string>
<string name="scan_documents">Scan documents</string>
<string name="share_placeholder">Share (%d)</string>
<string-array name="filter_date"> <string-array name="filter_date">