Rom*_*uba 42 android android-layout
我制作复杂的布局,并使用"include"作为我的自定义组件,就像这样
<include layout="@layout/topbar"/>
Run Code Online (Sandbox Code Playgroud)
并且topbar定义如下:
<?xml version="1.0" encoding="utf-8"?>
<my.package.TopBarLayout
... a lot of code
Run Code Online (Sandbox Code Playgroud)
现在,我想将我的自定义属性传递给"topbar",就像这样
<include layout="@layout/topbar" txt:trName="@string/contacts"/>
Run Code Online (Sandbox Code Playgroud)
但我没有结果.我从那个页面了解到我不能设置任何属性,而是id,height和width.
那么,我如何将我的自定义属性传递给包含,以及如何使其工作?
Sir*_*lot 68
我知道这是一个古老的问题但是我发现它现在可以归功于Data Binding.
首先,您需要在项目中启用数据绑定.
然后将数据绑定添加到要包含的布局:
<?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>
Run Code Online (Sandbox Code Playgroud)
最后,将变量从主布局传递到包含的布局,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
...
</data>
...
xmlns:app="http://schemas.android.com/apk/res-auto"
...
<include layout="@layout/included_layout"
android:id="@+id/title"
app:title="@{@string/title}"/>
...
</layout>
Run Code Online (Sandbox Code Playgroud)
除了包含标记上的布局参数,可见性或ID之外,其他属性是不可能的.这包括自定义属性.
您可以通过查看第705行附近的LayoutInflater.parseInclude方法的来源来验证这一点: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创建自定义包装器视图,并为其添加属性.然后,从包装器中执行include.让包装器类实现提取属性并传递给它的单个子节点,这是包含布局的根视图.
所以,假设我们为一个名为SingleSettingWrapper的包装器声明了一些自定义属性,如下所示 -
<declare-styleable name="SingleSettingWrapper">
<attr name="labelText" format="string"/>
</declare-styleable>
Run Code Online (Sandbox Code Playgroud)
然后,我们创建两个自定义视图类 - 一个用于包装器(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>
Run Code Online (Sandbox Code Playgroud)
对于孩子,我们可以在那里放置任何我们想要的复杂布局.我会把一些基本的东西,但你真的可以包括任何东西 -
<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>
Run Code Online (Sandbox Code Playgroud)
对于包装器(这是键),我们在构造函数中读取所有自定义属性.然后,我们覆盖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);
*/
}
}
Run Code Online (Sandbox Code Playgroud)
或者,您也可以实现子进程并让它从包装器接收消息并自行修改(而不是像上面那样让包装器修改子进程).
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
}
}
Run Code Online (Sandbox Code Playgroud)
在一天结束时,您希望<include>
布局的每个XML文件将包含大约7行XML for wrapper + include而不是您想要的单个包含,但如果包含的视图包含数百行,那么还是会更好.例如 -
<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>
Run Code Online (Sandbox Code Playgroud)
在实践中,这似乎工作得很好,并且设置起来相对简单.我希望它对某人有帮助.
归档时间: |
|
查看次数: |
25019 次 |
最近记录: |