android listview下拉刷新动画,android 安卓 listview 支持下拉刷新 上拉加载更多

【1】重写listViewimport java.text.SimpleDateFormat;

import java.util.Date;

import com.example.testdddleapk.R;

import android.content.Context;

import android.util.AttributeSet;

import android.util.Log;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.animation.Animation;

import android.view.animation.LinearInterpolator;

import android.view.animation.RotateAnimation;

import android.widget.AbsListView;

import android.widget.AbsListView.OnScrollListener;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import android.widget.ListAdapter;

import android.widget.ListView;

import android.widget.ProgressBar;

import android.widget.TextView;

public class RefreshListView extends ListView implements OnScrollListener {

private static final int DONE = 0;

private static final int PULL_TO_REFRESH = 1;

private static final int RELEASE_TO_REFRESH = 2;

private static final int REFRESHING = 3;

private static final float RATIO = 3;// 用来设置实际间距和上边距之间的比例

private int state;// 当前下拉刷新的状态

private int firstVisibleIndex;// 在listview中第一个可以看见的item

private View headView;

private ImageView headArrow;

private ProgressBar progressBar;

private TextView headTitle;

private TextView headLastUpdate;

private int headContentWidth;

private int headContentHeight;

private Animation animation;

private Animation reverseAnimation;

private OnRefreshListner refreshListner;// 刷新监听器

private boolean isRefreshable;

private boolean isRecored = false;// 用来记录第一次按下坐标点,在整个滑动的过程中 只记录一次

private float startY;

private boolean isBack = false;// 是从 松开刷新状态 来到的 下拉刷新状态

public RefreshListView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

private void init(Context context) {

// listview 设置滑动时缓冲背景色

setCacheColorHint(0xcc000000);

headView = View.inflate(context, R.layout.listview_header, null);

headArrow = (ImageView) headView.findViewById(R.id.iv_listview_header_arrow);

progressBar = (ProgressBar) headView.findViewById(R.id.pb_listview_header);

headTitle = (TextView) headView.findViewById(R.id.tv_listview_header_last_update_time);

headLastUpdate = (TextView) headView .findViewById(R.id.tv_listview_header_state);

headArrow.setMinimumWidth(50);

headArrow.setMinimumHeight(70);

MeasureView(headView);

headContentWidth = headView.getMeasuredWidth();

headContentHeight = headView.getMeasuredHeight();

headView.setPadding(0, -1*headContentHeight, 0, 0);

// 为listView加入顶部View

addHeaderView(headView);

setOnScrollListener(this);

animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

animation.setDuration(250);

animation.setFillAfter(true);// 设定动画结束时,停留在动画结束位置 (保留动画效果)

animation.setInterpolator(new LinearInterpolator());// 匀速变化

reverseAnimation = new RotateAnimation(0, -180,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);

reverseAnimation.setDuration(200);

reverseAnimation.setFillAfter(true);// 设定动画结束时,停留在动画结束位置 (保留动画效果)

reverseAnimation.setInterpolator(new LinearInterpolator());// 匀速变化

// 设置当前headView的状态

state = DONE;

// 设置当前下拉刷新是否可用

isRefreshable = false;

}

/**

* 测量headView的 宽高

*/

private void MeasureView(View child) {

ViewGroup.LayoutParams lp = child.getLayoutParams();

if (null == lp) {

lp = new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);

}

int measureChildWidth = ViewGroup.getChildMeasureSpec(0, 0, lp.width);

int measureChildHeight;

if (lp.height > 0) {

measureChildHeight = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);

} else {

measureChildHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);

}

child.measure(measureChildWidth, measureChildHeight);

}

private float tempY=0;

private float downY=0;

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

downY=event.getY();

System.out.println("downY:"+downY);

if (firstVisibleIndex == 0 && !isRecored) {

startY = event.getY();

isRecored = true;

}

break;

case MotionEvent.ACTION_MOVE:

//float tempY = event.getY();

tempY = event.getY();

System.out.println("tempy:"+tempY);

if (firstVisibleIndex == 0 && !isRecored) {

startY = tempY;

isRecored = true;

}

if (state != REFRESHING) {

if (state == PULL_TO_REFRESH) {

// 向下拉了 从下拉刷新的状态 来到 松开刷新的状态

if ((tempY - startY) / RATIO >= headContentHeight

&& (tempY - startY) > 0) {

state = RELEASE_TO_REFRESH;

changeHeadViewOfState();

}

// 向上推了 从下拉刷新的状态 来到 刷新完成的状态

else if ((tempY - startY) <= 0) {

state = DONE;

changeHeadViewOfState();

}

} else if (state == RELEASE_TO_REFRESH) {

// 向上推了 还没有完全将HEADVIEW 隐藏掉(可以看到一部分)

// 从松开刷新的状态 来到 下拉刷新的状态

if ((tempY - startY) / RATIO 

&& (tempY - startY) > 0) {

state = PULL_TO_REFRESH;

changeHeadViewOfState();

isBack = true;

}

// 向上推了 一下子推到了最上面 从松开刷新的状态 来到 刷新完成的状态 (数据不刷新的)

else if ((tempY - startY) <= 0) {

state = DONE;

changeHeadViewOfState();

}

} else if (state == DONE) {

// 刷新完成的状态 来到 下拉刷新的状态

if ((tempY - startY) > 0) {

state = PULL_TO_REFRESH;

changeHeadViewOfState();

}

}

if (state == PULL_TO_REFRESH) {

headView.setPadding(0,(int) ((tempY - startY) / RATIO - headContentHeight),0, 0);

}

if (state == RELEASE_TO_REFRESH) {

headView.setPadding(0, (int) ((tempY - startY) / RATIO - headContentHeight),0, 0);

}

}

break;

case MotionEvent.ACTION_UP:

if (state != REFRESHING) {

if (state == PULL_TO_REFRESH) {

// 松手

state = DONE;

changeHeadViewOfState();

}

else if (state == RELEASE_TO_REFRESH) {

// 松手

state = REFRESHING;

changeHeadViewOfState();

// 执行数据刷新方法

onRefresh();

}

}

isRecored = false;

isBack = false;

break;

}

return super.onTouchEvent(event);

}

/**

* 执行下拉刷新

*/

private void onRefresh() {

if (refreshListner != null) {

refreshListner.onRefresh();

}

}

/**

* HeadView的状态变化效果

*/

private void changeHeadViewOfState() {

switch (state) {

case PULL_TO_REFRESH:

headArrow.setVisibility(View.VISIBLE);

progressBar.setVisibility(View.GONE);

headTitle.setVisibility(View.VISIBLE);

headLastUpdate.setVisibility(View.VISIBLE);

headArrow.clearAnimation();

headTitle.setText("下拉可以刷新");

//由 松开刷新  到  下拉刷新

if(isBack){

headArrow.startAnimation(animation);

isBack = false;

}

break;

case RELEASE_TO_REFRESH:

headArrow.setVisibility(View.VISIBLE);

progressBar.setVisibility(View.GONE);

headTitle.setVisibility(View.VISIBLE);

headLastUpdate.setVisibility(View.VISIBLE);

headArrow.clearAnimation();

headArrow.startAnimation(reverseAnimation);

headTitle.setText("松开可以刷新");

break;

case REFRESHING:

headArrow.setVisibility(View.GONE);

progressBar.setVisibility(View.VISIBLE);

headTitle.setVisibility(View.VISIBLE);

headLastUpdate.setVisibility(View.VISIBLE);

headArrow.clearAnimation();

headTitle.setText("正在刷新...");

headView.setPadding(0, 0, 0, 0);

break;

case DONE:

headArrow.setVisibility(View.VISIBLE);

progressBar.setVisibility(View.GONE);

headTitle.setVisibility(View.VISIBLE);

headLastUpdate.setVisibility(View.VISIBLE);

headArrow.clearAnimation();

headTitle.setText("下拉可以刷新");

headView.setPadding(0, -1 * headContentHeight, 0, 0);

break;

}

}

private int lastPos;//最后一个可见的item的位置

private int count;//item总数,注意不是当前可见的item总数

private boolean hasFoot = false;//是否有了Foot

public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {

firstVisibleIndex = firstVisibleItem;

lastPos = getLastVisiblePosition();

count = totalItemCount;

//因为刚进入的时候,lastPos=-1,count=0,这个时候不能让它执行onAddFoot方法

if(lastPos==count-1 && !hasFoot && lastPos != -1&&((tempY-startY)<0)){

hasFoot = true;

onAddFoot();

}

}

public void onScrollStateChanged(AbsListView view, int scrollState) {

if(isFootLoading) return;

if(lastPos==count-1 && lastPos != -1&&hasFoot&&footer!=null&&((tempY-downY)>0)){

this.removeFooterView(footer);

}

if(hasFoot && scrollState==SCROLL_STATE_IDLE&&((tempY-downY)<0)){

isFootLoading = true;

onFootLoading();

}

}

/**

* 设置下拉刷新监听

*/

public void setOnRefreshListner(OnRefreshListner listener) {

// 设置下拉刷新可用

isRefreshable = true;

refreshListner = listener;

}

//执行底部加载

public void onFootLoading(){

if(footLoadingListener!=null && isFootLoading &&hasFoot&&(tempY-downY)<0)  {

footLoadingListener.onFootLoading();  }

}

public void setOnAddFootListener(OnAddFootListener addFootListener){

onAddFootListener = addFootListener;

}

//执行添加foot

public void onAddFoot(){

if(onAddFootListener!=null && hasFoot)

onAddFootListener.addFoot();

}

//是否添加Foot的监听器,如果写在OnFootLoadingListener中会有延迟,效果不好

//应该是先进入添加Foot的状态,再进入FootLoading的状态

public OnAddFootListener onAddFootListener;

//是否进入从底部加载数据的状态的监听器

public OnFootLoadingListener footLoadingListener;

//正在加载底部数据

private boolean isFootLoading = false;

public void setOnFootLoadingListener(OnFootLoadingListener footLoading){

footLoadingListener = footLoading;

}

/**

* 下拉刷新监听器

*/

public interface OnRefreshListner {

// 下拉刷新的时候,在这里执行获取数据的过程

void onRefresh();

}

private View footer=null;

public void setFooter(View footer){

this.footer=footer;

}

/**

* 上拉刷新监听器

*/

public interface OnFootLoadingListener{

// 这里是执行后台获取数据的过程

void onFootLoading();

}

/**

* 添加Foot的监听器

*/

public interface OnAddFootListener{

// 这里是用户addFootView的操作

void addFoot();

}

/**

* 底部数据加载完成,用户需要加入一个removeFootView的操作

*/

public void onFootLoadingComplete(){

hasFoot = false;

isFootLoading = false;

}

/**

* 上拉刷新完成时 所执行的操作,更改状态,隐藏head

*/

public void onRefreshComplete() {

state = DONE;

changeHeadViewOfState();

headLastUpdate.setText("最后刷新时间: " + new Date().toLocaleString());

}

@Override

public void setAdapter(ListAdapter adapter) {

headLastUpdate.setText("最后刷新时间: " + new Date().toLocaleString());

super.setAdapter(adapter);

}

}

【2】下拉刷新头部布局文件listview_header.xml<?xml  version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal" >

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="10dip" >

android:id="@+id/iv_listview_header_arrow"

android:layout_width="40dp"

android:layout_height="40dp"

android:layout_gravity="center"

android:minWidth="30dip"

android:src="@drawable/arrow" />

android:id="@+id/pb_listview_header"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:indeterminateDrawable="@drawable/common_progressbar"

android:visibility="gone" />

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:gravity="center_horizontal"

android:orientation="vertical" >

android:id="@+id/tv_listview_header_state"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="下拉刷新"

android:textColor="#FF0000"

android:textSize="18sp" />

android:id="@+id/tv_listview_header_last_update_time"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="5dip"

android:text="最后刷新时间: 2014-10-10 12:56:12"

android:textColor="@android:color/white"

android:textSize="14sp" />

【3】上拉加载更多布局文件listview_footer.xml<?xml  version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:layout_margin="10dip"

android:gravity="center_vertical"

android:orientation="horizontal" >

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:indeterminateDrawable="@drawable/common_progressbar" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="10dip"

android:text="加载更多..."

android:textColor="#FF0000"

android:textSize="18sp" />

【4】progressBar--common_progressbar.xml<?xml  version="1.0" encoding="utf-8"?>

android:fromDegrees="0"

android:pivotX="50%"

android:pivotY="50%"

android:toDegrees="360" >

android:innerRadiusRatio="3"

android:shape="ring"

android:useLevel="false" >

android:centerColor="#FF6666"

android:endColor="#FF0000"

android:startColor="#FFFFFF"

android:type="sweep" />

【5】使用方法adapter=new myListAdapter(items,xxx.this);

listView.setAdapter(adapter);

/**

* 下拉刷新回调

*/

listView.setOnRefreshListner(new OnRefreshListner() {

public void onRefresh() {

new AsyncTask>(){

@Override

protected ArrayList doInBackground(Void... params) {

try {

//模拟从服务器获取数据的过程

Thread.sleep(1500);

} catch (InterruptedException e) {

e.printStackTrace();

}

return null;

}

//更新UI的方法,系统自动实现

@Override

protected void onPostExecute(ArrayList result) {

data.addAll(0,result);//注意是往前添加数据

adapter.notifyDataSetChanged();

listView.onRefreshComplete();//完成下拉刷新,这个方法要调用

super.onPostExecute(result);

}

}.execute();

}

});

//上拉加载更多功能

final View footer = View.inflate(getActivity(), R.layout.listview_footer, null);

listView.setOnAddFootListener(new OnAddFootListener() {

public void addFoot() {

listView.setFooter(footer);

listView.addFooterView(footer);

}

});

listView.setOnFootLoadingListener(new OnFootLoadingListener() {

public void onFootLoading() {

new AsyncTask>(){

@Override

protected ArrayList doInBackground(Void... params) {

try {

//模拟从服务器获取数据的过程

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

return null;

}

//在doInBackground后面执行

protected void onPostExecute(ArrayList result) {

data.addAll(result);//这个是往后添加数据

adapter.notifyDataSetChanged();

listView.onFootLoadingComplete();//完成上拉刷新,就是底部加载完毕,这个方法要调用

//移除footer,这个动作不能少

listView.removeFooterView(footer);

super.onPostExecute(result);

}

}.execute();

}

});

【6】注意事项

listview设置项目点击事件

listView.setOnItemClickListener(new OnItemClickListener() {

public void onItemClick(AdapterView> parent, View view,int position, long id) {

if(position==0||position==items.length()+1) return;

//获取每项的数据,position需减1,第0项为listview_head

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值