Add experimental app widget compose reimplementation
This commit is contained in:
parent
2e4100f676
commit
15cb4b4f29
@ -0,0 +1,190 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.ListView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.combinedClickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.composed
|
||||||
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.graphics.nativeCanvas
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.core.view.children
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reimplementation of View using composables.
|
||||||
|
* Only views that are supported by RemoteViews are supported here.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun ComposeAndroidView(
|
||||||
|
view: () -> View,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
var view_ by remember { mutableStateOf<View?>(null) }
|
||||||
|
|
||||||
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
view_ = view()
|
||||||
|
onDispose {
|
||||||
|
view_ = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (view_ != null) {
|
||||||
|
ComposeAndroidView(view_!!, modifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ComposeAndroidView(
|
||||||
|
view: View,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
if (view.visibility == View.GONE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view.visibility == View.INVISIBLE) {
|
||||||
|
Spacer(modifier = modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
val mod = modifier.view(view)
|
||||||
|
|
||||||
|
when (view) {
|
||||||
|
is FrameLayout -> ComposeFrameLayout(view, mod)
|
||||||
|
is LinearLayout -> ComposeLinearLayout(view, mod)
|
||||||
|
is ListView -> ComposeListView(view, mod)
|
||||||
|
is TextView -> ComposeTextView(view, mod)
|
||||||
|
is ImageView -> ComposeImageView(view, mod)
|
||||||
|
is ViewGroup -> {
|
||||||
|
Column(modifier = mod) {
|
||||||
|
for (child in view.children) {
|
||||||
|
ComposeAndroidView(
|
||||||
|
child,
|
||||||
|
modifier = Modifier.layoutParams(child.layoutParams)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(view.javaClass.toString(), modifier = mod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Text(view.javaClass.toString(), modifier = mod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Modifier.view(view: View): Modifier = this then Modifier.composed {
|
||||||
|
val density = LocalDensity.current
|
||||||
|
val backgroundDrawable = view.background
|
||||||
|
val background = when (backgroundDrawable) {
|
||||||
|
is ColorDrawable -> Modifier.background(Color(backgroundDrawable.color))
|
||||||
|
is Drawable -> Modifier.drawBehind {
|
||||||
|
backgroundDrawable.setBounds(
|
||||||
|
0, 0, size.width.roundToInt(), size.height.roundToInt()
|
||||||
|
)
|
||||||
|
backgroundDrawable.draw(this.drawContext.canvas.nativeCanvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
val padding = with(density) {
|
||||||
|
Modifier.padding(
|
||||||
|
start = view.paddingStart.toDp(),
|
||||||
|
top = view.paddingTop.toDp(),
|
||||||
|
end = view.paddingEnd.toDp(),
|
||||||
|
bottom = view.paddingBottom.toDp()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val clickable = when {
|
||||||
|
view.isClickable || view.isLongClickable -> Modifier.combinedClickable(
|
||||||
|
enabled = view.isEnabled,
|
||||||
|
onClick = {
|
||||||
|
if (view.isClickable) view.performClick()
|
||||||
|
},
|
||||||
|
onLongClick = { view.performLongClick() }
|
||||||
|
)
|
||||||
|
|
||||||
|
view.isClickable -> Modifier.clickable(
|
||||||
|
enabled = view.isEnabled,
|
||||||
|
onClick = { view.performClick() }
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
val graphicsLayer = Modifier.graphicsLayer {
|
||||||
|
translationX = view.translationX
|
||||||
|
translationY = view.translationY
|
||||||
|
rotationX = view.rotationX
|
||||||
|
rotationY = view.rotationY
|
||||||
|
rotationZ = view.rotation
|
||||||
|
scaleX = view.scaleX
|
||||||
|
scaleY = view.scaleY
|
||||||
|
shadowElevation = view.elevation
|
||||||
|
cameraDistance = view.cameraDistance
|
||||||
|
}
|
||||||
|
|
||||||
|
background then clickable then padding then graphicsLayer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun Modifier.layoutParams(params: ViewGroup.LayoutParams?) = this then Modifier.composed {
|
||||||
|
params ?: return@composed Modifier
|
||||||
|
val density = LocalDensity.current
|
||||||
|
|
||||||
|
val margins = if (params is ViewGroup.MarginLayoutParams) {
|
||||||
|
with(density) {
|
||||||
|
Modifier.padding(
|
||||||
|
start = params.marginStart.coerceAtLeast(0).toDp(),
|
||||||
|
top = params.topMargin.coerceAtLeast(0).toDp(),
|
||||||
|
end = params.marginEnd.coerceAtLeast(0).toDp(),
|
||||||
|
bottom = params.bottomMargin.coerceAtLeast(0).toDp()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
val width = when (params.width) {
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT -> Modifier.fillMaxWidth()
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT -> Modifier.wrapContentWidth()
|
||||||
|
else -> Modifier.width(with(density) { params.width.toDp() })
|
||||||
|
}
|
||||||
|
|
||||||
|
val height = when (params.height) {
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT -> Modifier.fillMaxHeight()
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT -> Modifier.wrapContentHeight()
|
||||||
|
else -> Modifier.height(with(density) { params.height.toDp() })
|
||||||
|
}
|
||||||
|
|
||||||
|
margins then width then height
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.core.view.children
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun ComposeFrameLayout(
|
||||||
|
view: FrameLayout,
|
||||||
|
modifier: Modifier,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = modifier,
|
||||||
|
contentAlignment = Alignment.TopStart,
|
||||||
|
) {
|
||||||
|
for (child in view.children) {
|
||||||
|
ComposeAndroidView(
|
||||||
|
child,
|
||||||
|
modifier = Modifier.frameLayoutChild(
|
||||||
|
this@Box,
|
||||||
|
child.layoutParams
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Modifier.frameLayoutChild(scope: BoxScope, params: ViewGroup.LayoutParams) = this then
|
||||||
|
Modifier.layoutParams(params) then
|
||||||
|
with(scope) {
|
||||||
|
if (params !is FrameLayout.LayoutParams) return@with Modifier
|
||||||
|
val alignment = when (params.gravity) {
|
||||||
|
Gravity.START or Gravity.TOP -> Alignment.TopStart
|
||||||
|
Gravity.START or Gravity.BOTTOM -> Alignment.BottomStart
|
||||||
|
Gravity.END or Gravity.TOP -> Alignment.TopEnd
|
||||||
|
Gravity.END or Gravity.BOTTOM -> Alignment.BottomEnd
|
||||||
|
Gravity.START or Gravity.CENTER_VERTICAL -> Alignment.CenterStart
|
||||||
|
Gravity.END or Gravity.CENTER_VERTICAL -> Alignment.CenterEnd
|
||||||
|
Gravity.CENTER_HORIZONTAL or Gravity.TOP -> Alignment.TopCenter
|
||||||
|
Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM -> Alignment.BottomCenter
|
||||||
|
Gravity.CENTER_HORIZONTAL or Gravity.CENTER_VERTICAL -> Alignment.Center
|
||||||
|
else -> Alignment.TopStart
|
||||||
|
}
|
||||||
|
Modifier.align(alignment)
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.graphics.BlendModeColorFilter
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.graphics.ColorMatrix
|
||||||
|
import androidx.compose.ui.graphics.toArgb
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun ComposeImageView(
|
||||||
|
view: ImageView,
|
||||||
|
modifier: Modifier,
|
||||||
|
) {
|
||||||
|
AsyncImage(
|
||||||
|
modifier = modifier.alpha(view.imageAlpha / 255f),
|
||||||
|
model = view.drawable,
|
||||||
|
contentDescription = view.contentDescription?.toString(),
|
||||||
|
contentScale = when (view.scaleType) {
|
||||||
|
ImageView.ScaleType.CENTER -> ContentScale.None
|
||||||
|
ImageView.ScaleType.FIT_XY -> ContentScale.FillBounds
|
||||||
|
ImageView.ScaleType.FIT_START,
|
||||||
|
ImageView.ScaleType.FIT_CENTER,
|
||||||
|
ImageView.ScaleType.FIT_END -> ContentScale.Fit
|
||||||
|
|
||||||
|
ImageView.ScaleType.CENTER_CROP -> ContentScale.Crop
|
||||||
|
ImageView.ScaleType.CENTER_INSIDE -> ContentScale.Inside
|
||||||
|
else -> ContentScale.None
|
||||||
|
},
|
||||||
|
alignment = when (view.scaleType) {
|
||||||
|
ImageView.ScaleType.FIT_XY,
|
||||||
|
ImageView.ScaleType.CENTER,
|
||||||
|
ImageView.ScaleType.FIT_CENTER,
|
||||||
|
ImageView.ScaleType.CENTER_CROP,
|
||||||
|
ImageView.ScaleType.CENTER_INSIDE -> Alignment.Center
|
||||||
|
|
||||||
|
ImageView.ScaleType.FIT_START -> Alignment.TopStart
|
||||||
|
ImageView.ScaleType.FIT_END -> Alignment.BottomEnd
|
||||||
|
else -> Alignment.Center
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,122 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.core.view.children
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun ComposeLinearLayout(
|
||||||
|
view: LinearLayout,
|
||||||
|
modifier: Modifier,
|
||||||
|
) {
|
||||||
|
|
||||||
|
if (view.orientation == LinearLayout.VERTICAL) {
|
||||||
|
val horizontalAlignment = when (view.gravity and Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
|
||||||
|
Gravity.START -> Alignment.Start
|
||||||
|
Gravity.CENTER_HORIZONTAL -> Alignment.CenterHorizontally
|
||||||
|
Gravity.END -> Alignment.End
|
||||||
|
else -> Alignment.Start
|
||||||
|
}
|
||||||
|
val verticalArrangement = when (view.gravity and Gravity.VERTICAL_GRAVITY_MASK) {
|
||||||
|
Gravity.TOP -> Arrangement.Top
|
||||||
|
Gravity.CENTER_VERTICAL -> Arrangement.Center
|
||||||
|
Gravity.BOTTOM -> Arrangement.Bottom
|
||||||
|
else -> Arrangement.Top
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = modifier,
|
||||||
|
horizontalAlignment = horizontalAlignment,
|
||||||
|
verticalArrangement = verticalArrangement,
|
||||||
|
) {
|
||||||
|
for (child in view.children) {
|
||||||
|
ComposeAndroidView(
|
||||||
|
child,
|
||||||
|
modifier = Modifier.linearLayoutChild(
|
||||||
|
this@Column,
|
||||||
|
child.layoutParams
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val horizontalArrangement =
|
||||||
|
when (view.gravity and Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
|
||||||
|
Gravity.START -> Arrangement.Start
|
||||||
|
Gravity.CENTER_HORIZONTAL -> Arrangement.Center
|
||||||
|
Gravity.END -> Arrangement.End
|
||||||
|
else -> Arrangement.Start
|
||||||
|
}
|
||||||
|
val verticalAlignment = when (view.gravity and Gravity.VERTICAL_GRAVITY_MASK) {
|
||||||
|
Gravity.TOP -> Alignment.Top
|
||||||
|
Gravity.CENTER_VERTICAL -> Alignment.CenterVertically
|
||||||
|
Gravity.BOTTOM -> Alignment.Bottom
|
||||||
|
else -> Alignment.Top
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = modifier,
|
||||||
|
verticalAlignment = verticalAlignment,
|
||||||
|
horizontalArrangement = horizontalArrangement,
|
||||||
|
) {
|
||||||
|
for (child in view.children) {
|
||||||
|
ComposeAndroidView(
|
||||||
|
child,
|
||||||
|
modifier = Modifier.linearLayoutChild(
|
||||||
|
this@Row,
|
||||||
|
child.layoutParams,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Modifier.linearLayoutChild(scope: RowScope, params: ViewGroup.LayoutParams) = this then
|
||||||
|
Modifier.layoutParams(params) then
|
||||||
|
with(scope) {
|
||||||
|
if (params !is LinearLayout.LayoutParams) return@with Modifier
|
||||||
|
val alignment = when (params.gravity and Gravity.VERTICAL_GRAVITY_MASK) {
|
||||||
|
Gravity.TOP -> Modifier.align(Alignment.Top)
|
||||||
|
Gravity.CENTER_VERTICAL -> Modifier.align(Alignment.CenterVertically)
|
||||||
|
Gravity.BOTTOM -> Modifier.align(Alignment.Bottom)
|
||||||
|
else -> Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
val weight = if ((params.weight) > 0f) {
|
||||||
|
Modifier.weight(params.weight)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
alignment then weight
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Modifier.linearLayoutChild(scope: ColumnScope, params: ViewGroup.LayoutParams) =
|
||||||
|
this then
|
||||||
|
Modifier.layoutParams(params) then
|
||||||
|
with(scope) {
|
||||||
|
if (params !is LinearLayout.LayoutParams) return@with Modifier
|
||||||
|
val alignment = when (params.gravity and Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
|
||||||
|
Gravity.START -> Modifier.align(Alignment.Start)
|
||||||
|
Gravity.CENTER_HORIZONTAL -> Modifier.align(Alignment.CenterHorizontally)
|
||||||
|
Gravity.END -> Modifier.align(Alignment.End)
|
||||||
|
else -> Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
val weight = if ((params.weight) > 0f) {
|
||||||
|
Modifier.weight(params.weight)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
alignment then weight
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.widget.ListView
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ComposeListView(
|
||||||
|
view: ListView,
|
||||||
|
modifier: Modifier,
|
||||||
|
) {
|
||||||
|
val adapter = view.adapter ?: return
|
||||||
|
LazyColumn(
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
|
items(
|
||||||
|
adapter.count,
|
||||||
|
contentType = { adapter.getItemViewType(it) },
|
||||||
|
) { index ->
|
||||||
|
val itemView = adapter.getView(index, null, view)
|
||||||
|
ComposeAndroidView(
|
||||||
|
itemView,
|
||||||
|
modifier = Modifier.layoutParams(itemView.layoutParams)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import androidx.compose.material.CircularProgressIndicator
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun ComposeProgressBar(
|
||||||
|
view: ProgressBar,
|
||||||
|
modifier: Modifier,
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
color = view.progressTintList?.defaultColor?.let { Color(it) } ?: MaterialTheme.colors.primary,
|
||||||
|
modifier = modifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package de.mm20.launcher2.ui.component.view
|
||||||
|
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.text.font.DeviceFontFamilyName
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.font.SystemFontFamily
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun ComposeTextView(
|
||||||
|
view: TextView,
|
||||||
|
modifier: Modifier,
|
||||||
|
) {
|
||||||
|
val density = LocalDensity.current
|
||||||
|
Text(
|
||||||
|
text = view.text.toString(),
|
||||||
|
color = Color(view.textColors.defaultColor),
|
||||||
|
style = MaterialTheme.typography.bodyMedium.copy(
|
||||||
|
fontSize = with(density) {
|
||||||
|
view.textSize.toSp()
|
||||||
|
},
|
||||||
|
fontWeight = if (isAtLeastApiLevel(28)) {
|
||||||
|
FontWeight(view.typeface.weight)
|
||||||
|
} else if (view.typeface.isBold) {
|
||||||
|
FontWeight.Bold
|
||||||
|
} else {
|
||||||
|
FontWeight.Normal
|
||||||
|
},
|
||||||
|
fontStyle = if (view.typeface.isItalic) {
|
||||||
|
FontStyle.Italic
|
||||||
|
} else {
|
||||||
|
FontStyle.Normal
|
||||||
|
},
|
||||||
|
),
|
||||||
|
modifier = modifier,
|
||||||
|
textAlign = when (view.textAlignment) {
|
||||||
|
TextView.TEXT_ALIGNMENT_CENTER -> TextAlign.Center
|
||||||
|
TextView.TEXT_ALIGNMENT_TEXT_START -> TextAlign.Start
|
||||||
|
TextView.TEXT_ALIGNMENT_TEXT_END -> TextAlign.End
|
||||||
|
else -> TextAlign.Start
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user