Android 包含具有自定义属性的布局

Android 包含具有自定义属性的布局,android,android-layout,Android,Android Layout,我正在构建一个复杂的布局,我想为我的自定义组件使用include标记,如下所示: <include layout="@layout/topbar"/> <my.package.TopBarLayout ... a lot of code <include layout="@layout/topbar" txt:trName="@string/contacts"/> <LinearLayout

我正在构建一个复杂的布局,我想为我的自定义组件使用
include
标记,如下所示:

<include layout="@layout/topbar"/>
<my.package.TopBarLayout
 ... a lot of code
<include layout="@layout/topbar" txt:trName="@string/contacts"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:txt="http://schemas.android.com/apk/res/com.example.test" />
现在,我想将自定义属性传递给“topbar”,如下所示:

<include layout="@layout/topbar"/>
<my.package.TopBarLayout
 ... a lot of code
<include layout="@layout/topbar" txt:trName="@string/contacts"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:txt="http://schemas.android.com/apk/res/com.example.test" />

然后在自定义组件代码中或理想情况下在xml中获取这些自定义属性的值

遗憾的是,我无法获得
txt:trName
属性的值,无法将其添加到
topbar
布局中,我只是没有收到任何代码。如果我从中正确理解,我可以通过
include
为使用的布局设置任何属性,但是
id
height
width


因此,我的问题是如何将自定义定义的属性传递给通过
include
添加的布局?

您必须在根xml元素中包含自定义名称空间。 如果您的包名为com.example.test,那么您的xml应该如下所示:

<include layout="@layout/topbar"/>
<my.package.TopBarLayout
 ... a lot of code
<include layout="@layout/topbar" txt:trName="@string/contacts"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:txt="http://schemas.android.com/apk/res/com.example.test" />


一个很好的教程是:

不幸的是,我唯一能做的就是无法在include标记上设置自定义属性,并将它们传递到include布局


在这一点上很可能是不可能的。

不可能在include标记上定义除布局参数、可见性或ID之外的其他属性。这包括自定义属性

您可以通过查看第705行附近的LayoutInflater.parseInclude方法的源来验证这一点:


充气机仅将ID和可见性属性应用于包含的布局。

我也有同样的问题。访问此线程后,我最终使用
View
setTag()
方法在
onCreate()
期间将标识信息附加到每个
视图,然后使用
getTag()
方法稍后检索它

不可能与自定义属性或API页面上声明的属性以外的任何属性一起使用(至少5.0.0版):


我今天遇到了这个问题。不管它值多少钱,我认为这是一个直截了当的解决办法。不要向include标记添加属性,而是为include创建一个自定义包装器视图并向其添加属性。然后,从包装器中执行include。让包装类实现提取属性并传递给它的单个子级,即include布局的根视图

假设我们为一个名为SingleSettingWrapper的包装器声明一些自定义属性,如下所示-

<declare-styleable name="SingleSettingWrapper">
    <attr name="labelText" format="string"/>
</declare-styleable>
或者,您也可以实现子级,让它从包装器接收消息并修改自身(而不是像我上面所做的那样让包装器修改子级)

在一天结束时,您希望
布局的每个XML文件都将包含包装+包含的大约7行XML,而不是您想要的单个包含,但是如果包含的视图包含数百行,您仍然会有更好的效果。比如说-

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <!-- this is the beginning of your custom attribute include -->
    <com.something.SingleSettingWrapper
        android:id="@+id/my_wrapper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        custom:labelText="@string/auto_lock_heading">
        <include layout="@layout/setting_single_item"/>
    </com.something.SingleSettingWrapper>
    <!-- this is the end of your custom attribute include -->
</LinearLayout>


在实践中,这似乎工作得很好,设置起来也相对简单。我希望它能帮助一些人。

我知道这是一个老问题,但我遇到了它,发现由于数据绑定,它现在是可能的

首先,您需要在项目中启用。使用
DataBindingUtil.充气
(如果是
活动
,则不要使用
setContentView
)使其工作

然后将数据绑定添加到要包括的布局:


...
...
最后,将变量从主布局传递到包含的布局,如下所示:

<include layout="@layout/topbar"/>
<my.package.TopBarLayout
 ... a lot of code
<include layout="@layout/topbar" txt:trName="@string/contacts"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:txt="http://schemas.android.com/apk/res/com.example.test" />

...
...
...

谢谢,但我知道,其中包括名称空间。问题是属性没有传递给Component是否正常工作?如何从xml绑定?当我尝试此操作时,包含的布局中没有文本。如何在包含标记中放置自定义属性?@DanChaltiel如果需要硬编码字符串,可以这样做
app:title='@{“foo”}'
为了使其工作,您需要记住,必须启用数据绑定,并且必须通过
DataBindingUtil.inflate
对其进行充气,而不仅仅是常规视图充气。但是是的,它是有效的。我犯了一个愚蠢的错误,用
app:title=“@string/title”
而不是
app:title=“@{@string/title}”
将视图包装到视图中有点太复杂了。这也是我采取的方法,因为不支持布局继承。我现在正在尝试设置包含元素()的样式,但是可能遇到了bug()。@RomanTruba您不需要在视图中包装视图。只需扩展视图。例如,扩展TextView并使用CustomTextView代替TextView@ChrisSprague我不确定你是否理解这里的问题。include中的布局已被删除complex@RomanTruba我经常使用非常类似的方法,效果很好。上面的解释比需要的要复杂一点,可以进行清理,但总体概念是好的。具体地说,如果操作正确,就没有理由声明“您将永远不会包含此包装器”。