commit ca7bdc04f8016be45c47f75fb5f1d7882b3e53e1 Author: 15102926882 <1090599600@qq.com> Date: Fri May 8 01:16:27 2026 +0800 提交验收用的doc和src目录 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..b3405b3 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +My Application \ No newline at end of file diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..7643783 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,123 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..ca16a99 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml new file mode 100644 index 0000000..91f9558 --- /dev/null +++ b/.idea/deviceManager.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..38a70eb --- /dev/null +++ b/README.md @@ -0,0 +1,102 @@ +# 小米便签项目分工方案 + +## 项目成员分工 + +| 姓名 | 负责模块 | 文件路径 | +|------|----------|----------| +| 张仕杰 | Data层(数据访问) | `app/src/main/java/com/example/myapplication/data/` 目录下所有文件 | +| 李琦 | ViewModel层(业务逻辑) | `app/src/main/java/com/example/myapplication/viewmodel/NoteViewModel.kt` | +| 张宇航 | UI层(界面展示) | `app/src/main/java/com/example/myapplication/ui/` 目录下所有文件 | +| 孟欣瑞 | 主题和入口(UI主题+MainActivity) | `app/src/main/java/com/example/myapplication/ui/theme/` 目录下所有文件 + `app/src/main/java/com/example/myapplication/MainActivity.kt` | + +## Git分支管理方案 + +### 分支命名规则 +- 张仕杰:`zhang-shijie-data` +- 李琦:`li-qi-viewmodel` +- 张宇航:`zhang-yuhang-ui` +- 孟欣瑞:`meng-xinrui-theme` + +### Git操作步骤(以张仕杰为例) + +```bash +# 1. 切换到张仕杰的分支 +git checkout zhang-shijie-data + +# 2. 添加Data层相关文件 +git add app/src/main/java/com/example/myapplication/data/Note.kt +git add app/src/main/java/com/example/myapplication/data/NoteDao.kt +git add app/src/main/java/com/example/myapplication/data/NoteDatabase.kt +git add app/src/main/java/com/example/myapplication/data/NoteRepository.kt + +# 3. 提交 +git commit -m "张仕杰完成:Note、NoteDao、Database、Repository 共约200行" + +# 4. 推送 +git push origin zhang-shijie-data +``` + +### 李琦的Git操作步骤 + +```bash +# 1. 切换到李琦的分支 +git checkout li-qi-viewmodel + +# 2. 添加ViewModel层相关文件 +git add app/src/main/java/com/example/myapplication/viewmodel/NoteViewModel.kt + +# 3. 提交 +git commit -m "李琦完成:NoteViewModel 共约160行" + +# 4. 推送 +git push origin li-qi-viewmodel +``` + +### 张宇航的Git操作步骤 + +```bash +# 1. 切换到张宇航的分支 +git checkout zhang-yuhang-ui + +# 2. 添加UI层相关文件 +git add app/src/main/java/com/example/myapplication/ui/NoteListScreen.kt +git add app/src/main/java/com/example/myapplication/ui/NoteEditorScreen.kt +git add app/src/main/java/com/example/myapplication/ui/NoteItem.kt + +# 3. 提交 +git commit -m "张宇航完成:NoteListScreen、NoteEditorScreen、NoteItem 共约350行" + +# 4. 推送 +git push origin zhang-yuhang-ui +``` + +### 孟欣瑞的Git操作步骤 + +```bash +# 1. 切换到孟欣瑞的分支 +git checkout meng-xinrui-theme + +# 2. 添加主题和MainActivity相关文件 +git add app/src/main/java/com/example/myapplication/ui/theme/Color.kt +git add app/src/main/java/com/example/myapplication/ui/theme/Theme.kt +git add app/src/main/java/com/example/myapplication/ui/theme/Type.kt +git add app/src/main/java/com/example/myapplication/MainActivity.kt + +# 3. 提交 +git commit -m "孟欣瑞完成:Color、Theme、Type、MainActivity 共约280行" + +# 4. 推送 +git push origin meng-xinrui-theme +``` + +## 合并流程 +1. 每位成员在自己的分支上完成开发 +2. 创建Pull Request,请求合并到`main`分支 +3. 团队成员进行代码审查 +4. 审查通过后合并到`main`分支 + +## 注意事项 +- 所有代码注释已添加负责人信息 +- 请确保每次提交前运行`./gradlew build`验证构建成功 +- 遵循Kotlin编码规范和Android最佳实践 +- 如遇冲突,请及时沟通解决 \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..0010c6f --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,74 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.ksp) + alias(libs.plugins.compose.compiler) +} + +android { + namespace = "com.example.myapplication" + compileSdk = 35 + + defaultConfig { + applicationId = "com.example.myapplication" + minSdk = 24 + targetSdk = 35 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + compose = true + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + + // Compose + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation.fragment) + implementation(libs.androidx.navigation.ui) + implementation(libs.androidx.lifecycle.viewmodel.compose) + + // Room + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + ksp(libs.androidx.room.compiler) + + // Testing + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..e9283cf --- /dev/null +++ b/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.myapplication + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.myapplication", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..db74694 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/example/myapplication/MainActivity.kt b/app/src/main/java/com/example/myapplication/MainActivity.kt new file mode 100644 index 0000000..956c8a4 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/MainActivity.kt @@ -0,0 +1,76 @@ +package com.example.myapplication + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.viewModels +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.ui.Modifier +import androidx.navigation.NavType +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument +import com.example.myapplication.ui.NoteEditorScreen +import com.example.myapplication.ui.NoteListScreen +import com.example.myapplication.ui.theme.XiaomiNoteTheme +import com.example.myapplication.viewmodel.NoteViewModel + +/** + * 小米便签主活动 - 孟欣瑞负责 + * + * 应用入口点,负责初始化 Compose UI 和导航 + * 使用 MVVM 架构,通过 ViewModel 管理业务逻辑 + */ +class MainActivity : ComponentActivity() { + + // ViewModel 实例,由 Android 自动管理生命周期 + private val viewModel: NoteViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // 使用 Compose 设置 UI + setContent { + XiaomiNoteTheme { + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + // 导航宿主 + val navController = rememberNavController() + + NavHost( + navController = navController, + startDestination = "list" + ) { + // 列表页面 + composable("list") { + NoteListScreen( + navController = navController, + viewModel = viewModel + ) + } + + // 编辑页面 + composable( + route = "editor/{noteId}", + arguments = listOf( + navArgument("noteId") { type = NavType.IntType } + ) + ) { backStackEntry -> + val noteId = backStackEntry.arguments?.getInt("noteId") ?: 0 + NoteEditorScreen( + navController = navController, + viewModel = viewModel, + noteId = noteId + ) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/data/Note.kt b/app/src/main/java/com/example/myapplication/data/Note.kt new file mode 100644 index 0000000..00855e2 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/data/Note.kt @@ -0,0 +1,34 @@ +package com.example.myapplication.data + +import androidx.room.Entity +import androidx.room.PrimaryKey + +/** + * 便签数据实体类 - 张仕杰负责 + * + * 使用 Room 的 @Entity 注解定义数据库表结构 + * 存储便签的标题、内容、创建时间和更新时间 + * + * @property id 便签的唯一标识符,自增主键 + * @property title 便签标题 + * @property content 便签内容 + * @property createTime 创建时间(毫秒时间戳) + * @property updateTime 最后更新时间(毫秒时间戳) + */ +@Entity(tableName = "notes") +data class Note( + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + + /** 便签标题 */ + val title: String = "", + + /** 便签内容 */ + val content: String = "", + + /** 创建时间(毫秒时间戳) */ + val createTime: Long = System.currentTimeMillis(), + + /** 最后更新时间(毫秒时间戳) */ + val updateTime: Long = System.currentTimeMillis() +) diff --git a/app/src/main/java/com/example/myapplication/data/NoteDao.kt b/app/src/main/java/com/example/myapplication/data/NoteDao.kt new file mode 100644 index 0000000..7e65092 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/data/NoteDao.kt @@ -0,0 +1,70 @@ +package com.example.myapplication.data + +import androidx.room.* +import kotlinx.coroutines.flow.Flow + +/** + * 便签数据访问对象(DAO) - 张仕杰负责 + * + * 定义所有与数据库交互的方法 + * 使用 Flow 实现响应式数据流,当数据库数据变化时自动更新 + */ +@Dao +interface NoteDao { + + /** + * 查询所有便签,按更新时间倒序排列 + * + * @return 返回 Flow>,当数据库变化时自动发射新数据 + */ + @Query("SELECT * FROM notes ORDER BY updateTime DESC") + fun getAllNotes(): Flow> + + /** + * 根据 ID 查询单个便签 + * + * @param noteId 便签 ID + * @return 返回 Flow,当该便签数据变化时自动更新 + */ + @Query("SELECT * FROM notes WHERE id = :noteId") + fun getNoteById(noteId: Int): Flow + + /** + * 插入新便签 + * + * @param note 要插入的便签对象 + * @return 返回新插入便签的 ID + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertNote(note: Note): Long + + /** + * 更新现有便签 + * + * @param note 要更新的便签对象 + */ + @Update + suspend fun updateNote(note: Note) + + /** + * 删除便签 + * + * @param note 要删除的便签对象 + */ + @Delete + suspend fun deleteNote(note: Note) + + /** + * 根据 ID 删除便签 + * + * @param noteId 要删除的便签 ID + */ + @Query("DELETE FROM notes WHERE id = :noteId") + suspend fun deleteNoteById(noteId: Int) + + /** + * 删除所有便签 + */ + @Query("DELETE FROM notes") + suspend fun deleteAllNotes() +} diff --git a/app/src/main/java/com/example/myapplication/data/NoteDatabase.kt b/app/src/main/java/com/example/myapplication/data/NoteDatabase.kt new file mode 100644 index 0000000..0e8f219 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/data/NoteDatabase.kt @@ -0,0 +1,56 @@ +package com.example.myapplication.data + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +/** + * 便签数据库类 - 张仕杰负责 + * + * 使用 Room 持久化库管理 SQLite 数据库 + * 采用单例模式确保整个应用只有一个数据库实例 + * + * @property noteDao 提供便签数据访问对象 + */ +@Database( + entities = [Note::class], + version = 1, + exportSchema = false +) +abstract class NoteDatabase : RoomDatabase() { + + /** + * 获取便签数据访问对象 + * + * @return NoteDao 实例,用于执行数据库操作 + */ + abstract fun noteDao(): NoteDao + + companion object { + @Volatile + private var INSTANCE: NoteDatabase? = null + + /** + * 获取数据库单例实例 + * + * 使用双重检查锁定模式确保线程安全 + * + * @param context 应用上下文 + * @return NoteDatabase 单例实例 + */ + fun getDatabase(context: Context): NoteDatabase { + return INSTANCE ?: synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + NoteDatabase::class.java, + "note_database" + ) + .fallbackToDestructiveMigration() // 数据库版本变化时销毁重建 + .build() + INSTANCE = instance + instance + } + } + } +} diff --git a/app/src/main/java/com/example/myapplication/data/NoteRepository.kt b/app/src/main/java/com/example/myapplication/data/NoteRepository.kt new file mode 100644 index 0000000..284a9db --- /dev/null +++ b/app/src/main/java/com/example/myapplication/data/NoteRepository.kt @@ -0,0 +1,73 @@ +package com.example.myapplication.data + +import kotlinx.coroutines.flow.Flow + +/** + * 便签数据仓库 - 张仕杰负责 + * + * 作为数据层的统一入口,封装所有数据操作 + * 遵循单一职责原则,只负责数据管理 + * + * @property noteDao 数据访问对象,执行实际的数据库操作 + */ +class NoteRepository(private val noteDao: NoteDao) { + + /** + * 获取所有便签列表(响应式) + * + * @return Flow> 当数据库变化时自动更新 + */ + fun getAllNotes(): Flow> = noteDao.getAllNotes() + + /** + * 根据 ID 获取单个便签(响应式) + * + * @param noteId 便签 ID + * @return Flow 当该便签变化时自动更新 + */ + fun getNoteById(noteId: Int): Flow = noteDao.getNoteById(noteId) + + /** + * 创建新便签 + * + * @param note 要创建的便签对象 + * @return 新创建便签的 ID + */ + suspend fun createNote(note: Note): Long { + return noteDao.insertNote(note) + } + + /** + * 更新现有便签 + * + * @param note 要更新的便签对象 + */ + suspend fun updateNote(note: Note) { + noteDao.updateNote(note) + } + + /** + * 删除便签 + * + * @param note 要删除的便签对象 + */ + suspend fun deleteNote(note: Note) { + noteDao.deleteNote(note) + } + + /** + * 根据 ID 删除便签 + * + * @param noteId 要删除的便签 ID + */ + suspend fun deleteNoteById(noteId: Int) { + noteDao.deleteNoteById(noteId) + } + + /** + * 删除所有便签 + */ + suspend fun deleteAllNotes() { + noteDao.deleteAllNotes() + } +} diff --git a/app/src/main/java/com/example/myapplication/ui/NoteEditorScreen.kt b/app/src/main/java/com/example/myapplication/ui/NoteEditorScreen.kt new file mode 100644 index 0000000..dd4ec39 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/NoteEditorScreen.kt @@ -0,0 +1,123 @@ +package com.example.myapplication.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.Check +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavController +import com.example.myapplication.viewmodel.NoteViewModel + +/** + * 便签编辑页面 - 张宇航负责 + * + * 用于创建新便签或编辑现有便签 + * 提供标题和内容输入框,支持保存和返回操作 + * + * @param navController 导航控制器 + * @param viewModel 便签 ViewModel + * @param noteId 便签 ID,0 表示创建新便签 + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun NoteEditorScreen( + navController: NavController, + viewModel: NoteViewModel, + noteId: Int +) { + // 收集当前编辑的便签 + val currentNote by viewModel.currentNote.collectAsStateWithLifecycle() + + // 输入框状态 + var title by remember { mutableStateOf("") } + var content by remember { mutableStateOf("") } + + // 如果是编辑现有便签,加载数据 + LaunchedEffect(noteId) { + if (noteId > 0) { + viewModel.loadNote(noteId) + } + } + + // 当加载到便签数据时,填充输入框 + LaunchedEffect(currentNote) { + currentNote?.let { note -> + title = note.title + content = note.content + } + } + + Scaffold( + topBar = { + // 顶部应用栏 + TopAppBar( + title = { Text(if (noteId > 0) "编辑便签" else "新建便签") }, + navigationIcon = { + // 返回按钮 + IconButton(onClick = { navController.popBackStack() }) { + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = "返回" + ) + } + }, + actions = { + // 保存按钮 + IconButton( + onClick = { + viewModel.saveNote(title, content, if (noteId > 0) noteId else null) + navController.popBackStack() + } + ) { + Icon( + imageVector = Icons.Default.Check, + contentDescription = "保存" + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primary, + titleContentColor = MaterialTheme.colorScheme.onPrimary, + navigationIconContentColor = MaterialTheme.colorScheme.onPrimary, + actionIconContentColor = MaterialTheme.colorScheme.onPrimary + ) + ) + } + ) { paddingValues -> + // 编辑区域 + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .padding(16.dp) + ) { + // 标题输入框 + OutlinedTextField( + value = title, + onValueChange = { title = it }, + label = { Text("标题") }, + modifier = Modifier.fillMaxWidth(), + singleLine = true, + textStyle = MaterialTheme.typography.headlineMedium + ) + + Spacer(modifier = Modifier.height(16.dp)) + + // 内容输入框 + OutlinedTextField( + value = content, + onValueChange = { content = it }, + label = { Text("内容") }, + modifier = Modifier + .fillMaxWidth() + .weight(1f), + textStyle = MaterialTheme.typography.bodyLarge, + maxLines = Int.MAX_VALUE + ) + } + } +} diff --git a/app/src/main/java/com/example/myapplication/ui/NoteItem.kt b/app/src/main/java/com/example/myapplication/ui/NoteItem.kt new file mode 100644 index 0000000..51596d7 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/NoteItem.kt @@ -0,0 +1,110 @@ +package com.example.myapplication.ui + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.example.myapplication.data.Note +import com.example.myapplication.ui.theme.TextSecondaryLight +import java.text.SimpleDateFormat +import java.util.* + +/** + * 便签列表项组件 - 张宇航负责 + * + * 显示单个便签的标题、内容预览和更新时间 + * 支持点击编辑和长按删除操作 + * + * @param note 要显示的便签数据 + * @param onClick 点击便签时的回调 + * @param onDelete 点击删除按钮时的回调 + */ +@Composable +fun NoteItem( + note: Note, + onClick: () -> Unit, + onDelete: () -> Unit +) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + .clickable(onClick = onClick), + shape = RoundedCornerShape(12.dp), + elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + // 标题和删除按钮 + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + // 便签标题 + Text( + text = if (note.title.isNotEmpty()) note.title else "无标题", + style = MaterialTheme.typography.titleLarge, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f) + ) + + // 删除按钮 + IconButton( + onClick = onDelete, + modifier = Modifier.size(32.dp) + ) { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = "删除便签", + tint = MaterialTheme.colorScheme.error + ) + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + // 内容预览 + if (note.content.isNotEmpty()) { + Text( + text = note.content, + style = MaterialTheme.typography.bodyMedium, + maxLines = 3, + overflow = TextOverflow.Ellipsis, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Spacer(modifier = Modifier.height(8.dp)) + } + + // 更新时间 + Text( + text = formatTime(note.updateTime), + style = MaterialTheme.typography.bodySmall, + color = TextSecondaryLight + ) + } + } +} + +/** + * 格式化时间戳为可读字符串 + * + * @param timestamp 毫秒时间戳 + * @return 格式化后的时间字符串 + */ +private fun formatTime(timestamp: Long): String { + val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()) + return dateFormat.format(Date(timestamp)) +} diff --git a/app/src/main/java/com/example/myapplication/ui/NoteListScreen.kt b/app/src/main/java/com/example/myapplication/ui/NoteListScreen.kt new file mode 100644 index 0000000..5aca610 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/NoteListScreen.kt @@ -0,0 +1,127 @@ +package com.example.myapplication.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import com.example.myapplication.data.Note +import com.example.myapplication.viewmodel.NoteViewModel + +/** + * 便签列表页面 - 张宇航负责 + * + * 显示所有便签的列表,支持创建新便签 + * 提供空状态提示和浮动操作按钮 + * + * @param navController 导航控制器 + * @param viewModel 便签 ViewModel + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun NoteListScreen( + navController: NavController, + viewModel: NoteViewModel +) { + // 收集便签列表状态 + val notes by viewModel.allNotes.collectAsState() + + Scaffold( + topBar = { + // 顶部应用栏 + TopAppBar( + title = { Text("小米便签") }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primary, + titleContentColor = MaterialTheme.colorScheme.onPrimary + ) + ) + }, + floatingActionButton = { + // 浮动操作按钮 - 添加新便签 + FloatingActionButton( + onClick = { + viewModel.clearCurrentNote() + navController.navigate("editor/0") + }, + containerColor = MaterialTheme.colorScheme.primary + ) { + Icon( + imageVector = Icons.Default.Add, + contentDescription = "添加新便签", + tint = MaterialTheme.colorScheme.onPrimary + ) + } + } + ) { paddingValues -> + // 主内容区域 + Box( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + ) { + if (notes.isEmpty()) { + // 空状态提示 + EmptyState() + } else { + // 便签列表 + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(vertical = 8.dp) + ) { + items(notes, key = { it.id }) { note -> + NoteItem( + note = note, + onClick = { + navController.navigate("editor/${note.id}") + }, + onDelete = { + viewModel.deleteNote(note) + } + ) + } + } + } + } + } +} + +/** + * 空状态提示组件 + * + * 当没有便签时显示提示信息 + */ +@Composable +private fun EmptyState() { + Column( + modifier = Modifier + .fillMaxSize() + .padding(32.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = "暂无便签", + style = MaterialTheme.typography.headlineMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "点击右下角按钮添加新便签", + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center + ) + } +} diff --git a/app/src/main/java/com/example/myapplication/ui/theme/Color.kt b/app/src/main/java/com/example/myapplication/ui/theme/Color.kt new file mode 100644 index 0000000..77008c3 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/theme/Color.kt @@ -0,0 +1,47 @@ +package com.example.myapplication.ui.theme + +import androidx.compose.ui.graphics.Color + +/** + * 小米便签颜色定义 - 孟欣瑞负责 + * + * 采用小米便签的经典配色方案 + * 支持亮色和暗色主题 + */ + +// 主色调 - 小米橙 +val XiaomiOrange = Color(0xFFFF6900) +val XiaomiOrangeDark = Color(0xFFFF8534) + +// 背景色 +val BackgroundLight = Color(0xFFF5F5F5) +val BackgroundDark = Color(0xFF1A1A1A) + +// 卡片背景色 +val CardBackgroundLight = Color(0xFFFFFFFF) +val CardBackgroundDark = Color(0xFF2D2D2D) + +// 文字颜色 +val TextPrimaryLight = Color(0xFF333333) +val TextPrimaryDark = Color(0xFFE0E0E0) + +val TextSecondaryLight = Color(0xFF999999) +val TextSecondaryDark = Color(0xFF999999) + +// 分割线颜色 +val DividerLight = Color(0xFFE0E0E0) +val DividerDark = Color(0xFF404040) + +// 删除按钮颜色 +val DeleteRed = Color(0xFFFF3B30) +val DeleteRedDark = Color(0xFFFF453A) + +// 便签卡片颜色(多种颜色可选) +val NoteColors = listOf( + Color(0xFFFFF9E6), // 淡黄 + Color(0xFFE6F3FF), // 淡蓝 + Color(0xFFE6FFE6), // 淡绿 + Color(0xFFFFE6F0), // 淡粉 + Color(0xFFF0E6FF), // 淡紫 + Color(0xFFFFF0E6) // 淡橙 +) diff --git a/app/src/main/java/com/example/myapplication/ui/theme/Theme.kt b/app/src/main/java/com/example/myapplication/ui/theme/Theme.kt new file mode 100644 index 0000000..9f06c15 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/theme/Theme.kt @@ -0,0 +1,107 @@ +package com.example.myapplication.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +/** + * 小米便签亮色主题配色方案 - 孟欣瑞负责 + * + * 使用小米经典的橙色作为主色调 + * 搭配清爽的浅色背景 + */ +private val LightColorScheme = lightColorScheme( + primary = XiaomiOrange, + onPrimary = CardBackgroundLight, + primaryContainer = XiaomiOrangeDark, + onPrimaryContainer = TextPrimaryLight, + secondary = XiaomiOrangeDark, + onSecondary = CardBackgroundLight, + background = BackgroundLight, + onBackground = TextPrimaryLight, + surface = CardBackgroundLight, + onSurface = TextPrimaryLight, + surfaceVariant = CardBackgroundLight, + onSurfaceVariant = TextSecondaryLight, + error = DeleteRed, + onError = CardBackgroundLight +) + +/** + * 小米便签暗色主题配色方案 - 孟欣瑞负责 + * + * 深色背景配合橙色点缀 + * 适合夜间使用 + */ +private val DarkColorScheme = darkColorScheme( + primary = XiaomiOrangeDark, + onPrimary = CardBackgroundDark, + primaryContainer = XiaomiOrange, + onPrimaryContainer = TextPrimaryDark, + secondary = XiaomiOrange, + onSecondary = CardBackgroundDark, + background = BackgroundDark, + onBackground = TextPrimaryDark, + surface = CardBackgroundDark, + onSurface = TextPrimaryDark, + surfaceVariant = CardBackgroundDark, + onSurfaceVariant = TextSecondaryDark, + error = DeleteRedDark, + onError = CardBackgroundDark +) + +/** + * 小米便签主题 - 孟欣瑞负责 + * + * 根据系统设置自动切换亮色/暗色主题 + * 支持 Android 12+ 的动态颜色 + * + * @param darkTheme 是否使用暗色主题,默认跟随系统设置 + * @param dynamicColor 是否使用动态颜色(Android 12+),默认启用 + * @param content 主题包裹的内容 + */ +@Composable +fun XiaomiNoteTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + // Android 12+ 支持动态颜色 + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + // 使用自定义配色方案 + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + // 设置状态栏颜色 + window.statusBarColor = colorScheme.primary.toArgb() + // 设置状态栏图标为浅色(暗色主题)或深色(亮色主题) + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} diff --git a/app/src/main/java/com/example/myapplication/ui/theme/Type.kt b/app/src/main/java/com/example/myapplication/ui/theme/Type.kt new file mode 100644 index 0000000..a3b1f30 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/theme/Type.kt @@ -0,0 +1,87 @@ +package com.example.myapplication.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +/** + * 小米便签字体排版定义 - 孟欣瑞负责 + * + * 定义应用中使用的各种文字样式 + * 遵循 Material Design 3 的排版规范 + */ +val Typography = Typography( + // 大标题 - 用于应用标题 + headlineLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, + fontSize = 32.sp, + lineHeight = 40.sp, + letterSpacing = 0.sp + ), + + // 中标题 - 用于便签标题 + headlineMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.SemiBold, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing = 0.sp + ), + + // 小标题 - 用于列表项标题 + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 20.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + + // 正文大 - 用于编辑框内容 + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ), + + // 正文中 - 用于普通文本 + bodyMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.25.sp + ), + + // 正文小 - 用于时间戳等辅助信息 + bodySmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.4.sp + ), + + // 标签 - 用于按钮等 + labelLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp + ), + + // 小标签 - 用于小按钮 + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) +) diff --git a/app/src/main/java/com/example/myapplication/viewmodel/NoteViewModel.kt b/app/src/main/java/com/example/myapplication/viewmodel/NoteViewModel.kt new file mode 100644 index 0000000..eafb359 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/viewmodel/NoteViewModel.kt @@ -0,0 +1,159 @@ +package com.example.myapplication.viewmodel + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.viewModelScope +import com.example.myapplication.data.Note +import com.example.myapplication.data.NoteDatabase +import com.example.myapplication.data.NoteRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +/** + * 便签 ViewModel - 李琦负责 + * + * 负责管理便签相关的业务逻辑和 UI 状态 + * 作为 View 层和 Model 层之间的桥梁 + * + * @param application 应用程序上下文 + */ +class NoteViewModel(application: Application) : AndroidViewModel(application) { + + // 数据仓库实例 + private val repository: NoteRepository + + // 所有便签列表的状态流 + private val _allNotes = MutableStateFlow>(emptyList()) + val allNotes: StateFlow> = _allNotes.asStateFlow() + + // 当前编辑的便签 + private val _currentNote = MutableStateFlow(null) + val currentNote: StateFlow = _currentNote.asStateFlow() + + // 加载状态 + private val _isLoading = MutableStateFlow(false) + val isLoading: StateFlow = _isLoading.asStateFlow() + + init { + // 初始化数据仓库 + val noteDao = NoteDatabase.getDatabase(application).noteDao() + repository = NoteRepository(noteDao) + + // 开始监听数据库变化 + observeNotes() + } + + /** + * 监听便签数据变化 + * + * 当数据库中的便签数据发生变化时,自动更新 StateFlow + */ + private fun observeNotes() { + viewModelScope.launch { + repository.getAllNotes().collect { notes -> + _allNotes.value = notes + } + } + } + + /** + * 加载指定 ID 的便签 + * + * @param noteId 便签 ID + */ + fun loadNote(noteId: Int) { + viewModelScope.launch { + repository.getNoteById(noteId).collect { note -> + _currentNote.value = note + } + } + } + + /** + * 创建新便签 + * + * @param title 便签标题 + * @param content 便签内容 + */ + fun createNote(title: String, content: String) { + viewModelScope.launch { + val note = Note( + title = title, + content = content, + createTime = System.currentTimeMillis(), + updateTime = System.currentTimeMillis() + ) + repository.createNote(note) + } + } + + /** + * 更新现有便签 + * + * @param note 要更新的便签对象 + */ + fun updateNote(note: Note) { + viewModelScope.launch { + val updatedNote = note.copy(updateTime = System.currentTimeMillis()) + repository.updateNote(updatedNote) + } + } + + /** + * 保存便签(创建或更新) + * + * @param title 便签标题 + * @param content 便签内容 + * @param noteId 如果是编辑现有便签,传入其 ID;否则传 0 或 null + */ + fun saveNote(title: String, content: String, noteId: Int? = null) { + viewModelScope.launch { + _isLoading.value = true + try { + if (noteId != null && noteId > 0) { + // 更新现有便签 + val existingNote = _currentNote.value + if (existingNote != null) { + updateNote(existingNote.copy(title = title, content = content)) + } + } else { + // 创建新便签 + createNote(title, content) + } + } finally { + _isLoading.value = false + } + } + } + + /** + * 删除便签 + * + * @param note 要删除的便签对象 + */ + fun deleteNote(note: Note) { + viewModelScope.launch { + repository.deleteNote(note) + } + } + + /** + * 根据 ID 删除便签 + * + * @param noteId 要删除的便签 ID + */ + fun deleteNoteById(noteId: Int) { + viewModelScope.launch { + repository.deleteNoteById(noteId) + } + } + + /** + * 清空当前编辑的便签 + */ + fun clearCurrentNote() { + _currentNote.value = null + } +} diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..16313e0 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..e288451 --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..c40cb36 --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,3 @@ + + 48dp + \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..d25b0f2 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml new file mode 100644 index 0000000..25d225b --- /dev/null +++ b/app/src/main/res/values-v23/themes.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml new file mode 100644 index 0000000..d73f4a3 --- /dev/null +++ b/app/src/main/res/values-w1240dp/dimens.xml @@ -0,0 +1,3 @@ + + 200dp + \ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -0,0 +1,3 @@ + + 48dp + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..c8524cd --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..125df87 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,3 @@ + + 16dp + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..9197893 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + 小米便签 + 设置 + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..f6322c2 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,12 @@ + + + + +