Commit da0caede authored by wanglei's avatar wanglei

...

parent fbf33e18
......@@ -25,18 +25,8 @@
android:supportsRtl="true"
android:theme="@style/Theme.DataRecovery"
tools:targetApi="34">
<activity
android:name=".activity.recyclebin.RecycleBinActivity"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
</activity>
<activity
android:name=".activity.SplashActivity"
android:exported="true"
......@@ -48,6 +38,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.recyclebin.RecycleBinDetailActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".activity.screenshot.ScreenShotAnimationActivity"
android:exported="false"
......@@ -195,9 +191,7 @@
<receiver
android:name=".fcm.CloseNotificationReceiver"
android:exported="false" />
<!-- 添加以下接收器 -->
android:exported="false" /> <!-- 添加以下接收器 -->
<!-- 注册广播 -->
<receiver
android:name=".fcm.FcmReceiver"
......
......@@ -80,13 +80,7 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() {
job = startProgress()
binding.llStart.visibility = View.GONE
binding.llProgress.visibility = View.VISIBLE
if (ConfigHelper.admobTrueMaxFlase) {
AdmobNativeUtils.loadNativeAd()
AdmobInterstitialUtils.loadInterstitialAd(this)
} else {
AdMaxOpenUtils.loadAppOpenAd(this)
AdMaxInterstitialUtils.loadInterstitialAd(this)
}
preloadAd()
} else {
binding.llStart.visibility = View.VISIBLE
binding.llProgress.visibility = View.GONE
......@@ -108,8 +102,16 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() {
)
startActivity(intent)
}
}
private fun preloadAd() {
if (ConfigHelper.admobTrueMaxFlase) {
AdmobNativeUtils.loadNativeAd()
AdmobInterstitialUtils.loadInterstitialAd(this)
} else {
AdMaxOpenUtils.loadAppOpenAd(this)
AdMaxInterstitialUtils.loadInterstitialAd(this)
}
}
private fun progressCollect() {
......@@ -192,13 +194,7 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() {
oneClickStart = true
ifAgreePrivacy = true
(application as MyApplication).initApp()
if (ConfigHelper.admobTrueMaxFlase) {
AdmobNativeUtils.loadNativeAd()
AdmobInterstitialUtils.loadInterstitialAd(this)
} else {
AdMaxOpenUtils.loadAppOpenAd(this)
AdMaxInterstitialUtils.loadInterstitialAd(this)
}
preloadAd()
binding.llStart.visibility = View.GONE
binding.llProgress.visibility = View.VISIBLE
job = startProgress()
......
......@@ -67,20 +67,30 @@ class MediaContentObserver(val context: Context, val handler: Handler? = null) :
val recycleBinFile = File(recycleBinDir, ".$name")
if (!recycleBinFile.exists()) {
recycleBinFile.createNewFile()
} else {
if (recycleBinFile.length()==0L){
src.copyTo(recycleBinFile, true)
LogEx.logDebug(TAG, "size=${src.length()}")
val binBean = RecycleBinBean(src.path, 0, src.length(), mimeType)
val binFile = File(recycleBinDir, ".$name.bin")
binFile.createNewFile()
binFile.writeText(Gson().toJson(binBean))
LogEx.logDebug(TAG, "回收站备份成功")
handler?.sendEmptyMessage(99)
}
}
src.copyTo(recycleBinFile, true)
LogEx.logDebug(TAG, "size=${src.length()}")
val binBean = RecycleBinBean(src.path, 0, src.length(), mimeType)
val binFile = File(recycleBinDir, ".$name.bin")
binFile.createNewFile()
binFile.writeText(Gson().toJson(binBean))
LogEx.logDebug(TAG, "回收站备份成功")
handler?.sendEmptyMessage(99)
// if (!recycleBinFile.exists()) {
// recycleBinFile.createNewFile()
// } else {
// if (recycleBinFile.length()==0L){
// src.copyTo(recycleBinFile, true)
// LogEx.logDebug(TAG, "size=${src.length()}")
// val binBean = RecycleBinBean(src.path, 0, src.length(), mimeType)
// val binFile = File(recycleBinDir, ".$name.bin")
// binFile.createNewFile()
// binFile.writeText(Gson().toJson(binBean))
// LogEx.logDebug(TAG, "回收站备份成功")
// handler?.sendEmptyMessage(99)
// }
// }
}
}
......@@ -8,9 +8,7 @@ import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.help.BaseApplication
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.File
import java.lang.reflect.Type
@RequiresApi(Build.VERSION_CODES.Q)
class MyFileObserver(val handler: Handler? = null, files: List<File>) : FileObserver(files, ALL_EVENTS) {
......@@ -19,9 +17,8 @@ class MyFileObserver(val handler: Handler? = null, files: List<File>) : FileObse
override fun onEvent(event: Int, path: String?) {
if (path != null) {
// LogEx.logDebug(TAG, "onEvent=$event path=$path")
val filteredEvent = event and ALL_EVENTS
LogEx.logDebug(TAG, "filteredEvent=$filteredEvent path=$path")
// LogEx.logDebug(TAG, "filteredEvent=$filteredEvent path=$path")
when (filteredEvent) {
CLOSE_NOWRITE -> {
......@@ -29,6 +26,7 @@ class MyFileObserver(val handler: Handler? = null, files: List<File>) : FileObse
OPEN -> {}
MOVED_FROM -> {
LogEx.logDebug(TAG, "MOVED_FROM path=$path")
recordRecycleBinFile(path)
}
......@@ -41,10 +39,12 @@ class MyFileObserver(val handler: Handler? = null, files: List<File>) : FileObse
}
DELETE -> {
LogEx.logDebug(TAG, "DELETE path=$path")
recordRecycleBinFile(path)
}
DELETE_SELF -> {
LogEx.logDebug(TAG, "DELETE_SELF path=$path")
recordRecycleBinFile(path)
}
}
......@@ -54,32 +54,48 @@ class MyFileObserver(val handler: Handler? = null, files: List<File>) : FileObse
}
private fun recordRecycleBinFile(path: String) {
val file = BaseApplication.context.filesDir
val recycleBinDir = File(file, "RecycleBin")
if (!recycleBinDir.exists()) {
recycleBinDir.mkdirs()
}
private fun recordRecycleBinFile(namePath: String) {
val recycleFile = recycleBinDir.listFiles()?.find { it.name.contains(path) }
val recycleBinFile = recycleBinDir.listFiles()?.find { it.name.contains(".$path.bin") }
val recycleBinFile = findRecycleBinFile(namePath)
val recycleBinJsonFile = findRecycleBinJsonFile(namePath)
LogEx.logDebug(TAG, "recycleFile=$recycleFile")
LogEx.logDebug(TAG, "recycleBinFile=$recycleBinFile")
LogEx.logDebug(TAG, "recycleBinJsonFile=$recycleBinJsonFile")
if (recycleFile != null && recycleBinFile != null) {
if (recycleBinFile != null && recycleBinJsonFile != null) {
runCatching {
val rJson = recycleBinFile.readText()
val rJson = recycleBinJsonFile.readText()
val bean = Gson().fromJson(rJson, RecycleBinBean::class.java)
bean.deleted = true
bean.deleteTime = System.currentTimeMillis()
val wJson = Gson().toJson(bean)
recycleBinFile.writeText(wJson)
recycleBinJsonFile.writeText(wJson)
LogEx.logDebug(TAG, "writeText wJson=$wJson")
handler?.sendEmptyMessage(100)
}
}
}
companion object {
fun getRecycleBinDir(): File {
val file = BaseApplication.context.filesDir
val recycleBinDir = File(file, "RecycleBin")
if (!recycleBinDir.exists()) {
recycleBinDir.mkdirs()
}
return recycleBinDir
}
fun findRecycleBinFile(namePath: String): File? {
return getRecycleBinDir().listFiles()?.find { it.name.contains(namePath) }
}
fun findRecycleBinJsonFile(namePath: String): File? {
return getRecycleBinDir().listFiles()?.find { it.name.contains(".$namePath.bin") }
}
}
}
\ No newline at end of file
package com.base.filerecoveryrecyclebin.activity.recyclebin
import android.content.Intent
import android.os.Build
import android.os.Environment
import android.os.Handler
import androidx.annotation.RequiresApi
import androidx.lifecycle.lifecycleScope
import com.base.filerecoveryrecyclebin.adapter.RecycleBinAdapter
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.databinding.ActivityRecycleBinBinding
import com.base.filerecoveryrecyclebin.help.BaseActivity
import com.base.filerecoveryrecyclebin.help.PermissionHelp.checkStorePermission
import com.base.filerecoveryrecyclebin.help.PermissionHelp.requestStorePermission
import com.base.filerecoveryrecyclebin.service.StayNotificationService
import com.base.filerecoveryrecyclebin.service.StayNotificationService.Companion.FILE_OBSERVER_ACTION
import com.base.filerecoveryrecyclebin.service.StayNotificationService.Companion.MEDIA_OBSERVER_ACTION
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.base.filerecoveryrecyclebin.view.DialogViews.showGerPermission
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
@RequiresApi(Build.VERSION_CODES.Q)
class RecycleBinActivity : BaseActivity<ActivityRecycleBinBinding>() {
private val TAG = "RecycleBinActivity"
private lateinit var handler: Handler
private lateinit var recycleBinAdapter: RecycleBinAdapter
override val binding: ActivityRecycleBinBinding by lazy {
ActivityRecycleBinBinding.inflate(layoutInflater)
}
override fun initView() {
handler = Handler(mainLooper) { message ->
if (message.what == 99) {
LogEx.logDebug(TAG, "媒体库更新了")
}
if (message.what == 100) {
LogEx.logDebug(TAG, "回收站数据更新了")
}
true
}
StayNotificationService.mainHandler = handler
startService(Intent(this, StayNotificationService::class.java).apply {
this.action = MEDIA_OBSERVER_ACTION
})
startService(Intent(this, StayNotificationService::class.java).apply {
this.action = FILE_OBSERVER_ACTION
putExtra("isStart", true)
})
recycleBinAdapter = RecycleBinAdapter()
binding.rv.adapter = recycleBinAdapter
if (checkStorePermission()) {
initData()
} else {
showGerPermission(allow = {
requestStorePermission(launcher, result = { flag ->
if (flag) {
initData()
}
})
})
}
}
override fun initListener() {
super.initListener()
binding.swipeRefreshLayout.setOnRefreshListener {
binding.swipeRefreshLayout.isRefreshing = true
initData()
lifecycleScope.launch {
delay(1500)
binding.swipeRefreshLayout.isRefreshing = false
}
}
}
override fun onDestroy() {
super.onDestroy()
startService(Intent(FILE_OBSERVER_ACTION).apply {
putExtra("isStart", false)
})
}
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val file = this@RecycleBinActivity.filesDir
val recycleBinDir = File(file, "RecycleBin")
if (!recycleBinDir.exists()) {
recycleBinDir.mkdirs()
}
val binList = recycleBinDir.listFiles()?.filter { it.name.contains(".bin") }
val beanList = arrayListOf<RecycleBinBean>()
binList?.forEach {
val bean = Gson().fromJson(it.readText(), RecycleBinBean::class.java)
beanList.add(bean)
}
launch(Dispatchers.Main) {
recycleBinAdapter.setData(beanList)
}
}
}
}
\ No newline at end of file
package com.base.filerecoveryrecyclebin.activity.recyclebin
import android.graphics.Color
import android.os.Build
import androidx.annotation.RequiresApi
import com.base.filerecoveryrecyclebin.activity.recyclebin.MyFileObserver.Companion.findRecycleBinFile
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.databinding.ActivityRecycleBinDetailBinding
import com.base.filerecoveryrecyclebin.help.BaseActivity
import com.base.filerecoveryrecyclebin.utils.BarUtils
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.base.filerecoveryrecyclebin.view.DialogViews.showRecycleBinDetailDialog
import com.bumptech.glide.Glide
import com.google.gson.Gson
import java.io.File
class RecycleBinDetailActivity : BaseActivity<ActivityRecycleBinDetailBinding>() {
private val TAG = "RecycleBinDetailActivity"
override val binding: ActivityRecycleBinDetailBinding by lazy {
ActivityRecycleBinDetailBinding.inflate(layoutInflater)
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
val json = intent.extras?.getString("Json") ?: ""
LogEx.logDebug(TAG, "json=$json")
val bean = Gson().fromJson(json, RecycleBinBean::class.java)
if (bean.mimeType == "image/jpeg") {
val file = File(bean.path)
val binFile = findRecycleBinFile(file.name)
binFile?.let { path ->
Glide.with(this).load(path).centerCrop().into(binding.iv)
showRecycleBinDetailDialog(bean, binFile)
}
}
if (bean.mimeType == "") {
}
}
override fun initListener() {
super.initListener()
}
}
\ No newline at end of file
package com.base.filerecoveryrecyclebin.adapter
import android.annotation.SuppressLint
import android.os.Build
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.activity.recyclebin.MyFileObserver.Companion.findRecycleBinFile
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.databinding.ItemRecyclebinFileBinding
import com.base.filerecoveryrecyclebin.help.KotlinExt.toFormatSize
......@@ -14,7 +17,7 @@ import com.base.filerecoveryrecyclebin.view.XmlEx.inflate
import com.bumptech.glide.Glide
import java.io.File
class RecycleBinAdapter : RecyclerView.Adapter<RecycleBinAdapter.RBAV>() {
class RecycleBinAdapter(val click: (bean: RecycleBinBean) -> Unit) : RecyclerView.Adapter<RecycleBinAdapter.RBAV>() {
private val beanList = arrayListOf<RecycleBinBean>()
......@@ -31,16 +34,21 @@ class RecycleBinAdapter : RecyclerView.Adapter<RecycleBinAdapter.RBAV>() {
return beanList.size
}
@RequiresApi(Build.VERSION_CODES.Q)
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: RBAV, position: Int) {
val binding = ItemRecyclebinFileBinding.bind(holder.itemView)
val bean = beanList[position]
val file = File(bean.path)
val binFile = findRecycleBinFile(file.name)
val context = holder.itemView.context
Glide.with(context).load(bean.path).centerCrop().into(binding.iv)
Glide.with(context).load(binFile?.absoluteFile).centerCrop().into(binding.iv)
binding.tvName.text = file.name
binding.tvTime.text = "delete time:" + bean.deleteTime.toFormatTime()
binding.tvSize.text = bean.size.toFormatSize()
binding.root.setOnClickListener {
click.invoke(bean)
}
}
@SuppressLint("NotifyDataSetChanged")
......
......@@ -156,7 +156,9 @@ object AdMaxInterstitialUtils {
LogEx.logDebug(TAG, "!shouldShowAd")
return
}
if (interstitialAd?.isReady == true) {
return
}
if (AdMaxInit.isAdMaxInit.get()) {
LogEx.logDebug(TAG, "loadInterstitialAd")
interstitialAd?.loadAd()
......
......@@ -15,7 +15,7 @@ import com.base.filerecoveryrecyclebin.utils.LogEx
import org.json.JSONObject
object AdMaxOpenUtils {
private val TAG = "com.base.filerecoveryrecyclebin.ads.max.AdMaxOpenUtils"
private val TAG = "AdMaxOpenUtils"
private var appOpenAd: MaxAppOpenAd? = null
private var openLoadTime = Long.MAX_VALUE
private var onHidden: (() -> Unit)? = null
......@@ -135,6 +135,9 @@ object AdMaxOpenUtils {
LogEx.logDebug(TAG, "!shouldShowAd")
return
}
if (appOpenAd?.isReady == true) {
return
}
if (AdMaxInit.isAdMaxInit.get()) {
LogEx.logDebug(TAG, "appOpenAd load")
......
package com.base.filerecoveryrecyclebin.fragment
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.view.View
import androidx.annotation.RequiresApi
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.base.filerecoveryrecyclebin.activity.MainActivity
import com.base.filerecoveryrecyclebin.activity.recyclebin.MyFileObserver.Companion.getRecycleBinDir
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinDetailActivity
import com.base.filerecoveryrecyclebin.adapter.RecycleBinAdapter
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.databinding.FragmentRecycleBinBinding
......@@ -32,6 +36,7 @@ class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>() {
FragmentRecycleBinBinding.inflate(layoutInflater)
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun setView() {
handler = Handler(requireActivity().mainLooper) { message ->
......@@ -54,7 +59,11 @@ class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>() {
this.action = StayNotificationService.FILE_OBSERVER_ACTION
putExtra("isStart", true)
})
recycleBinAdapter = RecycleBinAdapter()
recycleBinAdapter = RecycleBinAdapter { bean ->
startActivity(Intent(requireContext(), RecycleBinDetailActivity::class.java).apply {
putExtra("Json", Gson().toJson(bean))
})
}
binding.rv.adapter = recycleBinAdapter
val launcher = (requireActivity() as MainActivity).launcher
......@@ -86,14 +95,11 @@ class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>() {
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val file = requireActivity().filesDir
val recycleBinDir = File(file, "RecycleBin")
if (!recycleBinDir.exists()) {
recycleBinDir.mkdirs()
}
val binList = recycleBinDir.listFiles()?.filter { it.name.contains(".bin") }
val binList = getRecycleBinDir().listFiles()?.filter { it.name.contains(".bin") }
val beanList = arrayListOf<RecycleBinBean>()
binList?.forEach {
LogEx.logDebug(TAG, it.absolutePath)
......@@ -105,7 +111,7 @@ class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>() {
launch(Dispatchers.Main) {
binding.rv.isVisible = deleteFile.isNotEmpty()
binding.llEmpty.isVisible = deleteFile.isEmpty()
recycleBinAdapter.setData(beanList)
recycleBinAdapter.setData(deleteFile)
}
}
......
......@@ -12,14 +12,19 @@ import android.view.View
import androidx.lifecycle.LifecycleCoroutineScope
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.ads.admob.AdmobInterstitialUtils.showInterAdSp
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.databinding.DialogCameraSettingBinding
import com.base.filerecoveryrecyclebin.databinding.DialogDeletePermanentlyBinding
import com.base.filerecoveryrecyclebin.databinding.DialogExitFunctionBinding
import com.base.filerecoveryrecyclebin.databinding.DialogImageTakeBinding
import com.base.filerecoveryrecyclebin.databinding.DialogPermissonOpenBinding
import com.base.filerecoveryrecyclebin.databinding.DialogRecoveringBinding
import com.base.filerecoveryrecyclebin.databinding.DialogRecyclebinFileRestoreBinding
import com.base.filerecoveryrecyclebin.databinding.DialogRemoveFileTipBinding
import com.base.filerecoveryrecyclebin.help.KotlinExt.toFormatSize
import com.base.filerecoveryrecyclebin.help.KotlinExt.toFormatTime
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.base.filerecoveryrecyclebin.view.DialogViews.showDeletePermanentlyDialog
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.coroutines.Dispatchers
......@@ -275,5 +280,31 @@ object DialogViews {
}
}
@SuppressLint("SetTextI18n")
fun Context.showRecycleBinDetailDialog(bean: RecycleBinBean, binFile: File) {
val binding = DialogRecyclebinFileRestoreBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).create()
dialog.setView(binding.root)
dialog.show()
dialog.setCanceledOnTouchOutside(false)
dialog.setCancelable(false)
val params = dialog.window?.attributes
params?.gravity = Gravity.BOTTOM
params?.y = resources.getDimensionPixelOffset(R.dimen.dp_35)
params?.width = resources.getDimensionPixelOffset(R.dimen.dp_355)
params?.dimAmount = 0f
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
dialog.window?.attributes = params
binding.tvName.text = File(bean.path).name
binding.tvSize.text = bean.size.toFormatSize()
binding.tvTime.text = "Delete time:${bean.deleteTime.toFormatTime()}"
binding.tvRestore.setOnClickListener {
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="22dp" />
<solid android:color="#4773FF" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.recyclebin.RecycleBinDetailActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ 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="@dimen/dp_345"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="15dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="18dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_restore"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="14sp"
tools:text="1721110745805_Trash_Screenshot_2024-07-16-14-07-233_00m.miui.ho" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textColor="#999999"
android:textSize="14sp"
tools:text="1MB" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
android:textColor="#999999"
android:textSize="14sp"
tools:text="2024/07/16" />
</LinearLayout>
<TextView
android:id="@+id/tv_restore"
android:layout_width="98dp"
android:layout_height="45dp"
android:layout_marginEnd="15dp"
android:background="@drawable/bg_4773ff_22"
android:gravity="center"
android:text="Restore"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
......@@ -4,4 +4,6 @@
<dimen name="dp_300">300dp</dimen>
<dimen name="dp_345">345dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="dp_355">355dp</dimen>
<dimen name="dp_35">35dp</dimen>
</resources>
\ 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