以下代码是我写的练习程序,更好的代码可以从这里查看:代码
生日卡片
package com.example.happybirthday
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.Image
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.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.happybirthday.ui.theme.HappyBirthdayTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingImage(
message = stringResource(R.string.happy_birthday_sam),
from = stringResource(R.string.signature_text)
)
}
}
}
}
}
@Composable
fun GreetingText(message: String,from: String,modifier: Modifier = Modifier) {
Column (verticalArrangement = Arrangement.Center, modifier = modifier){
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.CenterHorizontally)
)
}
}
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box(modifier) {
Image(
painter = image,
contentDescription = null,
contentScale = ContentScale.Crop,
alpha = 0.5F
)
GreetingText(
message = message,
from = from,
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
)
}
}
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingImage(
message = stringResource(R.string.happy_birthday_sam),
from = stringResource(R.string.signature_text)
)
}
}
strings.xml
<resources>
<string name="app_name">Happy Birthday</string>
<string name="happy_birthday_sam">Happy Birthday Sam!</string>
<string name="signature_text">From Emma</string>
</resources>
Compose 文章
package com.example.composearticle
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.composearticle.ui.theme.ComposeArticleTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
ComposeArticleTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.bg_compose_background)
Column {
Image(
painter = image,
contentDescription = null,
contentScale = ContentScale.FillWidth
)
Text(
text = "Jetpack Compose tutorial",
fontSize = 24.sp,
modifier = Modifier.padding(16.dp)
)
Text(
text = "Jetpack Compose is a modern toolkit for building native Android UI. Compose simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs.",
modifier = Modifier.padding(start = 16.dp,end=16.dp)
)
Text(
text = "In this tutorial, you build a simple UI component with declarative functions. You call Compose functions to say what elements you want and the Compose compiler does the rest. Compose is built around Composable functions. These functions let you define your app\\'s UI programmatically because they let you describe how it should look and provide data dependencies, rather than focus on the process of the UI\\'s construction, such as initializing an element and then attaching it to a parent. To create a Composable function, you add the @Composable annotation to the function name.",
modifier = Modifier.padding(16.dp)
)
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
ComposeArticleTheme {
Greeting("Android")
}
}
TaskCompleted
package com.example.taskcompleted
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.taskcompleted.ui.theme.TaskCompletedTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TaskCompletedTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.ic_task_completed)
Column(
verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
) {
Image(
painter = image,
contentDescription = null
)
Text(
text = "All tasks completed",
modifier = Modifier.padding(top = 24.dp, bottom = 8.dp),
fontWeight = FontWeight.Bold
)
Text(
text = "Nice work!",
fontSize = 16.sp
)
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
TaskCompletedTheme {
Greeting("Android")
}
}
ComposeQuadrant
package com.example.composequadrant
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.composequadrant.ui.theme.ComposeQuadrantTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
ComposeQuadrantTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
){
ComposeQuadrantApp();
}
}
}
}
}
@Composable
fun ComposeQuadrantApp() {
Column(Modifier.fillMaxWidth()) {
Row (Modifier.weight(1f)){
ComposableInfoCard(
title = stringResource(R.string.first_title),
description = stringResource(R.string.first_description),
backgroundColor = Color(0xFFEADDFF),
modifier = Modifier.weight(1f)
)
ComposableInfoCard(
title = stringResource(R.string.second_title),
description = stringResource(R.string.second_description),
backgroundColor = Color(0xFFD0BCFF),
modifier = Modifier.weight(1f)
)
}
Row(Modifier.weight(1f)) {
ComposableInfoCard(
title = stringResource(R.string.third_title),
description = stringResource(R.string.third_description),
backgroundColor = Color(0xFFB69DF8),
modifier = Modifier.weight(1f)
)
ComposableInfoCard(
title = stringResource(R.string.fourth_title),
description = stringResource(R.string.fourth_description),
backgroundColor = Color(0xFFF6EDFF),
modifier = Modifier.weight(1f)
)
}
}
}
@Composable
private fun ComposableInfoCard(
title: String,
description:String,
backgroundColor: Color,
modifier: Modifier= Modifier
){
Column(modifier = modifier
.fillMaxSize()
.background(backgroundColor)
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = title,
modifier = Modifier.padding(bottom = 16.dp),
fontWeight = FontWeight.Bold
)
Text(
text = description,
textAlign = TextAlign.Justify
)
}
}
@Preview(showBackground = true)
@Composable
fun ComposeQuadrantAppPreview() {
ComposeQuadrantTheme {
ComposeQuadrantApp()
}
}
名片应用
package com.example.businesscard
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.Image
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.businesscard.ui.theme.BusinessCardTheme
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Call
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.Icon
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BusinessCardTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Column(Modifier.fillMaxWidth().background(color = Color(0xFFCBE4CF))) {
Column(
modifier = Modifier
.weight(5f)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
val image = painterResource(R.drawable.android_logo)
Box(
modifier = Modifier
.background(Color.Black)
.width(width = 100.dp)
.height(height = 100.dp)
)
{
Image(
painter = image,
contentDescription = null,
modifier = Modifier.width(width = 100.dp)
)
}
Text(
text = "Jennifer Doe",
modifier = Modifier.padding(top = 24.dp, bottom = 8.dp),
fontSize = 48.sp
)
Text(
text = "Android Developer Extraordinaire",
fontSize = 16.sp,
color = Color(0xFF036339),
fontWeight = FontWeight.Bold
)
}
Column(
modifier = Modifier
.weight(2f)
.fillMaxSize() // 填充父容器大小
.wrapContentSize(Alignment.Center) // 在父容器中居中
) {
Row {
Icon(imageVector = Icons.Filled.Call, contentDescription = "Call", tint = Color(0xFF006633), modifier = Modifier.padding(end = 10.dp))
Text(
text = "+11(123)444 5555 666",
textAlign = TextAlign.Justify
)
}
Row {
Icon(imageVector = Icons.Filled.Share, contentDescription = "Share", tint = Color(0xFF006633),modifier = Modifier.padding(end = 10.dp))
Text(
text = "@AndroidDev"
)
}
Row {
Icon(imageVector = Icons.Filled.Email, contentDescription = "Email", tint = Color(0xFF006633),modifier = Modifier.padding(end = 10.dp))
Text(
text = "jen.joe@android.com"
)
}
}
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
BusinessCardTheme {
Greeting("Android")
}
}
创建交互式 Dice Roller 应用
package com.example.diceroller
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.diceroller.ui.theme.DiceRollerTheme
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
DiceRollerTheme {
DiceRollerApp()
}
}
}
}
@Preview
@Composable
fun DiceRollerApp(){
DiceWithButtonAndImage(modifier = Modifier
.fillMaxSize()
.wrapContentSize(Alignment.Center)
)
}
@Composable
fun DiceWithButtonAndImage(modifier: Modifier = Modifier){
var result by remember { mutableStateOf(1) }
val imageResource = when (result) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
Column (
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(painter = painterResource(imageResource), contentDescription = result.toString())
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { result = (1..6).random() }) {
Text(stringResource(R.string.roll))
}
}
}
总结
- 定义可组合函数。
- 使用组合创建布局。
- 使用
Button
可组合函数创建按钮。 - 导入
drawable
资源。 - 使用
Image
可组合函数显示图片。 - 使用可组合函数构建交互式界面。
- 使用
remember
可组合函数将组合中的对象存储到内存中。 - 使用
mutableStateOf()
函数刷新界面以创建可观察对象。
小费计算器
package com.example.calculator
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
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.safeDrawingPadding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.calculator.ui.theme.CalculatorTheme
import java.text.NumberFormat
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.text.input.KeyboardType
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContent {
CalculatorTheme {
Surface(
modifier = Modifier.fillMaxSize(),
) {
TipTimeLayout()
}
}
}
}
}
@Composable
fun TipTimeLayout() {
var amountInput by remember { mutableStateOf("") }
val amount = amountInput.toDoubleOrNull() ?: 0.0
val tip = calculateTip(amount)
Column(
modifier = Modifier
.statusBarsPadding()
.padding(horizontal = 40.dp)
.safeDrawingPadding(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = stringResource(R.string.calculate_tip),
modifier = Modifier
.padding(bottom = 16.dp, top = 40.dp)
.align(alignment = Alignment.Start)
)
EditNumberField(
value = amountInput,
onValueChange = { amountInput = it },
modifier = Modifier
.padding(bottom = 32.dp)
.fillMaxWidth()
)
Text(
text = stringResource(R.string.tip_amount, tip),
style = MaterialTheme.typography.displaySmall
)
Spacer(modifier = Modifier.height(150.dp))
}
}
/**
* Calculates the tip based on the user input and format the tip amount
* according to the local currency.
* Example would be "$10.00".
*/
private fun calculateTip(amount: Double, tipPercent: Double = 15.0): String {
val tip = tipPercent / 100 * amount
return NumberFormat.getCurrencyInstance().format(tip)
}
@Composable
fun EditNumberField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier
) {
TextField(
value = value,
onValueChange = onValueChange,
modifier = modifier,
label = { Text(stringResource(R.string.bill_amount)) },
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
}
@Preview(showBackground = true)
@Composable
fun TipTimeLayoutPreview() {
CalculatorTheme {
TipTimeLayout()
}
}
小费计算器2
package com.example.calculator
import android.os.Bundle
import androidx.compose.material3.Switch
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.calculator.ui.theme.CalculatorTheme
import java.text.NumberFormat
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContent {
CalculatorTheme {
Surface(
modifier = Modifier.fillMaxSize(),
) {
TipTimeLayout()
}
}
}
}
}
@Composable
fun TipTimeLayout() {
var roundUp by remember { mutableStateOf(false) }
var amountInput by remember { mutableStateOf("") }
val amount = amountInput.toDoubleOrNull() ?: 0.0
var tipInput by remember { mutableStateOf("") }
val tipPercent = tipInput.toDoubleOrNull() ?: 0.0
val tip = calculateTip(amount,tipPercent,roundUp)
Column(
modifier = Modifier
.statusBarsPadding()
.padding(horizontal = 40.dp)
.verticalScroll(rememberScrollState())
.safeDrawingPadding(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = stringResource(R.string.calculate_tip),
modifier = Modifier
.padding(bottom = 16.dp, top = 40.dp)
.align(alignment = Alignment.Start)
)
EditNumberField(
label = R.string.how_was_the_service,
leadingIcon = R.drawable.money,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
value = amountInput,
onValueChange = { amountInput = it },
modifier = Modifier
.padding(bottom = 32.dp)
.fillMaxWidth()
)
EditNumberField(
label = R.string.how_was_the_service,
leadingIcon = R.drawable.percent,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
value = tipInput,
onValueChange = { tipInput = it },
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth()
)
RoundTheTipRow(
roundUp = roundUp,
onRoundUpChanged = { roundUp = it },
modifier = Modifier.padding(bottom = 32.dp)
)
Text(
text = stringResource(R.string.tip_amount, tip),
style = MaterialTheme.typography.displaySmall
)
Spacer(modifier = Modifier.height(150.dp))
}
}
/**
* Calculates the tip based on the user input and format the tip amount
* according to the local currency.
* Example would be "$10.00".
*/
private fun calculateTip(
amount: Double,
tipPercent: Double = 15.0,
roundUp: Boolean): String {
var tip = tipPercent / 100 * amount
if (roundUp) {
tip = kotlin.math.ceil(tip)
}
return NumberFormat.getCurrencyInstance().format(tip)
}
@Composable
fun EditNumberField(
@StringRes label: Int,
@DrawableRes leadingIcon: Int,
keyboardOptions: KeyboardOptions,
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier
) {
TextField(
value = value,
leadingIcon = { Icon(painter = painterResource(id = leadingIcon), null) },
onValueChange = onValueChange,
modifier = modifier,
label = { Text(stringResource(label)) },
singleLine = true,
keyboardOptions = keyboardOptions
)
}
@Composable
fun RoundTheTipRow(
roundUp: Boolean,
onRoundUpChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier
.fillMaxWidth()
.size(48.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(text = stringResource(R.string.round_up_tip))
Switch(
modifier = modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.End),
checked = roundUp,
onCheckedChange = onRoundUpChanged,
)
}
}
@Preview(showBackground = true)
@Composable
fun TipTimeLayoutPreview() {
CalculatorTheme {
TipTimeLayout()
}
}
代码下载
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator.git