android學習之ListView下拉刷新

好久沒寫博客了,今天做了一個關於ListView下拉刷新的功能,其實最近谷歌出了SwipeRefreshLayout + RecyclerView 實現 上拉刷新 和 下拉刷新。
谷歌公司只提供了下拉刷新的功能,RecyclerView的出現基本就是爲了替代ListView,GridView的。
作爲一個新手嘛,還是從基礎的來,下次再去看看RecyclerView實現方式,小夥伴們等等咯,過段是時間SwipeRefreshLayout + RecyclerView 實現 上拉刷新 和 下拉刷新的博客,我會寫一篇的。

好了言歸正傳,先上今天的代碼(暈。。不知道是不是網的原因效果圖上傳不了)
佈局代碼:

<?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="match_parent"
              android:orientation="horizontal">

    <!-- 內容 -->

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="30dp" >

        <!-- 箭頭圖像、進度條 -->

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true" >

            <!-- 箭頭 -->

            <ImageView
                android:id="@+id/lvHeaderArrowIv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/ic_launcher" />

            <!-- 進度條 -->

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

        <!-- 提示、最近更新 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <!-- 提示 -->

            <TextView
                android:id="@+id/lvHeaderTipsTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下拉刷新"
                android:textColor="#000000"
                android:textSize="20sp" />

            <!-- 最近更新 -->

            <TextView
                android:id="@+id/lvHeaderLastUpdatedTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="上次更新"
                android:textColor="#000000"
                android:textSize="10sp" />
        </LinearLayout>
    </RelativeLayout>


</LinearLayout>

listView佈局:

<?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="match_parent">



    <com.jp.tools.MyListView
        android:id="@+id/list_thing"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>
</LinearLayout>

自定義listview類:

package com.jp.tools;

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.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.jp.activity.R;

import java.util.Date;

/**
 * Created by Administrator on 2015/8/20.
 */
public class MyListView extends ListView implements AbsListView.OnScrollListener
{
    private final static int RELEASE_To_REFRESH = 0;// 下拉過程的狀態值
    private final static int PULL_To_REFRESH = 1; // 從下拉返回到不刷新的狀態值
    private final static int REFRESHING = 2;// 正在刷新的狀態值
    private final static int DONE = 3;
    private final static int LOADING = 4;
    // 實際的padding的距離與界面上偏移距離的比例
    private final static int RATIO = 3;
    private LayoutInflater inflater;

    // ListView頭部下拉刷新的佈局
    private LinearLayout headerView;
    private TextView lvHeaderTipsTv;
    private TextView lvHeaderLastUpdatedTv;
    private ImageView lvHeaderArrowIv;
    private ProgressBar lvHeaderProgressBar;

    // 定義頭部下拉刷新的佈局的高度
    private int headerContentHeight;

    private RotateAnimation animation;
    private RotateAnimation reverseAnimation;

    private int startY;
    private int state;
    private boolean isBack;

    // 用於保證startY的值在一個完整的touch事件中只被記錄一次
    private boolean isRecored;

    private OnRefreshListener refreshListener;

    private boolean isRefreshable;


    public MyListView(Context context)
    {
        super(context);
        init(context);
    }

    public MyListView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(context);
    }

    private void init(Context context)
    {
        setCacheColorHint(context.getResources().getColor(R.color.write));
        inflater = LayoutInflater.from(context);
        headerView = (LinearLayout) inflater.inflate(R.layout.lv_header, null);
        lvHeaderTipsTv = (TextView) headerView.findViewById(R.id.lvHeaderTipsTv);
        lvHeaderLastUpdatedTv = (TextView) headerView.findViewById(R.id.lvHeaderLastUpdatedTv);
        lvHeaderArrowIv = (ImageView) headerView.findViewById(R.id.lvHeaderArrowIv);
        //設置下拉刷新圖標的最小寬度跟高度
        lvHeaderArrowIv.setMinimumWidth(70);
        lvHeaderArrowIv.setMinimumHeight(50);

        lvHeaderProgressBar = (ProgressBar) headerView.findViewById(R.id.lvHeaderProgressBar);
        measureView(headerView);
        headerContentHeight = headerView.getMeasuredHeight();
        //設置內邊距,正好距離頂部爲一個負的整個佈局的高度,正好把頭部隱藏
        headerView.setPadding(0, -1 * headerContentHeight, 0, 0);
        //重繪一下
        headerView.invalidate();
        //將下拉刷新佈局加入到list的頂部
        addHeaderView(headerView, null, false);
        //設置監聽滾動事件
        setOnScrollListener(this);

        //設置動畫
        animation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        animation.setInterpolator(new LinearInterpolator());
        animation.setDuration(250);
        animation.setFillAfter(true);

        reverseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        animation.setInterpolator(new LinearInterpolator());
        animation.setDuration(200);
        animation.setFillAfter(true);
        //一開始的狀態就是下拉刷新的狀態,所以DONE
        state = DONE;
        //是否正在刷新
        isRefreshable = false;

    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState)
    {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
    {
        if (firstVisibleItem == 0) {
            isRefreshable = true;
        } else {
            isRefreshable = false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev)
    {
        if (isRefreshable) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (!isRecored) {
                        isRecored = true;
                        startY = (int) ev.getY();// 手指按下時記錄當前位置
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (state != REFRESHING && state != LOADING) {
                        if (state == PULL_To_REFRESH) {
                            state = DONE;
                            changeHeaderViewByState();
                        }
                        if (state == RELEASE_To_REFRESH) {
                            state = REFRESHING;
                            changeHeaderViewByState();
                            onLvRefresh();
                        }
                    }
                    isRecored = false;
                    isBack = false;

                    break;

                case MotionEvent.ACTION_MOVE:
                    int tempY = (int) ev.getY();
                    if (!isRecored) {
                        isRecored = true;
                        startY = tempY;
                    }
                    if (state != REFRESHING && isRecored && state != LOADING) {
                        // 保證在設置padding的過程中,當前的位置一直是在head,否則如果當列表超出屏幕的話,當在上推的時候,列表會同時進行滾動
                        // 可以鬆手去刷新了
                        if (state == RELEASE_To_REFRESH) {
                            setSelection(0);
                            // 往上推了,推到了屏幕足夠掩蓋head的程度,但是還沒有推到全部掩蓋的地步
                            if (((tempY - startY) / RATIO < headerContentHeight)// 由鬆開刷新狀態轉變到下拉刷新狀態
                                    && (tempY - startY) > 0) {
                                state = PULL_To_REFRESH;
                                changeHeaderViewByState();
                            }
                            // 一下子推到頂了
                            else if (tempY - startY <= 0) {// 由鬆開刷新狀態轉變到done狀態
                                state = DONE;
                                changeHeaderViewByState();
                            }
                        }
                        // 還沒有到達顯示鬆開刷新的時候,DONE或者是PULL_To_REFRESH狀態
                        if (state == PULL_To_REFRESH) {
                            setSelection(0);
                            // 下拉到可以進入RELEASE_TO_REFRESH的狀態
                            if ((tempY - startY) / RATIO >= headerContentHeight) {// 由done或者下拉刷新狀態轉變到鬆開刷新
                                state = RELEASE_To_REFRESH;
                                isBack = true;
                                changeHeaderViewByState();
                            }
                            // 上推到頂了
                            else if (tempY - startY <= 0) {// 由DOne或者下拉刷新狀態轉變到done狀態
                                state = DONE;
                                changeHeaderViewByState();
                            }
                        }
                        // done狀態下
                        if (state == DONE) {
                            if (tempY - startY > 0) {
                                state = PULL_To_REFRESH;
                                changeHeaderViewByState();
                            }
                        }
                        // 更新headView的size
                        if (state == PULL_To_REFRESH) {
                            headerView.setPadding(0, -1 * headerContentHeight
                                    + (tempY - startY) / RATIO, 0, 0);

                        }
                        // 更新headView的paddingTop
                        if (state == RELEASE_To_REFRESH) {
                            headerView.setPadding(0, (tempY - startY) / RATIO
                                    - headerContentHeight, 0, 0);
                        }

                    }
                    break;

                default:
                    break;
            }
        }
        return super.onTouchEvent(ev);

    }

    //當狀態改變時候,調用該方法,以更新界面
    private void changeHeaderViewByState()
    {
        switch (state) {
            case RELEASE_To_REFRESH:
                lvHeaderArrowIv.setVisibility(View.VISIBLE);
                lvHeaderProgressBar.setVisibility(View.GONE);
                lvHeaderTipsTv.setVisibility(View.VISIBLE);
                lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);

                lvHeaderArrowIv.clearAnimation();//清除動畫
                lvHeaderArrowIv.startAnimation(animation);//開始動畫效果

                lvHeaderTipsTv.setText("鬆開刷新");
                break;
            case PULL_To_REFRESH:
                lvHeaderProgressBar.setVisibility(View.GONE);
                lvHeaderTipsTv.setVisibility(View.VISIBLE);
                lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
                lvHeaderArrowIv.clearAnimation();
                lvHeaderArrowIv.setVisibility(View.VISIBLE);

                if (isBack) {
                    isBack = false;
                    lvHeaderArrowIv.clearAnimation();
                    lvHeaderArrowIv.startAnimation(reverseAnimation);

                    lvHeaderTipsTv.setText("下拉刷新");
                } else {
                    lvHeaderTipsTv.setText("下拉刷新");
                }
                break;
            case REFRESHING:
                headerView.setPadding(0, 0, 0, 0);
                lvHeaderProgressBar.setVisibility(View.VISIBLE);
                lvHeaderArrowIv.clearAnimation();
                lvHeaderArrowIv.setVisibility(View.GONE);
                lvHeaderTipsTv.setText("正在刷新...");
                lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
                break;
            case DONE:
                headerView.setPadding(0, -1 * headerContentHeight, 0, 0);

                lvHeaderProgressBar.setVisibility(View.GONE);
                lvHeaderArrowIv.clearAnimation();
                lvHeaderArrowIv.setImageResource(R.drawable.ic_action_favor_on_pressed);
                lvHeaderTipsTv.setText("下拉刷新");
                lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
                break;

        }
    }

    //對於headView寬高處理
    private void measureView(View child)
    {
        ViewGroup.LayoutParams params = child.getLayoutParams();
        if (params == null) {
            params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }

        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, params.width);
        int lpHeight = params.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);

        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }

    public void setonRefreshListener(OnRefreshListener refreshListener)
    {
        this.refreshListener = refreshListener;
        isRefreshable = true;
    }


    public interface OnRefreshListener
    {
        public void OnRefresh();
    }

    public void onRefreshComplete()
    {
        state = DONE;
        lvHeaderLastUpdatedTv.setText("最近更新:" + new Date().toLocaleString());
        changeHeaderViewByState();
    }

    private void onLvRefresh()
    {
        if (refreshListener != null) {
            refreshListener.OnRefresh();
        }
    }

    @Override
    public void setAdapter(ListAdapter adapter)
    {
        lvHeaderLastUpdatedTv.setText("最近更新:" + new Date().toLocaleString());
        super.setAdapter(adapter);
    }
}

適配器:

public class LvAdapter extends BaseAdapter {  
    private List<String> list;  
    private Context context;  

    public LvAdapter(List<String> list, Context context) {  
        this.list = list;  
        this.context = context;  
    }  

    @Override  
    public int getCount() {  
        return list.size();  
    }  

    @Override  
    public Object getItem(int position) {  
        return list.get(position);  
    }  

    @Override  
    public long getItemId(int position) {  
        return position;  
    }  

    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        TextView tv = new TextView(context.getApplicationContext());  
        tv.setText(list.get(position));  
        return tv;  
    }  

}  

接下來在activity調用:

public class MainActivity extends Activity {  
    private List<String> list;  
    private MyListView lv;  
    private LvAdapter adapter;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        lv = (MyListView) findViewById(R.id.lv);  
        list = new ArrayList<String>();  
        list.add("loonggg");  
        list.add("listView下拉刷新~~");   
        list.add("listView下拉刷新~~"); 
        list.add("listView下拉刷新~~"); 
        list.add("listView下拉刷新~~"); 
        list.add("listView下拉刷新~~"); 
        list.add("listView下拉刷新~~"); 
        adapter = new LvAdapter(list, this);  
        lv.setAdapter(adapter);  

        lv.setonRefreshListener(new OnRefreshListener() {  

            @Override  
            public void onRefresh() {  
                new AsyncTask<Void, Void, Void>() {  
                    protected Void doInBackground(Void... params) {  
                        try {  
                            Thread.sleep(1000);  
                        } catch (Exception e) {  
                            e.printStackTrace();  
                        }  
                        list.add("刷新後添加的內容");  
                        return null;  
                    }  

                    @Override  
                    protected void onPostExecute(Void result) {  
                        adapter.notifyDataSetChanged();  
                        lv.onRefreshComplete();  
                    }  
                }.execute(null, null, null);  
            }  
        });  
    }  
}  

我這裏只做了個下拉刷新,上拉刷新原理差不多。

還有今天是七夕啊,祝程序猿們七夕快樂,小鵬也放棄了女朋友,特地大晚上還來發博客,看到的關注一下~~
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章