Java 在自定义视图中获取android属性

Java 在自定义视图中获取android属性,java,android,xml,kotlin,view,Java,Android,Xml,Kotlin,View,我有一个扩展RelativeLayout的自定义视图。我在attrs.xml中有一些自定义属性。有没有一种方法可以像我们使用自定义属性那样获得常见的android属性,比如android:clickable class MyView(context: Context, attributeSet: AttributeSet?): RelativeLayout(context, attributeSet) { init { val attrs = context.obtainStyl

我有一个扩展RelativeLayout的自定义视图。我在
attrs.xml
中有一些自定义属性。有没有一种方法可以像我们使用自定义属性那样获得常见的android属性,比如
android:clickable

class MyView(context: Context, attributeSet: AttributeSet?): RelativeLayout(context, attributeSet) {
  init {
      val attrs = context.obtainStyledAttributes(attributeSet, R.styleable.MyView)
    
      if (attrs.getBoolean(android.R.attr.clickable, true)) {
          ...
      }
    
      attrs.recycle()
  }
}


此编译器接受,但在运行时崩溃。有人遇到过类似的用例吗?我希望避免为SDK中已经定义的自定义视图创建重复的属性。

是的,也许这个应该可以

attrs.xml
中,您应该这样声明smth

    <declare-styleable name="MyCustomView">
        <attr name="android:clickable" />
    </declare-styleable>

或多或少,答案一直在我面前。有一件事我必须明白,当你创建一个stylable时,它基本上是一个
IntArray
。现在,当您获取属性并传递可设置样式的引用时,它会根据其定义映射属性。 因此,为了获得本地属性中没有声明的其他属性,比如SDK中的
android:
,您需要将这些引用作为
IntArray
传递进来:

class MyView(context: Context, attributeSet: AttributeSet?): RelativeLayout(context, attributeSet) {
    init {
        val attrs = context.obtainStyledAttributes(attributeSet, intArrayOf(android.R.attr.clickable))

        if (attrs.getBoolean(0, true)) {
            ...
        }

        attrs.recycle()
    }
}

通过扩展
RelativeLayout
自定义视图将继承其属性。您通常不需要“触摸”它们,除非您的意图是改变家长的行为,这实际上可能会让用户/开发人员感到困惑/不可预测。检查为什么会崩溃?什么是stacktrace?我知道。如果SDK中已经存在此类属性,我希望避免这种情况。为什么要避免它?因为我不希望有重复的属性名称。这可能会在将来混淆为什么有
android:clickable
app:clickable
,如果两者都表示相同的预期行为。这一方法将允许您在声明
时拦截
android:clickable
。请仔细阅读,您只需在视图中声明
android:clickable
class MyView(context: Context, attributeSet: AttributeSet?): RelativeLayout(context, attributeSet) {
    init {
        val attrs = context.obtainStyledAttributes(attributeSet, intArrayOf(android.R.attr.clickable))

        if (attrs.getBoolean(0, true)) {
            ...
        }

        attrs.recycle()
    }
}