Skip to content

Commit 5ee3b97

Browse files
committed
feat: 输入体验优化, 支持横竖屏< TheLayout.kt, TheLayoutScopeInstance.kt >
refactor: 默认视图独立到 DefView.kt
1 parent 2d362fb commit 5ee3b97

File tree

12 files changed

+673
-278
lines changed

12 files changed

+673
-278
lines changed

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ dependencies {
5454
implementation "androidx.compose.ui:ui:$compose_version"
5555
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
5656
implementation 'androidx.compose.material3:material3:1.0.0-alpha16'
57+
implementation "androidx.compose.material:material-icons-extended:$compose_version"
58+
// 适用 compose 的系统ui控制(代码设置沉浸状态栏和导航栏)
59+
implementation 'com.google.accompanist:accompanist-systemuicontroller:0.26.1-alpha'
5760
testImplementation 'junit:junit:4.13.2'
5861
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
5962
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

app/src/main/java/io/github/kineks/composecalculator/App.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import android.annotation.SuppressLint
44
import android.app.Application
55
import android.content.Context
66

7-
class App: Application() {
7+
class App : Application() {
88

99
companion object {
1010
@SuppressLint("StaticFieldLeak")

app/src/main/java/io/github/kineks/composecalculator/Ext.kt

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ fun TextFieldValue.append(text: String,offset: Int = 0): TextFieldValue {
4444
)
4545
}
4646

47+
fun String.replaceIfEqual(oldValue: String?,newValue: String) = let {
48+
(if (it == oldValue) it.substring(
49+
0,
50+
it.lastIndex
51+
) else it) + newValue
52+
}
53+
4754
fun String.parse(): Double = this
4855
.replace("","-")
4956
.replace("×","*")
@@ -67,4 +74,25 @@ fun String.subZeroAndDot(): String {
6774
return s
6875
}
6976

70-
fun getString(@StringRes id: Int) = App.context.getString(id)
77+
fun getString(@StringRes id: Int) = App.context.getString(id)
78+
79+
val OperatorMap = mutableMapOf(
80+
Pair("+", Operator.plus),
81+
Pair("-", Operator.minus),
82+
Pair("", Operator.minus),
83+
Pair("*", Operator.times),
84+
Pair("×", Operator.times),
85+
Pair("/", Operator.div),
86+
Pair("÷", Operator.div),
87+
Pair("%", Operator.rem),
88+
Pair("=", Operator.equal),
89+
)
90+
91+
enum class Operator {
92+
plus, // + 加
93+
minus, // - 减
94+
times, // * 乘
95+
div, // / 除
96+
rem, // % 求余
97+
equal // = 等于,如果是缺省值则返回数值本身
98+
}
Lines changed: 3 additions & 255 deletions
Original file line numberDiff line numberDiff line change
@@ -1,270 +1,18 @@
11
package io.github.kineks.composecalculator
22

3-
import android.annotation.SuppressLint
43
import android.os.Bundle
54
import androidx.activity.ComponentActivity
65
import androidx.activity.compose.setContent
7-
import androidx.compose.foundation.background
8-
import androidx.compose.foundation.clickable
9-
import androidx.compose.foundation.layout.*
10-
import androidx.compose.foundation.lazy.grid.GridCells
11-
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
12-
import androidx.compose.foundation.shape.RoundedCornerShape
13-
import androidx.compose.foundation.text.KeyboardActions
14-
import androidx.compose.foundation.text.KeyboardOptions
15-
import androidx.compose.material3.*
16-
import androidx.compose.runtime.*
17-
import androidx.compose.ui.Alignment
18-
import androidx.compose.ui.ExperimentalComposeUiApi
19-
import androidx.compose.ui.Modifier
20-
import androidx.compose.ui.draw.alpha
21-
import androidx.compose.ui.graphics.Color
22-
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
23-
import androidx.compose.ui.text.TextRange
24-
import androidx.compose.ui.text.TextStyle
25-
import androidx.compose.ui.text.input.ImeAction
26-
import androidx.compose.ui.text.input.TextFieldValue
27-
import androidx.compose.ui.text.style.TextAlign
28-
import androidx.compose.ui.tooling.preview.Preview
29-
import androidx.compose.ui.unit.ExperimentalUnitApi
30-
import androidx.compose.ui.unit.TextUnit
31-
import androidx.compose.ui.unit.TextUnitType
32-
import androidx.compose.ui.unit.dp
33-
import androidx.compose.ui.zIndex
6+
import io.github.kineks.composecalculator.ui.DefaultView
347
import io.github.kineks.composecalculator.ui.theme.ComposeCalculatorTheme
35-
import io.github.kineks.composecalculator.ui.view.ColorList
36-
import io.github.kineks.composecalculator.ui.view.NumberButton
37-
import io.github.kineks.composecalculator.ui.view.OperatorButton
388

399
class MainActivity : ComponentActivity() {
4010
override fun onCreate(savedInstanceState: Bundle?) {
4111
super.onCreate(savedInstanceState)
4212
setContent {
43-
DefaultView()
44-
}
45-
}
46-
}
47-
48-
@SuppressLint("UnrememberedMutableState")
49-
@OptIn(ExperimentalMaterial3Api::class, ExperimentalUnitApi::class, ExperimentalComposeUiApi::class)
50-
@Composable
51-
fun DefaultView() {
52-
ComposeCalculatorTheme {
53-
54-
var colorDisplay by remember {
55-
mutableStateOf(false)
56-
}
57-
58-
var textFieldValue: TextFieldValue by remember {
59-
mutableStateOf(TextFieldValue())
60-
}
61-
var textFieldLabel: String by remember {
62-
mutableStateOf("")
63-
}
64-
val textFieldCursorEnabled by mutableStateOf(textFieldValue.text.isNotEmpty())
65-
66-
67-
val onClick by remember {
68-
mutableStateOf({ text: String ->
69-
textFieldLabel = ""
70-
textFieldValue = textFieldValue.append(text)
71-
})
72-
}
73-
val clearTextField by remember {
74-
mutableStateOf({
75-
textFieldValue = TextFieldValue()
76-
textFieldLabel = ""
77-
})
78-
}
79-
val setTextField: (String) -> Unit by remember {
80-
mutableStateOf({ text ->
81-
textFieldValue = TextFieldValue(
82-
text = text,
83-
selection = TextRange(text.length)
84-
)
85-
})
86-
}
87-
val startCalculatingEquations by remember {
88-
mutableStateOf({
89-
try {
90-
if (textFieldValue.text == getString(R.string.data_error)) {
91-
clearTextField()
92-
} else {
93-
textFieldLabel = textFieldValue.text
94-
setTextField(
95-
textFieldValue.text.parse().toString().subZeroAndDot()
96-
)
97-
}
98-
} catch (e: Exception) {
99-
setTextField(getString(R.string.data_error))
100-
}
101-
})
102-
}
103-
val keyboard = LocalSoftwareKeyboardController.current
104-
keyboard?.hide()
105-
106-
Box(
107-
modifier = Modifier
108-
.fillMaxSize()
109-
.background(color = MaterialTheme.colorScheme.background),
110-
contentAlignment = Alignment.TopCenter
111-
) {
112-
113-
Column(
114-
modifier = Modifier.matchParentSize(), verticalArrangement = Arrangement.Bottom
115-
) {
116-
if (colorDisplay) ColorList()
117-
118-
Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.BottomEnd) {
119-
Surface(
120-
color = MaterialTheme.colorScheme.surface,
121-
shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp),
122-
tonalElevation = 5.dp,
123-
shadowElevation = 5.dp,
124-
modifier = Modifier
125-
.fillMaxWidth()
126-
.fillMaxHeight()
127-
.padding(bottom = 50.dp)
128-
) {}
129-
TextField(
130-
value = textFieldValue,
131-
onValueChange = { textFieldValue = it },
132-
label = {
133-
Text(
134-
text = textFieldLabel,
135-
style = MaterialTheme.typography.headlineMedium,
136-
modifier = Modifier
137-
.alpha(0.8f)
138-
.clickable {
139-
if (textFieldLabel.isNotEmpty())
140-
setTextField(textFieldLabel)
141-
}
142-
)
143-
},
144-
keyboardActions = KeyboardActions(
145-
onDone = {
146-
startCalculatingEquations()
147-
}
148-
),
149-
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
150-
shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp),
151-
modifier = Modifier
152-
.fillMaxWidth()
153-
.zIndex(1f)
154-
.padding(bottom = 50.dp),
155-
textStyle = TextStyle(
156-
fontSize = TextUnit(
157-
50f + 80f / (textFieldValue.text.length / 6 + 1), TextUnitType.Sp
158-
), textAlign = TextAlign.End
159-
),
160-
colors = TextFieldDefaults.textFieldColors(
161-
textColor = MaterialTheme.colorScheme.onSurface,
162-
disabledTextColor = MaterialTheme.colorScheme.onSurface,
163-
cursorColor = if (textFieldCursorEnabled)
164-
MaterialTheme.colorScheme.primary
165-
else
166-
Color.Transparent,
167-
errorCursorColor = Color.Transparent,
168-
focusedIndicatorColor = Color.Transparent,
169-
unfocusedIndicatorColor = Color.Transparent,
170-
errorIndicatorColor = Color.Transparent,
171-
disabledIndicatorColor = Color.Transparent,
172-
focusedLeadingIconColor = Color.Transparent,
173-
unfocusedLeadingIconColor = Color.Transparent,
174-
disabledLeadingIconColor = Color.Transparent,
175-
errorLeadingIconColor = Color.Transparent,
176-
focusedTrailingIconColor = Color.Transparent,
177-
unfocusedTrailingIconColor = Color.Transparent,
178-
disabledTrailingIconColor = Color.Transparent,
179-
errorTrailingIconColor = Color.Transparent,
180-
containerColor = Color.Transparent,
181-
182-
focusedLabelColor = MaterialTheme.colorScheme.onSurface,
183-
unfocusedLabelColor = MaterialTheme.colorScheme.onSurface,
184-
disabledLabelColor = MaterialTheme.colorScheme.onSurface,
185-
errorLabelColor = MaterialTheme.colorScheme.onSurface,
186-
187-
placeholderColor = Color.Transparent,
188-
disabledPlaceholderColor = Color.Transparent
189-
)
190-
)
191-
192-
}
193-
194-
195-
LazyVerticalGrid(
196-
columns = GridCells.Fixed(4),
197-
modifier = Modifier.padding(10.dp),
198-
verticalArrangement = Arrangement.Bottom,
199-
userScrollEnabled = false
200-
) {
201-
202-
item {
203-
OperatorButton(
204-
text = "AC",
205-
color = MaterialTheme.colorScheme.onTertiary,
206-
backgroundColor = MaterialTheme.colorScheme.tertiary,
207-
tonalElevation = 40.dp
208-
) { clearTextField() }
209-
}
210-
item { OperatorButton(text = "( )", clickable = {
211-
textFieldValue = textFieldValue.append("()",-1)
212-
}) }
213-
item { OperatorButton(text = "%", clickable = onClick) }
214-
item { OperatorButton(text = "÷", clickable = onClick) }
215-
216-
item { NumberButton(text = "7", clickable = onClick) }
217-
item { NumberButton(text = "8", clickable = onClick) }
218-
item { NumberButton(text = "9", clickable = onClick) }
219-
item { OperatorButton(text = "×", clickable = onClick) }
220-
221-
item { NumberButton(text = "4", clickable = onClick) }
222-
item { NumberButton(text = "5", clickable = onClick) }
223-
item { NumberButton(text = "6", clickable = onClick) }
224-
item { OperatorButton(text = "", clickable = onClick) }
225-
226-
item { NumberButton(text = "1", clickable = onClick) }
227-
item { NumberButton(text = "2", clickable = onClick) }
228-
item { NumberButton(text = "3", clickable = onClick) }
229-
item { OperatorButton(text = "+", clickable = onClick) }
230-
231-
item {
232-
NumberButton(text = "", clickable = {
233-
when (textFieldValue.text.length) {
234-
0 -> {}
235-
1 -> clearTextField()
236-
else -> setTextField(
237-
textFieldValue.text.substring(
238-
0, textFieldValue.text.lastIndex
239-
)
240-
)
241-
}
242-
textFieldLabel = ""
243-
})
244-
}
245-
item { NumberButton(text = "0", clickable = onClick) }
246-
item { NumberButton(text = "", clickable = onClick) }
247-
item {
248-
OperatorButton(
249-
text = "=",
250-
color = MaterialTheme.colorScheme.secondaryContainer,
251-
backgroundColor = MaterialTheme.colorScheme.onSecondaryContainer,
252-
alpha = 0.95f,
253-
tonalElevation = 0.dp
254-
) {
255-
startCalculatingEquations()
256-
}
257-
}
258-
}
13+
ComposeCalculatorTheme {
14+
DefaultView()
25915
}
260-
26116
}
26217
}
26318
}
264-
265-
266-
@Preview(showBackground = true)
267-
@Composable
268-
fun DefaultPreview() {
269-
DefaultView()
270-
}

0 commit comments

Comments
 (0)