Android listview加载不同布局与adapter用法
2016-06-10 20:03
567 查看
Android listview加载不同布局与adapter用法
android开发过程中会经常用到listview,虽然recycleview也出来了,但是还是存在一些bug没有解决,还不是特别的成熟,那我们就来介绍一下listview的使用及其加载不同布局的item的一般写法。
首先我们listview需要加载不同的布局,首先我们需要些几个不同的布局(我写不同item的布局喜欢以inflate_功能_type_one来命名,大家可以根据自己的习惯,但是一定要有一个好的编程习惯哦!!!)
布局一:
布局二:
布局三:
接下来就是需要写的是MyAdapter了,我这里是继承BaseAdapter来写的,首先我们需要重写BaseAdapter的四个方法,getCount(listview需要展示的个数,根据数据源而定的,我在这里是写的规固定的)、getItem(获取数据源的单个实体类)、getItemId(获取下角标位置)、getView(UI控件的获取及其数据的挂载)。
这里,我们需要写的是不同布局item显示的样式,我们还需要重写其他两个方法:getItemViewType(获取每一个下角标(position)相对应得item类型),getViewTypeCount(几种布局的显示的总数)。
注意:
因为在实际开发项目中,我们要加载的数据往往是特别大的,这时候我们就要考虑布局的复用,说到复用我们就要来了解一下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(getLayoutInflater().inflate(R.layout.inflate_type_one, parent,false);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。
getView方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个子View,如:一个TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以。
我们就需要先写几个不同item需要的viewHolder类:
getView方法:
实现效果截图:
![](http://img.blog.csdn.net/20160610200155290)
![](http://img.blog.csdn.net/20160610200212041)
最后附整体代码:
大家有什么android开发问题可以一起交流(QQ:965244491 附微信二维码
android开发过程中会经常用到listview,虽然recycleview也出来了,但是还是存在一些bug没有解决,还不是特别的成熟,那我们就来介绍一下listview的使用及其加载不同布局的item的一般写法。
首先我们listview需要加载不同的布局,首先我们需要些几个不同的布局(我写不同item的布局喜欢以inflate_功能_type_one来命名,大家可以根据自己的习惯,但是一定要有一个好的编程习惯哦!!!)
布局一:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/txt_inflat_type_one" android:background="#44C494" android:layout_width="match_parent" android:layout_height="40dp"> </TextView>
布局二:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:background="#ffa07a" android:layout_width="match_parent" android:layout_height="40dp"> <TextView android:id="@+id/txt_inflat_type_two" android:layout_width="200dp" android:layout_height="match_parent" /> <ImageView android:id="@+id/img_inflat_type_two" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@null" android:background="@mipmap/ic_launcher"/> </LinearLayout>
布局三:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="40dp"> <TextView android:id="@+id/txt_inflat_type_there_1" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/txt_inflat_type_there_2" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
接下来就是需要写的是MyAdapter了,我这里是继承BaseAdapter来写的,首先我们需要重写BaseAdapter的四个方法,getCount(listview需要展示的个数,根据数据源而定的,我在这里是写的规固定的)、getItem(获取数据源的单个实体类)、getItemId(获取下角标位置)、getView(UI控件的获取及其数据的挂载)。
这里,我们需要写的是不同布局item显示的样式,我们还需要重写其他两个方法:getItemViewType(获取每一个下角标(position)相对应得item类型),getViewTypeCount(几种布局的显示的总数)。
注意:
//listview显示时的不同布局的item private int TypeOne=0;//注意这个不同布局的类型起始值必须从0开始 private int TypeTwo=1; private int TypeThere=2;
因为在实际开发项目中,我们要加载的数据往往是特别大的,这时候我们就要考虑布局的复用,说到复用我们就要来了解一下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(getLayoutInflater().inflate(R.layout.inflate_type_one, parent,false);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。
getView方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个子View,如:一个TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以。
我们就需要先写几个不同item需要的viewHolder类:
private class TypeOneViewHolder{ private TextView txt_inflat_type_one; } private class TypeTwoViewHolder{ private TextView txt_inflat_type_two; private ImageView img_inflat_type_two; } private class TypeThereViewHolder{ private TextView txt_inflat_type_there_1; private TextView txt_inflat_type_there_2; }
getView方法:
@Override public View getView(int position, View convertView, ViewGroup parent) { TypeOneViewHolder typeOneViewHolder = null; TypeTwoViewHolder typeTwoViewHolder = null; TypeThereViewHolder typeThereViewHolder = null; int Type=getItemViewType(position); //第一次没有加载convertView if(convertView==null){ if(Type==TypeOne){ convertView=getLayoutInflater().inflate(R.layout.inflate_type_one,parent,false); typeOneViewHolder=new TypeOneViewHolder(); typeOneViewHolder.txt_inflat_type_one= (TextView) convertView.findViewById(R.id.txt_inflat_type_one); convertView.setTag(typeOneViewHolder); }else if(Type==TypeTwo){ convertView=getLayoutInflater().inflate(R.layout.inflate_type_two,parent,false); typeTwoViewHolder=new TypeTwoViewHolder(); typeTwoViewHolder.txt_inflat_type_two= (TextView) convertView.findViewById(R.id.txt_inflat_type_two); typeTwoViewHolder.img_inflat_type_two= (ImageView) convertView.findViewById(R.id.img_inflat_type_two); convertView.setTag(typeTwoViewHolder); }else if(Type==TypeThere){ convertView=getLayoutInflater().inflate(R.layout.inflate_type_there,parent,false); typeThereViewHolder=new TypeThereViewHolder(); typeThereViewHolder.txt_inflat_type_there_1= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_1); typeThereViewHolder.txt_inflat_type_there_2= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_2); convertView.setTag(typeThereViewHolder); } }else { //布局的复用convertView //根据setTag()和getTag()方法来实现布局的复用 if(Type==TypeOne){ typeOneViewHolder= (TypeOneViewHolder) convertView.getTag(); }else if(Type==TypeTwo){ typeTwoViewHolder= (TypeTwoViewHolder) convertView.getTag(); }else if(Type==TypeThere){ typeThereViewHolder= (TypeThereViewHolder) convertView.getTag(); } } //设置数据 if(Type==TypeOne){ typeOneViewHolder.txt_inflat_type_one.setText("第一种布局"+position); }else if(Type==TypeTwo){ typeTwoViewHolder.txt_inflat_type_two.setText("第二种布局"+position); typeTwoViewHolder.img_inflat_type_two.setImageResource(R.mipmap.ic_launcher); }else if(Type==TypeThere){ typeThereViewHolder.txt_inflat_type_there_1.setText("第三种布局"+position+"左"); typeThereViewHolder.txt_inflat_type_there_2.setText("第三种布局"+position+"右"); } return convertView; }
实现效果截图:
最后附整体代码:
package com.example.administrator.baseadapterapplication;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
/**
* Android listview加载不同布局与adapter用法
*@author wujun
*
*/
public class MainActivity extends AppCompatActivity {
private ListView listView;
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initView() {
listView= (ListView) findViewById(R.id.listview);
}
private void initData() {
myAdapter=new MyAdapter(MainActivity.this);
listView.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
}
//适配器
private class MyAdapter extends BaseAdapter {
private Context mcontext;
//listview显示时的不同布局的item
private int TypeOne=0;//注意这个不同布局的类型起始值必须从0开始
private int TypeTwo=1;
private int TypeThere=2;
private MyAdapter(Context context){
mcontext=context;
}
@Override
public int getCount() {
return 30;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
//item的不同布局的判断
@Override
public int getItemViewType(int position) {
// return super.getItemViewType(position);
if(position==1||position==5||position==10||position==15||position==20||position==26){
return TypeOne;
}else if(position==2||position==6||position==8||position==13||position==23||position==0){
return TypeTwo;
}else {
return TypeThere;
}
}
@Override
public int getViewTypeCount() {
// return super.getViewTypeCount();
return 3;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TypeOneViewHolder typeOneViewHolder = null;
TypeTwoViewHolder typeTwoViewHolder = null;
TypeThereViewHolder typeThereViewHolder = null;
int Type=getItemViewType(position);
if(convertView==null){
if(Type==TypeOne){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_one,parent,false);
typeOneViewHolder=new TypeOneViewHolder();
typeOneViewHolder.txt_inflat_type_one= (TextView) convertView.findViewById(R.id.txt_inflat_type_one);
convertView.setTag(typeOneViewHolder);
}else if(Type==TypeTwo){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_two,parent,false);
typeTwoViewHolder=new TypeTwoViewHolder();
typeTwoViewHolder.txt_inflat_type_two= (TextView) convertView.findViewById(R.id.txt_inflat_type_two);
typeTwoViewHolder.img_inflat_type_two= (ImageView) convertView.findViewById(R.id.img_inflat_type_two);
convertView.setTag(typeTwoViewHolder);
}else if(Type==TypeThere){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_there,parent,false);
typeThereViewHolder=new TypeThereViewHolder();
typeThereViewHolder.txt_inflat_type_there_1= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_1);
typeThereViewHolder.txt_inflat_type_there_2= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_2);
convertView.setTag(typeThereViewHolder);
}
}else {
if(Type==TypeOne){
typeOneViewHolder= (TypeOneViewHolder) convertView.getTag();
}else if(Type==TypeTwo){
typeTwoViewHolder= (TypeTwoViewHolder) convertView.getTag();
}else if(Type==TypeThere){
typeThereViewHolder= (TypeThereViewHolder) convertView.getTag();
}
}
//设置数据
if(Type==TypeOne){
typeOneViewHolder.txt_inflat_type_one.setText("第一种布局"+position);
}else if(Type==TypeTwo){
typeTwoViewHolder.txt_inflat_type_two.setText("第二种布局"+position);
typeTwoViewHolder.img_inflat_type_two.setImageResource(R.mipmap.ic_launcher);
}else if(Type==TypeThere){
typeThereViewHolder.txt_inflat_type_there_1.setText("第三种布局"+position+"左");
typeThereViewHolder.txt_inflat_type_there_2.setText("第三种布局"+position+"右");
}
return convertView;
}
private class TypeOneViewHolder{ private TextView txt_inflat_type_one; } private class TypeTwoViewHolder{ private TextView txt_inflat_type_two; private ImageView img_inflat_type_two; } private class TypeThereViewHolder{ private TextView txt_inflat_type_there_1; private TextView txt_inflat_type_there_2; }
}
}
大家有什么android开发问题可以一起交流(QQ:965244491 附微信二维码
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories