Commit 40fc93ff authored by wanglei's avatar wanglei

Initial commit

parent 673dec70
......@@ -73,10 +73,11 @@ dependencies {
androidTestImplementation libs.androidx.espresso.core
implementation("com.github.JavaNoober.BackgroundLibrary:libraryx:1.7.6")
implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation 'com.airbnb.android:lottie:6.4.0'
implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation("com.github.JavaNoober.BackgroundLibrary:libraryx:1.7.6")
implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'
implementation("com.google.android.gms:play-services-ads:23.1.0")
......
......@@ -2,6 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
......@@ -13,6 +19,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.EasyFileManager"
tools:targetApi="31">
<activity
android:name=".activity.splash.SplashActivity"
android:exported="true"
......@@ -28,10 +35,18 @@
<activity
android:name=".activity.MainActivity"
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".activity.FileCategoryActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".activity.FileManagerActivity"
android:exported="false" />
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
......@@ -42,7 +57,6 @@
<meta-data
android:name="com.google.android.gms.ads.flag.NATIVE_AD_DEBUGGER_ENABLED"
android:value="false" />
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" />
......
{"v":"5.5.7","fr":60,"ip":0,"op":60,"w":640,"h":140,"nm":"合成 1","ddd":0,"assets":[{"id":"image_0","w":157,"h":175,"u":"images/","p":"img_0.png","e":0},{"id":"image_1","w":86,"h":50,"u":"images/","p":"img_1.png","e":0},{"id":"image_2","w":540,"h":114,"u":"images/","p":"img_2.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"bu.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[518,94.5,0],"to":[5.917,0,0],"ti":[-5.917,0,0]},{"t":30,"s":[553.5,94.5,0]}],"ix":2},"a":{"a":0,"k":[78.5,87.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":2,"nm":"on.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":22,"s":[0]},{"t":31,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[502.25,57.5,0],"ix":2},"a":{"a":0,"k":[43,25,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"qx2.png","cl":"png","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[320,57,0],"ix":2},"a":{"a":0,"k":[270,57,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
package com.base.easyfilemanager.activity
import android.content.Context
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Environment
import android.view.View
import android.widget.LinearLayout
import androidx.activity.addCallback
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import com.base.easyfilemanager.adapter.FileBrowseAdapter
import com.base.easyfilemanager.bean.FileBean
import com.base.easyfilemanager.bean.FileCategoryBean
import com.base.easyfilemanager.databinding.ActivityFileCategoryBinding
import com.base.easyfilemanager.helps.BaseActivity
import com.base.easyfilemanager.helps.MediaStoreEx.geFileMedia
import com.base.easyfilemanager.helps.MediaStoreEx.getAudioMedia
import com.base.easyfilemanager.helps.MediaStoreEx.getImageMedia
import com.base.easyfilemanager.helps.MediaStoreEx.getVideoMedia
import com.base.easyfilemanager.helps.PermissionHelp.checkStorePermission
import com.base.easyfilemanager.helps.PermissionHelp.requestStorePermission
import com.base.easyfilemanager.helps.ads.AdmobUtils
import com.base.easyfilemanager.view.DialogViews.showGerPermission
import com.base.easyfilemanager.view.FileDeleteDialog.showFileDeleteDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.File
class FileCategoryActivity : BaseActivity<ActivityFileCategoryBinding>() {
private val TAG = "FileCategoryActivity"
private var type: String = ""
private lateinit var adapter: FileBrowseAdapter
override val binding: ActivityFileCategoryBinding by lazy {
ActivityFileCategoryBinding.inflate(layoutInflater)
}
override fun initView() {
type = intent.extras?.getString("type") ?: ""
binding.tvTittle.text = type
adapter = FileBrowseAdapter { size ->
binding.tvDelete.isSelected = size > 0
binding.tvDelete.isEnabled = size > 0
}
binding.rv.adapter = adapter
binding.rv.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL))
if (checkStorePermission()) {
initData()
} else {
dialog = showGerPermission(deny = { finishToMain() }) {
requestStorePermission(launcher, result = { flag ->
if (flag) {
initData()
} else {
finishToMain()
}
})
}
}
}
override fun initListener() {
binding.flBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
onBackPressedDispatcher.addCallback {
AdmobUtils.showInterstitialAd(this@FileCategoryActivity) {
finishToMain()
}
}
binding.tvDelete.setOnClickListener {
val deleteList = adapter.getSelect()
showFileDeleteDialog {
binding.progressbar.visibility = View.VISIBLE
lifecycleScope.launch(Dispatchers.Main) {
async {
try {
deleteList.forEach {
val deleteFile = File(it.path)
if (deleteFile.isFile) deleteFile.delete()
}
} catch (e: Exception) {
}
}.await()
adapter.removeData(deleteList)
binding.progressbar.visibility = View.GONE
}
}
}
}
private fun initData() {
binding.progressbar.visibility = View.VISIBLE
val list = arrayListOf<FileBean>()
when (type) {
FileCategoryBean.Audio -> {
getAudioMedia(list)
list.forEach { fileBean -> fileBean.type = "mp3" }
}
FileCategoryBean.Image -> {
getImageMedia(list)
list.forEach { fileBean -> fileBean.type = "jpg" }
}
FileCategoryBean.Video -> {
getVideoMedia(list)
list.forEach { fileBean -> fileBean.type = "mp4" }
}
FileCategoryBean.ZIP -> {
geFileMedia(list, arrayOf("application/zip"))
list.forEach { fileBean -> fileBean.type = "zip" }
}
FileCategoryBean.APK -> {
geFileMedia(list, arrayOf("application/vnd.android.package-archive"))
list.forEach { fileBean -> fileBean.type = "apk" }
}
}
binding.progressbar.visibility = View.GONE
if (list.isEmpty()) {
binding.ivEmpty.isVisible = true
} else {
adapter.setData(list)
}
}
}
\ No newline at end of file
package com.base.easyfilemanager.activity
import com.base.easyfilemanager.databinding.ActivityFileManagerBinding
import com.base.easyfilemanager.helps.BaseActivity
class FileManagerActivity : BaseActivity<ActivityFileManagerBinding>() {
override val binding: ActivityFileManagerBinding by lazy {
ActivityFileManagerBinding.inflate(layoutInflater)
}
override fun initView() {
}
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.base.easyfilemanager.databinding.ActivityMainBinding
import com.base.easyfilemanager.helps.BaseActivity
import com.base.easyfilemanager.helps.MediaStoreEx.updateMediaStore
class MainActivity : BaseActivity<ActivityMainBinding>() {
......@@ -15,6 +16,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
override fun initView() {
updateMediaStore()
}
}
\ No newline at end of file
......@@ -8,5 +8,6 @@ object SplashJumpUtils {
fun jumpNextPage(context: Activity) {
context.startActivity(Intent(context, MainActivity::class.java))
context.finish()
}
}
\ No newline at end of file
package com.base.easyfilemanager.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.easyfilemanager.R
import com.base.easyfilemanager.bean.FileBean
import com.base.easyfilemanager.databinding.ItemFileListBinding
import com.base.easyfilemanager.helps.XmlEx.inflate
import com.bumptech.glide.Glide
class FileBrowseAdapter(private val select: (size: Int) -> Unit) : RecyclerView.Adapter<FileBrowseAdapter.FB>() {
private val fileList = arrayListOf<FileBean>()
inner class FB(view: View) : ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FB {
return FB(R.layout.item_file_list.inflate(parent))
}
override fun onBindViewHolder(holder: FB, position: Int) {
}
override fun getItemCount(): Int {
return fileList.size
}
override fun onBindViewHolder(holder: FB, position: Int, payloads: MutableList<Any>) {
val binding = ItemFileListBinding.bind(holder.itemView)
val context = holder.itemView.context
val data = fileList[position]
if (payloads.isEmpty()) {
data.loadImageIcon(context, binding.ivIcon)
binding.tvName.text = data.name
binding.tvPath.text = data.path
binding.ivSelector.isSelected = data.isSelect
binding.root.setOnClickListener {
data.isSelect = !data.isSelect
binding.ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "局部刷洗")
select.invoke(fileList.filter { it.isSelect }.size)
}
} else {
binding.ivSelector.isSelected = data.isSelect
super.onBindViewHolder(holder, position, payloads)
}
}
@SuppressLint("NotifyDataSetChanged")
fun setData(data: List<FileBean>, clear: Boolean = false) {
if (clear) {
fileList.clear()
}
fileList.addAll(data)
notifyDataSetChanged()
}
private fun FileBean.loadImageIcon(context: Context, ivIcon: ImageView) {
when {
isImage() or isVideo() -> Glide.with(context).load(path).centerCrop().into(ivIcon)
isAudio() -> ivIcon.setImageResource(R.mipmap.audio)
isZip() -> ivIcon.setImageResource(R.mipmap.zip)
isApk() -> ivIcon.setImageResource(R.mipmap.apk)
isEmptyFile() -> ivIcon.setImageResource(R.mipmap.empty)
}
}
fun getSelect(): List<FileBean> {
return fileList.filter { it.isSelect }
}
@SuppressLint("NotifyDataSetChanged")
fun removeData(deleteList: List<FileBean>) {
fileList.removeAll(deleteList.toSet())
notifyDataSetChanged()
}
}
......@@ -8,7 +8,9 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.easyfilemanager.R
import com.base.easyfilemanager.bean.FileCategoryBean
import com.base.easyfilemanager.databinding.ItemFileCategoryBinding
import com.base.easyfilemanager.databinding.ItemRecentMediaBinding
import com.base.easyfilemanager.helps.XmlEx.inflate
import com.bumptech.glide.Glide
class FileCategoryAdapter(val mode: String = MODE_CATEGORY, val click: (key: String) -> Unit) :
RecyclerView.Adapter<FileCategoryAdapter.DC>() {
......@@ -21,6 +23,7 @@ class FileCategoryAdapter(val mode: String = MODE_CATEGORY, val click: (key: Str
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DC {
return when (mode) {
MODE_DOCUMENT -> DC(R.layout.item_file_category.inflate(parent))
MODE_RECENT -> DC(R.layout.item_recent_media.inflate(parent))
else -> DC(R.layout.item_file_category.inflate(parent))
}
}
......@@ -41,6 +44,13 @@ class FileCategoryAdapter(val mode: String = MODE_CATEGORY, val click: (key: Str
click.invoke(data.key)
}
}
MODE_RECENT->{
val binding = ItemRecentMediaBinding.bind(holder.itemView)
Glide.with(context).load(data.url).centerCrop().into(binding.iv)
binding.root.setOnClickListener {
click.invoke(data.key)
}
}
}
}
......
package com.base.easyfilemanager.bean
import java.io.File
data class FileBean(
var name: String = "",
var path: String,
val size: Long,
val isDir: Boolean = false,
var type: String = "",
val time: Long = 0L,
var isSelect: Boolean = false
) {
fun isEmptyFile() = !isDir && (File(path).length() == 0L)
fun isEmptyDir() = isDir
fun isImage() = !isDir && type in listOf("png", "jpg", "gif")
fun isVideo() = !isDir && type in listOf("mp4")
fun isAudio() = !isDir && type in listOf("mp3")
fun isLargeFile() = !isDir && size >= 10 * 1024 * 1024
fun isZip() = !isDir && type in listOf("zip", "tar", "7z")
fun isApk() = !isDir && type in listOf("apk")
fun isDoc() = !isDir && type in listOf("pdf", "doc", "docx", "xls", "ppt", "txt")
fun isDocx() = !isDir && type in listOf("docx")
fun isPdf() = !isDir && type in listOf("pdf")
fun isXls() = !isDir && type in listOf("xls", "xlsx")
fun isTxt() = !isDir && type in listOf("txt")
fun isPpt() = !isDir && type in listOf("ppt")
fun isOther() = !isImage() && !isVideo() && !isAudio() && !isZip() && !isApk()
fun isJunk() = !isDir && type in listOf("tmp", "cache", "temp")
}
\ No newline at end of file
package com.base.easyfilemanager.fragment
import android.animation.ValueAnimator
import android.content.Intent
import android.view.View
import android.view.animation.LinearInterpolator
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.base.easyfilemanager.activity.MainActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
import com.base.easyfilemanager.R
import com.base.easyfilemanager.activity.FileCategoryActivity
import com.base.easyfilemanager.activity.MainActivity
import com.base.easyfilemanager.adapter.FileCategoryAdapter
import com.base.easyfilemanager.bean.FileCategoryBean
import com.base.easyfilemanager.bean.FileCategoryBean.Companion.Image
import com.base.easyfilemanager.databinding.FragmentFileCategoryBinding
import com.base.easyfilemanager.helps.BaseFragment
import com.base.easyfilemanager.helps.KotlinExt.toFormatSize
import com.base.easyfilemanager.helps.MediaStoreEx
import com.base.easyfilemanager.helps.PermissionHelp.checkStorePermission
import com.base.easyfilemanager.helps.PermissionHelp.requestStorePermission
import com.base.easyfilemanager.helps.StatFsHelper.availableSize
import com.base.easyfilemanager.helps.StatFsHelper.totalSize
import com.base.easyfilemanager.view.DialogViews.showGerPermission
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlin.random.Random
class FileCategoryFragment : BaseFragment<FragmentFileCategoryBinding>() {
......@@ -24,71 +35,129 @@ class FileCategoryFragment : BaseFragment<FragmentFileCategoryBinding>() {
}
private lateinit var categoryAdapter: FileCategoryAdapter
private lateinit var recentAdapter: FileCategoryAdapter
private lateinit var valueAnimator: ValueAnimator
private val categoryList = listOf(
FileCategoryBean(FileCategoryBean.ZIP, R.mipmap.zip, FileCategoryBean.ZIP),
FileCategoryBean(FileCategoryBean.Video, R.mipmap.video, FileCategoryBean.Video),
FileCategoryBean(FileCategoryBean.Audio, R.mipmap.audio, FileCategoryBean.Audio),
FileCategoryBean(FileCategoryBean.APK, R.mipmap.apk, FileCategoryBean.APK),
FileCategoryBean(FileCategoryBean.Image, R.mipmap.image, FileCategoryBean.Image),
FileCategoryBean(FileCategoryBean.Empty, R.mipmap.empty, FileCategoryBean.Empty),
FileCategoryBean(FileCategoryBean.Video, R.mipmap.video, FileCategoryBean.Video),
FileCategoryBean(FileCategoryBean.ZIP, R.mipmap.zip, FileCategoryBean.ZIP),
FileCategoryBean(FileCategoryBean.APK, R.mipmap.apk, FileCategoryBean.APK),
// FileCategoryBean(FileCategoryBean.Empty, R.mipmap.empty, FileCategoryBean.Empty),
)
override fun setView() {
valueAnimator = ValueAnimator.ofFloat(0f, 360f)
valueAnimator.run {
duration = 1000
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
interpolator = LinearInterpolator()
addUpdateListener {
binding.ivXuanZhuan.rotation = it.animatedValue as Float
}
start()
}
categoryAdapter = FileCategoryAdapter(FileCategoryAdapter.MODE_MEDIA, ::itemClick)
binding.rvMedia.adapter = categoryAdapter
categoryAdapter = FileCategoryAdapter(FileCategoryAdapter.MODE_CATEGORY, ::itemClick)
val layoutManager = GridLayoutManager(requireContext(), 3)
layoutManager.spanSizeLookup = object : SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
// 根据你的需求来决定每个item应该占据的列数
// 例如,如果每个item都应该平分宽度,可以返回1
return 1
}
}
binding.rvCategory.layoutManager = layoutManager
binding.rvCategory.adapter = categoryAdapter
categoryAdapter.setData(categoryList)
binding.tvAuthorization.setOnClickListener {
requireContext().showGerPermission(deny = {}, allow = {
val launcher = (requireActivity() as MainActivity).launcher
requireContext().requestStorePermission(launcher, result = { flag ->
if (flag) {
binding.llPermission.visibility = View.GONE
binding.tvAuthorization.visibility = View.GONE
binding.rvRecent.visibility = View.VISIBLE
loadRecentImageVideo()
binding.llAll.isVisible = true
loadRecentImageVideo()
} else {
binding.llAll.isVisible = false
}
})
})
}
binding.llAll.isVisible = requireContext().checkStorePermission()
binding.llAll.setOnClickListener {
itemClick(Image)
itemClick(FileCategoryBean.Image)
}
recentAdapter = FileCategoryAdapter(FileCategoryAdapter.MODE_RECENT, ::itemClick)
binding.rvRecent.adapter = recentAdapter
if (requireContext().checkStorePermission()) {
refreshRecent()
}
val total = totalSize().toFormatSize().split(" ")
binding.tvTotal.text = total[0]
binding.tvTotalUnit.text = total[1]
val used = (totalSize() - availableSize()).toFormatSize().split(" ")
binding.tvUsed.text = used[0]
binding.tvUsedUnit.text = used[1]
}
private fun itemClick(key: String) {
// requireContext().startActivity(Intent(requireContext(), FileCategoryActivity::class.java).apply {
// putExtra("type", key)
// })
requireContext().startActivity(Intent(requireContext(), FileCategoryActivity::class.java).apply {
putExtra("type", key)
})
}
fun refreshRecent() {
if (isVisible) {
private fun refreshRecent() {
binding.llPermission.visibility = View.GONE
binding.rvRecent.visibility = View.VISIBLE
loadRecentImageVideo()
}
}
private fun loadRecentImageVideo() = lifecycleScope.launch(Dispatchers.Main) {
val imageList = arrayListOf<FileCategoryBean>()
async {
val list = MediaStoreEx.recentImage(requireContext()).map { FileCategoryBean(key = Image, url = it.toString()) }
val list =
MediaStoreEx.recentImage(requireContext()).map { FileCategoryBean(key = FileCategoryBean.Image, url = it.toString()) }
imageList.addAll(list)
}.await()
if (imageList.isEmpty()) {
binding.llEmpty.visibility = View.VISIBLE
} else {
categoryAdapter.setData(imageList)
recentAdapter.setData(imageList)
}
}
override fun onStart() {
super.onStart()
}
override fun onPause() {
super.onPause()
valueAnimator.pause()
}
override fun onResume() {
super.onResume()
valueAnimator.resume()
}
override fun onDestroy() {
super.onDestroy()
valueAnimator.cancel()
}
}
\ No newline at end of file
package com.base.easyfilemanager.helps
import android.util.Base64
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
object AESHelper {
private const val aesKey = "bgp8skv94x8r420k"
private val cipher by lazy {
Cipher.getInstance("AES/GCM/NoPadding")
}
fun encrypt(content: String): String {
try {
val iv = ByteArray(12).apply {
SecureRandom().nextBytes(this)
}
val contentBytes = content.toByteArray(Charsets.UTF_8)
val params = GCMParameterSpec(128, iv)
cipher.init(
Cipher.ENCRYPT_MODE,
secretKey, params
)
val encryptData = cipher.doFinal(contentBytes)
assert(encryptData.size == contentBytes.size + 16)
val message = ByteArray(12 + contentBytes.size + 16)
System.arraycopy(iv, 0, message, 0, 12)
System.arraycopy(encryptData, 0, message, 12, encryptData.size)
return String(Base64.encode(message, Base64.NO_WRAP), Charsets.UTF_8)
} catch (_: Exception) {
}
return content
}
@Synchronized
fun decrypt(content: String): String {
try {
val con = content.replace(" ".toRegex(), "+")
val contentByte = Base64.decode(con, Base64.NO_WRAP)
require(contentByte.size >= 12 + 16)
val params = GCMParameterSpec(128, contentByte, 0, 12)
cipher.init(
Cipher.DECRYPT_MODE,
secretKey, params
)
val decryptData = cipher.doFinal(contentByte, 12, contentByte.size - 12)
return String(decryptData, Charsets.UTF_8)
} catch (_: Exception) {
}
return content
}
private val secretKey by lazy {
SecretKeySpec(aesKey.toByteArray(), "AES")
}
}
\ No newline at end of file
package com.base.easyfilemanager.helps
import java.io.File
class FileHelp {
}
\ No newline at end of file
package com.base.easyfilemanager.helps
import android.view.View
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.Locale
object KotlinExt {
private val aesMap = mutableMapOf<Int, String>()
fun Int.string(vararg arg: Any) = try {
(aesMap[this] ?: BaseApplication.context.getString(this).decode()).run {
aesMap[this@string] = this
String.format(this, *arg)
}
} catch (_: Exception) {
""
}
fun String.decode() = AESHelper.decrypt(this)
.replace("\\r", "\r")
.replace("\\n", "\n")
.replace("\\'", "'")
.replace("\\\"", "\"")
.replace("\\?", "?")
.replace("&amp;", "&")
fun Collection<View>.setOnClickListener(listener: (View) -> Unit) {
this.forEach {
it.setOnClickListener(listener)
}
}
fun View.setTrackedOnClickListener(action: (view: View) -> Unit) {
setOnClickListener {
action(this)
var view: View? = this
while (view != null) {
try {
val obj = JSONObject()
obj.put("view_id", resources.getResourceEntryName(view.id))
break
} catch (_: Exception) {
view = view.parent as? View
}
}
}
}
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
package com.base.easyfilemanager.helps
import android.annotation.SuppressLint
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import com.base.easyfilemanager.bean.FileBean
object MediaStoreEx {
fun recentImage(context: Context): ArrayList<Uri> {
......@@ -71,5 +75,188 @@ object MediaStoreEx {
return list
}
@SuppressLint("Range")
fun Context.getAudioMedia(list: ArrayList<FileBean>): ArrayList<FileBean> {
val projection = arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.SIZE
)
var cursor: Cursor? = null
try {
cursor = this.contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
projection,
null, // 选择条件,null表示查询所有
null, // 选择参数,配合选择条件使用
MediaStore.Audio.Media.DEFAULT_SORT_ORDER // 排序顺序
)
if (cursor != null) {
while (cursor.moveToNext()) {
// 获取音乐文件的属性
val title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE))
val artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))
val album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM))
val path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
val size = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)).toLong()
// 其他属性...
list.add(FileBean(name = title, path = path, size))
}
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
@SuppressLint("Range")
fun Context.getImageMedia(list: ArrayList<FileBean>): ArrayList<FileBean> {
val projection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.TITLE,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.DATE_TAKEN
)
var cursor: Cursor? = null
try {
cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
null, // 选择条件,null表示查询所有
null, // 选择参数,配合选择条件使用
MediaStore.Images.Media.DATE_TAKEN + " DESC" // 按日期降序排序
)
if (cursor != null) {
while (cursor.moveToNext()) {
// 获取图片文件的属性
val title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.TITLE))
val path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA))
val size = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.SIZE)).toLong()
// 其他属性...
list.add(FileBean(title, path, size))
}
cursor.close()
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
@SuppressLint("Range")
fun Context.getVideoMedia(list: ArrayList<FileBean>): ArrayList<FileBean> {
val projection = arrayOf(
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.MIME_TYPE,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.DATE_TAKEN,
MediaStore.Video.Media.SIZE,
)
var cursor: Cursor? = null
try {
cursor = contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
null, // 选择条件,null表示查询所有
null, // 选择参数,配合选择条件使用
MediaStore.Video.Media.DATE_TAKEN + " DESC" // 按日期降序排序
)
if (cursor != null) {
while (cursor.moveToNext()) {
// 获取视频文件的属性
val path = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA))
val title = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE))
val size = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.SIZE)).toLong()
// 其他属性...
list.add(FileBean(title, path, size))
}
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
@SuppressLint("Range")
fun Context.geFileMedia(list: ArrayList<FileBean>, selectionArgs: Array<String>): ArrayList<FileBean> {
val projection = arrayOf(
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.TITLE,
MediaStore.Files.FileColumns.SIZE,
)
// 选择条件,筛选出MIME类型为application/zip的文件
val selection = MediaStore.Files.FileColumns.MIME_TYPE + "=?"
// val selectionArgs = arrayOf("application/zip")
var cursor: Cursor? = null
try {
cursor = contentResolver.query(
MediaStore.Files.getContentUri("external"), // 你也可以使用INTERNAL_CONTENT_URI来查询内部存储
projection,
selection,
selectionArgs,
null // 无排序
)
if (cursor != null) {
while (cursor.moveToNext()) {
val tittle = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.TITLE))
val path = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA))
val size = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.SIZE)).toLong()
// 其他属性...
list.add(FileBean(tittle, path, size))
}
cursor.close()
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
val commonMediaDir = arrayOf(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).absolutePath,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).absolutePath,
)
fun Context.updateMediaStore(
filePath: Array<String> = commonMediaDir
) {
MediaScannerConnection.scanFile(
this, filePath, null
) { path: String?, uri: Uri? -> }
}
}
package com.base.easyfilemanager.helps
import android.os.Environment
import android.os.StatFs
import android.util.Log
object StatFsHelper {
var totalsize = 0L
fun totalSize(): Long {
return if (totalsize > 0) {
totalsize
} else try {
val statFs = StatFs(Environment.getExternalStorageDirectory().path)
val statFs2 = StatFs(Environment.getRootDirectory().path)
Log.i(
"storeByteDebug",
"store1: " + statFs2.blockSizeLong * statFs2.blockCountLong + "====store2: " + statFs.blockSizeLong * statFs.blockCountLong
)
var blockSizeLong =
statFs2.blockSizeLong * statFs2.blockCountLong + statFs.blockSizeLong * statFs.blockCountLong
blockSizeLong = getClosestPowerOfTwo(blockSizeLong)
totalsize = blockSizeLong
blockSizeLong
} catch (e10: java.lang.Exception) {
0L
}
}
fun a(j10: Long): Long {
var tmep = j10
var i7 = 0L
while (true) {
val j11: Long = 1000
if (tmep < j11) {
break
}
tmep /= j11
i7++
}
for (i10 in 0 until i7) {
tmep *= 1024
}
return tmep
}
fun availableSize(): Long {
try {
val statFs = StatFs(Environment.getExternalStorageDirectory().path)
val statFs2 = StatFs(Environment.getRootDirectory().path)
val blackSize =
statFs2.blockSizeLong * statFs2.availableBlocksLong + statFs.blockSizeLong * statFs.availableBlocksLong
return a(blackSize)
} catch (e10: Exception) {
return 0L
}
}
fun getClosestPowerOfTwo(size: Long): Long {
var powerOfTwo: Long = 1
while (powerOfTwo < size) {
powerOfTwo *= 2
}
return powerOfTwo
}
}
\ No newline at end of file
package com.base.easyfilemanager.view
import android.app.Activity
import android.view.Gravity
import android.view.ViewGroup
import android.widget.PopupWindow
import androidx.core.view.updatePadding
import com.base.easyfilemanager.databinding.PopupLayoutAdPreparBinding
import com.base.easyfilemanager.helps.BarUtils
import kotlin.random.Random
class AdPreparationPop(private val activity: Activity, val onDismiss: () -> Unit) : PopupWindow() {
init {
width = ViewGroup.LayoutParams.MATCH_PARENT
height = ViewGroup.LayoutParams.MATCH_PARENT
isOutsideTouchable = false
isFocusable = true
isClippingEnabled = false
}
private val binding by lazy {
PopupLayoutAdPreparBinding.inflate(activity.layoutInflater)
}
fun show() {
contentView = binding.root
activity.window.decorView.post {
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
BarUtils.setStatusBarLightMode(activity, false)
showAtLocation(activity.window.decorView, Gravity.CENTER, 0, 0)
}
binding.root.postDelayed({
dismiss()
onDismiss.invoke()
}, Random.nextLong(2500, 4000))
}
override fun dismiss() {
super.dismiss()
BarUtils.setStatusBarLightMode(activity, true)
}
}
\ No newline at end of file
package com.base.easyfilemanager.view
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import com.base.easyfilemanager.R
import com.base.easyfilemanager.databinding.DialogPermissonOpenBinding
object DialogViews {
@SuppressLint("SetTextI18n")
fun Context.showGerPermission(
deny: ((view: Dialog) -> Unit)? = null,
allow: ((view: Dialog) -> Unit)? = null
): Dialog {
val dialog = Dialog(this)
val binding = DialogPermissonOpenBinding.inflate(LayoutInflater.from(this))
dialog.requestWindowFeature(1)
dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.window!!.setLayout(-1, -1)
dialog.setCanceledOnTouchOutside(false)
dialog.setCancelable(false)
dialog.setContentView(binding.root)
val str = this.resources.getString(R.string.app_name)
// SpanUtils.with(binding.idTvTt)
// .append("Allow ${str} to access ")
// .setFontSize(13, true)
// .setForegroundColor(0xFF999999.toInt())
// .append("All Files Access ")
// .setBold()
// .setFontSize(13, true)
// .setForegroundColor(0xFF4273FF.toInt())
// .append("permission to manage files of your device?")
// .setFontSize(13, true)
// .setForegroundColor(0xFF999999.toInt())
// .create()
binding.idTvTt.text =
"Our application needs to access your files to find media file Before you authorize, we need to confirm with you:"
binding.idFullLottie.imageAssetsFolder = "permission_finger/images/"
binding.idFullLottie.setAnimation("permission_finger/data.json")
binding.idFullLottie.playAnimation()
binding.idDeny.setOnClickListener {
dialog.dismiss()
deny?.invoke(dialog)
}
binding.idTvAllow.setOnClickListener {
dialog.dismiss()
allow?.invoke(dialog)
}
dialog.show()
return dialog
}
}
\ No newline at end of file
package com.base.easyfilemanager.view
import android.content.Context
import android.text.SpannableString
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import com.base.easyfilemanager.R
import com.base.easyfilemanager.databinding.DialogFileDeleteBinding
object FileDeleteDialog {
fun Context.showFileDeleteDialog(click: () -> Unit) {
val binding = DialogFileDeleteBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).setView(binding.root).create()
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(true)
dialog.show()
//修改dialog的尺寸
val lp = dialog.window?.attributes
lp?.width = this.resources.getDimensionPixelOffset(R.dimen.dp_310)
lp?.height = ViewGroup.LayoutParams.WRAP_CONTENT
dialog.window?.attributes = lp
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
val text = "Selected files cannot be recovered after deleting, continue anyway?"
val spannableString = SpannableString(text)
val start = text.indexOf("cannot")
if (start != -1) {
val end = start + "cannot be recovered".length
val colorSpan = ForegroundColorSpan(ContextCompat.getColor(this, R.color.color_f04949)) // 使用资源文件中的颜色
spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
binding.tvDesc.text = spannableString
binding.tvDelete.setOnClickListener {
dialog.dismiss()
click.invoke()
}
binding.tvCancel.setOnClickListener {
dialog.dismiss()
}
}
}
\ 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/image_selected" android:state_selected="true" />
<item android:drawable="@mipmap/image_unselected" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FDFDFD"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_action_bar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingHorizontal="15dp"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:src="@mipmap/fanhui"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:text=""
android:textColor="#FF333333"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/fl_back"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<com.noober.background.view.BLTextView
android:id="@+id/tv_delete"
android:layout_width="278dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:layout_marginBottom="30dp"
android:enabled="false"
android:gravity="center"
android:text="Delete"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold"
app:bl_corners_radius="24dp"
app:bl_selected_solid_color="#2D4059"
app:bl_unSelected_solid_color="#999999"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--suppress AndroidElementNotAllowed -->
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:indeterminateTint="#0066FD" />
<ImageView
android:id="@+id/iv_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/queshengtu"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</FrameLayout>
</FrameLayout>
</LinearLayout>
\ 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.FileManagerActivity">
</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="300dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardCornerRadius="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/app_name"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Selected files cannot be recovered after deleting, continue anyway?"
android:textSize="14sp"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="24dp"
android:layout_marginBottom="20dp">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:text="CANCEL"
android:textColor="#999999"
android:textSize="15sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DELETE"
android:textColor="#F24949"
android:textSize="15sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<com.noober.background.view.BLLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:orientation="vertical"
app:bl_corners_radius="10dp"
app:bl_solid_color="@color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="24dp"
android:text="Permission request"
android:textColor="#000000"
android:textSize="17sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/id_tv_tt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="22dp"
android:layout_marginBottom="38dp"
android:textSize="13sp" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/id_full_lottie"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
app:lottie_autoPlay="true"
app:lottie_loop="true" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="23dp"
android:layout_marginTop="40dp"
android:layout_marginBottom="14dp">
<com.noober.background.view.BLTextView
android:id="@+id/id_deny"
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_marginEnd="13dp"
android:layout_weight="1"
android:gravity="center"
android:text="Deny"
android:textColor="#000000"
android:textSize="17sp"
app:bl_corners_radius="18dp"
app:bl_solid_color="#F5F5F5"
tools:ignore="HardcodedText" />
<com.noober.background.view.BLTextView
android:id="@+id/id_tv_allow"
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_weight="1"
android:gravity="center"
android:text="Allow"
android:textColor="@color/white"
android:textSize="17sp"
app:bl_corners_radius="18dp"
app:bl_solid_color="#355bea"
tools:ignore="HardcodedText" />
</androidx.appcompat.widget.LinearLayoutCompat>
</com.noober.background.view.BLLinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
\ No newline at end of file
......@@ -12,9 +12,9 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="48dp"
android:text="Document tools"
android:text="File Manager"
android:textColor="@color/black"
android:textSize="15sp"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
......@@ -22,30 +22,162 @@
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<androidx.cardview.widget.CardView
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="172dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:elevation="5dp"
app:cardCornerRadius="12dp">
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_document"
<FrameLayout
android:id="@+id/fl_yuan"
android:layout_width="146dp"
android:layout_height="146dp"
android:layout_margin="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_xuan_zhuan"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/yuan"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_manager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:overScrollMode="never" />
</androidx.cardview.widget.CardView>
android:text="Manager"
android:textColor="@color/white"
android:textSize="18sp"
tools:ignore="HardcodedText" />
</FrameLayout>
<LinearLayout
android:id="@+id/ll_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@id/ll_used"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/fl_yuan"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.noober.background.view.BLTextView
android:layout_width="9dp"
android:layout_height="9dp"
android:layout_gravity="center_vertical"
app:bl_corners_radius="12dp"
app:bl_solid_color="#7FBAFF" />
<TextView
android:id="@+id/tv_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="25sp"
tools:text="128" />
<TextView
android:id="@+id/tv_total_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="8dp"
android:textColor="@color/black"
android:textSize="14sp"
tools:text="GB" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="Total"
android:textColor="#666666"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_used"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/fl_yuan"
app:layout_constraintTop_toBottomOf="@id/ll_total">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.noober.background.view.BLTextView
android:layout_width="9dp"
android:layout_height="9dp"
android:layout_gravity="center_vertical"
app:bl_corners_radius="12dp"
app:bl_solid_color="#72E5BC" />
<TextView
android:id="@+id/tv_used"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="25sp"
tools:text="128" />
<TextView
android:id="@+id/tv_used_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="8dp"
android:textColor="@color/black"
android:textSize="14sp"
tools:text="GB" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="Used"
android:textColor="#666666"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:text="Folder"
android:layout_marginTop="20dp"
android:text="Category"
android:textColor="@color/black"
android:textSize="15sp"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
......@@ -54,15 +186,17 @@
tools:ignore="HardcodedText" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_media"
android:layout_width="wrap_content"
android:id="@+id/rv_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="12dp"
android:layout_marginTop="6dp"
android:orientation="horizontal"
android:layout_gravity="center"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="5dp"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="3"
tools:itemCount="6"
tools:listitem="@layout/item_file_category" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
......@@ -156,7 +290,7 @@
android:layout_height="wrap_content"
android:text="No Permission"
android:textColor="#343434"
android:textSize="7sp"
android:textSize="15sp"
tools:ignore="HardcodedText,SmallSp" />
</LinearLayout>
......@@ -171,7 +305,7 @@
android:text="Authorization"
android:textColor="@color/white"
android:textSize="14sp"
app:bl_corners_radius="12dp"
app:bl_corners_radius="20dp"
app:bl_solid_color="@color/theme_color"
tools:ignore="HardcodedText,SmallSp" />
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<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="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="25dp"
android:layout_marginVertical="10dp"
android:layout_margin="5dp"
android:elevation="0dp"
android:orientation="vertical"
app:cardCornerRadius="10dp"
tools:ignore="UseCompoundDrawables">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_marginTop="15dp"
android:layout_gravity="center_horizontal"
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="45dp"
android:minHeight="45dp"
android:scaleType="centerCrop"
tools:ignore="ContentDescription" />
<TextView
android:layout_marginBottom="20dp"
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:textColor="#333333"
android:textSize="12sp" />
</LinearLayout>
\ No newline at end of file
android:textSize="13sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_gravity="center_vertical"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="5dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true" />
<TextView
android:id="@+id/tv_path"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
android:src="@drawable/bg_selected"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</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="70dp"
android:layout_height="70dp"
android:layout_margin="13dp"
android:elevation="0dp"
app:cardCornerRadius="4dp">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/id_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#B3000000">
<com.noober.background.view.BLLinearLayout
android:id="@+id/id_ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="43dp"
android:gravity="center_vertical"
app:bl_corners_radius="10dp"
app:bl_solid_color="@color/white">
<ProgressBar
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginVertical="20dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="11dp"
android:indeterminateTint="#355bea" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Advertising in preparation..."
android:textColor="#000000"
android:textSize="13sp"
tools:ignore="HardcodedText" />
</com.noober.background.view.BLLinearLayout>
</FrameLayout>
\ No newline at end of file
......@@ -3,4 +3,5 @@
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="theme_color">#8F5CE4</color>
<color name="color_f04949">#f04949</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="dp_310">310dp</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