我正在尝试创建一个自定义的“布局构建器”,其中包含所有子项的一些视图标记(例如相对布局)将从基于某些条件(访问权限)定义布局的XML文件中删除。 / p>
我有一个名为wrapper.xml的主布局包装器:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
然后我有例如test.xml文件定义保存在/ res / raw文件夹中的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/section1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</RelativeLayout>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<RelativeLayout
android:id="@+id/section2"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</RelativeLayout>
</LinearLayout>
可以说,特定用户无权访问第一部分,因此将从test.xml文件中删除一部分。
XMLDocumentParser(负责将.xml文件解析为Document):
public class XMLDocumentParser implements IXMLDocumentParser {
@Override
public Document getDomElement(Context context, int resource) {
Document doc = null;
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
try{
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(context.getResources().openRawResource(resource), "UTF-8");
//doc = docBuilder.parse(new BOMInputStream(context.getResources().openRawResource(resource), false, ByteOrderMark.UTF_8));
}
catch (ParserConfigurationException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (SAXException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
return null;
}
return doc;
}
XML布局构建器(负责删除部分并创建XMLPullParser):
public class XMLLayoutBuilder implements IXMLLayoutBuilder {
private IXMLDocumentParser documentParser;
private Context context;
public XMLLayoutBuilder(Context context) {
this.context = context;
documentParser = new XMLDocumentParser();
}
@Override
public XmlPullParser removeUnauthorizedSections(HashMap<String, String> permissions, int resource) {
Document doc = documentParser.getDomElement(context, resource);
Node rootNode = doc.getDocumentElement();
NodeList topLayouts = rootNode.getChildNodes();
for(int i = 0; i < topLayouts.getLength(); i++){
Node element = topLayouts.item(i);
/*
if(Check for permissions for specific layout and section){
//Remove node with all its children
rootNode.removeChild(element);
}
*/
}
return getXMLPullParserFromString(getStringFromDocument(doc));
}
private String getStringFromDocument(Document doc)
{
try
{
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
return writer.toString();
}
catch(TransformerException ex)
{
ex.printStackTrace();
return null;
}
}
private XmlPullParser getXMLPullParserFromString(String xml){
if(xml == null) return null;
XmlPullParser pullParser;
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
pullParser = factory.newPullParser();
pullParser.setInput(new StringReader(xml));
} catch (XmlPullParserException e) {
e.printStackTrace();
return null;
}
return pullParser;
}
MainActivity(应该将XMLPullParser的内容扩展到wrapper.xml布局的根元素):
public class MainActivity extends ActionBarActivity {
private Button btn_login;
private IHttpRequestProcessor processor;
private ILayoutBuilder layoutBuilder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wrapper);
layoutBuilder = new LayoutBuilder();
LinearLayout ll = (LinearLayout)findViewById(R.id.ll_root);
layoutBuilder.buildLayout(null, R.raw.test2, getApplicationContext(), ll);
}
}
LayoutBuilder:
public class LayoutBuilder implements ILayoutBuilder {
private IXMLLayoutBuilder xmlLayoutBuilder;
@Override
public View buildLayout(HashMap<String, String> permissions, int resource, Context context, ViewGroup root) {
xmlLayoutBuilder = new XMLLayoutBuilder(context);
XmlPullParser xmlParser = xmlLayoutBuilder.removeUnauthorizedSections(permissions, resource);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(xmlParser, null);
return null;
}
}
当我运行应用程序时,我收到此错误:
11-03 12:23:38.822: E/AndroidRuntime(1731): FATAL EXCEPTION: main
11-03 12:23:38.822: E/AndroidRuntime(1731): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.managmentsystem/com.example.managmentsystem.MainActivity}: android.view.InflateException: START_TAG <LinearLayout {http://schemas.android.com/apk/res/android}android:layout_width='match_parent' {http://schemas.android.com/apk/res/android}android:layout_height='match_parent' {http://schemas.android.com/apk/res/android}android:orientation='vertical'>@1:216 in java.io.StringReader@52732da4: Error inflating class <unknown>
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.ActivityThread.access$600(ActivityThread.java:141)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.os.Handler.dispatchMessage(Handler.java:99)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.os.Looper.loop(Looper.java:137)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.ActivityThread.main(ActivityThread.java:5103)
11-03 12:23:38.822: E/AndroidRuntime(1731): at java.lang.reflect.Method.invokeNative(Native Method)
11-03 12:23:38.822: E/AndroidRuntime(1731): at java.lang.reflect.Method.invoke(Method.java:525)
11-03 12:23:38.822: E/AndroidRuntime(1731): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
11-03 12:23:38.822: E/AndroidRuntime(1731): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-03 12:23:38.822: E/AndroidRuntime(1731): at dalvik.system.NativeStart.main(Native Method)
11-03 12:23:38.822: E/AndroidRuntime(1731): Caused by: android.view.InflateException: START_TAG <LinearLayout {http://schemas.android.com/apk/res/android}android:layout_width='match_parent' {http://schemas.android.com/apk/res/android}android:layout_height='match_parent' {http://schemas.android.com/apk/res/android}android:orientation='vertical'>@1:216 in java.io.StringReader@52732da4: Error inflating class <unknown>
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.LayoutInflater.createView(LayoutInflater.java:620)
11-03 12:23:38.822: E/AndroidRuntime(1731): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:669)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:694)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.LayoutInflater.inflate(LayoutInflater.java:469)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.LayoutInflater.inflate(LayoutInflater.java:373)
11-03 12:23:38.822: E/AndroidRuntime(1731): at layoutbuilder.LayoutBuilder.buildLayout(LayoutBuilder.java:23)
11-03 12:23:38.822: E/AndroidRuntime(1731): at com.example.managmentsystem.MainActivity.onCreate(MainActivity.java:40)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.Activity.performCreate(Activity.java:5133)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
11-03 12:23:38.822: E/AndroidRuntime(1731): ... 11 more
11-03 12:23:38.822: E/AndroidRuntime(1731): Caused by: java.lang.reflect.InvocationTargetException
11-03 12:23:38.822: E/AndroidRuntime(1731): at java.lang.reflect.Constructor.constructNative(Native Method)
11-03 12:23:38.822: E/AndroidRuntime(1731): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.LayoutInflater.createView(LayoutInflater.java:594)
11-03 12:23:38.822: E/AndroidRuntime(1731): ... 21 more
11-03 12:23:38.822: E/AndroidRuntime(1731): Caused by: java.lang.ClassCastException: android.util.XmlPullAttributes cannot be cast to android.content.res.XmlBlock$Parser
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.content.res.Resources$Theme.obtainStyledAttributes(Resources.java:1366)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.content.Context.obtainStyledAttributes(Context.java:416)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.View.<init>(View.java:3317)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.view.ViewGroup.<init>(ViewGroup.java:459)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.widget.LinearLayout.<init>(LinearLayout.java:176)
11-03 12:23:38.822: E/AndroidRuntime(1731): at android.widget.LinearLayout.<init>(LinearLayout.java:172)
11-03 12:23:38.822: E/AndroidRuntime(1731): ... 24 more