具有类引用的自定义属性

时间:2017-04-29 14:55:29

标签: android

我正在尝试创建一个行为类似工具的自定义属性:context ,即

  • Android Studio自动完成功能
  • 项目类名参考
  • 如果我更改了我的类目录,则支持自动重构

这是我的resources.xml

<declare-styleable name="RecyclerView">
    <attr name="adapter" format="string"></attr>
</declare-styleable>

这是用法

    <example.com.br.appname.RecyclerView
         android:id="@+id/accounts"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_marginTop="8dp"
         app:adapter="example.com.br.appname.AccountAdapter" >
    </example.com.br.appname.RecyclerView>

我尝试使用格式引用,但它也没有编译。

错误:(17,22)不允许字符串类型(在'adapter'处,值为'example.com.br.appname.AccountAdapter')。

2 个答案:

答案 0 :(得分:2)

我认为目前不可能。我可以想到的其他类似的自定义attrs,例如来自设计库的app:layout_behavior,或者只是来自app:layoutManager的{​​{1}},它们都需要完整的类名,没有您的要求。

最好将它们存储在RecyclerView资源文件中,并记住在重构类名时检查它。

您可以考虑提交功能请求,因为Android Studio在特殊情况下具有此功能(stringstools:context位于class<view>标记,Manifest中的类。 ..),但我怀疑他们会为此添加一个新的属性格式。

答案 1 :(得分:1)

所以...

  • 显然,你可以!
  • Google does this too
  • Android Studio知道正在从XML引用该类
      • Refactor > Rename有效
      • Find Usages有效
      • 依此类推...

不要在 ... / src / main / res / values / attrs.xml

中指定format属性
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyCustomView">
        ....
        <attr name="give_me_a_class"/>
        ....
    </declare-styleable>

</resources>

在某些布局文件中使用它 ... / src / main / res / layout / activity__main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- make sure to use $ dollar signs for nested classes -->
    <MyCustomView
        app:give_me_a_class="class.type.name.Outer$Nested/>

    <MyCustomView
        app:give_me_a_class="class.type.name.AnotherClass/>

</SomeLayout>

在您的视图初始化代码中解析类 ... / src / main / java /.../ MyCustomView.kt

class MyCustomView(
        context:Context,
        attrs:AttributeSet)
    :View(context,attrs)
{
    // parse XML attributes
    ....
    private val giveMeAClass:SomeCustomInterface
    init
    {
        context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
        {
            try
            {
                // very important to use the class loader from the passed-in context
                giveMeAClass = context::class.java.classLoader!!
                        .loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
                        .newInstance() // instantiate using 0-args constructor
                        .let {it as SomeCustomInterface}
            }
            finally
            {
                recycle()
            }
        }
    }