开源RefreshListView下拉刷新效果

来源:互联网 发布:数码大师 mac版下载 编辑:程序博客网 时间:2024/06/16 22:52

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<animation-list> element, and a series of nested <item> tags. Each item defines a frame of the animation. See the example below. 

<!-- Animation frames are wheel0.png -- wheel5.png files inside the res/drawable/ folder --> <animation-list android:id="@+id/selected" android:oneshot="false">    <item android:drawable="@drawable/wheel0" android:duration="50" />    <item android:drawable="@drawable/wheel1" android:duration="50" />    <item android:drawable="@drawable/wheel2" android:duration="50" />    <item android:drawable="@drawable/wheel3" android:duration="50" />    <item android:drawable="@drawable/wheel4" android:duration="50" />    <item android:drawable="@drawable/wheel5" android:duration="50" /> </animation-list>

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开源项目:仿慕课下拉刷新


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;//正常状态    private final int PULL = 1;//提示下拉刷新状态    private final int RELESE = 2;//提示释放状态    private final int REFLASHING = 3;//正在刷新状态    private final int RATIO = 3;//比值    private View headerView;//顶部刷新视图    private int headerViewHeight;//顶部布局文件的高度    private int firstVisibleItem;//当前第一个可见的item的位置    private boolean isEnd;//是否结束刷新    private boolean isRefreable;//是否可以刷新    private boolean isRemark;//标记,当前是在ListView是否是在第一个    private float startY;    private float offsetY;    private int state;//当前的状态    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);        //添加动画        tip = (TextView) headerView.findViewById(R.id.tip);        img = (ImageView) headerView.findViewById(R.id.img);        img.setBackgroundResource(R.drawable.c);        drawableAnim = (AnimationDrawable) img.getBackground();        //关闭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) {//如果现在时结束的状态,即刷新完毕了,可以再次刷新了,在refreshComplete中设置            if (isRefreable) {//如果现在是可刷新状态   在setOnRefreshListener中设置为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;                            //加载最新数据                            refreshViewByState();                            onRefreshListener.onRefresh();                        } else if (state == PULL) {                            state = NONE;                            refreshViewByState();                            setSelection(0);                        }                        isRemark = false;                        break;                }            }        }        return super.onTouchEvent(ev);    }    /**     * 判断移动过程操作     * @param ev     */    private void onMove(MotionEvent ev) {        //再次得到y坐标,用来和startY相减来计算offsetY位移值        float tempY = ev.getY();        //再起判断一下是否为listview顶部并且没有记录y坐标        if (firstVisibleItem == 0 && !isRemark) {            isRemark = true;            startY = tempY;        }        if (state != REFLASHING && isRemark) {            //计算y的偏移量            offsetY = tempY - startY;            //计算当前滑动的高度            float currentHeight = (-headerViewHeight+offsetY/3);            //如果当前的状态是释放刷新,并且已经记录y坐标            if (state == RELESE && isRemark) {                setSelection(0);                //如果当前滑动的距离小于headerView的总高度                if (-headerViewHeight+offsetY/RATIO<0) {                    //状态改为下拉刷新                    state = PULL;                    refreshViewByState();                } else if (offsetY <= 0) {//如果当前y的位移值小于0,即为headerView隐藏了                    //状态改为正常状态                    state = NONE;                    refreshViewByState();                }            }            //如果当前状态为下拉刷新并且已经记录y坐标            if (state == PULL && isRemark) {                setSelection(0);                //如果下拉距离大于等于headerView的总高度                if (-headerViewHeight+offsetY/RATIO>=0) {                    //状态改为释放刷新                    state = RELESE;                    refreshViewByState();                } else if (offsetY <= 0) {//如果当前y的位移值小于0,即为headerView隐藏了                    //状态改为正常状态                    state = NONE;                    refreshViewByState();                }            }            //如果当前状态为正常并且已经记录y坐标            if (state == NONE && isRemark) {                //如果位移值大于0                if (offsetY>=0) {                    //将状态改为释放刷新状态                    state = PULL;                    refreshViewByState();                }            }            //如果为下拉刷新状态            if (state == PULL) {                topPadding((int)(-headerViewHeight+offsetY/RATIO));            }            //如果为释放刷新状态            if (state == RELESE) {                topPadding((int)(-headerViewHeight+offsetY/RATIO));            }        }    }    /**     * 根据当前状态,改变界面显示     */    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;        }    }    /**     * 获取完数据     */    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
<?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:orientation="vertical"    android:background="@android:color/white">    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:layout_gravity="center_horizontal"        android:paddingBottom="20dp"        android:paddingTop="12dp">            <ImageView                android:id="@+id/img"                android:layout_width="40dp"                android:layout_height="40dp"                android:background="@drawable/head_image_0"                android:layout_marginRight="5dp"/>            <TextView                android:id="@+id/tip"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:singleLine="true"                android:text="下拉刷新"                android:textSize="12sp"                android:layout_marginTop="5dp"                android:layout_marginLeft="5dp"                android:layout_gravity="center_vertical"/>    </LinearLayout></LinearLayout>

activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent">   <com.example.openrefreshlistview.RefreshListView       android:id="@+id/listview"       android:layout_width="match_parent"       android:layout_height="match_parent"       android:scrollbars="none"/></RelativeLayout>

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 List<String> mDatas;    private ArrayAdapter<String> mAdapter;    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<String>(Arrays.asList(data));        /*Open Declaration android.widget.ArrayAdapter.ArrayAdapter<String>(Context context,           int textViewResourceId, List<String> objects)*/        mAdapter = new ArrayAdapter<String>(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();    }}



0 0