1.GridVIew
GridVIew常用属性与自定义适配器
常用属性
android:numColumns="auto_fit"列数设置为自动
android:columnWidth="90dp"每列的宽度,即item的宽度
android:stretchMode="columnWidth"缩放与列宽大小同步
android:verticalSpacing="10dp"两行之间的边距
android:horizontalSpacing="10dp"两列之间的边距
自定义适配器
在MainActivity.java中自定义一个适配器继承自BaseAdapter,static class MyAdapter extends BaseAdapter{},(注:这里之所以用static修饰,是因为内部类优先考虑定义成静态类,这样子相当于外部类,它不依赖于外部的对象,因而效率更高。)然后重写四个方法getCount()、getItem()、getItemId()、getView()。
定义一个整型数组来存放图片资源的id:int[] images = {R.drawable.p0,...,...};然后getCount()返回的是images.lenght; getItem()返回的是images[position]; getItemId()返回的是Position;
重点关注的是getView()方法。先在MyAdapter类中添加代码:private Context context;public MyAdapter(Context context){this.context = context;} 然后创建一个ImageView:ImageVIew iv = new ImageView(context); 然后调用setImageResoure()方法,参数images[position]; 然后return iv。
最后加载适配器.gridView.setAdapter(new MyAdapter(this));
GridView图文排列
简单的图片排列
MainActivity.java
package com.example.gridviewtest; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; public class MainActivity extends Activity { private GridView gridView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gridView = (GridView) findViewById(R.id.gridView1); gridView.setAdapter(new MyAdapter(this)); } static class MyAdapter extends BaseAdapter{ int[] images = {R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7,}; private Context context; public MyAdapter(Context context){ this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return images.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return images[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ImageView iv = new ImageView(context); iv.setImageResource(images[position]); return iv; } } }
<GridView android:id="@+id/gridView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:gravity="center" android:columnWidth="90dp" android:horizontalSpacing="10dp" android:verticalSpacing="10dp" android:stretchMode="columnWidth" android:numColumns="auto_fit" > </GridView>
图文排列
实现代码基本同上,多定义一组字符串数组用来显示文字,返回的名称可以是图片的名称,也可以是文字的名称
在getView()方法里,因考虑到效率问题,本次不采用new一个ImageView和TextView的方法。在layout文件夹中新建一个item.xml文件,添加ImageView和TextView组件
在getView()方法里添加代码:LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.infalte(R.layout.item,null);
然后通过view.findViewById()实例化ImageView和TextView;
然后调用setImageResource方法和setText方法放置资源文件;
最后返回view。
程序拓展:
可以为每个视图设置点击事件,setOnItemClickListener(new AdapterView.OnItemClickListener());其中onItemClick的四个参数:parent表示GridView,view表示item.xml中的布局LinearLayout,position表示位置,id表示编号
MainActivity.java代码
package com.example.gridviewtest2; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private GridView gridView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gridView = (GridView) findViewById(R.id.gridView1); gridView.setAdapter(new MyAdapter(this)); gridView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "parent="+parent, Toast.LENGTH_SHORT).show(); } }); } static class MyAdapter extends BaseAdapter{ String[] names={"Android1","Android2","Android3","Android4","Android5","Android6","Android7","Android8"}; int[] images = {R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher}; private Context context; public MyAdapter(Context context){ this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return names.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return names[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View view, ViewGroup parent) { // TODO Auto-generated method stub LayoutInflater inflater = LayoutInflater.from(context); View view1 = inflater.inflate(R.layout.item, null); ImageView iv = (ImageView) view1.findViewById(R.id.imageview); TextView tv = (TextView) view1.findViewById(R.id.textview); iv.setImageResource(images[position]); tv.setText(names[position]); return view1; } } }
<GridView android:id="@+id/gridView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:numColumns="3" android:horizontalSpacing="10dp" android:verticalSpacing="10dp" android:stretchMode="columnWidth" android:columnWidth="60dp" android:gravity="center" > </GridView>
<?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="vertical" > <ImageView android:id="@+id/imageview" android:layout_width="wrap_content" android:layout_height="wrap_content" ></ImageView> <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
2.ListView
ListView是安卓中最常用的一种视图组件,它以垂直列表的方式列出需要显示的列表项
ListView基本属性配置
android:cacheColorHint="#00000000"设置拖动背景为透明
android:dividerHeight="30px"item之间的高度
android:divider="@drawable/ic_launcher"item之间的背景或者说是颜色
android:fadingEdge="vertical"上边和下边有黑色的阴影,值为none就没有阴影
android:drawSelectorOnTop="false"点击某条记录不放,颜色会在记录的后面,成为背景色
android:scrollbars="horizontal|vertical"显示滚动条,并且会自动显示和隐藏
android:fastScrollEnable="true"快速滚动
android:listSelector="@color/pink"item选中时的颜色
android:entries="@array/citys"设置列表填充的内容
ListView_ListActivity和单选多选
ListActivity(继承Activity)提供了一个列表项的视图来显示数据,可以绑定指定的数据源。ArrayAdapter arrayAdapter = ArrayAdapter.createFromResource(this,R.array.name,android.R.layout.simple_list_item_1);
重写onListItemClick方法:Toas.makeText(this,(ListView)v.getText(),Toast.LENGTH_SHOW).show();
单选和多选模式
先在values写好一个array.xml资源文件,通过getResources()的getStringArray来绑定array资源,类型类String数组;
创建一个ArrayAdapter适配器实例(单选布局文件为android.R.layout.simple_list_item_single_choice,多选为android.R.layout.simple_list_item_multiple_choice),调用它的setChoiceMode方法(单选为ListView.CHOICE_MODE_SINGLE,多选为ListView.CHOICE_MODE_MULTIPLE).
arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <array name="names"> <item>贝贝1</item> <item>贝贝2</item> <item>贝贝3</item> <item>贝贝4</item> <item>贝贝5</item> <item>贝贝6</item> <item>贝贝7</item> <item>贝贝8</item> <item>贝贝9</item> <item>贝贝10</item> <item>贝贝11</item> </array> </resources>
private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView1); String[] arr = getResources().getStringArray(R.array.names); // ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice,arr); // listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); // listView.setAdapter(arrayAdapter); // ArrayAdapter<String> arrayAdapter1 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice,arr); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setAdapter(arrayAdapter1); }
ListView_SimpleAdapter
使用SimpleAdapter建立复杂的列表项
SimpleAdapter(Context context,List<? extends Map<String,?>> data,int resource,String[] from,int[] to)
参数:
context:SimpleAdapter关联的view运行的环境;
data:一个Map组成的List。在列表中的每个条目对应列表中的一行,每一个map中应包含所有在from参数中指定的键;
resource:一个定义列表项的布局文件的资源ID,布局文件中至少应包含在to中定义了的ID。
from:一个将被添加到map映射的键名;
to:将绑定的数据视图的ID,跟from参数对应,这里应该全是TextView。
1.准备数据,每个HashMap是一条记录
HashMap<String, String> title1 = new HashMap<>();
title1.put("title","title--1");
HashMap<String, String> title2 = new HashMap<>();
title2.put("title","title--2");
......(title3,4,5,6)
ArrayList<Map<String,String>> list = new ArrayList<>();
list.add(title1);
list.add(title2);
......(title3,4,5,6)
2.把数据填充到Adapter
SimpleAdapter sa = new SimpleAdapter(this,list,R.layoutlist_.item(自定义的布局文件),new String[]{"titlle"},new int[]{R.id.textView_title}(自定义textView组件的id) );
listView.setAdapter(sa);
SimpleAdapter补充
把上文HashMap<>改为HashMap<String,Object>后,不仅可以存放字符串还可以存放图片资源
title1.put("icon",R.drawable.icon);
SimpleAdapter sa = new SimpleAdapter(this,list,R.layoutlist_.item(自定义的布局文件),new String[]{"titlle","icon"},new int[]{R.id.textView_title,R.id.imageView_icon});
MainActivity.java
package com.example.simpleadaptertest; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends Activity { private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView1); HashMap<String, Object> data1 = new HashMap<String, Object>(); data1.put("icon", R.drawable.ic_launcher); data1.put("info", "我是内容1"); HashMap<String, Object> data2 = new HashMap<String, Object>(); data2.put("icon", R.drawable.ic_launcher); data2.put("info", "我是内容2"); HashMap<String, Object> data3 = new HashMap<String, Object>(); data3.put("icon", R.drawable.ic_launcher); data3.put("info", "我是内容3"); HashMap<String, Object> data4 = new HashMap<String, Object>(); data4.put("icon", R.drawable.ic_launcher); data4.put("info", "我是内容4"); ArrayList<Map<String, Object>> list = new ArrayList<Map<String,Object>>(); list.add(data1); list.add(data2); list.add(data3); list.add(data4); SimpleAdapter sa = new SimpleAdapter(this, list, R.layout.list_item, new String[]{"icon","info"},new int[]{R.id.iv_images,R.id.tv_info}); listView.setAdapter(sa); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
activity_man.xml
<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="com.example.simpleadaptertest.MainActivity" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > </ListView> </RelativeLayout>
list_item.xml
<?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/iv_images" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dp" android:paddingRight="10dp" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tv_info" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
ListView_自定义适配器
使用BaseAdapter实现更加灵活的列表
由于BaseAdapter是一个抽象类,因此需要自己写一个类继承它
public int getCount()
public Object getItem(int position)
public long getItemId(int position)
public View getView(int position,View convertView,ViewGroup parent)
具体代码:
创建一个MyAdapter继承BaseAdapter实现其4个方法,定义一个字符串数组和一个整型数组用来存放文字和图片资源。getCount返回titles.length,getItem返回titles[position],getItemId返回position,重点是getView方法。
这里需要一个构造方法(因为需要用它来实例化LayoutInflater),private Context context; public My Adapter(Context context){this.context = context;}
在getView方法添加代码:
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.list_item,null);
通过view的FindViewById实例化textView和imageView;
然后调用setText和setImageResource方法加载资源;
最后return view。
MainActivity.java代码
package com.example.baseadaptertest; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(new MyAdapter(this)); } static class MyAdapter extends BaseAdapter{ int[] icons = {R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher}; String[] titles = {"我是标题1","我是标题2","我是标题3","我是标题4", "我是标题5","我是标题6",}; String[] infos = {"我是内容1","我是内容2","我是内容3","我是内容4", "我是内容5","我是内容6",}; private Context context; public MyAdapter(Context context){ this.context = context; } public int getCount() { // TODO Auto-generated method stub return titles.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return titles[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.list_item, null); ImageView iv = (ImageView) view.findViewById(R.id.img); TextView title = (TextView) view.findViewById(R.id.title); TextView info = (TextView) view.findViewById(R.id.info); iv.setImageResource(icons[position]); title.setText(titles[position]); info.setText(infos[position]); return view; } } }
activity_main.xml
<ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > </ListView>
list_item.xml
<?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/img" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp"/> <TextView android:id="@+id/info" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp"/> </LinearLayout> </LinearLayout>
ListView_使用convertView优化对象的创建
重复使用convertView
public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub if(convertView == null){ LayoutInflater inflater = LayoutInflater.from(context); convertView = inflater.inflate(R.layout.list_item, null); } System.out.println(position+"--------"+convertView); ImageView iv = (ImageView) convertView.findViewById(R.id.img); TextView title = (TextView) convertView.findViewById(R.id.title); TextView info = (TextView) convertView.findViewById(R.id.info); iv.setImageResource(icons[position]); title.setText(titles[position]); info.setText(infos[position]); return convertView; }
ListView_ViewHolder优化
使用ViewHolder提供在容器中查找组件的效率
实现步骤:
创建一个ViewHolder类,用于保存第一次查找的组件,避免下次重复查找;
在if语句中new一个ViewHolder对象,再实例化组件后定义为viewHolder.tv_icon;再添加convert.setTag(viewHolder);
如果convertView不为空,viewHolder = (ViewHolder)convertView.getTag();
viewHolder.tv_title.setText(titles[position]);
public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder viewHolder; if(convertView == null){ LayoutInflater inflater = LayoutInflater.from(context); convertView = inflater.inflate(R.layout.list_item, null); viewHolder = new ViewHolder(); viewHolder.iv = (ImageView) convertView.findViewById(R.id.img); viewHolder.title = (TextView) convertView.findViewById(R.id.title); viewHolder.info = (TextView) convertView.findViewById(R.id.info); convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.iv.setImageResource(icons[position]); viewHolder.title.setText(titles[position]); viewHolder.info.setText(infos[position]); return convertView; }
static class ViewHolder{ ImageView iv; TextView title; TextView info; }
ListView刷新分页
新建一个News外部类,定义title和context变量;
在MainActivity中定义一个初始化数据方法:private void initData(),先在外部定义一个index,然后再initData方法里添加一个for循环(先在方法外new一个类为News名称为news的Vector容器),在for循环里添加代码:News n = new News(); n.title = "title--"+index; n.context ="context--"+index; index++; news.add(n);
在onCreate()添加代码:initData();
新建一个MyAdapter继承自BaseAdapter,实现其4个方法,getCount返回news.size()(news的总数); getItem返回news.get(position); getItemId返回position;getView方法采用ViewHolder优化的代码,注意viewHolder.tv_title.setText(n.title)之前要加一句代码:News n = news.get(position);
News.java
package com.example.myadapterdemo; public class News { String title; String context; }
MainActivity.java
package com.example.myadapterdemo; import java.util.Vector; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { private ListView listView; private Vector<News> news = new Vector<News>(); private MyAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView1); initData(); adapter = new MyAdapter(); listView.setAdapter(adapter); } private int index = 1; private void initData(){ for(int i=0;i<10;i++){ News n = new News(); n.title = "title--"+index; n.context = "context"+index; index++; news.add(n); } } class MyAdapter extends BaseAdapter{ // private Context context; // public MyAdapter(Context context){ // this.context = context; // } @Override public int getCount() { // TODO Auto-generated method stub return news.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return news.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder vh; if(convertView==null){ // LayoutInflater inflater = LayoutInflater.from(context); // convertView = inflater.inflate(R.layout.list_item, null); convertView = getLayoutInflater().inflate(R.layout.list_item, null); vh = new ViewHolder(); vh.textView = (TextView)convertView.findViewById(R.id.tv_title); vh.textView2 = (TextView) convertView.findViewById(R.id.tv_content); convertView.setTag(vh); }else{ vh = (ViewHolder) convertView.getTag(); } News n = news.get(position); vh.textView.setText(n.title); vh.textView2.setText(n.context); return convertView; } class ViewHolder{ TextView textView; TextView textView2; } } }
activity_main.xml
<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="com.example.myadapterdemo.MainActivity" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > </ListView> </RelativeLayout>
list_item.xml
<?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="vertical" > <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_content" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
调用listView的addFooterView方法为列表添加加载数据提示
首先新建一个loading的xml文件,添加一个小的进度条和一个小的textview;
然后在onCreate添加代码:View footerView = getLayoutInflater().inflate(R.layout.loading,null);addFooterView传入footerView参数;
loading.xml
<?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="wrap_content" android:orientation="horizontal" android:gravity="center"> <ProgressBar android:id="@+id/progress_bar" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@android:attr/progressBarStyleSmall"/> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正在玩命加载中..." android:textAppearance="?android:attr/textAppearanceSmall" /> </LinearLayout>
MainActivity.java
View footerView = getLayoutInflater().inflate(R.layout.loading, null); listView.addFooterView(footerView);
创建一个线程,再次加载一遍数据
class loadDataThread extends Thread{ @Override public void run() { initData(); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } adapter.notifyDataSetChanged();//这句会报错,因为子线程不能直接访问UI线程的组件 } }
让MainActivity实现onScrollListener监听事件,重写两个方法,onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)和onScrollStateChanged(AbsListView view, int scrollState)。先定义一个可视的最后一个item的索引:visibleLastIndex,在onScroll方法添加代码:visibleLastIndex = firstVisibleItem+visibleItemCount-1;然后再onScrollStateChanged方法添加代码:if(adapter.getCount()==visibleLastIndex&&scrollState==SCROLL_STATE_IDLE){ new loadDataThread().start(); }
为了解决线程之间的通信问题,引入了Handler机制:先定义一个静态的常整型变量DATE_UPDATE,在子线程中发送此标记提醒主线程,子线程已完成更新操作,这里新建一个Handler对象,重写它的handleMessage方法:使用switch语句,如果case DATE_UPDATE,调用notifyDataSetChanged方法。
private int visibleLastIndex; public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { visibleLastIndex = firstVisibleItem+visibleItemCount-1; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if(adapter.getCount()==visibleLastIndex&&scrollState==SCROLL_STATE_IDLE){ new loadDataThread().start(); } }
class loadDataThread extends Thread{ @Override public void run() { initData(); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // adapter.notifyDataSetChanged(); //通过handler给主线程发送一个标记 handler.sendEmptyMessage(DATE_UPDATE); } }
private static final int DATE_UPDATE = 0x1;//十六进制的一
//线程之间通信的机制Handler private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch(msg.what){ case DATE_UPDATE: adapter.notifyDataSetChanged(); break; } }; };