Rebuild unit converter in Jetpack Compose
This commit is contained in:
parent
89a2754eaf
commit
120bca4b39
@ -109,8 +109,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.bundles.materialdialogs)
|
implementation(libs.bundles.materialdialogs)
|
||||||
|
|
||||||
implementation(libs.bundles.groupie)
|
|
||||||
|
|
||||||
implementation(libs.draglinearlayout)
|
implementation(libs.draglinearlayout)
|
||||||
implementation(libs.viewpropertyobjectanimator)
|
implementation(libs.viewpropertyobjectanimator)
|
||||||
|
|
||||||
|
|||||||
@ -100,13 +100,6 @@ val OpenSourceLicenses = arrayOf(
|
|||||||
copyrightNote = "Copyright (C) 2020 Wasabeef",
|
copyrightNote = "Copyright (C) 2020 Wasabeef",
|
||||||
url = "https://github.com/afollestad/material-dialogs"
|
url = "https://github.com/afollestad/material-dialogs"
|
||||||
),
|
),
|
||||||
OpenSourceLibrary(
|
|
||||||
name = "Groupie",
|
|
||||||
description = "Groupie is a simple, flexible library for complex RecyclerView layouts.",
|
|
||||||
licenseName = R.string.mit_license_name,
|
|
||||||
licenseText = R.raw.license_mit,
|
|
||||||
url = "https://github.com/lisawray/groupie"
|
|
||||||
),
|
|
||||||
OpenSourceLibrary(
|
OpenSourceLibrary(
|
||||||
name = "DragLinearLayout",
|
name = "DragLinearLayout",
|
||||||
description = "An Android LinearLayout that supports draggable and swappable child Views",
|
description = "An Android LinearLayout that supports draggable and swappable child Views",
|
||||||
|
|||||||
@ -321,21 +321,6 @@ dependencyResolutionManagement {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
version("groupie", "2.8.0")
|
|
||||||
alias("groupie.core")
|
|
||||||
.to("com.xwray", "groupie")
|
|
||||||
.versionRef("groupie")
|
|
||||||
alias("groupie.ktx")
|
|
||||||
.to("com.xwray", "groupie-kotlin-android-extensions")
|
|
||||||
.versionRef("groupie")
|
|
||||||
bundle(
|
|
||||||
"groupie",
|
|
||||||
listOf(
|
|
||||||
"groupie.core",
|
|
||||||
"groupie.ktx"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
alias("draglinearlayout")
|
alias("draglinearlayout")
|
||||||
.to("com.jmedeisis", "draglinearlayout")
|
.to("com.jmedeisis", "draglinearlayout")
|
||||||
.version("1.1.0")
|
.version("1.1.0")
|
||||||
|
|||||||
@ -71,7 +71,6 @@ dependencies {
|
|||||||
implementation(libs.glide)
|
implementation(libs.glide)
|
||||||
implementation(libs.draglinearlayout)
|
implementation(libs.draglinearlayout)
|
||||||
implementation(libs.lottie.core)
|
implementation(libs.lottie.core)
|
||||||
implementation(libs.bundles.groupie)
|
|
||||||
implementation(libs.glidetransformations)
|
implementation(libs.glidetransformations)
|
||||||
|
|
||||||
implementation(libs.accompanist.insets)
|
implementation(libs.accompanist.insets)
|
||||||
|
|||||||
@ -1,49 +1,37 @@
|
|||||||
package de.mm20.launcher2.ui.legacy.component
|
package de.mm20.launcher2.ui.legacy.component
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.text.SpannableStringBuilder
|
|
||||||
import android.text.Spanned
|
|
||||||
import android.text.method.LinkMovementMethod
|
|
||||||
import android.text.style.ClickableSpan
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.browser.customtabs.CustomTabsIntent
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.material3.LocalContentColor
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
|
||||||
import com.xwray.groupie.ExpandableGroup
|
|
||||||
import com.xwray.groupie.ExpandableItem
|
|
||||||
import com.xwray.groupie.GroupAdapter
|
|
||||||
import com.xwray.groupie.Section
|
|
||||||
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
|
|
||||||
import com.xwray.groupie.kotlinandroidextensions.Item
|
|
||||||
import de.mm20.launcher2.ktx.sp
|
|
||||||
import de.mm20.launcher2.search.data.CurrencyUnitConverter
|
|
||||||
import de.mm20.launcher2.search.data.UnitConverter
|
import de.mm20.launcher2.search.data.UnitConverter
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.LegacyLauncherTheme
|
||||||
import de.mm20.launcher2.ui.databinding.ViewUnitconverterBinding
|
import de.mm20.launcher2.ui.databinding.ViewUnitconverterBinding
|
||||||
|
import de.mm20.launcher2.ui.search.UnitConverterItem
|
||||||
import de.mm20.launcher2.unitconverter.UnitConverterViewModel
|
import de.mm20.launcher2.unitconverter.UnitConverterViewModel
|
||||||
import de.mm20.launcher2.unitconverter.UnitValue
|
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import java.text.DateFormat
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class UnitConverterView : FrameLayout {
|
class UnitConverterView : FrameLayout {
|
||||||
|
|
||||||
constructor(context: Context) : super(context)
|
constructor(context: Context) : super(context)
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
|
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(
|
||||||
|
context,
|
||||||
|
attrs,
|
||||||
|
defStyleRes
|
||||||
|
)
|
||||||
|
|
||||||
private val unitConverter: LiveData<UnitConverter?>
|
private val unitConverter: LiveData<UnitConverter?>
|
||||||
private val adapter: GroupAdapter<GroupieViewHolder>
|
|
||||||
|
|
||||||
private val binding = ViewUnitconverterBinding.inflate(LayoutInflater.from(context), this, true)
|
private val binding = ViewUnitconverterBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
|
|
||||||
@ -54,141 +42,24 @@ class UnitConverterView : FrameLayout {
|
|||||||
if (it == null) visibility = View.GONE
|
if (it == null) visibility = View.GONE
|
||||||
else {
|
else {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
bind(it)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
adapter = GroupAdapter()
|
|
||||||
binding.unitConverterValues.also {
|
|
||||||
it.adapter = adapter
|
|
||||||
it.addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
binding.composeView.setContent {
|
||||||
private fun bind(converter: UnitConverter) {
|
val converter by unitConverter.observeAsState()
|
||||||
val title = converter.inputValue.formattedValue + " " + converter.inputValue.formattedName
|
LegacyLauncherTheme {
|
||||||
binding.unitConverterInput.text = title
|
// TODO: Temporary solution until parent widget card is rewritten in Compose
|
||||||
|
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
|
||||||
/*val sb = StringBuilder()
|
Column {
|
||||||
for (unit in converter.values) {
|
converter?.let {
|
||||||
|
UnitConverterItem(
|
||||||
sb.append("${unit.formatted}\n")
|
unitConverter = it,
|
||||||
}
|
)
|
||||||
sb.removeSuffix("\n")
|
|
||||||
unitConverterValues.text = sb.toString()
|
|
||||||
unitConverterIcon.setImageResource(when (converter.dimension) {
|
|
||||||
Dimension.LENGTH -> R.drawable.ic_unit_length
|
|
||||||
Dimension.MASS -> R.drawable.ic_unit_mass
|
|
||||||
Dimension.TIME -> R.drawable.ic_unit_time
|
|
||||||
Dimension.DATA -> R.drawable.ic_unit_datasize
|
|
||||||
Dimension.VELOCITY -> R.drawable.ic_unit_velocity
|
|
||||||
else -> 0
|
|
||||||
})*/
|
|
||||||
|
|
||||||
adapter.clear()
|
|
||||||
|
|
||||||
val maxValueLength = converter.values.maxByOrNull { it.formattedValue.length }?.formattedValue?.length
|
|
||||||
?: 0
|
|
||||||
|
|
||||||
val section = Section().apply {
|
|
||||||
addAll(converter.values.subList(0, min(converter.values.size, 5)).map {
|
|
||||||
ValueItem(it, maxValueLength * 8f * sp)
|
|
||||||
})
|
|
||||||
}.also {
|
|
||||||
adapter.add(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (converter.values.size > 5) {
|
|
||||||
binding.showAllButton.visibility = View.VISIBLE
|
|
||||||
binding.showAllButton.setOnClickListener {
|
|
||||||
section.addAll(converter.values.subList( 5, converter.values.size).map {
|
|
||||||
ValueItem(it, maxValueLength * 8f * sp)
|
|
||||||
})
|
|
||||||
binding.showAllButton.visibility = View.GONE
|
|
||||||
binding.showAllButton.setOnClickListener(null)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
binding.showAllButton.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (converter is CurrencyUnitConverter) {
|
|
||||||
val df = DateFormat.getDateInstance(DateFormat.SHORT)
|
|
||||||
val date = Date().apply {
|
|
||||||
time = converter.updateTimestamp
|
|
||||||
}
|
|
||||||
val infoText = SpannableStringBuilder()
|
|
||||||
.append("European Central Bank (${df.format(date)})", object : ClickableSpan() {
|
|
||||||
override fun onClick(widget: View) {
|
|
||||||
CustomTabsIntent
|
|
||||||
.Builder()
|
|
||||||
.setToolbarColor(0xFF003299.toInt())
|
|
||||||
.build()
|
|
||||||
.launchUrl(context,
|
|
||||||
Uri.parse("https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html"))
|
|
||||||
}
|
}
|
||||||
}, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
}
|
||||||
.append(" • ")
|
}
|
||||||
.append(context.getString(R.string.disclaimer), object : ClickableSpan() {
|
|
||||||
override fun onClick(widget: View) {
|
|
||||||
MaterialDialog(context).show {
|
|
||||||
title(res = R.string.disclaimer)
|
|
||||||
message(res = R.string.disclaimer_currency_converter)
|
|
||||||
positiveButton(res = R.string.close) {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
|
|
||||||
binding.unitConverterInfo.apply {
|
|
||||||
text = infoText
|
|
||||||
visibility = View.VISIBLE
|
|
||||||
movementMethod = LinkMovementMethod.getInstance()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
binding.unitConverterInfo.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ValueItem(private val value: UnitValue, val valueWidth: Float) : Item() {
|
|
||||||
override fun getLayout(): Int {
|
|
||||||
return R.layout.unit_converter_row
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
|
|
||||||
viewHolder.itemView.findViewById<TextView>(R.id.value).let {
|
|
||||||
it.text = value.formattedValue
|
|
||||||
it.layoutParams = it.layoutParams.apply {
|
|
||||||
width = valueWidth.toInt()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewHolder.itemView.findViewById<TextView>(R.id.name).text = value.formattedName
|
|
||||||
viewHolder.itemView.findViewById<TextView>(R.id.symbol).text = value.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExpandItem : Item(), ExpandableItem {
|
|
||||||
|
|
||||||
private lateinit var expandableGroup: ExpandableGroup
|
|
||||||
|
|
||||||
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
|
|
||||||
viewHolder.itemView.visibility = if (expandableGroup.isExpanded) View.GONE else View.VISIBLE
|
|
||||||
viewHolder.itemView.setOnClickListener {
|
|
||||||
expandableGroup.onToggleExpanded()
|
|
||||||
viewHolder.itemView.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLayout(): Int {
|
|
||||||
return R.layout.unit_converter_show_all
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setExpandableGroup(onToggleListener: ExpandableGroup) {
|
|
||||||
expandableGroup = onToggleListener
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
package de.mm20.launcher2.ui.search
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.*
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import de.mm20.launcher2.search.data.UnitConverter
|
||||||
|
import de.mm20.launcher2.ui.R
|
||||||
|
import de.mm20.launcher2.unitconverter.Dimension
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UnitConverterItem(
|
||||||
|
unitConverter: UnitConverter,
|
||||||
|
) {
|
||||||
|
var showAll by remember { mutableStateOf(false) }
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(bottom = 8.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = unitConverter.inputValue.let { "${it.formattedValue} ${it.formattedName}" },
|
||||||
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
softWrap = false
|
||||||
|
)
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(12.dp)
|
||||||
|
.size(48.dp),
|
||||||
|
color = MaterialTheme.colorScheme.primaryContainer,
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = getDimensionIcon(unitConverter.dimension),
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
Column {
|
||||||
|
for ((i, unit) in unitConverter.values.withIndex()) {
|
||||||
|
if (!showAll && i >= 5) break
|
||||||
|
Text(
|
||||||
|
text = unit.formattedValue,
|
||||||
|
style = MaterialTheme.typography.bodyMedium.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 16.dp, bottom = 12.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
for ((i, unit) in unitConverter.values.withIndex()) {
|
||||||
|
if (!showAll && i >= 5) break
|
||||||
|
val text = AnnotatedString.Builder().apply {
|
||||||
|
append(" ${unit.formattedName} (${unit.symbol})")
|
||||||
|
}.toAnnotatedString()
|
||||||
|
Text(
|
||||||
|
text = "${unit.formattedName} (${unit.symbol})",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(end = 16.dp, bottom = 12.dp, start = 8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!showAll && unitConverter.values.size > 5) {
|
||||||
|
TextButton(
|
||||||
|
onClick = { showAll = true },
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.End)
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(id = R.string.unit_converter_show_all))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDimensionIcon(dimension: Dimension): ImageVector {
|
||||||
|
return when (dimension) {
|
||||||
|
Dimension.Mass -> Icons.Rounded.FitnessCenter
|
||||||
|
Dimension.Length -> Icons.Rounded.Straighten
|
||||||
|
Dimension.Velocity -> Icons.Rounded.Speed
|
||||||
|
Dimension.Volume -> TODO()
|
||||||
|
Dimension.Area -> Icons.Rounded.SquareFoot
|
||||||
|
Dimension.Currency -> Icons.Rounded.Toll
|
||||||
|
Dimension.Data -> Icons.Rounded.Storage
|
||||||
|
Dimension.Bitrate -> TODO()
|
||||||
|
Dimension.Pressure -> TODO()
|
||||||
|
Dimension.Energy -> Icons.Rounded.Bolt
|
||||||
|
Dimension.Frequency -> TODO()
|
||||||
|
Dimension.Temperature -> Icons.Rounded.Thermostat
|
||||||
|
Dimension.Time -> Icons.Rounded.Schedule
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,89 +10,9 @@
|
|||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:elevation="@dimen/card_elevation">
|
android:elevation="@dimen/card_elevation">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
|
android:id="@+id/composeView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"/>
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:animateLayoutChanges="true"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/unitConverterInput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="1.0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="13 kilometers" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/unitConverterInfo"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:textColor="@color/text_color_secondary"
|
|
||||||
android:textSize="10sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/showAllButton"
|
|
||||||
tools:text="European Central Bank (24.04.2020)" />
|
|
||||||
|
|
||||||
<!--<TextView
|
|
||||||
android:id="@+id/unitConverterValues"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/unitConverterIcon"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/unitConverterInput"
|
|
||||||
tools:text="0.013 kilometers (km)\n130 centimeters (cm)\n1300 millimeters (mm)\n 13.1234 yards (yd)"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/unitConverterIcon"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:srcCompat="@tools:sample/avatars"/>-->
|
|
||||||
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/unitConverterValues"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:nestedScrollingEnabled="false"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:overScrollMode="never"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/unitConverterInput" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/showAllButton"
|
|
||||||
android:visibility="gone"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/unit_converter_show_all"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/unitConverterValues" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</de.mm20.launcher2.ui.legacy.view.LauncherCardView>
|
</de.mm20.launcher2.ui.legacy.view.LauncherCardView>
|
||||||
Loading…
x
Reference in New Issue
Block a user