Android:<declare-styleable>方法属性

时间:2016-04-12 17:34:55

标签: android declare-styleable

如何在属性中接受方法作为值? 与View的onClick属性类似:

<Button android:onClick="onClickMethod"/>

如何定义接受方法的自定义属性?

我知道我们在资源中使用<declare-styleable>,但我们如何让它接受方法呢?

2 个答案:

答案 0 :(得分:4)

Android使用反射来查找方法的名称并调用它。您可以在第4209行的源代码中看到一个示例 https://github.com/android/platform_frameworks_base/blob/master/core%2Fjava%2Fandroid%2Fview%2FView.java#L4209

             case R.styleable.View_onClick:
                if (context.isRestricted()) {
                    throw new IllegalStateException("The android:onClick attribute cannot "
                            + "be used within a restricted context");
                }

                final String handlerName = a.getString(attr);
                if (handlerName != null) {
                    setOnClickListener(new DeclaredOnClickListener(this, handlerName));
                }
                break;

如果方法名称不为null,则会创建一个新的DeclareOnClickListener()类,并使用方法名称对其进行初始化。

{44}在第4435行定义DeclareOnClickListener()https://github.com/android/platform_frameworks_base/blob/master/core%2Fjava%2Fandroid%2Fview%2FView.java#L4435

答案 1 :(得分:0)

解决方案:

我解决了这个问题:BindingAdapter 和 Lambda


1️⃣ ➖ 实现 CustomView with lambda getter 函数 onItemClick

class CustomView(
      context: Context,
      attrs: AttributeSet
) : View(context, attrs) {

fun onItemClick(block: () -> Unit) {
    block()  |or|  block.invoke()
}

2️⃣ ➖ 在 build.gradle(:app) 中添加数据绑定kapt

plugins {
   id 'kotlin-kapt'
}

android {
    ...
    buildFeatures {
        dataBinding = true
    }
    ...
}

3️⃣ ➖ 实现BindingAdapter

@BindingAdapter("onItemClick")
fun CustomView.onItemClick(block: () -> Unit) {
    this.onItemClick(block)
}

4️⃣ ➖ 使用 BindingAdapter

<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">

<data>

    <variable
        name="activityMain"
        type="com.veldan.MainActivity" />
</data>

<com.veldan.CustomView
        android:id="@+id/recycle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        onItemClick="@{() -> activityMain.onItemClick()}" />

</layout>

5️⃣ ➖ 活动绑定

class MainActivity : AppCompatActivity() {

private val TAG = this::class.simpleName

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater).also {
        it.activityMain = this
        setContentView(it.root)
    }
}

fun onItemClick() {
    Log.i(TAG, "onItemClick: ")
}

附注。 Vel_daN:喜欢你所做的。 ?