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.R
|
||||||
import com.sockenklaus.batterytracker.databinding.FragmentAddBatteryBinding
|
import com.sockenklaus.batterytracker.databinding.FragmentAddBatteryBinding
|
||||||
import com.sockenklaus.batterytracker.room.entities.Battery
|
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.BatteryTrackerTheme
|
||||||
import com.sockenklaus.batterytracker.util.validateDecimal
|
import com.sockenklaus.batterytracker.util.validateDecimal
|
||||||
|
|
||||||
@@ -58,7 +58,8 @@ class AddBatteryFragment : Fragment() {
|
|||||||
Column(
|
Column(
|
||||||
Modifier.padding(outerPadding)
|
Modifier.padding(outerPadding)
|
||||||
) {
|
) {
|
||||||
MyOutlinedTextField(
|
|
||||||
|
MyOutlinedTextFieldWithSuffix(
|
||||||
value = model.batteryName,
|
value = model.batteryName,
|
||||||
onValueChange = { value ->
|
onValueChange = { value ->
|
||||||
model.batteryName = value
|
model.batteryName = value
|
||||||
@@ -77,7 +78,7 @@ class AddBatteryFragment : Fragment() {
|
|||||||
|
|
||||||
Spacer(Modifier.size(innerPadding))
|
Spacer(Modifier.size(innerPadding))
|
||||||
|
|
||||||
MyOutlinedTextField(
|
MyOutlinedTextFieldWithSuffix(
|
||||||
value = model.declaredCapacity,
|
value = model.declaredCapacity,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
model.declaredCapacity = validateDecimal(it, model.declaredCapacity)
|
model.declaredCapacity = validateDecimal(it, model.declaredCapacity)
|
||||||
@@ -85,6 +86,7 @@ class AddBatteryFragment : Fragment() {
|
|||||||
labelId = R.string.hint_enter_declared_capacity,
|
labelId = R.string.hint_enter_declared_capacity,
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||||
leadingIcon = { Icon(Icons.Default.BatteryFull, "Icon Battery Full") },
|
leadingIcon = { Icon(Icons.Default.BatteryFull, "Icon Battery Full") },
|
||||||
|
suffix = "Ah"
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.size(outerPadding))
|
Spacer(Modifier.size(outerPadding))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import com.google.android.material.datepicker.MaterialDatePicker
|
|||||||
import com.sockenklaus.batterytracker.R
|
import com.sockenklaus.batterytracker.R
|
||||||
import com.sockenklaus.batterytracker.databinding.FragmentAddChargeBinding
|
import com.sockenklaus.batterytracker.databinding.FragmentAddChargeBinding
|
||||||
import com.sockenklaus.batterytracker.room.entities.Battery
|
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.BatteryTrackerTheme
|
||||||
import com.sockenklaus.batterytracker.ui.theme.Gray500
|
import com.sockenklaus.batterytracker.ui.theme.Gray500
|
||||||
import com.sockenklaus.batterytracker.util.validateDecimal
|
import com.sockenklaus.batterytracker.util.validateDecimal
|
||||||
@@ -121,7 +121,7 @@ class AddChargeFragment : Fragment() {
|
|||||||
|
|
||||||
Spacer(Modifier.size(innerPadding))
|
Spacer(Modifier.size(innerPadding))
|
||||||
|
|
||||||
MyOutlinedTextField(
|
MyOutlinedTextFieldWithSuffix(
|
||||||
value = model.charge,
|
value = model.charge,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
model.charge = validateDecimal(it, model.charge)
|
model.charge = validateDecimal(it, model.charge)
|
||||||
@@ -129,9 +129,10 @@ class AddChargeFragment : Fragment() {
|
|||||||
},
|
},
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||||
labelId = R.string.hint_charge,
|
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,
|
isError = model.chargeHasError,
|
||||||
helperTextId = R.string.helper_required
|
helperTextId = R.string.helper_required,
|
||||||
|
suffix = "Ah"
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.size(innerPadding))
|
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="button_save_charge">Save Charge</string>
|
||||||
<string name="date">Date</string>
|
<string name="date">Date</string>
|
||||||
<string name="charge">Charge</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="select_battery_id">Select Battery ID</string>
|
||||||
<string name="hint_enter_battery_name">Enter Battery Name</string>
|
<string name="hint_enter_battery_name">Enter Battery Name</string>
|
||||||
<string name="hint_enter_declared_capacity">Enter declared capacity</string>
|
<string name="hint_enter_declared_capacity">Enter declared capacity</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user