扣丁学堂笔记第05天高级UI组件(一)
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; }@Overridepublic int getCount() {// TODO Auto-generated method stubreturn images.length;}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn images[position];}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubImageView iv = new ImageView(context);iv.setImageResource(images[position]);return iv;} } }
activity_main.xml
<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()方法里添加代码:LayoutInflaterinflater = 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() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// TODO Auto-generated method stubToast.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; }@Overridepublic int getCount() {// TODO Auto-generated method stubreturn names.length;}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn names[position];}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View view, ViewGroup parent) {// TODO Auto-generated method stubLayoutInflater 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;} } }
activity_main.xml
<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>
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" > <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>
MainActivity.java
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;@Overrideprotected 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 stubreturn titles.length;}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn titles[position];}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubLayoutInflater 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 stubif(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 stubViewHolder 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;// } @Overridepublic int getCount() {// TODO Auto-generated method stubreturn news.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn news.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic 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 blocke.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;}@Overridepublic 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 blocke.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; } }; };
由于是采用实现接口的方式,别忘了在onCreate方法添加listView.setOnScrollListener(this);
更多相关文章
- Delphi XE5 Android 运行黑屏卡死的解决方法
- Android编程: 调试方法
- ListView常用属性、方法
- Android 控件(button)对齐方法实现详解
- Kotlin 写 Android 单元测试(四),Robolectric 在 JVM 上测试安卓相
- Android Studio更新升级方法
- android 实现 APP 保活且正常升级的方法