Android简单的使用listview动态生成不同页面

前些日子,在oschina中看到一个网友的问题,是Android技术的。他需要在在后台java代码中根据服务器传回来的数据类型去动态的生成控件来展示数据。由于他是一个Android新手,如果要做真正的后台动态生成控件的话,会比较吃力,我给他建议使用listview控件,将数据要求中所有可能用到的界面在xml布局中弄好,然后后台根据数据要求,引入对应的数据的界面到listview的item中即可。如此也就简单易懂了。

需求:实现一份问卷,备选答案展现形式由服务器传过来的数据决定。即,根据数据要求,选择不同的控件展现答案。

服务器传过来的数据类型有:text、radio、checkbox等。

详细代码实现:

界面布局:activity_main.xml

<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界面需要为每一种可能的展现形式定义一个布局文件。

数据要求的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>

这里就不再写其它类型的布局了,都是雷同的。

后台代码:MainActivity.java

 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设置长宽,需要先设置它父亲的长度,然后通过它父亲的长宽来设置它的长宽。

到此止了。

你可能感兴趣的:(android,textview,自定义适配器,动态生成,EditView)