自定义属性与类引用

6

我正在尝试创建一个类似于tools: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>

我曾尝试使用 reference 格式,但编译未成功。

Error:(17, 22) 不允许使用字符串类型(在“adapter”处的值为“example.com.br.appname.AccountAdapter”)。

2个回答

2

我认为目前这是不可能的。其他类似的自定义属性,例如设计库中的app:layout_behavior,或者来自RecyclerView的简单app:layoutManager,都需要完整的类名,而没有你的要求。

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

你可以考虑提交一个功能请求,因为Android Studio在特定情况下具有此功能(tools:context<view><fragment>标签中的class,清单中的类...),但我怀疑他们会添加一个新的属性格式仅用于此目的。


嗯...我想我需要放弃用这种方式做了...也许我需要在程序中实现,而不是在布局文件中...这很遗憾 :( - Leandro Silva
2
如果这是为您自己的应用程序(而不是库),并且您只有相对较少的适配器,您可以使用“枚举”属性(例如,“FloatingActionButton”具有大小枚举,“mini”和“normal”)列出所有适配器与短名称。 - natario

2

所以...

  • 显然,你可以做到!
  • Google也这样做了
  • Android Studio理解该类是从XML中引用的
      • 重构 > 重命名有效
      • 查找用法有效
      • 等等...

.../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()
            }
        }
    }

在 AS 4.0 Canary 中,我不得不在 styleable 之外声明 attr 才能编译。 - TheWanderer
@TheWanderer 嘿!你能发一个例子吗?或者修改我的答案吗?你说得对,这个解决方案对我不再起作用了,而且我的旧代码正在崩溃,但我不确定如何在styleable之外声明它...我现在只是添加了format="string"。谢谢!! - Eric
1
只需在打开资源标签下方添加一个具有相同名称和指定格式的attr标签即可。 - TheWanderer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接