基本视图完成,引入ObjectBox 还没有完成
parent
fce70dcda8
commit
783d2921f0
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("io.objectbox")
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
@ -67,5 +68,14 @@ dependencies {
|
|||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||
|
||||
// google fonts 感觉有些字体用不了
|
||||
implementation("androidx.compose.ui:ui-text-google-fonts:1.6.1")
|
||||
|
||||
// implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
|
||||
// implementation("androidx.compose.runtime:runtime-livedata:1.7.0")
|
||||
// implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
||||
|
||||
// view model
|
||||
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:name=".WeightTrackApp"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
|
|
|||
|
|
@ -1,30 +1,42 @@
|
|||
package com.eacenic.weighttrack
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
|
|
@ -32,18 +44,22 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.eacenic.weighttrack.ui.theme.WeightTrackTheme
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContent {
|
||||
WeightTrackTheme {
|
||||
// A surface container using the 'background' color from the theme
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
|
|
@ -55,73 +71,93 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WeightTrackLayout() {
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
@SuppressLint("StateFlowValueCalledInComposition")
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Composable
|
||||
fun WeightTrackLayout(
|
||||
weightTrackViewModel: WeightTrackViewModel = viewModel()
|
||||
) {
|
||||
val weightRecords by weightTrackViewModel.historyData.collectAsState()
|
||||
|
||||
var openBottomSheet by rememberSaveable { mutableStateOf(false) }
|
||||
var bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = Color.Gray
|
||||
color = Color.White
|
||||
) {
|
||||
Column {
|
||||
Row {
|
||||
CurrentWeight()
|
||||
}
|
||||
Button(onClick = {
|
||||
openBottomSheet = true
|
||||
}) {
|
||||
Text(text = "添加")
|
||||
}
|
||||
}
|
||||
|
||||
if (openBottomSheet) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { openBottomSheet = false },
|
||||
sheetState = bottomSheetState
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 20.dp)
|
||||
) {
|
||||
CurrentWeight(62.6f, Modifier.padding(top = 20.dp))
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxHeight(0.9f)
|
||||
) {
|
||||
Row {
|
||||
Button(
|
||||
onClick = {
|
||||
scope.launch { bottomSheetState.hide() }.invokeOnCompletion {
|
||||
if (!bottomSheetState.isVisible) {
|
||||
openBottomSheet = false
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(text = "关闭")
|
||||
}
|
||||
this.items(weightRecords) {
|
||||
// Text(text = "${it.weight}")
|
||||
WeightRecordItem(weightRecord = it)
|
||||
}
|
||||
}
|
||||
EditButton(onClick = { openBottomSheet = true })
|
||||
}
|
||||
|
||||
BottomSheetEditor(
|
||||
expandBottomSheet = openBottomSheet,
|
||||
onDismiss = {
|
||||
openBottomSheet = false
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Composable
|
||||
fun CurrentWeight() {
|
||||
Row (
|
||||
fun WeightRecordItem(weightRecord: WeightRecord) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(vertical = 5.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "${weightRecord.weight}",
|
||||
modifier = Modifier.align(Alignment.CenterStart),
|
||||
fontFamily = doodleShadowFontFamily,
|
||||
fontSize = 36.sp,
|
||||
)
|
||||
Text(
|
||||
text = dateTimeFormatter.format(weightRecord.date),
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
fontFamily = doodleShadowFontFamily,
|
||||
fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CurrentWeight(
|
||||
currentWeight: Float,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Row (
|
||||
modifier = modifier
|
||||
.wrapContentHeight()
|
||||
.padding(20.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(0.9f)
|
||||
.fillMaxWidth()
|
||||
.height(120.dp)
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(Color.Cyan)
|
||||
|
||||
) {
|
||||
Text(
|
||||
text = "62.6",
|
||||
text = "$currentWeight",
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
fontSize = 80.sp,
|
||||
fontFamily = doodleShadowFontFamily
|
||||
|
|
@ -129,3 +165,115 @@ fun CurrentWeight() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EditButton(
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
) {
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.height(48.dp)
|
||||
.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(5.dp),
|
||||
colors = ButtonDefaults.buttonColors(Color.Cyan),
|
||||
onClick = onClick,
|
||||
) {
|
||||
Text(text = "ADD", color = Color.Black, fontSize = 36.sp, fontFamily = doodleShadowFontFamily)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun BottomSheetEditor(
|
||||
expandBottomSheet: Boolean = false,
|
||||
onDismiss: () -> Unit,
|
||||
weightTrackViewModel: WeightTrackViewModel = viewModel()
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
var text by remember { mutableStateOf("") }
|
||||
var clickable by remember { mutableStateOf(false) }
|
||||
|
||||
if (expandBottomSheet) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = onDismiss,
|
||||
sheetState = bottomSheetState
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.wrapContentHeight()
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = text,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onValueChange = {
|
||||
val newVal = it.toFloatOrNull()
|
||||
if ((it.isNotEmpty() && newVal == null) || (newVal !=null && newVal > 1000f)) {
|
||||
Toast.makeText(context, "只能输入数字,且要求数字小于1000", Toast.LENGTH_SHORT).show()
|
||||
return@OutlinedTextField
|
||||
}
|
||||
text = it
|
||||
clickable = text.isNotEmpty()
|
||||
},
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier
|
||||
.height(20.dp)
|
||||
.fillMaxWidth())
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
scope.launch { bottomSheetState.hide() }.invokeOnCompletion {
|
||||
if (!bottomSheetState.isVisible) {
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(text = "CANCEL", fontSize = 18.sp, fontFamily = doodleShadowFontFamily)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(60.dp))
|
||||
Button(
|
||||
onClick = {
|
||||
Toast.makeText(context, "save weight", Toast.LENGTH_SHORT).show()
|
||||
weightTrackViewModel.addWeightRecord(WeightRecord(text.toFloat(), LocalDateTime.now()))
|
||||
text = ""
|
||||
onDismiss()
|
||||
},
|
||||
enabled = clickable
|
||||
) {
|
||||
Text(text = "CONFIRM", fontSize = 18.sp, fontFamily = doodleShadowFontFamily)
|
||||
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier
|
||||
.height(40.dp)
|
||||
.fillMaxWidth())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.eacenic.weighttrack
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity
|
||||
data class WeightRecord(
|
||||
@Id
|
||||
var id: Long = 0,
|
||||
var weight: Float,
|
||||
var date: LocalDateTime,
|
||||
var isDeleted: Boolean = false
|
||||
)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.eacenic.weighttrack
|
||||
|
||||
import android.app.Application
|
||||
|
||||
class WeightTrackApp: Application() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.eacenic.weighttrack
|
||||
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.lifecycle.ViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import java.time.LocalDateTime
|
||||
|
||||
const val TAG = "WeightTrackViewModel"
|
||||
class WeightTrackViewModel: ViewModel() {
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private var _historyData = MutableStateFlow<List<WeightRecord>>(mutableListOf<WeightRecord>(
|
||||
WeightRecord(62.6f, LocalDateTime.now()),
|
||||
WeightRecord(63.6f, LocalDateTime.now()),
|
||||
WeightRecord(65.6f, LocalDateTime.now())
|
||||
))
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
val historyData: StateFlow<List<WeightRecord>> = _historyData
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
fun addWeightRecord(newRecord: WeightRecord) {
|
||||
val newRecords = _historyData.value.toMutableList()
|
||||
newRecords.add(newRecord)
|
||||
_historyData.value = newRecords
|
||||
Log.e(TAG, "$newRecord")
|
||||
Log.e(TAG, "${_historyData.value}")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,13 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("io.objectbox:objectbox-gradle-plugin:3.8.0")
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("com.android.application") version "8.2.2" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
|
||||
|
|
|
|||
Loading…
Reference in New Issue