Android Unit Converter

简介

本文将介绍一个基于 Jetpack Compose 的 Android 应用,该应用能够帮助用户在不同的单位之间进行转换。我们将深入了解该应用的实现细节以及使用的关键组件和概念。

实现界面

首先,让我们创建一个 UnitConverter 组件。该组件将负责显示应用的界面和处理用户输入。

UnitConverter 组件中,我们将使用 ColumnRow 布局来排列组件。在界面的顶部,我们将显示一个标题,用于向用户说明该应用是一个单位转换器。

接下来,我们将添加一个输入框,用于用户输入要转换的值。我们将使用 Jetpack Compose 的 OutlinedTextField 组件实现此输入框,并通过绑定一个变量来跟踪用户输入的值。

在输入框下方,我们将添加两个下拉框。一个用于选择输入单位,另一个用于选择输出单位。我们将使用 Jetpack Compose 的 ButtonDropdownMenu 组件实现这些下拉框。当用户选择单位时,我们将更新相应的状态,并触发单位转换逻辑。

最后,我们将在界面底部显示转换结果。我们将使用 Jetpack Compose 的 Text 组件来显示转换后的值,并在文本中指明所选择的输入和输出单位。

单位转换逻辑

UnitConverter 组件中,我们将定义一些状态变量来跟踪用户输入和选择的单位。每当用户输入值或选择单位时,我们将更新相应的状态变量,并触发单位转换逻辑。

单位转换的逻辑非常简单。我们将获取用户输入的值,并将其乘以输入单位和输出单位之间的转换系数,从而得到转换后的结果。然后,我们将在界面上显示这个结果。

应用展示

代码

完整的代码示例可以在 GitHub 上找到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package com.samsung.unitconverter

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
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.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
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.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.samsung.unitconverter.ui.theme.UnitConverterTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
UnitConverterTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
UnitConverter()
}
}
}
}
}

@Composable
fun UnitConverter() {

var inputValue by remember{ mutableStateOf("1") }
var outputValue by remember{ mutableStateOf("1") }
var inputUnit by remember{ mutableStateOf("Meters") }
var outputUnit by remember{ mutableStateOf("Meters") }
// DropdownMenu(left input) should be expanded or not expanded
var iExpanded by remember{ mutableStateOf(false) }
var oExpanded by remember{ mutableStateOf(false) }
// 100cm * 0.01 = 1m
val iConversionFactor = remember{ mutableStateOf(1.0) }
val oConversionFactor = remember{ mutableStateOf(1.0) }

fun converUnits() {
// elvis operator: if value is null or not a number -> 0.0 else value.toDouble()
val inputValueDouble = inputValue.toDoubleOrNull() ?: 0.0
val result = inputValueDouble * iConversionFactor.value / oConversionFactor.value
outputValue = result.toString()
}

Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Unit Converter", style = MaterialTheme.typography.headlineLarge)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = inputValue,
onValueChange = {
// it means whatever you type on the TextField
inputValue = it
converUnits()
},
// description
label = { Text(text = "Enter Value")})
Spacer(modifier = Modifier.height(16.dp))

Row {
// input box
Box {
Button(onClick = { iExpanded = true }) {
Text("Select")
Icon(Icons.Default.ArrowDropDown,
contentDescription = "Arrow Down")
}
DropdownMenu(expanded = iExpanded,
// 点击下拉菜单外的区域触发
onDismissRequest = { iExpanded = false }) {
DropdownMenuItem(text = { Text("Centimeters") },
onClick = {
iExpanded = false
inputUnit = "Centimeters"
iConversionFactor.value = 0.01
converUnits()
})
DropdownMenuItem(text = { Text("Meters") },
onClick = {
iExpanded = false
inputUnit = "Meters"
iConversionFactor.value = 1.0
converUnits()
})
DropdownMenuItem(text = { Text("Feets") },
onClick = {
iExpanded = false
inputUnit = "Feets"
iConversionFactor.value = 0.3048
converUnits()
})
DropdownMenuItem(text = { Text("Mil继续:

```kotlin
DropdownMenuItem(text = { Text("Milimeters") },
onClick = {
iExpanded = false
inputUnit = "Milimeters"
iConversionFactor.value = 0.001
converUnits()
})
}

}
Spacer(modifier = Modifier.width(16.dp))
// output box
Box {
Button(onClick = { oExpanded = true }) {
Text("Select")
Icon(Icons.Default.ArrowDropDown,
contentDescription = "Arrow Down")
}
DropdownMenu(expanded = oExpanded, onDismissRequest = { oExpanded = false }) {
DropdownMenuItem(text = { Text("Centimeters") },
onClick = {
oExpanded = false
outputUnit = "Centimeters"
oConversionFactor.value = 0.01
converUnits()
})
DropdownMenuItem(text = { Text("Meters") },
onClick = {
oExpanded = false
outputUnit = "Meters"
oConversionFactor.value = 1.0
converUnits()
})
DropdownMenuItem(text = { Text("Feets") },
onClick = {
oExpanded = false
outputUnit = "Feets"
oConversionFactor.value = 0.3048
converUnits()
})
DropdownMenuItem(text = { Text("Milimeters") },
onClick = {
oExpanded = false
outputUnit = "Milimeters"
oConversionFactor.value = 0.001
converUnits()
})
}
}
}
Spacer(modifier = Modifier.height(16.dp))
Text("${inputValue} ${inputUnit} = ${outputValue} ${outputUnit}", style = MaterialTheme.typography.headlineMedium)
}

}

@Preview
@Composable
fun UnitConverterPreview() {
UnitConverter()
}

Android Unit Converter
https://leopol1d.github.io/2024/01/27/Android-Unit-Converter/
作者
Leopold
发布于
2024年1月27日
许可协议