ListView下拉刷新的一些常见错误
来源:互联网 发布:js控制浏览器最小化 编辑:程序博客网 时间:2024/04/25 08:51
第一篇博客
(ListView下拉刷新常见错误)
开篇之前还是感谢我今次的这个冲动(写博客),不然我现在也不会有这篇文章,以后也不会有这种写博客的习惯。对于博客,个人还是比较支持,因为你可以在前辈的博客里面学到很多有用的知识,人是不断求进的,不要拘于小节才是王道。好了,入正文了。
android是一个开源项目,各种效果经过几年的时间已经有了很多现成的框架,直接上网下载cp过来就ok了。但个人认为,懂其如何套用之外,还要真正懂其原理,这才是以后遇到什么问题就知道如何解决问题,而且扩展性的空间也很大,对吧。首先说明一下,在你开始新建项目的时候,你要明白几个方法/属性/常量的值是代表什么的。(方法不只一种,这里是用到重写ListView控件的方法,仅供参考)
方法:
(1)public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) 这个是ListView控件滑动的时候所触发的一个方法(可以理解为随时监控ListView滑动的情况),其中只、主要有三个重要参数:
firstVisibleItem:为你在手机屏幕看到当前ListView的第一个子项索引;
visibleItemCount:为你在手机屏幕看到当前ListView最后一个子项索引(半个也算一个);
totalItemCount:为你ListView子项的总数目(adapter的size),要注意的是,当你设置了头部(head)view与底部(foot)view 的时候,则totalItemCount 则变成totalItemCount+2;
情景想像:当你的ListView有大量子集时(出现滚动条),此刻你处于一个中间状态,那么你的手指不断向下滑,那么当滚动到顶部的时候(碰到顶部),这时候的firstVisibleItem就等于0。(不知道你明白这三个参数的关系没有,在不出现头底部的时候。firstVisibleItem+visibleItemCount=totalItemCount)。
(2)public void onScrollStateChanged(AbsListView view, int scrollState) 这是在ListView控件里面一个监控手势的方法,其中有一个重要的参数----scrollState。
scrollState:为判断你做出的动作,常用作与下面三个常量作判断(if (scrollState == XXX))
<1>SCROLL_STATE_IDLE 你滚动屏幕的时候,强行停止滚动所触发的一个事件
<2>SCROLL_STATE_FLING 你拖动控件之后(手指离开屏幕),然后控件随着惯性的作用下自动滚动期间所触发的事件
<3>SCROLL_STATE_TOUCH_SCROLL 你拖动控件(手指一直不离开屏幕)的时候所触发的一个事件
(3)重写控件的onTouchEvent
这个方法是作用于刷新状态的控制,这个可由你们自由控制,当手指滑到什么程度的时候就达到刷新的状态。
通常控制在三个行为上:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP
好了,到现在为止已经部署好最关键的三个步骤,接下来就是添加 头部view 与 底部 view。
这里要注意一个问题,也是害我很惨的地方。例如 :this.addHeaderView(linHead); 一定要放在 setAdapter(new adapter(this.getContext())); 的前面。再强调一次,是前面。不然会抛出异常,这个追究下去,可以查看setAdapter的源码。
当然还要添加一些数据测试了,这里就不多说了。
下面贴出一个demo,仅供参考:
文件清单:com/example/listview_rewrite/MainActivity.java
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private MyListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mListView = new MyListView(this);
setContentView(mListView);
}
}
文件清单:com/example/listview_rewrite/MyListView.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.TextView;
public class MyListView extends ListView implements OnScrollListener{
private int flag = -1;
private boolean b = false;
private int sy,dy;
private boolean bb = false;
private LayoutInflater mlayoutInflater;
private LinearLayout linHead_container;
private LinearLayout linFoot_container;
private LinearLayout linHead;
private LinearLayout linFoot;
public final class ViewHolder{
public TextView tv;
}
//初始化数据
private void init(){
setAdapter(new adapter(this.getContext()));
}
public class adapter extends BaseAdapter {
private LayoutInflater mLayoutInflater ;
public adapter(Context context){
//构造方法,获得布局引用
this.mLayoutInflater = LayoutInflater.from(context);
}
@Override
public View getView(int arg0, View convertView, ViewGroup arg2) {
//ViewHolder的作用就是避免重复创建,节省资源,提高效率为主要目的
ViewHolder holder = null;
if (convertView == null) {
holder=new ViewHolder();
//获得ListView的子项布局
convertView = mLayoutInflater.inflate(R.layout.textview, null);
holder.tv = (TextView)convertView.findViewById(R.id.tv);
convertView.setTag(holder);
}else {
holder = (ViewHolder)convertView.getTag();
}
holder.tv.setText(getData().get(arg0).get("title").toString());
return convertView;
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return getData().size();
}
};
//添加头部view与底部view一定要在初始化数据前面
public MyListView(Context context) {
super(context);
mlayoutInflater = LayoutInflater.from(context);
View v = mlayoutInflater.inflate(R.layout.foot, null);
linFoot = (LinearLayout)v.findViewById(R.id.foot);
linFoot_container = (LinearLayout)v.findViewById(R.id.foot_container);
this.addFooterView(linFoot);
v = mlayoutInflater.inflate(R.layout.head, null);
linHead = (LinearLayout)v.findViewById(R.id.head);
linHead_container = (LinearLayout)v.findViewById(R.id.head_container);
this.addHeaderView(linHead);
linHead_container.setVisibility(View.GONE);
linFoot_container.setVisibility(View.GONE);
init();
//设置监听
this.setOnScrollListener(this);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
this.setOnScrollListener(this);
mlayoutInflater = LayoutInflater.from(context);
// TODO Auto-generated constructor stub
}
public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
this.setOnScrollListener(this);
mlayoutInflater = LayoutInflater.from(context);
// TODO Auto-generated constructor stub
}
//设置数据
private ArrayList<Map<String, Object>> getData() {
ArrayList<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object>map = new HashMap<String, Object>();
for (int i = 0; i < 60; i++) {
map.put("title", "title"+(i+1));
list.add(map);
}
return list;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
sy = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
dy = (int) (event.getRawY() - sy);
// if(Math.abs(dy)>=480/3 ){
// if(flag == 1){
// Log.i("AAAAA", "底部刷新到了临界点1/3");
// bb = true;
// }else if(flag ==2){
// Log.i("AAAAA", "顶部刷新到了临界点1/3");
// bb = true;
// }else{
// bb = false;
// }
// }
//等于1就代表滑到底部了
if(flag == 1 ){
//小于0就代表向上滑动
if(dy<0){
//设置底部view为可见
linFoot_container.setVisibility(View.VISIBLE);
//笔者手机的分辨率是320*480
if(Math.abs(dy)>=480/3 ){
Log.i("AAAAA", "底部刷新到了临界点1/3");
bb = true;
}
}
}
//等于2就代表到达顶部了
else if(flag ==2){
//大于0就代表向下滑动
if(dy>0){
//设置顶部view为可见
linHead_container.setVisibility(View.VISIBLE);
//笔者手机的分辨率是320*480
if(Math.abs(dy)>=480/3 ){
Log.i("AAAAA", "顶部刷新到了临界点1/3");
bb = true;
}
}
}
break;
//松开手的时候,底部与顶部的view就隐藏了
case MotionEvent.ACTION_UP:
if(bb){
Log.i("AAAAA", "松手开始加载信息。。。。。");
if(flag == 1){
linFoot_container.setVisibility(View.GONE);
}else if(flag ==2){
linHead_container.setVisibility(View.GONE);
}else{
linFoot_container.setVisibility(View.GONE);
linHead_container.setVisibility(View.GONE);
}
}
else{
linFoot_container.setVisibility(View.GONE);
linHead_container.setVisibility(View.GONE);
}
break;
}
return super.onTouchEvent(event);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
Log.i("AAAA", "一共有f"+firstVisibleItem+"项。。。。");
Log.i("AAAA", "一共有v"+visibleItemCount+"项。。。。");
Log.i("AAAA", "一共有t"+totalItemCount+"项。。。。");
if(firstVisibleItem + visibleItemCount == totalItemCount
&& totalItemCount >0 ){
Log.i("AAAA", "到底部了。。。。");
b = true;
flag = 1;
}else if(firstVisibleItem ==0 && totalItemCount>0){
Log.i("AAAA", "到最顶了。。。。");
b = true;
flag = 2;
}else{
b = false;
flag = -1;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == SCROLL_STATE_FLING || scrollState==SCROLL_STATE_TOUCH_SCROLL
&& b && flag ==1){
Log.i("AAAA", "在这个时候加载底部信息。。。。");
}else if((scrollState == SCROLL_STATE_FLING || scrollState==SCROLL_STATE_TOUCH_SCROLL
&& b && flag ==2)){
Log.i("AAAA", "在这个时候加载头部信息。。。。");
}
}
}
文件清单:ListView_reWrite\res\layout\foot.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:id="@+id/foot"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/foot_container"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/btn"
android:text="查看更多"/>
</LinearLayout>
</LinearLayout>
文件清单:ListView_reWrite\res\layout\head.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:id="@+id/head"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/head_container"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="正在加载中。。。"/>
</LinearLayout>
</LinearLayout>
文件清单:ListView_reWrite\res\layout\textview.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv"/>
</LinearLayout>
好了,这篇文章将要结束了,还有一点没有讲的,是否会有朋友问,为什么在布局文件里面一定要嵌套多一个 LinearLayout呢? 正是这个原因,因为你要做到隐藏头部或底部view的时候
经测试是不作用根LinearLayout的,所以要做一个容器装载里面的view,然后调用就可以成功收放自如view了。
研究了一个下午,总算有点成果,对ListView 的理解也有初步认识,当然上面只是简单布局,还有使用,ListView的例子还有各式各样等等,这只是一个开始而已,不自满,求向上。
第一篇文章,写得不怎么清晰简洁,以后力求不冗余,讲重点,谢谢大家了,有疑问可以提出,能看到的都会尽量回答,大家交流学习。
- ListView下拉刷新的一些常见错误
- ListView 下拉刷新错误
- Listview的下拉刷新
- listView的下拉刷新
- listView的下拉刷新
- android listview 的下拉刷新
- Android listView的下拉刷新
- ListView下拉刷新的实现
- Android ListView的下拉刷新
- 自定义下拉刷新的listview
- ListView下拉刷新的实现
- RefreshListView listView的下拉刷新
- 别致的下拉刷新listview
- Adroid ListView的下拉刷新的实现
- 自定义的下拉刷新的listview
- Android中ListView的下拉刷新(二)
- Android中ListView的下拉刷新
- 自定义组件,下拉刷新的ListView
- testng多浏览器支持(二)将系统中的文件放入配置文件中进行读取
- USB DEVIEC MASS STORAGE:(linux2.6.16mxc)
- 关于如GMail等邮箱每天可发送邮件量额度的问题
- block在ARC和非ARC的内存释放
- 理解和使用蓝牙BlueZ中的FTP与PBAP协议
- ListView下拉刷新的一些常见错误
- mtk笔试题-----快速删除单链表中一个结点。时间复杂度为o(1)
- 接口与抽象类的选择
- swing jtree实现叶子节点闪动效果类似于QQ好友列表
- Internet 连接共享访问被启用时,出现了一个错误
- 提高java反射速度的方法method.setAccessible(true)
- USB gadget设备驱动解析(1) [精华]
- 设计模式Observer
- BufferReader.PrintWriter