Fixed #7
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
package com.sockenklaus.batterytracker.ui.composables
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.TextFieldDefaults.OutlinedTextFieldDecorationBox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.takeOrElse
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.sockenklaus.batterytracker.ui.theme.Gray500
|
||||
|
||||
@Composable
|
||||
fun MyOutlinedTextFieldWithSuffix(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = MaterialTheme.shapes.small,
|
||||
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors(),
|
||||
suffix: String = "",
|
||||
helperTextId: Int? = null,
|
||||
labelId: Int
|
||||
) {
|
||||
// If color is not provided via the text style, use content color as a default
|
||||
val textColor = textStyle.color.takeOrElse {
|
||||
colors.textColor(enabled).value
|
||||
}
|
||||
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor))
|
||||
|
||||
val helperTextColor = if(isError){
|
||||
MaterialTheme.colors.error
|
||||
} else {
|
||||
Gray500
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
BasicTextField(
|
||||
value = value,
|
||||
modifier = modifier.padding(top = 8.dp)
|
||||
|
||||
.background(colors.backgroundColor(enabled).value, shape)
|
||||
.defaultMinSize(
|
||||
minWidth = TextFieldDefaults.MinWidth,
|
||||
minHeight = TextFieldDefaults.MinHeight
|
||||
),
|
||||
onValueChange = onValueChange,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = mergedTextStyle,
|
||||
cursorBrush = SolidColor(colors.cursorColor(isError).value),
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
interactionSource = interactionSource,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
OutlinedTextFieldDecorationBox(
|
||||
value = value,
|
||||
visualTransformation = visualTransformation,
|
||||
innerTextField = {
|
||||
Row {
|
||||
val alignModifier = Modifier.alignByBaseline()
|
||||
Box(alignModifier.weight(1f)){
|
||||
innerTextField()
|
||||
}
|
||||
Text(
|
||||
suffix,
|
||||
alignModifier,
|
||||
colors.trailingIconColor(enabled = enabled, isError = isError).value
|
||||
)
|
||||
}
|
||||
},
|
||||
placeholder = placeholder,
|
||||
label = { Text(stringResource(labelId)) },
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
singleLine = singleLine,
|
||||
enabled = enabled,
|
||||
isError = isError,
|
||||
interactionSource = interactionSource,
|
||||
colors = colors,
|
||||
border = {
|
||||
TextFieldDefaults.BorderBox(
|
||||
enabled,
|
||||
isError,
|
||||
interactionSource,
|
||||
colors,
|
||||
shape
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = if(helperTextId != null) stringResource(helperTextId) else "",
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = helperTextColor,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import androidx.navigation.fragment.findNavController
|
||||
import com.sockenklaus.batterytracker.R
|
||||
import com.sockenklaus.batterytracker.databinding.FragmentAddBatteryBinding
|
||||
import com.sockenklaus.batterytracker.room.entities.Battery
|
||||
import com.sockenklaus.batterytracker.ui.fragments.composables.MyOutlinedTextField
|
||||
import com.sockenklaus.batterytracker.ui.composables.MyOutlinedTextFieldWithSuffix
|
||||
import com.sockenklaus.batterytracker.ui.theme.BatteryTrackerTheme
|
||||
import com.sockenklaus.batterytracker.util.validateDecimal
|
||||
|
||||
@@ -58,7 +58,8 @@ class AddBatteryFragment : Fragment() {
|
||||
Column(
|
||||
Modifier.padding(outerPadding)
|
||||
) {
|
||||
MyOutlinedTextField(
|
||||
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = model.batteryName,
|
||||
onValueChange = { value ->
|
||||
model.batteryName = value
|
||||
@@ -77,7 +78,7 @@ class AddBatteryFragment : Fragment() {
|
||||
|
||||
Spacer(Modifier.size(innerPadding))
|
||||
|
||||
MyOutlinedTextField(
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = model.declaredCapacity,
|
||||
onValueChange = {
|
||||
model.declaredCapacity = validateDecimal(it, model.declaredCapacity)
|
||||
@@ -85,6 +86,7 @@ class AddBatteryFragment : Fragment() {
|
||||
labelId = R.string.hint_enter_declared_capacity,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||
leadingIcon = { Icon(Icons.Default.BatteryFull, "Icon Battery Full") },
|
||||
suffix = "Ah"
|
||||
)
|
||||
|
||||
Spacer(Modifier.size(outerPadding))
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.sockenklaus.batterytracker.R
|
||||
import com.sockenklaus.batterytracker.databinding.FragmentAddChargeBinding
|
||||
import com.sockenklaus.batterytracker.room.entities.Battery
|
||||
import com.sockenklaus.batterytracker.ui.fragments.composables.MyOutlinedTextField
|
||||
import com.sockenklaus.batterytracker.ui.composables.MyOutlinedTextFieldWithSuffix
|
||||
import com.sockenklaus.batterytracker.ui.theme.BatteryTrackerTheme
|
||||
import com.sockenklaus.batterytracker.ui.theme.Gray500
|
||||
import com.sockenklaus.batterytracker.util.validateDecimal
|
||||
@@ -121,7 +121,7 @@ class AddChargeFragment : Fragment() {
|
||||
|
||||
Spacer(Modifier.size(innerPadding))
|
||||
|
||||
MyOutlinedTextField(
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = model.charge,
|
||||
onValueChange = {
|
||||
model.charge = validateDecimal(it, model.charge)
|
||||
@@ -129,9 +129,10 @@ class AddChargeFragment : Fragment() {
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||
labelId = R.string.hint_charge,
|
||||
leadingIcon = { Icon(Icons.Default.BatteryChargingFull, "Icon Battery Chargin Full") },
|
||||
leadingIcon = { Icon(Icons.Default.BatteryChargingFull, "Icon Battery Charging Full") },
|
||||
isError = model.chargeHasError,
|
||||
helperTextId = R.string.helper_required
|
||||
helperTextId = R.string.helper_required,
|
||||
suffix = "Ah"
|
||||
)
|
||||
|
||||
Spacer(Modifier.size(innerPadding))
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
package com.sockenklaus.batterytracker.ui.fragments.composables
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.sockenklaus.batterytracker.ui.theme.Gray500
|
||||
|
||||
@Composable
|
||||
fun MyOutlinedTextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
labelId: Int,
|
||||
leadingIcon: (@Composable () -> Unit)? = null,
|
||||
trailingIcon: (@Composable () -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
helperTextId: Int? = null,
|
||||
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
|
||||
) {
|
||||
val helperTextColor = if(isError){
|
||||
MaterialTheme.colors.error
|
||||
} else {
|
||||
Gray500
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
keyboardOptions = keyboardOptions,
|
||||
label = { Text(stringResource(labelId)) },
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
isError = isError,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = colors
|
||||
)
|
||||
Text(
|
||||
text = if(helperTextId != null) stringResource(helperTextId) else "",
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = helperTextColor,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MyOutlinedTextField(
|
||||
value: TextFieldValue,
|
||||
onValueChange: (TextFieldValue) -> Unit,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
labelId: Int,
|
||||
leadingIcon: (@Composable () -> Unit)? = null,
|
||||
trailingIcon: (@Composable () -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
helperTextId: Int? = null,
|
||||
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
|
||||
) {
|
||||
val helperTextColor = if(isError){
|
||||
MaterialTheme.colors.error
|
||||
} else {
|
||||
Gray500
|
||||
}
|
||||
Column() {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
keyboardOptions = keyboardOptions,
|
||||
label = { Text(stringResource(labelId)) },
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
isError = isError,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = colors
|
||||
)
|
||||
Text(
|
||||
text = if(helperTextId != null) stringResource(helperTextId) else "",
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = helperTextColor,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<string name="button_save_charge">Save Charge</string>
|
||||
<string name="date">Date</string>
|
||||
<string name="charge">Charge</string>
|
||||
<string name="hint_charge">Enter Charge in Ah</string>
|
||||
<string name="hint_charge">Enter Charge</string>
|
||||
<string name="select_battery_id">Select Battery ID</string>
|
||||
<string name="hint_enter_battery_name">Enter Battery Name</string>
|
||||
<string name="hint_enter_declared_capacity">Enter declared capacity</string>
|
||||
|
||||
Reference in New Issue
Block a user