包含自定义属性的布局

我制作复杂的布局,并使用“包含”我的自定义组件,就像这样

<include layout="@layout/topbar"/> 

顶部栏定义如下:

 <?xml version="1.0" encoding="utf-8"?> <my.package.TopBarLayout ... a lot of code 

现在,我想将我的自定义属性传递给“topbar”

 <include layout="@layout/topbar" txt:trName="@string/contacts"/> 

但是我没有结果。 我从该页面了解到,我可以设置任何属性,但id,高度和宽度。

那么,如何传递我自定义的属性来包含,以及如何使其工作?

Related of "包含自定义属性的布局"

我知道这是一个古老的问题,但我碰到它,发现现在可以感谢数据绑定。

首先,您需要在您的项目中启用数据绑定 。

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

 <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="title" type="java.lang.String"/> </data> <RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/screen_header" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:gravity="center"> ... <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="20sp" android:textStyle="bold" android:text="@{title}"/> ... </RelativeLayout> </layout> 

最后,将主布局的variables传递给包含的布局,如下所示:

 ... xmlns:app="http://schemas.android.com/apk/res-auto" ... <include layout="@layout/included_layout" android:id="@+id/title" app:title="@{@string/title}"/> ... 

包含标签上的布局参数,可视性或ID以外的属性是不可能的。 这包括自定义属性。

您可以通过查看第705行的LayoutInflater.parseInclude方法的源代码来validation此问题: http ://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1 0.1 /机器人/视图/ LayoutInflater.java#640

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

我今天遇到这个问题。 无论什么是值得的,我认为有一个直接的工作。 为include标签添加属性而不是添加属性,为include添加属性和添加属性创build一个自定义的包装视图。 然后,做包装的包装。 让包装类实现提取属性并传递给它的单个子对象,这是包含布局的根视图。

所以说,我们声明一个名为SingleSettingWrapper的包装的一些自定义属性像这样 –

 <declare-styleable name="SingleSettingWrapper"> <attr name="labelText" format="string"/> </declare-styleable> 

然后,我们创build两个自定义视图类 – 一个用于包装(SingleSettingWrapper),另一个用于包含子对象(SingleSettingChild)

 <!-- You will never end up including this wrapper - it will be pasted where ever you wanted to include. But since the bulk of the XML is in the child, that's ok --> <com.something.SingleSettingWrapper android:id="@+id/wrapper" android:layout_width="match_parent" android:layout_height="wrap_content" custom:labelText="@string/my_label_string"> <!-- Include the child layout --> <include layout="@layout/setting_single_item"/> </com.something.SingleSettingWrapper> 

对于孩子,我们可以把任何复杂的布局放在我们想要的地方。 我只是把一些基本的东西,但你真的可以包括任何 –

 <com.something.SingleSettingItem xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <RelativeLayout > <!-- add whatever custom stuff here --> <!-- in this example there would be a text view for the label and maybe a bunch of other stuff --> <!-- blah blah blah --> </RelativeLayout> </com.something.SingleSettingItem> 

对于包装(这是关键),我们读取构造函数中的所有自定义属性。 然后,我们重写onViewAdded()并将这些自定义属性传递给我们的孩子。

 public class SingleSettingWrapper extends FrameLayout { private String mLabel; public SingleSettingWrapper(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SingleSettingWrapper, 0, 0); mLabel = a.getString(R.styleable.SingleSettingWrapper_labelText); a.recycle(); } public void onViewAdded(View child) { super.onViewAdded(child); if (!(child instanceof SingleSettingItem)) return; ((TextView)child.findViewById(R.id.setting_single_label)).setText(mLabel); /* Or, alternatively, call a custom method on the child implementation - ((SingleSettingItem)child)setLabel(mLabel); */ } } 

可选地,你也可以实现这个孩子,让它从包装器接收消息并修改自己(而不是像上面那样让包装器修改孩子)。

 public class SingleSettingItem extends LinearLayout { public SingleSettingItem(Context context, AttributeSet attrs) { super(context, attrs); } public void setLabel(String l) { // set the string into the resource here if desired, for example } } 

在一天结束的时候,你想要的每个XML文件<include>你的布局将包含大约7行的wrapper + include的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> 

实际上,这似乎工作得很好,而且设置起来相对简单。 我希望它可以帮助别人。

不幸的是,我唯一能做出贡献的是我也无法在包含标签上设置自定义属性,并让它们通过包含的布局。

这一点可能是不可能的。

您必须在您的自定义名称空间中包含您的根xml元素。 如果你的包名是com.example.test,你的xml shold就是这样的:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:txt="http://schemas.android.com/apk/res/com.example.test" /> 

一个很好的教程是: http : //blog.infidian.com/2008/05/02/android-tutorial-42-passing-custom-variables-via-xml-resource-files/

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