您的位置:首页 > 移动开发 > Android开发

Android 自定义Adapter

2016-08-16 22:32 176 查看
一、VC与模板概念的理解

MVC本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。

模型-视图-控制器(MVC)是Xerox PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,并且受到越来越多的使用 ColdFusion 和 PHP 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。

二、MVC如何工作

MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。

视图

视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services.

如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。

模型

模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。

控制器

控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。

现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。

自定义Adapter的实现

在xml中添加listview组件,



<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
然后创建自己list item模板



其中包括一个image(头像),name, age, info(黑色字体信息)。

<?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="horizontal" >
<ImageView
android:id="@+id/st_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/wangcai" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/st_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="旺财"
android:textColor="#0000ff"
android:textSize="22sp" />
<TextView
android:id="@+id/st_age"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="18"
android:textColor="#0000ff"
android:textSize="22sp" />
</LinearLayout>
<TextView
android:id="@+id/st_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="30dp"
android:text="我很高兴"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
下面是JAVA代码部分,开始实现自定义的Adapter。

就像使用Adapter一样,对V进行初始化,主要是findViewById。

setContentView(R.layout.activity_main);

lv = (ListView) this.findViewById(R.id.lv);

现在已经拥有了V部分,然后是创建M,即模型,使用自定义的数据填充。

ArrayList<Person> list = new ArrayList<Person>();

自定义的数据可以是数组,map,list,链表。只要是可以通过连续标号进行增删改查的类型就可以。如果使用数组需要自己实现功能。

使用了person类型的list,就需要自定义的person类,这个类中可以实现多属性的包含。

package com.example.a18_listview;
public class Person {
private int image;
private String name;
private int age;
private String info;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public int getImage() {
return image;
}
public Person(int image, String name, int age, String info) {
super();
this.image = image;
this.name = name;
this.age = age;
this.info = info;
}
public void setImage(int image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
类中定义了view list模版中需要的属性。

通过一定的方式填充model数据,这里简单的通过for循环和数组进行数据的填充。

private String names[] = { "如花", "旺财", "小翠", "小芳", "小刚", "小龙" };
private int images[] = { R.drawable.ruhua, R.drawable.wangcai,
R.drawable.xiaocui, R.drawable.xiaofang, R.drawable.xiaogang,
R.drawable.xiaolong };
private int ages[] = { 18, 19, 20, 21, 22, 23 };
private String infos[] = {"我很高兴"};

……
for (int i = 0; i < 6; i++) {
list.add(new Person(images[i], names[i], ages[i], infos[0]));

}
现在有了M和V ,只差C的实现。

创建自定义的Adapter,MyAdapter类。

参考Adapter系统实现,需要继承BaseAdapter类,并提示实现4个方法。

首先需要根据自己的需要实现构造函数,构造函数的参数可以根据要求定义。先看需要重写的方法吧。

第一个:获得传入的数据长度,即条目个数,需要返回list长度,或数组长度等。

@Override
public int getCount() {// 获取数量 将来要设定到lsitview控件上面的数据源的个数
// TODO Auto-generated method stub
return list.size();
}
第二个:获得条目,返回值为object表示可以返回任何类型,可以根据自己需要返回。此处返回的是list ID,也可以返回list条目中的项目,如 : return list.get(position);

@Override
public Object getItem(int position) {// 获取元素的对象(一般用在监听事件)
// TODO Auto-generated method stub
return position;
}
第三个:获得条目ID,如果在条目中定义了ID 这个属性,可以返回该值,此处,返回调用值,即list的ID 是顺序排列。

@Override
public long getItemId(int position) {// 获取元素的ID(一般用在监听事件)
// TODO Auto-generated method stub
return position;
}
第四个:填充listView视图,绘制listView视图

返回值为view类型,需要返回填充的listView模板的view类型。所以就需要在构造的时候将view传进来,但是一般layout的id容易获得,所以传入的一般是layout id,当然也可以直接传入view。

标记:构造器需要一个layout id类型参数。并用类属性保存。private int resource;

下面需要通过layout id得到layout的view类型。

View inflate = LayoutInflater.from(context).inflate(resource, null);

这句话的中需要用到context,上下文依赖关系,即是从哪个java代码包含的layout文件中查找id值(setContentView(R.layout.activity_main);),这是由于在xml中同名组件公用id,所以需要这个过程来查找id属于哪个xml。

标记:构造器需要一个context类型的参数。用于保存调用的上下文依赖关系。private Context context;

剩下的就很简单了,将list中项目的属性,依次填入listView模板中,注意,此处之需要完成一次的填充,可以使用入口参数position定位list的项目。这个方法是系统绘制时调用,由系统根据list的条目数(getCount() ),进行一次绘制。

根据position取出list中的条目。

标记:构造器需要将list传入,这个不用说,不传进来都不知道往模板上填什么。

Person person = list.get(position);

得到条目中的每个属性。

String name = person.getName();

int image = person.getImage();

int age = person.getAge();

根据layout中的组件id找到具体的组件,组件归属由前面得到的view参数获得。

// 設定到控件上面去

// 找控件

TextView tv = (TextView) inflate.findViewById(R.id.st_name);

ImageView iv = (ImageView) inflate.findViewById(R.id.st_image);

TextView st_age = (TextView) inflate.findViewById(R.id.st_age);

将list条目的属性填写到layout模板的组件中去。

/**

* 设定内容

*/

tv.setText(name);

iv.setImageResource(image);

st_age.setText(age + "");//age为int类型,而settext传入的参数为charsequence

最后将前面的到的view返回。

return inflate;

方法完整代码

/**
* getview获取listview的每一项的view视图(返回的是具体的内容)
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
/**
* 将布局(int)转化为view类型视图
*/
View inflate = LayoutInflater.from(context).inflate(
resource, null);
// 将arraylist数据源的数据设定到控件上面
Person person = list.get(position);
String name = person.getName();
int image = person.getImage();
int age = person.getAge();
// 設定到控件上面去
// 找控件
TextView tv = (TextView) inflate.findViewById(R.id.st_name);
ImageView iv = (ImageView) inflate.findViewById(R.id.st_image);
TextView st_age = (TextView) inflate.findViewById(R.id.st_age);
/**
* 设定内容
*/
tv.setText(name);
iv.setImageResource(image);
st_age.setText(age + "");//age为int类型,而settext传入的参数为charsequence
return inflate;
}
最后是完成构造器

根据前面的标记,知道要实现这4个方法,必须要的属性参数。

// 参数为 布局,数据源,
public MyAdapter(int resource, ArrayList<Person> list, Context context) {
this.resource = resource;
this.list = list;
this.context = context;
}
到这里,自己的myadapter类就完成了。回到主函数中进行MC与VC的关联,就完成了整个MVC过程。

和系统提供的adapter一样,对model和adapter关联,通过adapter的构造器把list数据提交给adapter。

/**
* 适配器
*/
MyAdapter adapter = new MyAdapter(R.layout.mylistview_item, list,
ThirdAct.this);
将viewlist和adapter关联,通过listview的set方法将adapter传递给listview。

这样listview就知道通过什么方式填充listview中的数据,即实现的getView()方法,同时adapter中携带了list数据,也就知道需要填写多少数据。

/**
* 将adapter适配器设定到listview中
*/
lv.setAdapter(adapter);
到这里就完成自定义的adapter。

入口函数代码:

package com.example.a18_listview;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
public class ThirdAct extends Activity {
private ListView lv;
private String names[] = { "如花", "旺财", "小翠", "小芳", "小刚", "小龙" };
private int images[] = { R.drawable.ruhua, R.drawable.wangcai,
R.drawable.xiaocui, R.drawable.xiaofang, R.drawable.xiaogang,
R.drawable.xiaolong };
private int ages[] = { 18, 19, 20, 21, 22, 23 };
private String infos[] = {"我很高兴"};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) this.findViewById(R.id.lv);
/**
* 数据源
*/
ArrayList<Person> list = new ArrayList<Person>();
for (int i = 0; i < 6; i++) {
list.add(new Person(images[i], names[i], ages[i], "我很高兴"));
}
/**
* 适配器
*/
MyAdapter adapter = new MyAdapter(R.layout.mylistview_item, list,
ThirdAct.this);
/**
* 将adapter适配器设定到listview中
*/
lv.setAdapter(adapter);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: