Commit a43f972d authored by wanglei's avatar wanglei

...

parent f5eaddd0
......@@ -63,4 +63,7 @@ dependencies {
//第三方UI
implementation("com.airbnb.android:lottie:6.4.0")
implementation("com.github.bumptech.glide:glide:4.16.0")
//网络
implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'
}
\ No newline at end of file
......@@ -18,4 +18,17 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
#-renamesourcefileattribute SourceFile
-dontwarn javax.annotation.Nullable
-keep class com.base.datarecovery.bean.** {*;}
-dontoptimize
-keepattributes Signature
-keep class com.squareup.okhttp.** { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.** { *; }
-keep class com.alibaba.idst.** { *; }
-keep class * extends com.google.gson.reflect.TypeToken
-keepattributes AnnotationDefault, RuntimeVisibleAnnotations
-keep class com.bytedance.sdk.** { *; }
package com.base.datarecovery.activity
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.view.View
import androidx.activity.addCallback
import com.base.datarecovery.adapter.FileMediaColumnsAdapter
import com.base.datarecovery.bean.ConstObject
import com.base.datarecovery.bean.FolderBean
import com.base.datarecovery.bean.RecoveryBean
import com.base.datarecovery.databinding.ActivityFileRecoveryBinding
import com.base.datarecovery.help.BaseActivity
import com.base.datarecovery.help.KotlinExt.toFormatTime
import com.base.datarecovery.utils.BarUtils
import com.google.gson.Gson
import java.io.File
import java.text.SimpleDateFormat
class FileRecoveryActivity : BaseActivity<ActivityFileRecoveryBinding>() {
private var type = 0
private var scanType = 0
override val binding: ActivityFileRecoveryBinding by lazy {
ActivityFileRecoveryBinding.inflate(layoutInflater)
}
private var folderBean: FolderBean? = null
private lateinit var adapter: FileMediaColumnsAdapter
private val timeList = arrayListOf<FolderBean>()
@SuppressLint("SetTextI18n")
override fun initView() {
type = intent.extras?.getInt("Type") ?: 0
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
scanType = intent.extras?.getInt("ScanType") ?: 0
val json = intent.extras?.getString("Data") ?: ""
folderBean = Gson().fromJson(json, FolderBean::class.java)
when (scanType) {
ConstObject.SCAN_PHOTOS -> {
var size = 0
folderBean?.recoveryList?.forEach {
val bitmap = BitmapFactory.decodeFile(it.path)
if (bitmap.height < 256 || bitmap.width < 256) {
size++
it.isThumbnails = true
}
}
binding.tvThumbnails.text = "Hide thumbnails (${size})"
}
ConstObject.SCAN_DOCUMENTS -> {
binding.clThumbnails.visibility = View.GONE
}
ConstObject.SCAN_VIDEOS -> {
binding.clThumbnails.visibility = View.GONE
}
}
adapter = FileMediaColumnsAdapter(2) { all ->
binding.ivSelectAll.isSelected = all
}
binding.rv.adapter = adapter
initData()
}
override fun initListener() {
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
onBackPressedDispatcher.addCallback {
finishToMain()
}
binding.switchThumbnails.setOnCheckedChangeListener { buttonView, isChecked ->
adapter.toggleThumbnails(isChecked)
}
binding.ivSelectAll.setOnClickListener {
binding.ivSelectAll.isSelected=!binding.ivSelectAll.isSelected
adapter.toggleAllSelect(binding.ivSelectAll.isSelected)
}
}
private fun initData() {
val hash = HashMap<String, ArrayList<RecoveryBean>>()
folderBean?.let {
it.recoveryList.forEach { recoveryBean ->
val file = File(recoveryBean.path)
val time = file.lastModified().toFormatTime()
if (hash[time].isNullOrEmpty()) {
hash[time] = arrayListOf()
}
hash[time]?.add(recoveryBean)
}
}
val list = arrayListOf<FolderBean>()
hash.forEach { (key, value) ->
list.add(FolderBean(time = key, recoveryList = value))
}
adapter.setData(list)
}
}
\ No newline at end of file
......@@ -16,6 +16,7 @@ import com.base.datarecovery.help.PermissionHelp.requestStorePermission
import com.base.datarecovery.utils.BarUtils
import com.base.datarecovery.utils.FileHexEx.isDocument
import com.base.datarecovery.utils.FileHexEx.isImage
import com.base.datarecovery.utils.FileHexEx.isVideo
import com.base.datarecovery.utils.LogEx
import com.base.datarecovery.view.DialogViews.showGerPermission
import kotlinx.coroutines.Dispatchers
......@@ -56,7 +57,8 @@ class FileScanActivity : BaseActivity<ActivityFileScanBinding>() {
}
3 -> {
binding.tvTittle.text = "Videos Recovery"
binding.ivIcon.setImageResource(R.mipmap.tu_videos_scan)
}
}
}
......@@ -89,6 +91,7 @@ class FileScanActivity : BaseActivity<ActivityFileScanBinding>() {
val filter = when (scanType) {
ConstObject.SCAN_PHOTOS -> ::isImage
ConstObject.SCAN_DOCUMENTS -> ::isDocument
ConstObject.SCAN_VIDEOS -> ::isVideo
else -> ::isImage
}
val root = Environment.getExternalStorageDirectory()
......
package com.base.datarecovery.activity
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import androidx.activity.addCallback
import com.base.datarecovery.adapter.FileFolderAdapter
import com.base.datarecovery.bean.ConstObject.SCAN_DOCUMENTS
import com.base.datarecovery.bean.ConstObject.SCAN_PHOTOS
import com.base.datarecovery.bean.ConstObject.SCAN_VIDEOS
import com.base.datarecovery.bean.FolderBean
import com.base.datarecovery.bean.RecoveryBean
import com.base.datarecovery.databinding.ActivityFileScanResultBinding
import com.base.datarecovery.help.BaseActivity
import com.base.datarecovery.utils.BarUtils
import com.base.datarecovery.utils.LogEx
import com.google.gson.Gson
import java.io.File
import java.util.HashMap
......@@ -48,11 +51,19 @@ class FileScanResultActivity : BaseActivity<ActivityFileScanResultBinding>() {
binding.tvTittle.text = "Document Recovery"
binding.tvFileType.text = "Documents"
}
SCAN_VIDEOS -> {
binding.tvTittle.text = "Video Recovery"
binding.tvFileType.text = "videos"
}
}
binding.tvFileNumber.text = beanList.size.toString()
fileFolderAdapter = FileFolderAdapter {
fileFolderAdapter = FileFolderAdapter(scanType) { folderBean ->
startActivity(Intent(this, FileRecoveryActivity::class.java).apply {
putExtra("ScanType", scanType)
putExtra("Data", Gson().toJson(folderBean))
})
}
binding.rv.adapter = fileFolderAdapter
initData()
......@@ -79,7 +90,7 @@ class FileScanResultActivity : BaseActivity<ActivityFileScanResultBinding>() {
val list = hashMap.map {
val folder = it.key.split("/").last()
FolderBean(folder, it.value)
FolderBean(folder, recoveryList = it.value)
}
binding.tvFolderNumber.text = list.size.toString()
fileFolderAdapter.setData(list)
......
......@@ -3,11 +3,16 @@ package com.base.datarecovery.adapter
import android.annotation.SuppressLint
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.datarecovery.R
import com.base.datarecovery.bean.ConstObject.SCAN_PHOTOS
import com.base.datarecovery.bean.ConstObject.SCAN_VIDEOS
import com.base.datarecovery.bean.FolderBean
import com.base.datarecovery.databinding.ItemFolderBinding
import com.base.datarecovery.databinding.ItemFolderRecoveryBinding
import com.base.datarecovery.utils.LogEx
import com.base.datarecovery.utils.ScreenUtil.dpToPx
import com.base.datarecovery.view.XmlEx.inflate
import com.bumptech.glide.Glide
......@@ -15,40 +20,80 @@ import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
class FileFolderAdapter(private val click: (bean: FolderBean) -> Unit) : RecyclerView.Adapter<FileFolderAdapter.FF>() {
class FileFolderAdapter(
private val scanType: Int, private val click: (bean: FolderBean) -> Unit
) : RecyclerView.Adapter<FileFolderAdapter.FF>() {
private val TAG = "FileFolderAdapter"
private val beanList = arrayListOf<FolderBean>()
class FF(view: View) : ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FF {
return FF(R.layout.item_folder_recovery.inflate(parent))
val layout = when (scanType) {
SCAN_PHOTOS, SCAN_VIDEOS -> R.layout.item_folder_recovery
else -> R.layout.item_folder
}
return FF(layout.inflate(parent))
}
override fun getItemCount(): Int {
return beanList.size
}
@SuppressLint("SetTextI18n")
@SuppressLint("SetTextI18n", "CheckResult")
override fun onBindViewHolder(holder: FF, position: Int) {
val bean = beanList[position]
val context = holder.itemView.context
val binding = ItemFolderRecoveryBinding.bind(holder.itemView)
runCatching {
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(context.dpToPx(10)))
val image1 = bean.recoveryList[0].path
Glide.with(context).load(image1).apply(options).into(binding.iv1)
val image2 = bean.recoveryList[1].path
Glide.with(context).load(image2).apply(options).into(binding.iv2)
val image3 = bean.recoveryList[2].path
Glide.with(context).load(image3).apply(options).into(binding.iv3)
}
binding.tvFolder.text = bean.folder
binding.tvFolderNumber.text = "(${bean.recoveryList.size})"
binding.root.setOnClickListener {
click.invoke(bean)
when (scanType) {
SCAN_PHOTOS, SCAN_VIDEOS -> {
LogEx.logDebug(TAG, "scanType=SCAN_PHOTOS or SCAN_VIDEOS")
val binding = ItemFolderRecoveryBinding.bind(holder.itemView)
runCatching {
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(context.dpToPx(10)))
val image1 = bean.recoveryList[0].path
val request1 = Glide.with(context).load(image1).apply(options)
if (scanType == SCAN_VIDEOS) {
request1.error(R.drawable.videotu)
}
request1.into(binding.iv1)
val image2 = bean.recoveryList[1].path
val request2 = Glide.with(context).load(image2).apply(options)
if (scanType == SCAN_VIDEOS) {
request2.error(R.drawable.videotu)
}
request2.into(binding.iv2)
val image3 = bean.recoveryList[2].path
val request3 = Glide.with(context).load(image3).apply(options)
if (scanType == SCAN_VIDEOS) {
request3.error(R.drawable.videotu)
}
request3.into(binding.iv3)
}
binding.tvFolder.text = bean.folder
binding.tvFolderNumber.text = "(${bean.recoveryList.size})"
binding.root.setOnClickListener {
click.invoke(bean)
}
}
else -> {
LogEx.logDebug(TAG, "scanType=$scanType")
val binding = ItemFolderBinding.bind(holder.itemView)
binding.tvFolder.text = bean.folder
binding.tvFileNumber.text = "${bean.recoveryList.size}"
binding.root.setOnClickListener {
click.invoke(bean)
}
}
}
}
@SuppressLint("NotifyDataSetChanged")
......
package com.base.datarecovery.adapter
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.datarecovery.R
import com.base.datarecovery.bean.FolderBean
import com.base.datarecovery.bean.RecoveryBean
import com.base.datarecovery.databinding.ItemMediaBinding
import com.base.datarecovery.help.KotlinExt.toFormatSize
import com.base.datarecovery.view.XmlEx.inflate
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import java.io.File
class FileMediaColumnsAdapter(
val columns: Int,
val allSelect: (all: Boolean) -> Unit,
) : RecyclerView.Adapter<FileMediaColumnsAdapter.MCV>() {
private val beanList = arrayListOf<FolderBean>()
private var hideThumbnails: Boolean = false
class MCV(view: View) : ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MCV {
return MCV(R.layout.item_media.inflate(parent))
}
override fun getItemCount(): Int {
return beanList.size
}
override fun onBindViewHolder(holder: MCV, position: Int) {
val binding = ItemMediaBinding.bind(holder.itemView)
val context = holder.itemView.context
val bean = beanList[position]
binding.tvTime.text = bean.time
binding.ivSelector.isSelected = bean.isSelect
val subAdapter = MediaColumnsAdapter()
binding.rvMediaColumns.layoutManager = GridLayoutManager(context, columns)
binding.rvMediaColumns.adapter = subAdapter
val list = if (hideThumbnails) bean.recoveryList.filter { !it.isThumbnails } else bean.recoveryList
subAdapter.setData(list)
binding.ivSelector.setOnClickListener {
bean.isSelect = !bean.isSelect
binding.ivSelector.isSelected = bean.isSelect
notifyItemChanged(position)
itemClick(bean.isSelect, subAdapter)
}
}
@SuppressLint("NotifyDataSetChanged")
fun setData(data: List<FolderBean>) {
beanList.clear()
beanList.addAll(data)
notifyDataSetChanged()
}
inner class MediaColumnsAdapter : RecyclerView.Adapter<MediaColumnsAdapter.CS>() {
private val list = arrayListOf<RecoveryBean>()
inner class CS(view: View) : ViewHolder(view) {
val iv = view.findViewById<ImageView>(R.id.iv)
val ivSelector = view.findViewById<ImageView>(R.id.iv_selector)
val tvSize = view.findViewById<TextView>(R.id.tv_size)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CS {
val layout = when (columns) {
2 -> R.layout.item_media_columns2
3 -> R.layout.item_media_columns3
4 -> R.layout.item_media_columns4
else -> R.layout.item_media_columns2
}
return CS(layout.inflate(parent))
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: CS, position: Int) {
}
override fun onBindViewHolder(holder: CS, position: Int, payloads: MutableList<Any>) {
val context = holder.itemView.context
val data = list[position]
if (payloads.isEmpty()) {
Glide.with(context).asBitmap().load(data.path).centerCrop().into(holder.iv)
holder.iv.tag = data.path
holder.ivSelector.isSelected = data.isSelect
holder.ivSelector.setOnClickListener {
data.isSelect = !data.isSelect
holder.ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "changeIv")
subItemClick(data)
}
val file = File(data.path)
holder.tvSize.text = file.length().toFormatSize()
} else {
holder.ivSelector.isSelected = data.isSelect
super.onBindViewHolder(holder, position, payloads)
}
}
@SuppressLint("NotifyDataSetChanged")
fun setData(bean: List<RecoveryBean>) {
list.clear()
list.addAll(bean)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun toggleSelect(select: Boolean) {
list.forEach {
it.isSelect = select
}
notifyDataSetChanged()
}
}
@SuppressLint("NotifyDataSetChanged")
fun subItemClick(data: RecoveryBean) {
val folderBean = beanList.find { it.recoveryList.contains(data) }
folderBean?.let { folder ->
val select = folder.recoveryList.all { it.isSelect }
if (folder.isSelect != select) {
folder.isSelect = select
notifyDataSetChanged()
}
}
val all = beanList.all { it.isSelect }
allSelect.invoke(all)
}
private fun itemClick(isSelect: Boolean, subAdapter: MediaColumnsAdapter) {
subAdapter.toggleSelect(isSelect)
val all = beanList.all { it.isSelect }
allSelect.invoke(all)
}
@SuppressLint("NotifyDataSetChanged")
fun toggleThumbnails(hideThumbnails: Boolean) {
this.hideThumbnails = hideThumbnails
notifyDataSetChanged()
}
fun toggleAllSelect(selected: Boolean) {
beanList.forEach {
it.isSelect = selected
it.recoveryList.forEach { bean -> bean.isSelect = selected }
}
notifyDataSetChanged()
}
}
\ No newline at end of file
......@@ -2,5 +2,8 @@ package com.base.datarecovery.bean
data class FolderBean(
val folder: String = "",
val time: String = "",
val recoveryList: ArrayList<RecoveryBean> = arrayListOf()
)
\ No newline at end of file
) {
var isSelect: Boolean = false
}
\ No newline at end of file
......@@ -3,4 +3,6 @@ package com.base.datarecovery.bean
data class RecoveryBean(
val path: String = "",
) {
var isSelect: Boolean = false
var isThumbnails: Boolean = false
}
\ No newline at end of file
package com.base.datarecovery.help
import android.view.View
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.Locale
object KotlinExt {
fun Number.toFormatSize(count: Int = 1): String {
var suffix = "B"
var fSize = this.toDouble()
if (fSize > 1024) {
suffix = "KB"
fSize /= 1024.0
}
if (fSize > 1024) {
suffix = "MB"
fSize /= 1024.0
}
if (fSize > 1024) {
suffix = "GB"
fSize /= 1024.0
}
return String.format("%.${count}f %s", fSize, suffix)
}
fun Long.toFormatTime(): String {
return SimpleDateFormat("MMM dd,yyyy", Locale.getDefault()).format(this)
}
}
\ No newline at end of file
......@@ -89,5 +89,42 @@ object FileHexEx {
return flag
}
fun isVideo(file: File): Boolean {
return isMp4(file) || isAvi(file) || isMkv(file)
}
fun isMp4(file: File): Boolean {
val mp4Hex = "6D70343269736F6D000061316D6F6F76"
val hex = FileHelp.readFileRange(file.absolutePath, 16, 32).byteArrayToHexString()
val flag = hex == mp4Hex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag
}
fun isAvi(file: File): Boolean {
val aviHex = "524946461C1BA900415649204C495354"
val hex = FileHelp.readFileRange(file.absolutePath, 0, 16).byteArrayToHexString()
val flag = hex == aviHex
LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag
}
fun isMkv(file: File): Boolean {
val mkvHex1 = "42F7810142F2810442F381084282886D"
val hex1 = FileHelp.readFileRange(file.absolutePath, 16, 32).byteArrayToHexString()
val flag1 = hex1 == mkvHex1
LogEx.logDebug(TAG, "flag1=$flag1 hex=${hex1} ${file.absolutePath}")
return if (flag1) {
true
} else {
val mkvHex2 = "42F7810142F2810442F381084282886D6174726F736B614287"
val hex2 = FileHelp.readFileRange(file.absolutePath, 9, 34).byteArrayToHexString()
val flag2 = hex2 == mkvHex2
LogEx.logDebug(TAG, "flag2=$flag2 hex=${hex2} ${file.absolutePath}")
flag2
}
}
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import android.util.Log
object LogEx {
val isOpen = true
val filterTAG = arrayOf(
"",
"FileScanActivity",
)
fun logDebug(tag: String, content: String, isMust: Boolean = false) {
......
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#2372FC" android:state_checked="true" />
<item android:color="#E3E6EB" android:state_checked="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/t_weixuan" android:state_selected="false" />
<item android:drawable="@mipmap/t_xuan" android:state_selected="true" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/quanxuan_n" android:state_selected="false" />
<item android:drawable="@mipmap/quanxuan_s" android:state_selected="true" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#801B1B1B" />
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#801B1B1B" />
<corners
android:topLeftRadius="12.5dp"
android:topRightRadius="12.5dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#801B1B1B" />
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:endColor="#EDF5FF"
android:startColor="#E7ECFF" />
<corners
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#BFBEC4" />
<corners android:radius="15dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- <solid android:color="#EDFF7A" />-->
<size
android:width="21dp"
android:height="21dp" />
<!-- 边缘全透明 -->
<stroke
android:width="1dp"
android:color="#00000000" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- <solid android:color="#EDFF7A" />-->
<size
android:width="21dp"
android:height="21dp" />
<!-- 边缘全透明 -->
<stroke
android:width="1dp"
android:color="#00000000" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- <solid android:color="#EDFF7A" />-->
<size
android:width="21dp"
android:height="21dp" />
<!-- 边缘全透明 -->
<stroke
android:width="1dp"
android:color="#00000000" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/switch_track_on" android:state_checked="true" />
<item android:drawable="@drawable/switch_track_off" android:state_checked="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E3E6EB" />
<size
android:width="105dp"
android:height="14dp" />
<corners android:radius="30dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#2372FD" />
<size
android:width="105dp"
android:height="14dp" />
<corners android:radius="30dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/wenjianjia"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_folder"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:textSize="16sp"
android:textStyle="bold"
tools:text="Documents" />
<TextView
android:id="@+id/tv_file_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="5dp"
android:textColor="#7D849E"
android:textStyle="bold"
tools:text="16" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/jianotu"
tools:ignore="ContentDescription" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText"
tools:text="Today" />
<LinearLayout
android:id="@+id/ll_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="8dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="5dp"
android:src="@drawable/b_circle_selector"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_media_columns"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="164dp"
android:layout_height="164dp"
android:layout_margin="8dp"
app:cardCornerRadius="15dp">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<FrameLayout
android:id="@+id/fl_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@drawable/b_circle_border_selector"
tools:ignore="ContentDescription" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_gravity="bottom"
android:background="@drawable/bg_801b1b1b_15">
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:textColor="@color/white"
android:textSize="15sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="8dp"
android:src="@mipmap/tuicon"
tools:ignore="ContentDescription" />
</FrameLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="105dp"
android:layout_height="105dp"
android:layout_margin="8dp"
app:cardCornerRadius="12.5dp">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<FrameLayout
android:id="@+id/fl_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:src="@drawable/b_circle_border_selector"
tools:ignore="ContentDescription" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="bottom"
android:background="@drawable/bg_801b1b1b_15">
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:textColor="@color/white"
android:textSize="12.5sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="8dp"
android:src="@mipmap/tuicon"
tools:ignore="ContentDescription" />
</FrameLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="105dp"
android:layout_height="105dp"
android:layout_margin="8dp"
app:cardCornerRadius="12.5dp">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<FrameLayout
android:id="@+id/fl_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:src="@drawable/b_circle_border_selector"
tools:ignore="ContentDescription" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_gravity="bottom"
android:background="@drawable/bg_801b1b1b_15">
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:textColor="@color/white"
android:textSize="10sp"
tools:ignore="SmallSp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="8dp"
android:src="@mipmap/tuicon"
tools:ignore="ContentDescription" />
</FrameLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment