ListView下拉刷新

来源:互联网 发布:韩国历史剧黑中国 知乎 编辑:程序博客网 时间:2024/06/04 19:57
package com.cattsoft.deliersystem.view;


import java.text.SimpleDateFormat;


import cn.trinea.android.common.util.PreferencesUtils;
import cn.trinea.android.common.util.TimeUtils;


import com.cattsoft.deliersystem.R;


import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;


public class RefrenshView extends ListView implements OnScrollListener {


/** 顶部布局文件 */
private View header;


/** 顶部布局的高度 */
private int headerHight;


/** 当前第一个可见的item */
private int firstVisibleItem;


/** 标记当前实在ListView最顶端按下 */
private boolean isRemark;


/** ListView当前滚动状态 */
private int scrollState;


/** 按下时开始的Y值 */
private int startY;


/** 当前状态 */
private int state;


/** 正常状态 */
private static final int NORMAL = 0;


/** 下拉刷新的状态 */
private static final int PULL = 1;


/** 提示松开刷新状态 */
private static final int RELESE = 2;


/** 正在刷新状态 */
private static final int REFRENSHING = 3;

private onRefrenshListener refrenshListener;


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


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


public RefrenshView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}


/** 初始化 */
private void initView(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
header = inflater.inflate(R.layout.header_layout, null);


measureView(header);
headerHight = header.getMeasuredHeight();
topPandding(-headerHight);


// 给ListView添加头部
this.addHeaderView(header);


this.setOnScrollListener(this);
}


/** 通知父布局该View所占的位置大小 */
private void measureView(View view) {
// 获取子布局的layoutParams
ViewGroup.LayoutParams p = view.getLayoutParams();
if (p == null) {
p = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
}


// 获取子布局的宽度
int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
int height;
int tempHeight = p.height;


// 设置子布局的高度
if (tempHeight > 0) {
// 高度不是空,填充布局
height = MeasureSpec.makeMeasureSpec(tempHeight,
MeasureSpec.EXACTLY);
} else {
height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}


// 通知父布局
view.measure(width, height);
}


/** 设置header布局的上边距为该布局的负数,即开始时为隐藏 */
private void topPandding(int top) {
header.setPadding(header.getPaddingLeft(), top,
header.getPaddingRight(), header.getPaddingBottom());
header.invalidate();
}


@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.scrollState = scrollState;


}


@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
}


@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if (firstVisibleItem == 0) {
isRemark = true;
startY = (int) ev.getY();
}
break;
case MotionEvent.ACTION_MOVE:
onMove(ev);
break;
case MotionEvent.ACTION_UP:
if (state == RELESE) {
state = REFRENSHING;
refrenshViewByState();
// 刷新数据
refrenshListener.refensh();
} else if (state == PULL) {
state = NORMAL;
isRemark = false;
refrenshViewByState();
}
break;
}
return super.onTouchEvent(ev);
}


/**
* 判断移动过程中的操作
*/
private void onMove(MotionEvent ev) {
if (!isRemark)
return;
// 当前移动的位置
int tempY = (int) ev.getY();
// 移动的距离
int space = tempY - startY;


// 实时改变距离顶部的距离
int topPandding = space - headerHight;


switch (state) {
case NORMAL:
// 如果状态大于0说明正在滚动,将状态改为下拉刷新
if (space > 0) {
state = PULL;
refrenshViewByState();
}
break;
case PULL:
topPandding(topPandding);
// 如果滚动的距离大于该View的高度超出10个像素,并且在滚动状态,将状态改为松开刷新状态
if (space > headerHight + 10
&& scrollState == SCROLL_STATE_TOUCH_SCROLL) {
state = RELESE;
refrenshViewByState();
}
break;
case RELESE:
topPandding(topPandding);
// 如果距离小于该View的高度超出10个像素,状态改为下拉刷新,如果小于等于0则变为正常状态
if (space < headerHight + 10) {
state = PULL;
refrenshViewByState();
} else if (space <= 0) {
state = NORMAL;
isRemark = false;
refrenshViewByState();
}
break;
}
}


/**
* 根据状态改变界面界面显示
*/
private void refrenshViewByState() {
ImageView refrensh_pull_to = (ImageView) header
.findViewById(R.id.refrensh_pull_to);
ProgressBar refrensh_pro = (ProgressBar) header
.findViewById(R.id.refrensh_pro);
TextView refrensh_msg = (TextView) header
.findViewById(R.id.refrensh_msg);
TextView refrensh_time = (TextView) header
.findViewById(R.id.refrensh_time);

refrensh_time.setText("上次更新   "+PreferencesUtils.getString(getContext(), "refrensh_time", "..."));

//状态为松开刷新时,为箭头添加旋转180动画
RotateAnimation anUp = new RotateAnimation(0, 180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
anUp.setDuration(500);
anUp.setFillAfter(true);

//状态为下拉刷新时,需转回来
RotateAnimation anDown = new RotateAnimation(180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
anDown.setDuration(500);
anDown.setFillAfter(true);


switch (state) {
case NORMAL:
refrensh_pull_to.clearAnimation();
topPandding(-headerHight);
break;
case PULL:
refrensh_pull_to.setVisibility(View.VISIBLE);
refrensh_pull_to.clearAnimation();
refrensh_pull_to.setAnimation(anDown);
refrensh_pro.setVisibility(View.GONE);
refrensh_msg.setText("下拉可以刷新!");
break;
case RELESE:
refrensh_pull_to.setVisibility(View.VISIBLE);
refrensh_pull_to.clearAnimation();
refrensh_pull_to.startAnimation(anUp);
refrensh_pro.setVisibility(View.GONE);
refrensh_msg.setText("松开可以刷新!");
break;
case REFRENSHING:
topPandding(headerHight/2-25);
refrensh_pull_to.clearAnimation();
refrensh_pull_to.setVisibility(View.GONE);
refrensh_pro.setVisibility(View.VISIBLE);
refrensh_msg.setText("正在刷新...");
break;
}
}

/**
* 供外部刷新完毕调用
*/
public void reflushComplete(){
state = NORMAL;
isRemark = false;
refrenshViewByState();

long currentTime = TimeUtils.getCurrentTimeInLong();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd h:mm:ss");
String time = format.format(currentTime);
PreferencesUtils.putString(getContext(), "refrensh_time", time);
}

public void setOnRefrenshListener(onRefrenshListener refrenshListener){
this.refrenshListener = refrenshListener; 
}

/**
* 刷新监听
* @author lenovo
*
*/
public interface onRefrenshListener{
/**
* 刷新完成
*/
public void refensh();
}

}


header_layout.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:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:gravity="center"
    android:orientation="horizontal" >


    <ImageView
        android:id="@+id/refrensh_pull_to"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/pull_to_refresh_arrow" />


    <ProgressBar
        android:id="@+id/refrensh_pro"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone" />


    <LinearLayout
        android:id="@+id/showMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:gravity="center"
        android:orientation="vertical" >


        <TextView
            android:id="@+id/refrensh_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下拉可以刷新"
            android:textColor="@color/searchHintColor"
            android:textSize="12dp" />


        <TextView
            android:id="@+id/refrensh_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上一次更新时间"
            android:textColor="@color/searchHintColor"
            android:textSize="12dp" />
    </LinearLayout>


</LinearLayout>


ProgressBar样式向设置成IOS一样请看我自定义ProgressBar,上面有文件代码和图片

0 0
原创粉丝点击