【问题标题】:Android: <declare-styleable> method attributesAndroid:<declare-styleable> 方法属性
【发布时间】:2016-08-03 11:33:39
【问题描述】:

如何在属性中接受方法作为值? 就像在视图的 onClick 属性中一样:

<Button android:onClick="onClickMethod"/>

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

我知道我们在资源中使用&lt;declare-styleable&gt;,但是我们如何让它接受方法呢?

【问题讨论】:

    标签: android declare-styleable


    【解决方案1】:

    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;
    

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

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

    【讨论】:

    • 我明白了。但是 android:onClick 的格式是什么?如果我尝试为我的 attr 使用参考格式,则 ide 会抱怨无法解析该符号:app:myOnClick="onClickMethod"
    • 您的myOnClick 声明应如下所示&lt;attr name="myOnClick" format="string" /&gt;。您使用字符串是因为它是用来查找方法名称的。
    • 有效!但是他们如何自动完成 onClick 的方法呢?
    【解决方案2】:

    解决方案:

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


    1️⃣ ➖ 实现 CustomView with lambda getter function onItemClick

    class CustomView(
          context: Context,
          attrs: AttributeSet
    ) : View(context, attrs) {
    
    fun onItemClick(block: () -> Unit) {
        block()  |or|  block.invoke()
    }
    

    2️⃣ ➖ 在 build.gradle(:app) 中添加 data bindingkapt

    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: ")
    }
    

    PS。 Vel_daN:爱​​你所做的。 ?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      • 2015-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      相关资源
      最近更新 更多