我添加了一个简单的复合控件,它从 XML 布局加载其布局并实现自己的 XML 属性。
但这仅在此控件位于主包 ( com.myapp
) 中时才有效。当我尝试将它移动到像 com.myapp.controls
这样的子包中时事情开始失败。
这是用于定义控件自定义属性的 attrs.xml:
<resources>
<declare-styleable name="CH2">
<attr name="textText" format="string" />
</declare-styleable>
<declare-styleable name="CH3">
<attr name="textFex" format="string" />
</declare-styleable>
</resources>
这是控制CH2.java,它在子包中执行不是 工作:
package com.myapp.controls;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class CH2 extends LinearLayout {
private TextView textView;
public CH2(Context context) throws Exception {
super(context);
init(context, null);
}
public CH2(Context context, AttributeSet attrs) throws Exception {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) throws Exception {
this.setOrientation(LinearLayout.VERTICAL);
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(com.myapp.R.layout.category_header, this, true);
View v = findViewById(com.myapp.R.id.chText);
this.textView = (TextView)v;
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, com.myapp.R.styleable.CH2);
String text = a.getString(com.myapp.R.styleable.CH2_textText);
this.textView.setText(text != null ? text : "<NULL!>");
a.recycle();
}
}
}
这是 CH3.java 的工作原理:
package com.myapp;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class CH3 extends LinearLayout {
private TextView textView;
public CH3(Context context) throws Exception {
super(context);
init(context, null);
}
public CH3(Context context, AttributeSet attrs) throws Exception {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) throws Exception {
this.setOrientation(LinearLayout.VERTICAL);
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(com.myapp.R.layout.category_header, this, true);
View v = findViewById(com.myapp.R.id.chText);
this.textView = (TextView)v;
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, com.myapp.R.styleable.CH3);
String text = a.getString(com.myapp.R.styleable.CH3_textFex);
this.textView.setText(text != null ? text : "<NULL!>");
a.recycle();
}
}
}
两个来源都使用相同的 category_header.xml。布局加载没有问题。我可以这样使用两者:
<com.myapp.controls.CH2
android:id="@+id/cH1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
myns:textText="Test 1" >
</com.myapp.controls.CH2>
<com.myapp.CH3
android:id="@+id/cH2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myns:textFex="Test 2"
>
</com.myapp.CH3>
我怎样才能使 CH2 工作?或者不可能使用另一个包?
Sidequest:我可以让两个控件使用相同的 XML 属性
textText
或者他们总是必须使用不同的属性?或者声明样式的名称可以与组件名称不同吗?使用新的声明样式的另一种方法:
<declare-styleable name="controls.CH2">
<attr name="textText" format="string" />
</declare-styleable>
但是好像不能用。 XML View 总是显示在布局文件中发现意外文本:,无论我如何使用 CH2:
xmlns:myns="http://schemas.android.com/apk/res/com.myapp"
xmlns:mynsc="http://schemas.android.com/apk/res/com.myapp.controls"
...
<com.myapp.controls.CH2
android:id="@+id/cH1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
mynsc:textText="TestTestTest"
>
</com.myapp.controls.CH2>
或者
xmlns:myns="http://schemas.android.com/apk/res/com.myapp"
...
<com.myapp.controls.CH2
android:id="@+id/cH1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
myns.controls:textText="TestTestTest"
>
</com.myapp.controls.CH2>
最佳答案
我刚刚回到我自己的属性文件,在任何地方都没有引用我的布局所在的非常深的子包……作为旁注,如果您在 attrs 文件中执行此操作,您可以让多个元素使用相同的属性:
<resources>
<attr name="textText" format="string"/>
<declare-styleable name="CH2">
<attr name="textText" />
</declare-styleable>
<declare-styleable name="CH3">
<attr name="textText" />
</declare-styleable>
</resources>
我对 android 源代码的研究显示了一些示例,它们完全按照您的描述执行操作,其中有一个自定义属性文件指向不同包中的查看类。我看到的唯一明显区别是 View 在布局中声明如下:
<view
class="com.myapp.controls.CH2"
android:id="@+id/cH1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
myns:textText="Test 1" >
</view>
<view
class="com.myapp.CH3"
android:id="@+id/cH2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myns:textFex="Test 2"
>
</view>
老实说,我无法告诉您为什么这会有所作为……但是每次他们需要使用的格式的自定义属性时
关于android - 其他包中的复合控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10032702/