所述的Android数据绑定导向讨论了一个活动或片段内结合的值,但是有执行数据与自定义视图结合的方法吗?
我想做的事情如下:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mypath.MyCustomView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="40dp"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
用my_custom_view.xml
:
<layout>
<data>
<variable
name="myViewModel"
type="com.mypath.MyViewModelObject" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{myViewModel.myText}" />
</LinearLayout>
</layout>
Run Code Online (Sandbox Code Playgroud)
虽然看起来可以通过在自定义视图上设置自定义属性来实现这一点,但如果要绑定很多值,这很快就会变得很麻烦.
有没有一个好方法来完成我想要做的事情?
尝试为int创建一个@BindingConversion时遇到一个神秘的问题.
以下代码适用于浮点数到字符串:
XML:
...
<variable
name="myViewModel"
type="... .SomeModel" />
...
<TextView
style="@style/StyleStuff"
android:text="@{myViewModel.number}" />
Run Code Online (Sandbox Code Playgroud)
码:
public class SomeModel {
public ObservableFloat number = new ObservableFloat();
}
Run Code Online (Sandbox Code Playgroud)
和设置:
viewModel.number.set(3.14f);
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试对字符串进行同样的操作,我会崩溃.
public ObservableInt number = new ObservableInt();
Run Code Online (Sandbox Code Playgroud)
同
viewModel.number.set(42);
Run Code Online (Sandbox Code Playgroud)
我得到以下内容:
FATAL EXCEPTION: main
Process: ...myapplication, PID: 14311
android.content.res.Resources$NotFoundException: String resource ID #0xfa0
at android.content.res.Resources.getText(Resources.java:1123)
at android.support.v7.widget.ResourcesWrapper.getText(ResourcesWrapper.java:52)
at android.widget.TextView.setText(TextView.java:4816)
at ...executeBindings(ActivityAdaptersBinding.java:336)
at android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:355)
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?谢谢!
根据https://developer.android.com/jetpack/compose/interop/interop-apis,ComposeView 和 AbstractComposeView 应该促进 Compose 和现有基于 XML 的应用程序之间的互操作性。
我在部署到设备时取得了一些成功,但包含 Compose 元素的 XML 预览对我不起作用。
作为一个简化的示例,请考虑:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="state"
type="ObservableState" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TestAtom
android:layout_width="match_parent"
android:layout_height="match_parent"
app:state="@{state}" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
使用以下自定义视图文件:
data class ObservableState(val text: ObservableField<String> = ObservableField("Uninitialized"))
data class State(val text: MutableState<String> = mutableStateOf(String()))
class TestAtom
@JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AbstractComposeView(context, attrs, defStyleAttr) {
val state by mutableStateOf(State())
fun setState(observableState: ObservableState?) …
Run Code Online (Sandbox Code Playgroud) 我希望向 @Composable 函数提供一个参数,该函数接受一种颜色,但仅接受离散列表中的一种颜色。
类似这样的事情:
enum class SpecialColor(val color: Color) {
ALPHA(MaterialTheme.colors.onSurface),
BETA(MaterialTheme.colors.onSecondary)
}
@Composable
fun ColorSample(specialColor: SpecialColor) {
Box(
modifier = Modifier
.width(100.dp)
.height(100.dp)
.background(specialColor.color)
)
}
@Preview
@Composable
fun PreviewSample() {
CustomTheme {
ColorSample(specialColor = SpecialColor.ALPHA)
}
}
Run Code Online (Sandbox Code Playgroud)
由于上面在可组合上下文之外引用MaterialTheme.colors,因此会发生以下错误:
@Composable 调用只能在 @Composable 函数的上下文中发生
如果直接引用颜色,而不是通过 MaterialTheme,则颜色将无法针对亮/暗模式等内容正确更新。
一种策略可能是将枚举值映射到 @Composable 函数本身内的 MaterialTheme 颜色。但这很麻烦、庞大,并且不能很好地扩展 - 想象一下更长的颜色列表和相同的 SpecialColor 列表需要重复用于许多功能。
另一种策略可能是直接使用 LocalContentColor 或类似的方法修改主题颜色,但这过于宽泛,并且会改变不仅仅是目标功能的颜色。
从实用程序 @Composable 函数返回颜色也不是一个选项,因为 @Composable 函数没有返回值。
那么...
关于如何提供 Compose Material 颜色的枚举列表之一作为参数有什么想法吗?
以一种干净且可扩展且可扩展的方式?