动态布局还是先从我们的需求出发,近期做的一个项目中提到了了一个需求:
需要动态的生成一个表单,表单中的标题、选项、提示文字等都是可以动态的增加删除的,而且动态的配置文件是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; }
/** * @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自动生成的布局方式去布局,这样做起来比较简单。
效果图