首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在自定义视图上双向绑定自定义属性

在自定义视图上双向绑定自定义属性
EN

Stack Overflow用户
提问于 2020-03-14 05:17:21
回答 1查看 2.3K关注 0票数 3

我很难实现从片段的视图模型到自定义视图上的属性的双向绑定。不存在双向绑定StringEditText的问题,单向绑定可以很好地与我的自定义SearchView一起工作。但是,当我在自定义视图上将"@{vm.entry.item}"更改为"@={vm.entry.item}"时,项目将不会编译,并抛出:

错误:找不到符号导入com.test.test.databinding.FragmentTestBindingImpl;

我阅读像这一个这样的教程已经有一段时间了,并且尝试使用BindingAdapter,但是没有运气。感觉我只是错过了一些显而易见的东西。

Kotlin

代码语言:javascript
复制
data class TestModel(
  var item: String? = null,
  var quantity: String? = null
)

class TestViewModel : ViewModel() {
  val entry = TestModel()
}

class TestFragment : Fragment() {

  private val vm: TestViewModel by lazy {
    ViewModelProvider(this).get(TestViewModel::class.java)
  }

  override fun onCreateView(
    inflater: LayoutInflater,
    parent: ViewGroup?,
    savedInstanceState: Bundle?
  ): View {
    val binding: FragmentTestBinding =
      DataBindingUtil.inflate(inflater, R.layout.fragment_test, parent, false)
    binding.setVariable(BR.vm, vm)
    binding.lifecycleOwner = viewLifecycleOwner
    return binding.root
  }
}

class SearchView(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs, 0) {

  var selected: String? = null

  init {
    inflate(context, R.layout.view_search, this)

    val input: AutoCompleteTextView = findViewById(R.id.search_input)
    input.threshold = 1
    input.setAdapter(SearchAdapter(context))

    input.setOnItemClickListener { adapterView, _, position, _ ->
      val item: SearchModel = adapterView.getItemAtPosition(position) as SearchModel
      input.setText(item.name)
      selected = item.code
    }
  }
}

片段布局

代码语言:javascript
复制
<?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="vm"
            type="com.test.test.ui.TestViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.test.test.ui.views.SearchView
            android:id="@+id/test_search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:selected="@={vm.entry.item}" />

        <EditText
            android:id="@+id/test_edit_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={vm.entry.quantity}" />

    </LinearLayout>

</layout>

SearchView布局

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/paddingDouble"
    android:orientation="horizontal">

    <AutoCompleteTextView
        android:id="@+id/search_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</merge>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-14 20:22:52

原来答案一直都在医生们里(疯狂,对吧?)

关键的收获似乎是,仅仅将[Inverse]BindingAdapter函数封装在一个伴生对象中是不够的。还必须用@JvmStatic对它们进行注释。

我的完整自定义视图现在如下所示:

代码语言:javascript
复制
class SearchView(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs, 0) {

  var selected: String? = null

  init {
    inflate(context, R.layout.view_search, this)
  }

  companion object {
    @BindingAdapter("selectedAttrChanged")
    @JvmStatic
    fun setListener(view: SearchView, listener: InverseBindingListener) {
      val input: AutoCompleteTextView = view.findViewById(R.id.search_input)
      input.threshold = 1
      input.setAdapter(SearchAdapter(view.context))
      input.setOnItemClickListener { adapterView, _, position, _ ->
        val item: SearchModel = adapterView.getItemAtPosition(position) as SearchModel
        input.setText(item.name)
        selected = item.code
        listener.onChange()
      }
    }

    @BindingAdapter("selected")
    @JvmStatic
    fun setTextValue(view: SearchView, value: String?) {
      if (value != view.selected) view.selected = value
    }

    @InverseBindingAdapter(attribute = "selected")
    @JvmStatic
    fun getTextValue(view: SearchView): String? = view.selected
  }
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60679957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档