动态布局还是先从我们的需求出发,近期做的一个项目中提到了了一个需求:
需要动态的生成一个表单,表单中的标题、选项、提示文字等都是可以动态的增加删除的,而且动态的配置文件是xml文件。
我们在写html的使用常常就用如此的方式来制作配置自己的html页面,因为接到这个需求的时候正是该网站向拓展自己的无线业务,故此,直接将自己的网页端应用数据与无线端绑定到一起去了。
如:
<!-- 机械 -->
<machine>
<hint>请简单描述机械综合状况。。。如:启动车辆,发动机运转正常,怠速平稳无异响,行驶过程中转向、制动良好。</hint>
<question>
<title>发动机</title>
<option>运转正常</option>
<option>轻微异响</option>
<option>异响</option>
</question>
<question>
<title>变速箱</title>
<option>怠速平稳</option>
<option>轻微冲档</option>
<option>冲档</option>
</question>
<question>
<title>刹车制动</title>
<option>良好</option>
<option>一般</option>
<option>需要修理</option>
</question>
<question>
<title>引擎箱</title>
<option>清洁</option>
<option>轻微渗油</option>
<option>室盖渗油</option>
</question>
</machine>
我们希望解析此段xml数据能够得到与网站类似的界面
分析
Android的界面布局就是有N多个layout.xml组成的。所以,解析xml对于Android系统来说是完全可行的。
在移动Android平台上我们能够用Simple API forXML(SAX) 、 Document Object Model(DOM)和Android附带的pull解析器解析XML文件。
1. SAX解析XML文件
SAX是一个解析速度快并且占用内存少的xml解析器,采用的是事件驱动,非常适合用于Android等移动设备。
2. DOM解析XML文件
DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来比较直观。
3.Pull解析与SAX类似
实际上我们使用的是一个开源的Html、Xml解析器Jsoup。jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法来取出和操作数据。最主要的原因是,开源小巧,我们可以方便的移植到后代的Jsp服务端去。
Jsoup的使用也比较简单,可以去到官网:http://jsoup.org/看看简单的demo就会了。下面是我用Jsoup解析之前的xml代码段。
public Questions getData(String tagName)
{
AssetManager am = null;
am = m_context.getAssets();
try
{
//打开Assets文件夹下的 question.xml文件 获得输入流
inputStream = am.open(Constant.QUESTION_XML_PATH);
}
catch (Exception e)
{
e.printStackTrace();
}
Questions questionList = new Questions(m_context);
Question question = null;
Document doc = null;
try
{
//使用Jsoup载入xml文件中的数据,默认编码UTF-8
doc = Jsoup.parse(inputStream, "UTF-8", "");
}
catch (IOException e1)
{
e1.printStackTrace();
}
//得到首个元素
Element element = doc.select(tagName).first();
//得到<hint></hint>中的值
String hint = element.getElementsByTag("hint").html();
questionList.setHint(hint);
//获取每一个<question>中的数据,并且打包为question 类
Elements qElements = element.getElementsByTag("question");
for (Element e : qElements)
{
question = new Question();
Elements optionElements = e.getAllElements();
for (Element op : optionElements)
{
String name = op.tagName();
//获取<title></title>中的值
if ("title".equalsIgnoreCase(name) )
question.setTitle(op.html());
//将多个<option>添加如列表
else if ("option".equalsIgnoreCase(name))
{
if (question.options == null)
question.options = new ArrayList<String>();
question.options.add(op.html());
}
}
if (questionList.questions == null)
questionList.questions = new ArrayList<Question>();
questionList.questions.add(question);
}
close();
return questionList;
}
而question类中我们只需要存储几个较为简单的数据就可以了。
/**
* @author zhoushengtao
* @since 2013-6-26 上午9:36:17
*/
package com.stchou.paiche.pojo;
import java.util.ArrayList;
public class Question
{
private String title;
private String select = "";//存储选择的结果,方便输出
public ArrayList<String> options = new ArrayList<String>();
public String getTitle()
{
return this.title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getSelect()
{
return this.select;
}
public void setSelect(String select)
{
this.select = select;
}
public int getPosition()
{
for(int i=0;i<options.size();i++)
if(options.get(i).equals(select))
return i;
return 0;
}
@Override
public String toString()
{
if (select.length() == 0)
select = options.get(0);
String textString = "<question>\n";
textString += "<title>" + title + "</title>\n";
if (options != null)
for (String text : options)
textString += "<option>" + text + "</option>\n";
textString += "<selected>" + select + "</selected>\n";
textString += "</question>\n";
return textString;
}
}
获得了我们根据xml解析来的数据之后再界面上的布局就很简单了,但是值得注意的是,我们平时使用的是layout.xml文件针对Android的Activity来布局,这里我们获得的是Question类,只能在代码中给其进行布局。这个没有一个所见即所得的界面写起来还是有点吃力。所以,根据布局还是的分析好自己的布局方式,在layout中写写,看看出来的效果,再从代码上各具xml自动生成的布局方式去布局,这样做起来比较简单。
效果图