Browse Source

Compose Material3

liuxiaolong 2 years ago
parent
commit
7444596cb6
38 changed files with 257 additions and 196 deletions
  1. 3 3
      app/build.gradle
  2. 2 0
      app/src/main/AndroidManifest.xml
  3. 45 40
      app/src/main/java/com/convenient/android/lib/ui/sample/MainActivity.kt
  4. 144 53
      app/src/main/java/com/convenient/android/lib/ui/sample/media/MediaFilesPage.kt
  5. 12 1
      app/src/main/java/com/convenient/android/lib/ui/sample/media/MediaFilesViewModel.kt
  6. 6 24
      app/src/main/java/com/convenient/android/lib/ui/sample/media/MediaSampleActivity.kt
  7. 8 5
      app/src/main/java/com/convenient/android/lib/ui/theme/Theme.kt
  8. 0 30
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  9. 23 0
      app/src/main/res/drawable/ic_launcher_foreground.xml
  10. 0 5
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  11. 0 5
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  12. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  13. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.webp
  14. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  15. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
  16. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  17. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.webp
  18. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  19. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
  20. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  21. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.webp
  22. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  23. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
  24. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  25. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
  26. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  27. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
  28. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  29. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
  30. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  31. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
  32. 2 10
      app/src/main/res/values-night/themes.xml
  33. 1 5
      app/src/main/res/values/colors.xml
  34. 4 0
      app/src/main/res/values/ic_launcher_background.xml
  35. 1 1
      app/src/main/res/values/strings.xml
  36. 2 9
      app/src/main/res/values/themes.xml
  37. 1 3
      lib_common/src/main/AndroidManifest.xml
  38. 3 2
      lib_common/src/main/java/com/convenient/android/common/media/scan/FileStore.kt

+ 3 - 3
app/build.gradle

@@ -4,12 +4,12 @@ plugins {
 }
 
 android {
-    compileSdk 32
+    compileSdk 33
 
     defaultConfig {
         applicationId "com.common.android.lib"
         minSdk 21
-        targetSdk 32
+        targetSdk 33
         versionCode 1
         versionName "1.0"
 
@@ -52,7 +52,7 @@ dependencies {
 
     //compose依赖
     implementation "androidx.compose.ui:ui:$compose_version"
-    implementation 'androidx.compose.material3:material3:1.0.0-alpha15'
+    implementation 'androidx.compose.material3:material3:1.0.0-beta01'
     implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
     implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
     implementation 'androidx.activity:activity-compose:1.5.1'

+ 2 - 0
app/src/main/AndroidManifest.xml

@@ -15,11 +15,13 @@
         android:label="@string/app_name"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
+        android:requestLegacyExternalStorage="true"
         android:theme="@style/Theme.Lib"
         tools:targetApi="31">
         <activity
             android:name=".ui.sample.media.MediaSampleActivity"
             android:exported="false" />
+
         <activity
             android:name="com.convenient.android.lib.ui.sample.MainActivity"
             android:exported="true">

+ 45 - 40
app/src/main/java/com/convenient/android/lib/ui/sample/MainActivity.kt

@@ -1,23 +1,28 @@
 package com.convenient.android.lib.ui.sample
 
+import android.annotation.SuppressLint
 import android.os.Bundle
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.*
 import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.material.*
+import androidx.compose.material.Icon
+import androidx.compose.material.Text
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.material.icons.filled.Build
+import androidx.compose.material.icons.filled.Home
+import androidx.compose.material3.*
 import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.convenient.android.common.extension.readyGo
 import com.convenient.android.lib.DateUtilActivity
 import com.convenient.android.lib.ui.sample.media.MediaSampleActivity
-import com.kdanmobile.jetpackcompose.sample.ui.theme.SampleTheme
+import com.convenient.android.lib.ui.theme.SampleTheme
 
 class MainActivity : ComponentActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -38,29 +43,27 @@ fun MainPagePreview() {
     }
 }
 
+@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
+@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 private fun MainPage() {
 
     var bottomSelectedState by remember { mutableStateOf(0) }
 
-    Scaffold(
-        topBar = {
-            TopAppBar {
-                Text(text = "BaseLib", modifier = Modifier
-                    .padding(horizontal = 20.dp)
-                    .fillMaxWidth(0.75f)
-                )
-            }
-        },
-        bottomBar = {
-            BottomBarView(bottomSelectedState) {
-                bottomSelectedState = it
-            }
-        }
-    ) {
-        when (bottomSelectedState) {
-            0 -> FuncListView()
-            else -> Text(text = "建设中")
+    Scaffold(bottomBar = {
+        BottomBarView(selectedPosition = bottomSelectedState, onItemSelected = {
+            bottomSelectedState = it
+        })
+    }) {
+            when(bottomSelectedState){
+                0->{
+                    FuncListView()
+                }
+                else->{
+                    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                        Text(text = "建设中")
+                    }
+                }
         }
     }
 }
@@ -77,40 +80,42 @@ private fun FuncListView() {
         FuncBean("DateUtils", DateUtilActivity::class.java),
         FuncBean("MediaUtils", MediaSampleActivity::class.java)
     )
-
-    LazyColumn {
-        items(funcList.size) { index ->
-            Button(modifier = Modifier
-                .fillMaxWidth()
-                .padding(horizontal = 16.dp), onClick = {
-                context.readyGo(funcList[index].class_)
-            }) {
-                Text(text = funcList[index].title)
+    Column {
+        LazyColumn() {
+            items(funcList.size) { index ->
+                ElevatedButton(modifier = Modifier
+                    .fillMaxWidth()
+                    .padding(horizontal = 16.dp), onClick = {
+                    context.readyGo(funcList[index].class_)
+                }) {
+                    Text(text = funcList[index].title)
+                }
             }
         }
     }
+
 }
 
 data class BottomItem(
     val title: String,
+    val icon: ImageVector
 )
 
 @Composable
 private fun BottomBarView(selectedPosition: Int, onItemSelected: (position: Int) -> Unit) {
     val itemList = arrayListOf(
-        BottomItem(title = "工具"),
-        BottomItem(title = "建设中"),
-        BottomItem(title = "建设中"),
-        BottomItem(title = "建设中")
+        BottomItem(title = "工具", Icons.Filled.Home),
+        BottomItem(title = "建设中", Icons.Filled.Build),
+        BottomItem(title = "建设中", Icons.Filled.Build),
+        BottomItem(title = "建设中", Icons.Filled.Build)
     )
-
-    BottomNavigation() {
+    NavigationBar() {
         itemList.forEachIndexed { index, bottomItem ->
-            BottomNavigationItem(
+            NavigationBarItem(
                 selected = selectedPosition == index,
                 onClick = { onItemSelected.invoke(index) },
                 icon = {
-                    Icon(Icons.Filled.Favorite, contentDescription = null)
+                    Icon(bottomItem.icon, contentDescription = null)
                 },
                 label = {
                     Text(bottomItem.title)

+ 144 - 53
app/src/main/java/com/convenient/android/lib/ui/sample/media/MediaFilesPage.kt

@@ -1,16 +1,18 @@
 package com.convenient.android.lib.ui.sample.media
 
-import android.annotation.SuppressLint
+import android.Manifest
+import android.app.Activity
 import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
 import android.os.Build
+import android.os.Environment
+import android.provider.Settings
 import androidx.activity.compose.rememberLauncherForActivityResult
 import androidx.activity.result.contract.ActivityResultContracts
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.*
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.foundation.text.KeyboardOptions
@@ -18,15 +20,13 @@ import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.*
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Delete
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.collectAsState
+import androidx.compose.material3.ElevatedButton
+import androidx.compose.runtime.*
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.vectorResource
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontWeight
@@ -36,14 +36,15 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.constraintlayout.compose.ConstraintLayout
 import androidx.constraintlayout.compose.Dimension
+import androidx.core.content.ContextCompat
 import androidx.lifecycle.viewmodel.compose.viewModel
 import com.convenient.android.common.extension.lengthToFitMemorySize
 import com.convenient.android.common.extension.spSave
 import com.convenient.android.common.extension.toFile
+import com.convenient.android.common.utils.ToastUtil
 import com.convenient.android.common.utils.date.DateUtils
-import com.convenient.android.common.utils.image.BitmapUtils
 import com.convenient.android.lib.R
-import com.kdanmobile.jetpackcompose.sample.ui.theme.SampleTheme
+import com.convenient.android.lib.ui.theme.SampleTheme
 
 /**
  * @classname:
@@ -52,10 +53,28 @@ import com.kdanmobile.jetpackcompose.sample.ui.theme.SampleTheme
  * description:
  */
 
+@Composable
+fun MediaPage(){
+    val context = LocalContext.current
+
+    var rememberPermission by remember {
+        mutableStateOf(ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
+    }
+    if (rememberPermission){
+        MediaFilesPage()
+    }else{
+        PermissionPage{
+            rememberPermission = true
+        }
+    }
+
+}
 
 @Composable
 fun MediaFilesPage() {
+
     val viewModel: MediaFilesViewModel = viewModel()
+
     val context = LocalContext.current
 
     val chooseDirLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult(), onResult = {
@@ -66,7 +85,6 @@ fun MediaFilesPage() {
         }
     })
 
-
     Column(
         modifier = Modifier
             .fillMaxWidth()
@@ -80,10 +98,22 @@ fun MediaFilesPage() {
         ) {
             val (btnFromFiles, btnFromMediaStore, btnChooseDir) = createRefs()
 
-            Button(onClick = { viewModel.changeQueryType(MediaQueryType.FILES) }, modifier = Modifier
+            ElevatedButton(
+                onClick = { chooseDirLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)) },
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .constrainAs(btnChooseDir) {
+                        top.linkTo(parent.top)
+                        start.linkTo(parent.start)
+                        end.linkTo(parent.end)
+                    }) {
+                Text(text = "选择文件夹")
+            }
+
+            ElevatedButton(onClick = { viewModel.changeQueryType(MediaQueryType.FILES) }, modifier = Modifier
                 .padding(end = 8.dp)
                 .constrainAs(btnFromFiles) {
-                    top.linkTo(parent.top)
+                    top.linkTo(btnChooseDir.bottom)
                     start.linkTo(parent.start)
                     end.linkTo(btnFromMediaStore.start)
                     width = Dimension.fillToConstraints
@@ -92,7 +122,7 @@ fun MediaFilesPage() {
 
             }
 
-            Button(onClick = { viewModel.changeQueryType(MediaQueryType.MEDIA_STORE) },
+            ElevatedButton(onClick = { viewModel.changeQueryType(MediaQueryType.MEDIA_STORE) },
                 modifier = Modifier
                     .padding(start = 8.dp)
                     .constrainAs(btnFromMediaStore) {
@@ -103,18 +133,6 @@ fun MediaFilesPage() {
                     }) {
                 Text(text = "从MediaStore获取")
             }
-            Button(
-                onClick = { chooseDirLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)) },
-                modifier = Modifier
-                    .fillMaxWidth()
-                    .constrainAs(btnChooseDir) {
-                        top.linkTo(btnFromFiles.bottom)
-                        start.linkTo(parent.start)
-                        end.linkTo(parent.end)
-                    }) {
-                Text(text = "选择文件夹")
-            }
-
         }
 
         QueryInfoPage(viewModel = viewModel)
@@ -129,37 +147,81 @@ fun MediaFilesPage() {
     }
 }
 
+@Composable
+private fun PermissionPage(permissionCallback : ()-> Unit) {
+
+    val context = LocalContext.current
+    val androidRStoragePermissionLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult(), onResult = {
+        if (it.resultCode == Activity.RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            if (Environment.isExternalStorageManager()) {
+                ToastUtil.showToast(context, "访问所有文件权限获取成功")
+                permissionCallback.invoke()
+            }
+        }
+    })
+
+    val permissionLaunch = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission(), onResult = {
+        if (it) {
+            ToastUtil.showToast(context, "存储权限获取成功")
+            permissionCallback.invoke()
+
+        }
+    })
+
+    Column(modifier = Modifier
+        .fillMaxWidth()
+        .fillMaxHeight(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {
+
+        ElevatedButton(onClick = {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+                if (Environment.isExternalStorageManager().not()) {
+                    androidRStoragePermissionLauncher.launch(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:${context.packageName}")))
+                } else {
+                    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
+                        ToastUtil.showToast(context, "已获取存储权限")
+                    }else{
+                        permissionLaunch.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+                    }
+                }
+            } else {
+                permissionLaunch.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+            }
+        }) {
+            Text(text = "获取存储权限")
+        }
+    }
+
+}
+
+
 @Composable
 fun QueryInfoPage(viewModel: MediaFilesViewModel) {
     val config = viewModel.config.collectAsState()
-
     val context = LocalContext.current
+
     val addIgnoreFolderLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult(), onResult = {
         it.data?.data?.let {
             val folder = resolveContentUri(context, it)
-            viewModel.changeConfig(config = config.value.copy(ignoreChildFiles = config.value.ignoreChildFiles.toMutableList().apply {
-                folder.toFile()?.let { it1 -> add(it1) }
-            }))
+            viewModel.addConfigIgnoreChildFiles(folder.toFile())
         }
     })
 
+
     val addIgnoreFileLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent(), onResult = {
         it?.let { uri ->
             val folder = UriTofilePath.getFilePathByUri(context, uri)
-            viewModel.changeConfig(config = config.value.copy(ignoreChildFiles = config.value.ignoreChildFiles.toMutableList().apply {
-                folder?.toFile()?.let { it1 -> add(it1) }
-            }))
+            viewModel.addConfigIgnoreChildFiles(folder.toFile())
         }
     })
 
     val dir = viewModel.dir.collectAsState()
     val queryType = viewModel.queryType.collectAsState()
 
-    InfoItem(title = "目录:", info = dir.value)
-    InfoItem(title = "获取方式:", info = queryType.value.name)
+    InfoItem(title = "目录:", info = dir.value, infoPosition = InfoPosition.END)
+    InfoItem(title = "获取方式:", info = queryType.value.name, infoPosition = InfoPosition.END)
 
     Column() {
-        InfoItem(title = "查询的文件格式:", info = config.value.supportMimeTypes.toString())
+        InfoItem(title = "查询的文件格式:", info = config.value.supportMimeTypes.toString(), infoPosition = InfoPosition.END)
         TextField(
             keyboardOptions = KeyboardOptions(autoCorrect = false, capitalization = KeyboardCapitalization.None),
             value = viewModel.getSupportMimeTypesFiledTextValue(config.value),
@@ -175,31 +237,34 @@ fun QueryInfoPage(viewModel: MediaFilesViewModel) {
     }
 
     Row {
-        InfoItem(title = "结果是否包含文件夹:", info = config.value.includeFolder.toString())
         val includeFolder = config.value.includeFolder
         RadioButton(selected = includeFolder, onClick = {
             viewModel.changeConfigIncludeFolder(includeFolder.not())
         })
+        InfoItem(title = "结果是否包含文件夹:", info = config.value.includeFolder.toString())
+
     }
 
     Row {
-        InfoItem(title = "遍历子文件夹:", info = config.value.recursively.toString())
         val recursively = config.value.recursively
         RadioButton(selected = recursively, onClick = {
             viewModel.changeConfig(config.value.copy(recursively = recursively.not()))
         })
+        InfoItem(title = "遍历子文件夹:", info = config.value.recursively.toString())
+
     }
 
     Column {
         InfoItem(title = "忽略的文件:", info = "")
-        Button(onClick = { addIgnoreFolderLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)) }) {
-            Text(text = "选择忽略的文件夹")
-        }
+        Row {
+            ElevatedButton(onClick = { addIgnoreFolderLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)) }) {
+                Text(text = "选择忽略的文件夹")
+            }
 
-        Button(onClick = { addIgnoreFileLauncher.launch("*/*") }) {
-            Text(text = "选择忽略的文件")
+            ElevatedButton(onClick = { addIgnoreFileLauncher.launch("*/*") }) {
+                Text(text = "选择忽略的文件")
+            }
         }
-
         for (ignoreChildFile in config.value.ignoreChildFiles) {
             Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
                 Text(modifier = Modifier.weight(3F), text = ignoreChildFile.absolutePath)
@@ -211,22 +276,43 @@ fun QueryInfoPage(viewModel: MediaFilesViewModel) {
             }
         }
     }
+}
 
-
+enum class InfoPosition {
+    TOP, BOTTOM, START, END
 }
 
 @Composable
-fun InfoItem(title: String, info: String) {
+fun InfoItem(title: String, info: String, infoPosition: InfoPosition = InfoPosition.BOTTOM) {
 
-    Column {
-        Text(text = title, style = TextStyle(fontSize = 14.sp, color = Color.Black, fontWeight = FontWeight.Bold))
-        if (info.isNotEmpty() && info.equals("[]").not()) {
-            Text(text = info, style = TextStyle(fontSize = 12.sp))
+
+    Column(verticalArrangement = Arrangement.Center) {
+        if (infoPosition == InfoPosition.TOP) {
+            info(info)
+        }
+        Row {
+            if (infoPosition == InfoPosition.START) {
+                info(info)
+            }
+            Text(text = title, style = TextStyle(fontSize = 14.sp, color = Color.Black, fontWeight = FontWeight.Bold))
+            if (infoPosition == InfoPosition.END) {
+                info(info)
+            }
+        }
+        if (infoPosition == InfoPosition.BOTTOM) {
+            info(info)
         }
         Spacer(modifier = Modifier.padding(top = 8.dp))
     }
 }
 
+@Composable
+fun info(info: String) {
+    if (info.isNotEmpty() && info.equals("[]").not()) {
+        Text(text = info, style = TextStyle(fontSize = 12.sp), modifier = Modifier.padding(horizontal = 8.dp))
+    }
+}
+
 @Composable
 fun ResultInfoPage(viewModel: MediaFilesViewModel) {
 
@@ -245,18 +331,23 @@ fun ResultInfoPage(viewModel: MediaFilesViewModel) {
 
     result.value.forEach { item ->
 
-        Row(modifier = Modifier.padding(vertical = 8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
+        Row(
+            modifier = Modifier
+                .padding(vertical = 8.dp)
+                .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically
+        ) {
 
             Image(
                 imageVector = ImageVector.vectorResource(id = if (item.isFile) R.drawable.ic_icons8_file else R.drawable.ic_icons8_folder),
                 modifier = Modifier.padding(top = 8.dp, bottom = 8.dp),
-                contentDescription = null)
+                contentDescription = null
+            )
 
             Column {
                 Text(text = item.name, style = TextStyle(color = Color.Black, fontWeight = FontWeight.Bold, fontSize = 14.sp))
                 Row {
                     Text(text = DateUtils.getFormatDate(item.lastModified), fontSize = 12.sp)
-                    Text(text = item.mediaPath.toFile()?.lengthToFitMemorySize()?:"", fontSize = 12.sp)
+                    Text(text = item.mediaPath.toFile()?.lengthToFitMemorySize() ?: "", fontSize = 12.sp)
                 }
             }
 

+ 12 - 1
app/src/main/java/com/convenient/android/lib/ui/sample/media/MediaFilesViewModel.kt

@@ -11,6 +11,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.launch
 import java.io.File
+import java.util.*
+import kotlin.collections.ArrayList
 
 /**
  * @classname:
@@ -49,9 +51,17 @@ class MediaFilesViewModel(application: Application) : AndroidViewModel(applicati
         _dir.value = dir
     }
 
+    fun addConfigIgnoreChildFiles(file: File?){
+        file?.let {
+            changeConfig(copyNewConfig {
+                this.ignoreChildFiles = this.ignoreChildFiles.toMutableList().apply { add(file) }
+            })
+        }
+    }
+
     fun removeConfigIgnoreChildFiles(file : File){
         changeConfig(copyNewConfig {
-            this.ignoreChildFiles.toMutableList().apply {
+            ignoreChildFiles = ignoreChildFiles.toMutableList().apply {
                 remove(file)
             }
         })
@@ -63,6 +73,7 @@ class MediaFilesViewModel(application: Application) : AndroidViewModel(applicati
         })
     }
 
+
     private fun copyNewConfig(config: MediaQueryConfig.()-> Unit) : MediaQueryConfig{
         return _config.value.copy().also(config)
     }

+ 6 - 24
app/src/main/java/com/convenient/android/lib/ui/sample/media/MediaSampleActivity.kt

@@ -3,49 +3,31 @@ package com.convenient.android.lib.ui.sample.media
 import android.content.ContentResolver
 import android.content.ContentUris
 import android.content.Context
-import android.content.Intent
 import android.database.Cursor
 import android.net.Uri
 import android.os.Build
 import android.os.Bundle
-import android.os.Environment
 import android.os.Environment.getExternalStorageDirectory
 import android.provider.DocumentsContract
 import android.provider.MediaStore
-import android.util.Log
 import androidx.activity.compose.setContent
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.lifecycle.lifecycleScope
-import com.convenient.android.common.base.viewbinding.BaseBindingActivity
+import com.convenient.android.common.base.view.BaseActivity
 import com.convenient.android.common.config.MyPdfBaseModule
-import com.convenient.android.common.extension.*
-import com.convenient.android.common.media.MediaBean
-import com.convenient.android.common.media.config.MediaQueryConfig
-import com.convenient.android.common.media.config.MediaSortOrder
-import com.convenient.android.common.media.config.MediaSortType
-import com.convenient.android.common.media.scan.FileStore
-import com.convenient.android.common.utils.date.DateUtils
-import com.convenient.android.lib.databinding.ActivityMediaSampleBinding
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
+import com.convenient.android.lib.ui.theme.SampleTheme
 import java.io.File
 
-class MediaSampleActivity : BaseBindingActivity<ActivityMediaSampleBinding>(ActivityMediaSampleBinding::inflate) {
-
+class MediaSampleActivity : BaseActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         MyPdfBaseModule.init(application, true, "1")
         setContent {
-            MediaFilesPage()
+            SampleTheme {
+                MediaPage()
+            }
         }
-
     }
 
-
-
 }
 
 fun resolveContentUri(context: Context, uri: Uri): String {

+ 8 - 5
app/src/main/java/com/convenient/android/lib/ui/theme/Theme.kt

@@ -1,4 +1,4 @@
-package com.kdanmobile.jetpackcompose.sample.ui.theme
+package com.convenient.android.lib.ui.theme
 
 import android.app.Activity
 import android.os.Build
@@ -15,7 +15,6 @@ import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalView
 import androidx.core.view.ViewCompat
-import com.convenient.android.lib.ui.theme.*
 
 private val DarkColorScheme = darkColorScheme(
     primary = Purple80,
@@ -24,10 +23,14 @@ private val DarkColorScheme = darkColorScheme(
 )
 
 private val LightColorScheme = lightColorScheme(
-    primary = OnPrimaryColor,
-    onPrimary = OnPrimaryColor,
+    primary = Purple80,
+    onPrimary = PurpleGrey80,
     secondary = PurpleGrey40,
     tertiary = Pink40,
+    primaryContainer = Purple80,
+    onPrimaryContainer = Purple80,
+    secondaryContainer = Purple80,
+    tertiaryContainer = Purple80
 )
 
 @Composable
@@ -49,7 +52,7 @@ fun SampleTheme(
     val view = LocalView.current
     if (!view.isInEditMode) {
         SideEffect {
-            (view.context as Activity).window.statusBarColor = statusBarColor.toArgb()
+            (view.context as Activity).window.statusBarColor = Purple80.toArgb()
             ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
         }
     }

File diff suppressed because it is too large
+ 0 - 30
app/src/main/res/drawable-v24/ic_launcher_foreground.xml


+ 23 - 0
app/src/main/res/drawable/ic_launcher_foreground.xml

@@ -0,0 +1,23 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+  <group android:scaleX="0.6075"
+      android:scaleY="0.6075"
+      android:translateX="24.84"
+      android:translateY="24.84">
+    <path
+        android:pathData="M22.457,59.78c-3.889,3.89 -5.173,19.37 -5.173,19.37s15.443,-1.397 19.332,-5.286c3.89,-3.889 3.89,-10.232 -0.075,-14.121 -3.851,-3.927 -10.157,-3.89 -14.084,0.038z"
+        android:fillColor="#F86734"/>
+    <path
+        android:pathData="M55.949,19.266l21.484,-3.058a2.403,2.403 0,0 1,2.719 2.718L77.13,40.448 55.949,19.266z"
+        android:fillColor="#063042"/>
+    <path
+        android:pathData="M51.229,28.894l-13.216,0.076c-0.528,0 -1.019,0.189 -1.397,0.566L26.535,39.618c-1.246,1.246 -0.378,3.398 1.435,3.398h9.213l14.084,-14.084 -0.038,-0.038zM67.465,45.13l-0.076,13.216a1.94,1.94 0,0 1,-0.566 1.397L56.742,69.824c-1.246,1.246 -3.399,0.378 -3.399,-1.435l0.038,-9.175L67.465,45.13z"
+        android:fillColor="#3DDC84"/>
+    <path
+        android:pathData="M39.94,74.015L22.381,56.458a2.53,2.53 0,0 1,0 -3.625l33.567,-33.567L77.13,40.448 43.6,73.978c-1.019,1.02 -2.68,1.02 -3.662,0.037z"
+        android:fillColor="#063042"/>
+  </group>
+</vector>

+ 0 - 5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@drawable/ic_launcher_background" />
-    <foreground android:drawable="@drawable/ic_launcher_foreground" />
-</adaptive-icon>

+ 0 - 5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@drawable/ic_launcher_background" />
-    <foreground android:drawable="@drawable/ic_launcher_foreground" />
-</adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp


+ 2 - 10
app/src/main/res/values-night/themes.xml

@@ -1,16 +1,8 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Base application theme. -->
-    <style name="Theme.Lib" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+    <style name="Theme.Lib" parent="Theme.MaterialComponents.DayNight.NoActionBar">
         <!-- Primary brand color. -->
-        <item name="colorPrimary">@color/purple_200</item>
-        <item name="colorPrimaryVariant">@color/purple_700</item>
-        <item name="colorOnPrimary">@color/black</item>
-        <!-- Secondary brand color. -->
-        <item name="colorSecondary">@color/teal_200</item>
-        <item name="colorSecondaryVariant">@color/teal_200</item>
-        <item name="colorOnSecondary">@color/black</item>
-        <!-- Status bar color. -->
-        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
+
         <!-- Customize your theme here. -->
     </style>
 </resources>

+ 1 - 5
app/src/main/res/values/colors.xml

@@ -1,10 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <color name="purple_200">#FFBB86FC</color>
-    <color name="purple_500">#FF6200EE</color>
-    <color name="purple_700">#FF3700B3</color>
-    <color name="teal_200">#FF03DAC5</color>
-    <color name="teal_700">#FF018786</color>
     <color name="black">#FF000000</color>
     <color name="white">#FFFFFFFF</color>
+
 </resources>

+ 4 - 0
app/src/main/res/values/ic_launcher_background.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="ic_launcher_background">#B0E2DA</color>
+</resources>

+ 1 - 1
app/src/main/res/values/strings.xml

@@ -1,3 +1,3 @@
 <resources>
-    <string name="app_name">Lib</string>
+    <string name="app_name">组件库</string>
 </resources>

+ 2 - 9
app/src/main/res/values/themes.xml

@@ -1,16 +1,9 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Base application theme. -->
-    <style name="Theme.Lib" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+    <style name="Theme.Lib" parent="Theme.MaterialComponents.Light.NoActionBar">
         <!-- Primary brand color. -->
-        <item name="colorPrimary">@color/purple_500</item>
-        <item name="colorPrimaryVariant">@color/purple_700</item>
-        <item name="colorOnPrimary">@color/white</item>
-        <!-- Secondary brand color. -->
-        <item name="colorSecondary">@color/teal_200</item>
-        <item name="colorSecondaryVariant">@color/teal_700</item>
-        <item name="colorOnSecondary">@color/black</item>
+
         <!-- Status bar color. -->
-        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
         <!-- Customize your theme here. -->
     </style>
 

+ 1 - 3
lib_common/src/main/AndroidManifest.xml

@@ -3,9 +3,7 @@
     package="com.convenient.android.common">
 
     <application>
-        <activity
-            android:name=".BaseActivity"
-            android:exported="false" />
+
     </application>
 
 </manifest>

+ 3 - 2
lib_common/src/main/java/com/convenient/android/common/media/scan/FileStore.kt

@@ -31,9 +31,10 @@ object FileStore : Query {
      *
      */
     override fun query(dir: String, config: MediaQueryConfig): List<MediaBean> {
-        val dirFile = if (dir.isEmpty()) Environment.getExternalStorageDirectory() else dir.toFile()
+        val dirFile = if (dir.isEmpty()) Environment.getExternalStorageDirectory() else "${dir}/".toFile()
 
 
+        val f = dirFile?.listFiles()
         val files: List<File> = dirFile?.listFilesInDirWithFilter(recursively = config.recursively, accept = {
 
             if (it.absolutePath.equals(dir)) {
@@ -52,7 +53,7 @@ object FileStore : Query {
                 return@listFilesInDirWithFilter false
             }
             //如果没有指定需要的文件格式,则全部返回
-            if (config.supportMimeTypes.isEmpty() || (config.supportMimeTypes.size == 1 && config.supportMimeTypes[0].isEmpty())) {
+            if (config.supportMimeTypes.isEmpty()) {
                 true
             } else {
                 config.supportMimeTypes.contains(it.extension.lowercase())