您的位置:首页 > 其它

自己实现一个下拉刷新的ListView

2016-03-22 17:53 429 查看
效果







实现一个下拉刷新的ListView

1.确定状态

下拉刷新的ListView一共有四种状态,分别是

常态(刷新完成或者是正常展示的时候)
正在下拉但是下拉的距离没有达到我们定义的可以刷新的距离(下拉可以刷新)
下拉的距离达到了可以刷新的距离(释放立即刷新)
正在刷新

2.确定实现方案

我们用一个FrameLayout包裹一个下拉刷新的头布局和一个ListView,最开始的时候使下拉刷新的头布局Margin为赋值,看不到
触摸事件拦截,当ListView的第一个Item可见并且我们向下拉的时候,拦截触摸事件
在触摸事件处理的时候,使下拉刷新的头布局和ListView的Margin变化,从而达到随手指下拉移动的效果,最开始显示的状态是“下拉可以刷新”
当下拉的距离达到可以刷新的距离的时候,我们改变状态为“释放立即刷新”
释放的时候,如果状态是“下拉可以刷新”,则直接回到初始状态,不掉用刷新的接口;如果状态是“释放立即刷新”,则调用刷新的接口,当回调刷新完成时,回到初始状态

3.代码实现

package com.example.myapp.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.myapp.R;

/**
* Created by zyr
* DATE: 16-3-16
* Time: 下午4:12
* Email: yanru.zhang@renren-inc.com
* 关于下拉刷新,我目前看到的办法是将刷新的部分和ListView包含在LinearlyLayout中,滑动的时候改变LinearlyLayout的padding
* 感觉用header,改变ListView的header的高度应该也可行把,没有试过
*
*
*
* 下拉刷新
* 1.往下拉,而且已经拉到最顶部
* 2.超过一定的距离
* 3.
*/
public class CustomPullToRefreshListView extends FrameLayout{
private Context mContext;
private View refreshView;
private ListView listView;
private TextView textView;
private int mWidth,mHeight,mRefreshWidth,mRefreshHeight;
private FrameLayout.LayoutParams refreshViewLayoutParams,listViewLayoutParams;
private int downX,downY,touchX,touchY,deltaX,deltaY,startX,startY,headMoveX,headMoveY;
private boolean isScrollDown = false;
private int currentStatus = STATUS_REFRESH_FINISHED;
/**
* 下拉状态
*/
public static final int STATUS_PULL_TO_REFRESH = 0;
/**
* 释放立即刷新状态
*/
public static final int STATUS_RELEASE_TO_REFRESH = 1;
/**
* 正在刷新状态
*/
public static final int STATUS_REFRESHING = 2;
/**
* 刷新完成或未刷新状态
*/
public static final int STATUS_REFRESH_FINISHED = 3;
/**
* 下拉超过这个高度释放就可以刷新
*/
public static final int REFRESH_HEIGHT = 200;
/***************************    OnRefreshListener   *************************/
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}

private OnRefreshListener onRefreshListener;
public interface OnRefreshListener{
void onRefresh();
}

public CustomPullToRefreshListView(Context context) {
this(context, null);
}

public CustomPullToRefreshListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CustomPullToRefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();
}

private void init() {
LayoutInflater.from(mContext).inflate(R.layout.layout_custom_pull_to_refresh_listview, this);
refreshView = findViewById(R.id.refresh_view);
refreshViewLayoutParams = (FrameLayout.LayoutParams)refreshView.getLayoutParams();
textView = (TextView)refreshView.findViewById(R.id.text_view);
listView = (ListView)findViewById(R.id.list_view);
listViewLayoutParams = (FrameLayout.LayoutParams)listView.getLayoutParams();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(w!=oldw || h!=oldh){
mWidth = w;
mHeight = h;
mRefreshWidth = refreshView.getMeasuredWidth();
mRefreshHeight = refreshView.getMeasuredHeight();
if(mRefreshHeight!=0){
refreshViewLayoutParams.setMargins(0,-mRefreshHeight,0,0);
refreshView.setLayoutParams(refreshViewLayoutParams);
}
}
}

/**************************     ListView    ************************/
public void setAdapter(ListAdapter adapter){
listView.setAdapter(adapter);
}

public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener){
listView.setOnItemClickListener(onItemClickListener);
}

public void setSelection(int position){
listView.setSelection(position);
}

/**************************     Touch    ************************/
/**
* 如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,
* 如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件
* @param ev
* @return
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
downX =(int) ev.getX();
downY =(int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
touchX =(int) ev.getX();
touchY =(int) ev.getY();
deltaX = touchX-downX;
deltaY = touchY-downY;
if(deltaY>=0){
isScrollDown = true;
}else{
isScrollDown = false;
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
downX = 0;
downY = 0;
touchX = 0;
touchY = 0;
deltaX = 0;
deltaY = 0;
startX = 0;
startY = 0;
break;
}
return super.dispatchTouchEvent(ev);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_MOVE:
if(isScrollDown && listView.getFirstVisiblePosition() ==0 && listView.getScrollY() == 0){
currentStatus = STATUS_PULL_TO_REFRESH;
textView.setText("下拉可以刷新");
startX =(int) ev.getX();
startY =(int) ev.getY();
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
headMoveY = (int) event.getY() - startY - mRefreshHeight;
refreshViewLayoutParams.setMargins(0, headMoveY, 0, 0);
refreshView.setLayoutParams(refreshViewLayoutParams);
listViewLayoutParams.setMargins(0, headMoveY + mRefreshHeight, 0, 0);
listView.setLayoutParams(listViewLayoutParams);
if(headMoveY > REFRESH_HEIGHT){
currentStatus = STATUS_RELEASE_TO_REFRESH;
textView.setText("释放立即刷新");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if(currentStatus == STATUS_RELEASE_TO_REFRESH){
currentStatus = STATUS_REFRESHING;
textView.setText("正在刷新。。。");
onRefreshListener.onRefresh();
}else{
refreshViewLayoutParams.setMargins(0, -mRefreshHeight, 0, 0);
refreshView.setLayoutParams(refreshViewLayoutParams);
listViewLayoutParams.setMargins(0,0 , 0,0);
listView.setLayoutParams(listViewLayoutParams);
}
break;
}
return super.onTouchEvent(event);
}

public void onRefreshComplete(){
if(currentStatus == STATUS_REFRESHING){
currentStatus = STATUS_REFRESH_FINISHED;
textView.setText("刷新成功!");
}
refreshViewLayoutParams.setMargins(0, -mRefreshHeight, 0, 0);
refreshView.setLayoutParams(refreshViewLayoutParams);
listViewLayoutParams.setMargins(0,0 , 0,0);
listView.setLayoutParams(listViewLayoutParams);
}
}

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primary_light">
</ListView>
<LinearLayout android:id="@+id/refresh_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:background="@color/gray">
<TextView android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Refresh"
android:textColor="@color/white"
android:textSize="20sp"/>
</LinearLayout>
</FrameLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: