下拉刷新XListView的简单分析

按照这篇博文里的思路分析和理解的

先要理解Scroller,看过的博文:

还要理解View的touch时间传递:

%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8BView%20%E4%BA%8B%E4%BB%B6%E4%BC%A0%E9%80%92

在实现中遇到的问题:

1、下拉时,下拉区域不会跟随下拉而变化,只显示其中一部分。图:

解决:采用设置下拉区域的paddind,实现跟随滚动效果,最终图:

2、当下拉超过极限高度后向上滑动时,listview会跟随滑动。解决方法是通过在onTouchEvent判断这一情况判断这一情况,详细在代码里。

代码:

下拉区域布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=""android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><RelativeLayoutandroid:id="@+id/xlistview_header_content"android:layout_width="fill_parent"android:layout_height="60dp"android:layout_marginBottom="2dp"android:gravity="center_horizontal" ><TextViewandroid:id="@+id/xlistview_header_hint_textview"android:layout_width="100dp"android:layout_height="wrap_content"android:layout_centerInParent="true"android:gravity="center"android:text="正在加载"android:textColor="@android:color/black"android:textSize="14sp" /><ImageViewandroid:id="@+id/xlistview_header_image"android:layout_width="30dp"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_toLeftOf="@id/xlistview_header_hint_textview"android:src="@drawable/indicator_arrow" /><ProgressBarandroid:id="@+id/xlistview_header_progressbar"android:layout_width="30dp"android:layout_height="30dp"android:layout_centerVertical="true"android:layout_toLeftOf="@id/xlistview_header_hint_textview"android:visibility="invisible" /></RelativeLayout></LinearLayout>下拉区域package com.example.test;import android.annotation.SuppressLint;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.TextView;public class XListViewHeader extends LinearLayout {private static final String HINT_NORMAL = "下拉刷新";private static final String HINT_READY = "松开刷新数据";private static final String HINT_LOADING = "正在加载…";// 正常状态,下拉未超过head高度public final static int STATE_NORMAL = 0;// 准备刷新状态,也就是箭头方向发生改变之后的状态,但是没有刷新public final static int STATE_READY = 1;// 刷新状态,箭头变成了progressBar,正在刷新public final static int STATE_REFRESHING = 2;// 布局容器,也就是根布局private LinearLayout mContentLayout;// 箭头图片private ImageView mImageView;// 刷新状态显示private ProgressBar mProgressBar;// 说明文本private TextView mHintTextView;// 记录当前的状态private int mState = -1;// 用于改变箭头的方向的动画private Animation mRotateUpAnim;private Animation mRotateDownAnim;// 动画持续时间private final int ROTATE_ANIM_DURATION = 180;private int headHeight;private Context context;public XListViewHeader(Context context) {super(context);this.context = context;init();}private void init() {LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);// 初始化高度为0mContentLayout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.xlistview_header, null);mContentLayout.setLayoutParams(lp);addView(mContentLayout);mImageView = (ImageView) mContentLayout.findViewById(R.id.xlistview_header_image);// 箭头图片mHintTextView = (TextView) mContentLayout.findViewById(R.id.xlistview_header_hint_textview);// 提示文本mProgressBar = (ProgressBar) mContentLayout.findViewById(R.id.xlistview_header_progressbar);// 进度条mRotateUpAnim = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);// 箭头向上旋转的动画mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);// 动画持续时间mRotateUpAnim.setFillAfter(true);// 动画终止时停留在最后,也就是保留动画以后的状态mRotateDownAnim = new RotateAnimation(-180, 0,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);mRotateDownAnim.setFillAfter(true);setState(STATE_NORMAL);// 初始化设置为正常模式}public void setState(int state) {if (state == mState) {return;}if (state == STATE_REFRESHING) {// 设置为正在刷新状态时,清楚所有动画,箭头隐藏, 进度条显示mImageView.clearAnimation();mImageView.setVisibility(View.GONE);mProgressBar.setVisibility(View.VISIBLE);} else {mImageView.setVisibility(View.VISIBLE);mProgressBar.setVisibility(View.GONE);}switch (state) {case STATE_NORMAL:if (mState == STATE_READY) {// 由准备状态变为正常状态,开启向下动画mImageView.startAnimation(mRotateDownAnim);} else {mImageView.clearAnimation();}mHintTextView.setText(HINT_NORMAL);break;case STATE_READY:if (mState == STATE_NORMAL) {mImageView.startAnimation(mRotateUpAnim);}mHintTextView.setText(HINT_READY);break;case STATE_REFRESHING:mHintTextView.setText(HINT_LOADING);break;}mState = state;}@SuppressLint("NewApi")public void setVisitHeight(int height) {if (height < 0) {height = 0;}LinearLayout.LayoutParams lp = (LayoutParams) mContentLayout.getLayoutParams();lp.height = height;mContentLayout.setLayoutParams(lp);mContentLayout.setPadding(mContentLayout.getPaddingLeft(), height- headHeight, mContentLayout.getPaddingRight(),mContentLayout.getPaddingBottom());// 设置padding是为了下拉时,head跟随着下拉。更好看}public int getVisitHeight() {return mContentLayout.getHeight();}public void show() {mContentLayout.setVisibility(View.VISIBLE);}public void hide() {mContentLayout.setVisibility(View.INVISIBLE);}public int getHeadHeight() {return headHeight;}public void setHeadHeight(int headHeight) {this.headHeight = headHeight;}}listviewpackage com.example.test;import android.content.Context;import android.view.MotionEvent;import android.view.ViewTreeObserver.OnGlobalLayoutListener;import android.view.animation.DecelerateInterpolator;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Scroller;public class XListView extends ListView {private Context context;// 滑动时长private final static int SCROLL_DURATION = 400;// 滑动比例private final static float OFFSET_RADIO = 2f;// 记录按下点的y坐标private float lastY;// 用来回滚private Scroller scroller;private IXListViewListener mListViewListener;private XListViewHeader headerView;private RelativeLayout headerViewContent;// header的高度private int headerHeight;// 是否能够刷新private boolean enableRefresh = true;// 是否正在刷新private boolean isRefreashing = false;// 记录当前手势是向上还是向下private int TOUCH_UP = 0, TOUCH_DOWN = 1;private int mTouch;public XListView(Context context) {super(context);this.context = context;init();}private void init() {scroller = new Scroller(context, new DecelerateInterpolator());headerView = new XListViewHeader(context);headerViewContent = (RelativeLayout) headerView.findViewById(R.id.xlistview_header_content);// 获得head的高度headerView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@SuppressWarnings("deprecation")@Overridepublic void onGlobalLayout() {headerHeight = headerViewContent.getHeight();headerView.setHeadHeight(headerHeight);getViewTreeObserver().removeGlobalOnLayoutListener(this);}});addHeaderView(headerView);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:lastY = ev.getRawY();break;case MotionEvent.ACTION_MOVE:float t = ev.getRawY() – lastY;lastY = ev.getRawY();if (t > 0) {mTouch = TOUCH_DOWN;} else {mTouch = TOUCH_UP;}// 当前是第一个item,且手势是向下,就显示下拉条,更新高度if (getFirstVisiblePosition() == 0&& (headerView.getVisitHeight() > 0 || t > 0)) {updateHeaderViewHeight(t / OFFSET_RADIO);}if (!isRefreashing && mTouch == TOUCH_UP&& headerView.getVisitHeight() > 0) {return true;// 当下拉高度达到header高度时候,松开即可刷新,,若此刻向上滑,listview会跟随滑动,return// true 代表消费这个事件,listview禁止滚动}break;case MotionEvent.ACTION_UP:if (getFirstVisiblePosition() == 0) {if (enableRefresh && headerView.getVisitHeight() > headerHeight) {isRefreashing = true;headerView.setState(headerView.STATE_REFRESHING);if (mListViewListener != null) {mListViewListener.onRefresh();//刷新事件}}}resetHeaderHeight();break;}return super.onTouchEvent(ev);}public void updateHeaderViewHeight(float f) {headerView.setVisitHeight((int) f + headerView.getVisitHeight());// 未处于刷新状态,更新箭头if (enableRefresh && !isRefreashing) {if (headerView.getVisitHeight() > headerHeight) {headerView.setState(XListViewHeader.STATE_READY);}else{headerView.setState(XListViewHeader.STATE_NORMAL);}}}// 下拉条动态消失public void resetHeaderHeight() {int height = headerView.getVisitHeight();int endheight = 0;if (isRefreashing) {endheight = headerHeight;}// y轴方向由 height 到 endheight ,第三个参数是增量,如果不是刷新则高度变为0,如果是,高度变为head原始高度scroller.startScroll(0, height, 0, endheight – height, SCROLL_DURATION);invalidate();}public void computeScroll() {if (scroller.computeScrollOffset()) {// 利用scroller ,设置高度,反复重绘headerView.setVisitHeight(scroller.getCurrY());postInvalidate();}super.computeScroll();}public void stopRefresh() {if (isRefreashing == true) {isRefreashing = false;resetHeaderHeight();}}public void setIxListener(IXListViewListener listener) {this.mListViewListener = listener;}interface IXListViewListener {public void onRefresh();// 刷新事件的回调函数}}mainactivitypackage com.example.test;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.widget.ArrayAdapter;import com.example.test.XListView.IXListViewListener;public class MainActivity extends Activity {private XListView xListView;private Handler handler = new Handler() {public void handleMessage(Message msg) {xListView.stopRefresh();}};protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);xListView = new XListView(this);ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1);xListView.setAdapter(adapter);for (int i = 0; i < 10; i++) {adapter.add("text" + i);}setContentView(xListView);xListView.setIxListener(new IXListViewListener() {public void onRefresh() {new Thread() {public void run() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}handler.sendEmptyMessage(0);}}.start();}});}}

下载

csdn博文编辑不能撤销么,写的东西都没了

怠惰是贫穷的制造厂。

下拉刷新XListView的简单分析

相关文章:

你感兴趣的文章:

标签云: