我正在尝试在现有View中添加自定义XML属性
将它们添加到自定义视图并不是一件大事,但我不知道如何在“基本”视图中访问这些属性(例如TextView,LinearLayout,ImageView ......)
当涉及片段和/或图书馆项目时,这将更加困难
到目前为止,这是我的代码
海关属性定义和XML(attrs.xml和布局):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="StarWars">
<attr name="jedi" format="string" />
<attr name="rank" format="string" />
</declare-styleable>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sw="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="28dp"
android:gravity="center_horizontal"
sw:jedi="Obiwan" />
<TextView
android:id="@+id/rank"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="28dp"
android:gravity="center_horizontal"
sw:rank="Master" />
由于我在片段上对此进行了充气(因此没有onCreate与attrs arg!),尝试获取2个sw自定义属性的唯一方法是:
将自定义LayoutInflater.Factory设置为onCreateView中的Fragment LayoutInflater
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
LayoutInflater layoutInflater = inflater.cloneInContext(inflater.getContext());
layoutInflater.setFactory(new StarWarsLayoutFactory());
View fragmentView = layoutInflater.inflate(R.layout.jedi, container, false);
((TextView) fragmentView.findViewById(android.R.id.jedi)).setText("Yep");
return fragmentView;
}
尝试在自定义LayoutInflater.Factory上获取自定义属性:
public class StarWarsLayoutFactory implements Factory {
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
*** What to do here ? ***
return null;
}
}
有人有过这样的问题吗?
我在这里缺少什么?
提前谢谢!答案 0 :(得分:2)
我终于做到了这一点:)
你必须像在OP上一样创建一个新的LayoutInflater.Factory
,但由于Factory用于所有膨胀的布局View,你必须在Factory.onCreateView
上返回null(让Android处理通货膨胀)您必须在某处缓存自定义XML属性
所以这里解决方案:
您的布局XML视图必须具有和android:id
创建将保留自定义属性的类:
public class AttributeParser {
private AttributeParserFactory mFactory;
private Map<Integer, HashMap<Integer, String>> mAttributeList;
private class AttributeParserFactory implements LayoutInflater.Factory{
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
String id = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "id");
if(id != null){
// String with the reference character "@", so we strip it to keep only the reference
id = id.replace("@", "");
TypedArray libraryStyledAttributeList = context.obtainStyledAttributes(attrs, R.styleable.NewsHubLibrary);
HashMap<Integer, String> libraryViewAttribute = new HashMap<Integer, String>();
int i = 0;
for(int attribute : R.styleable.NewsHubLibrary){
String attributeValue = libraryStyledAttributeList.getString(i);
if(attributeValue != null)
libraryViewAttribute.put(attribute, attributeValue);
i++;
}
if(!libraryViewAttribute.isEmpty())
mAttributeList.put(Integer.valueOf(id), libraryViewAttribute);
libraryStyledAttributeList.recycle();
}
return null;
}
}
public AttributeParser(){
mAttributeList = new HashMap<Integer, HashMap<Integer, String>>();
mFactory = new AttributeParserFactory();
}
public void clear() {
mAttributeList.clear();
}
public LayoutInflater getLayoutInflater(LayoutInflater inflater) {
clear();
LayoutInflater layoutInflater = inflater.cloneInContext(inflater.getContext());
layoutInflater.setFactory(mFactory);
return layoutInflater;
}
public void setFactory(LayoutInflater inflater){
inflater.cloneInContext(inflater.getContext()).setFactory(mFactory);
}
public void setViewAttribute(Activity activity) {
for(Entry<Integer, HashMap<Integer, String>> attribute : mAttributeList.entrySet())
if(activity.findViewById((Integer) attribute.getKey()) != null)
activity.findViewById((Integer) attribute.getKey()).setTag(attribute.getValue());
}
public void setViewAttribute(View view) {
for(Entry<Integer, HashMap<Integer, String>> attribute : mAttributeList.entrySet())
if(view.findViewById((Integer) attribute.getKey()) != null)
view.findViewById((Integer) attribute.getKey()).setTag(attribute.getValue());
}
public Map<Integer, HashMap<Integer, String>> getAttributeList() {
return mAttributeList;
}
public void setAttributeList(Map<Integer, HashMap<Integer, String>> attributeList) {
this.mAttributeList = attributeList;
}
}
LayoutInflater layoutInflater = mAttributeParser.getLayoutInflater(inflater);
View view = layoutInflater.inflate(R.layout.jedi, null);
mAttributeParser.setViewAttribute(view);
答案 1 :(得分:0)
标准TextView
等不会访问这些属性。您可以扩展它并提供包括读取这些自定义属性的功能。
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StarWars, 0, 0);
String jedi = a.getText(R.styleable.StarWars_jedi);
String rank = a.getText(R.styleable.StarWars_rank);
a.recycle();
请务必在最后致电recycle()
。