前些日子,在oschina中看到一个网友的问题,是Android技术的。他须要在在后台java代码中根据服务器传回来的数据类型去动态的生成控件来展现数据。因为他是一个Android新手,若是要作真正的后台动态生成控件的话,会比较吃力,我给他建议使用listview控件,将数据要求中全部可能用到的界面在xml布局中弄好,而后后台根据数据要求,引入对应的数据的界面到listview的item中便可。如此也就简单易懂了。java
需求:实现一份问卷,备选答案展示形式由服务器传过来的数据决定。即,根据数据要求,选择不一样的控件展示答案。android
服务器传过来的数据类型有:text、radio、checkbox等。web
详细代码实现:服务器
界面布局:activity_main.xmlapp
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+id/listView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:descendantFocusability="beforeDescendants" > </ListView> </LinearLayout>
主界面布局中使用了ListView 控件,下面就须要为其添加item界面,这就是核心部分,这个item界面须要为每一种可能的展示形式定义一个布局文件。ide
数据要求的text的展示布局代码:listview_item_text.xml布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:padding="20dp" > <TextView android:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="30dp" android:text="我是题目~~" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:id="@+id/answer" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="我是答案" /> </LinearLayout> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="测试下输入框文本" /> </LinearLayout>
数据要求是radio的展现布局代码:listview_item.xml测试
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:padding="20dp" > <TextView android:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="30dp" android:text="我是题目~~" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <RadioGroup android:id="@+id/sex" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <RadioButton android:id="@+id/boy" android:text="男" /> <RadioButton android:id="@+id/gril" android:text="女" /> </RadioGroup> </LinearLayout> </LinearLayout>
这里就再也不写其它类型的布局了,都是雷同的。this
后台代码:MainActivity.javacode
package com.example.listviewtest; import android.os.Bundle; import android.app.Activity; import android.widget.ListView; /** * @author Rickey * */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);//引入主布局 ListView view = (ListView) findViewById(R.id.listView1);//得到主布局的主控机listview String [] type = new String []{"text","radio"};//定义数据类型 ListviewAdapter adapter = new ListviewAdapter(this);//初始化listview适配器 adapter.setStr(type);//给适配器传值 view.setAdapter(adapter);//启动适配器,画出界面 } }
这里的listview不使用系统自带的简单适配器,由于我须要在适配器中根据数据的不一样,选择引入不一样的布局,因此就自定义了一个listview的适配器:ListviewAdapter.java
package com.example.listviewtest; import android.content.Context; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.RadioButton; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; /** * @author Rickey * */ public class ListviewAdapter extends BaseAdapter { private LayoutInflater inflater;//画布 private Context context;//当前上下文 public ListviewAdapter(Context context){ this.context = context;//初始化当前上下文 inflater = LayoutInflater.from(context); //初始化画布 } private String [] str = null;//须要显示的数据 /** * @return the str */ public String[] getStr() { return str; } /** * @param str the str to set */ public void setStr(String[] str) { this.str = str; } @Override public int getCount() {//须要显示多少条数据 // TODO Auto-generated method stub return str.length; } @Override public Object getItem(int position) {//当前数据 // TODO Auto-generated method stub return str[position]; } @Override public long getItemId(int position) {//当前数据的id // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) {//开始画出界面 // TODO 自动生成的方法存根 ViewHolder holder = new ViewHolder();//初始化ViewHolder对象 if (convertView == null) {//若是当前画出的对象为null if (str[position].equals("text")) {//文本 convertView = inflater.inflate(R.layout.listview_item_text, null);//引入待画出的布局 convertView.setTag(holder);//将界面tag赋给ViewHolder保存 textData(convertView, holder);//给界面赋值 } if (str[position].equals("radio")) {//单选 convertView = inflater.inflate(R.layout.listview_item, null);//引入待画出的布局 convertView.setTag(holder);//将界面tag赋给ViewHolder保存 radioDataVoid(convertView, holder);//给界面赋值 } } else {//不然 holder = (ViewHolder) convertView.getTag();//直接取tag给ViewHolder } return convertView;//将界面返回画出 } class ViewHolder {//子界面控制 TextView itemName;//题目 RadioButton boy;//单选按钮1 RadioButton gril;//单选按钮2 EditText answer;//编辑框的答案 Button button1;//测试编辑框按钮 } /** * 给textview界面赋值 * @param convertView * @param holder */ private void textData(final View convertView, final ViewHolder holder) { holder.itemName = (TextView) convertView.findViewById(R.id.textView1); holder.answer = (EditText) convertView.findViewById(R.id.answer); holder.button1 = (Button) convertView.findViewById(R.id.button1); holder.button1.setOnClickListener(new OnClickListener() {//测试编辑框答案的按钮设置点击监听事件 @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(context, holder.answer.getText().toString(), Toast.LENGTH_SHORT).show();//显示编辑框的答案值 } }); //上面与下面两个方法均可以,随便选一种就行 holder.answer.setOnEditorActionListener(new OnEditorActionListener() {//编辑框设置编辑完成监听,当用户点击键盘上的“完成”按钮,则将编辑框的答案值显示 @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // TODO Auto-generated method stub Toast.makeText(context, holder.answer.getText().toString(), Toast.LENGTH_SHORT).show(); return false; } }); } /** * 给单选的界面赋值 * @param convertView * @param holder */ private void radioDataVoid(final View convertView, final ViewHolder holder) { holder.itemName = (TextView) convertView.findViewById(R.id.textView1); holder.boy = (RadioButton) convertView.findViewById(R.id.boy); holder.gril = (RadioButton) convertView.findViewById(R.id.gril); holder.boy.setOnClickListener(new OnClickListener() {//为单选按钮设置点击选中监听 @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(context, "你选择了【"+holder.boy.getText().toString()+"】", Toast.LENGTH_SHORT).show(); } }); holder.gril.setOnClickListener(new OnClickListener() {//为单选按钮设置点击选中监听 @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(context, "你选择了【"+holder.gril.getText().toString()+"】", Toast.LENGTH_SHORT).show(); } }); } }
整个代码到这里就结束了。主要是在listview的适配器中作数据的判断和选择引入不一样的界面就能够实现了,简单容易理解。比较适合新手。若是要求真正的技术或者比较熟悉了Android这个技术了,这种方法仍是很不建议的,使用后台生成界面,最难的就是明白整么控制布局,Android的布局不像web,Android的布局严格的遵循一个相似于父子关系的规矩。好比给布局的一个textview设置长宽,须要先设置它父亲的长度,而后经过它父亲的长宽来设置它的长宽。
到此止了。