開源RefreshListView下拉刷新效果實(shí)現(xiàn)
1、AnimationDrawable
java.lang.Object ???? android.graphics.drawable.Drawable ? ???? android.graphics.drawable.DrawableContainer ? ? ???? android.graphics.drawable.AnimationDrawable 文檔概述:
An object used to create frame-by-frame animations, defined by a series of Drawable objects, which can be used as a View object's background.
An AnimationDrawable defined in XML consists of a single element, and a series of nested tags. Each item defines a frame of the animation. See the example below.?
Here is the code to load and play this animation.
?//?Load?the?ImageView?that?will?host?the?animation?and ?//?set?its?background?to?our?AnimationDrawable?XML?resource. ?ImageView?img?=?(ImageView)findViewById(R.id.spinning_wheel_image); ?img.setBackgroundResource(R.drawable.spin_animation); ?//?Get?the?background,?which?has?been?compiled?to?an?AnimationDrawable?object. ?AnimationDrawable?frameAnimation?=?(AnimationDrawable)?img.getBackground(); ?//?Start?the?animation?(looped?playback?by?default). ?frameAnimation.start();
https://github.com/FlyRecker/FlyMukeRefreshListView GitHub開源項(xiàng)目:仿慕課下拉刷新
RefreshListView.java?
package?com.example.openrefreshlistview;
import?android.annotation.SuppressLint;
import?android.content.Context;
import?android.graphics.drawable.AnimationDrawable;
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.ImageView;
import?android.widget.ListView;
import?android.widget.TextView;
/**
?*?Created?by?recker?on?16/5/13.
?*/
public?class?RefreshListView?extends?ListView?implements?AbsListView.OnScrollListener?{
????private?final?int?NONE?=?0;//正常狀態(tài)
????private?final?int?PULL?=?1;//提示下拉刷新狀態(tài)
????private?final?int?RELESE?=?2;//提示釋放狀態(tài)
????private?final?int?REFLASHING?=?3;//正在刷新狀態(tài)
????private?final?int?RATIO?=?3;//比值
????private?View?headerView;//頂部刷新視圖
????private?int?headerViewHeight;//頂部布局文件的高度
????private?int?firstVisibleItem;//當(dāng)前第一個(gè)可見的item的位置
????private?boolean?isEnd;//是否結(jié)束刷新
????private?boolean?isRefreable;//是否可以刷新
????private?boolean?isRemark;//標(biāo)記,當(dāng)前是在ListView是否是在第一個(gè)
????private?float?startY;
????private?float?offsetY;
????private?int?state;//當(dāng)前的狀態(tài)
????private?TextView?tip;
????private?ImageView?img;
????private?AnimationDrawable?drawableAnim;
????public?RefreshListView(Context?context)?{
????????super(context);
????????init(context);
????}
????public?RefreshListView(Context?context,?AttributeSet?attrs)?{
????????super(context,?attrs);
????????init(context);
????}
????public?RefreshListView(Context?context,?AttributeSet?attrs,?int?defStyleAttr)?{
????????super(context,?attrs,?defStyleAttr);
????????init(context);
????}
????@SuppressLint("NewApi")
private?void?init(Context?context)?{
????????headerView?=?LayoutInflater.from(context).inflate(R.layout.header_layout,?null);
????????
??/*void?android.widget.ListView.addHeaderView(View?v)
Add?a?fixed?view?to?appear?at?the?top?of?the?list.
*/
????????addHeaderView(headerView);
????????measureView(headerView);
????????headerViewHeight?=?headerView.getMeasuredHeight();
????????topPadding(-headerViewHeight);
????????//添加動(dòng)畫
????????tip?=?(TextView)?headerView.findViewById(R.id.tip);
????????img?=?(ImageView)?headerView.findViewById(R.id.img);
????????img.setBackgroundResource(R.drawable.c);
????????drawableAnim?=?(AnimationDrawable)?img.getBackground();
????????//關(guān)閉view的OverScroll
????????setOverScrollMode(OVER_SCROLL_NEVER);
????????setOnScrollListener(this);
????????state?=?NONE;
????????isEnd?=?true;
????????isRefreable?=?false;
????}
????/**
?????*?通知父布局,占用的寬,高
?????*?@param?view
?????*/
????private?void?measureView(View?view)?{
????????ViewGroup.LayoutParams?p?=?view.getLayoutParams();
????????if?(p?==?null)?{
????????????p?=?new?ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
????????????????????ViewGroup.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);
????}
????private?void?topPadding(int?topPadding)?{
????????headerView.setPadding(headerView.getPaddingLeft(),?topPadding,
????????????????headerView.getPaddingRight(),?headerView.getPaddingBottom());
????????headerView.invalidate();
????}
????@Override
????public?void?onScrollStateChanged(AbsListView?absListView,?int?scrollState)?{
????}
????@Override
????public?void?onScroll(AbsListView?absListView,?int?firstVisibleItem,
?????????????????????????int?visibleItemCount,?int?totalItemCount)?{
????????this.firstVisibleItem?=?firstVisibleItem;
????}
????@Override
????public?boolean?onTouchEvent(MotionEvent?ev)?{
????????if?(isEnd)?{//如果現(xiàn)在時(shí)結(jié)束的狀態(tài),即刷新完畢了,可以再次刷新了,在refreshComplete中設(shè)置
????????????if?(isRefreable)?{//如果現(xiàn)在是可刷新狀態(tài)???在setOnRefreshListener中設(shè)置為true
????????????????switch?(ev.getAction())?{
????????????????????case?MotionEvent.ACTION_DOWN:
????????????????????????if?(firstVisibleItem?==?0?&&?!isRemark)?{
????????????????????????????isRemark?=?true;
????????????????????????????startY?=?ev.getY();
????????????????????????}
????????????????????????break;
????????????????????case?MotionEvent.ACTION_MOVE:
????????????????????????onMove(ev);
????????????????????????break;
????????????????????case?MotionEvent.ACTION_UP:
????????????????????????if?(state?==?RELESE)?{
????????????????????????????state?=?REFLASHING;
????????????????????????????//加載最新數(shù)據(jù)
????????????????????????????refreshViewByState();
????????????????????????????onRefreshListener.onRefresh();
????????????????????????}?else?if?(state?==?PULL)?{
????????????????????????????state?=?NONE;
????????????????????????????refreshViewByState();
????????????????????????????setSelection(0);
????????????????????????}
????????????????????????isRemark?=?false;
????????????????????????break;
????????????????}
????????????}
????????}
????????return?super.onTouchEvent(ev);
????}
????/**
?????*?判斷移動(dòng)過程操作
?????*?@param?ev
?????*/
????private?void?onMove(MotionEvent?ev)?{
????????//再次得到y(tǒng)坐標(biāo),用來和startY相減來計(jì)算offsetY位移值
????????float?tempY?=?ev.getY();
????????//再起判斷一下是否為listview頂部并且沒有記錄y坐標(biāo)
????????if?(firstVisibleItem?==?0?&&?!isRemark)?{
????????????isRemark?=?true;
????????????startY?=?tempY;
????????}
????????if?(state?!=?REFLASHING?&&?isRemark)?{
????????????//計(jì)算y的偏移量
????????????offsetY?=?tempY?-?startY;
????????????//計(jì)算當(dāng)前滑動(dòng)的高度
????????????float?currentHeight?=?(-headerViewHeight+offsetY/3);
????????????//如果當(dāng)前的狀態(tài)是釋放刷新,并且已經(jīng)記錄y坐標(biāo)
????????????if?(state?==?RELESE?&&?isRemark)?{
????????????????setSelection(0);
????????????????//如果當(dāng)前滑動(dòng)的距離小于headerView的總高度
????????????????if?(-headerViewHeight+offsetY/RATIO<0)?{
????????????????????//狀態(tài)改為下拉刷新
????????????????????state?=?PULL;
????????????????????refreshViewByState();
????????????????}?else?if?(offsetY?=0)?{
????????????????????//狀態(tài)改為釋放刷新
????????????????????state?=?RELESE;
????????????????????refreshViewByState();
????????????????}?else?if?(offsetY?=0)?{
????????????????????//將狀態(tài)改為釋放刷新狀態(tài)
????????????????????state?=?PULL;
????????????????????refreshViewByState();
????????????????}
????????????}
????????????//如果為下拉刷新狀態(tài)
????????????if?(state?==?PULL)?{
????????????????topPadding((int)(-headerViewHeight+offsetY/RATIO));
????????????}
????????????//如果為釋放刷新狀態(tài)
????????????if?(state?==?RELESE)?{
????????????????topPadding((int)(-headerViewHeight+offsetY/RATIO));
????????????}
????????}
????}
????/**
?????*?根據(jù)當(dāng)前狀態(tài),改變界面顯示
?????*/
????private?void?refreshViewByState()?{
????????switch?(state)?{
????????????case?NONE:
????????????????topPadding(-headerViewHeight);
????????????????drawableAnim.stop();
????????????????break;
????????????case?PULL:
????????????????drawableAnim.stop();
????????????????tip.setText("下拉刷新");
????????????????break;
????????????case?RELESE:
????????????????drawableAnim.stop();
????????????????tip.setText("釋放刷新");
????????????????break;
????????????case?REFLASHING:
????????????????drawableAnim.start();
????????????????tip.setText("正在刷新");
????????????????break;
????????}
????}
????/**
?????*?獲取完數(shù)據(jù)
?????*/
????public?void?refreshComplete()?{
????????isEnd?=?true;
????????state?=?NONE;
????????refreshViewByState();
????}
????private?OnRefreshListener?onRefreshListener;
????public?void?setOnRefreshListener(OnRefreshListener?listener)?{
????????this.onRefreshListener?=?listener;
????????isRefreable?=?true;
????}
????public?interface?OnRefreshListener?{
????????void?onRefresh();
????}
????private?void?debug(String?str)?{
????????Log.d(RefreshListView.class.getSimpleName(),?str);
????}
}
header_layout.xml
activity_main.xml
MainActivity.java
package?com.example.openrefreshlistview;
import?android.os.Handler;
//import?android.support.v7.app.AppCompatActivity;
import?android.os.Bundle;
import?android.support.v7.app.ActionBarActivity;
import?android.widget.ArrayAdapter;
import?java.util.ArrayList;
import?java.util.Arrays;
import?java.util.List;
public?class?MainActivity?extends?ActionBarActivity
????????implements?RefreshListView.OnRefreshListener??{
????private?RefreshListView?mListView;
????private?ListmDatas;
????private?ArrayAdaptermAdapter;
????private?final?static?int?REFRESH_COMPLETE?=?0;
????private?Handler?mHandler?=?new?Handler(){
????????public?void?handleMessage(android.os.Message?msg)?{
????????????switch?(msg.what)?{
????????????????case?REFRESH_COMPLETE:
????????????????????mListView.refreshComplete();
????????????????????mAdapter.notifyDataSetChanged();
????????????????????break;
????????????????default:
????????????????????break;
????????????}
????????};
????};
????@Override
????protected?void?onCreate(Bundle?savedInstanceState)?{
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.activity_main);
????????mListView?=?(RefreshListView)?findViewById(R.id.listview);
????????String[]?data?=?new?String[]{"a","b","c","d",
????????????????"e","f","g","h","i",
????????????????"j","k","l","m","n","o","p","q","r","s"};
????????mDatas?=?new?ArrayList(Arrays.asList(data));
????????/*Open?Declaration?android.widget.ArrayAdapter.ArrayAdapter(Context?context,?
??????????int?textViewResourceId,?Listobjects)*/
????????mAdapter?=?new?ArrayAdapter(this,?android.R.layout.simple_list_item_1,mDatas);
????????mListView.setAdapter(mAdapter);
????????mListView.setOnRefreshListener(this);
????}
????@Override
????public?void?onRefresh()?{
????????new?Thread(new?Runnable()?{
????????????@Override
????????????public?void?run()?{
????????????????try?{
????????????????????Thread.sleep(3000);
????????????????????mDatas.add(0,?"new?data");
????????????????????mHandler.sendEmptyMessage(REFRESH_COMPLETE);
????????????????}?catch?(InterruptedException?e)?{
????????????????????e.printStackTrace();
????????????????}
????????????}
????????}).start();
????}
}




