1. 程式人生 > >android 自定義ListView實現下拉重新整理、分頁載入、點選事件——自定義控制元件學習(七)

android 自定義ListView實現下拉重新整理、分頁載入、點選事件——自定義控制元件學習(七)

package com.example.administrator.customerpulldownrefreshandpageload;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;


/**
 * Created by Administrator on 2016-09-27.
 */
public class CustomerListViewPullDownRefreshAndPageLoad extends RelativeLayout {
    private final String TAG = CustomerListViewPullDownRefreshAndPageLoad.class.getSimpleName();
    private final int REFRESHMSG_CODE = 0x994;
    private final int LOADMORE_CODE = 0x887;
    private ListView listView;
    private LinearLayout footer;
    private ArrayAdapter<String> adapter;
    private ViewGroup.MarginLayoutParams marginLayoutParams;
    private ViewGroup.MarginLayoutParams marginLayoutParamspro;

    //上方的存放圖示和文字的LinearLayout
    private LinearLayout linearLayout;
    //在上方存檔的內容包括以下的imageView progressBar textView
    private ImageView imageArrow;
    private ProgressBar progressBar;
    private TextView textViewTip;

    private final int MARGIN_TOP = -200;
    private final int IMAGE_SIZE = 50;


    private boolean pullFlag;
    private boolean returnFlag;
    //重新整理完成標誌
    private boolean refreshFinishFlag;

    private int oldY;
    private int newY;
    private int distance;

    //執行緒
    public Thread tempThreadRefresh;

    //介面
    public interface refreshEvent {
        //下拉重新整理
        void refresh();

        //分頁載入
        void loadMore(int startIndex, int endIndex);

        //item點選
        void onItemClick(AdapterView<?> parent, View view, int position, long id);
    }

    private refreshEvent refreshEvent;

    //分頁載入
    private boolean loadFinishFlag;
    private ProgressBar progressBarFooter;
    private TextView textViewTipFooter;
    private int startIndex;
    private int endIndex;
    private final int pageSize = 20;

    //執行緒
    public Thread tempThreadLoadMore;

    public CustomerListViewPullDownRefreshAndPageLoad(Context context, AttributeSet attrs) {
        super(context, attrs);
        listView = new ListView(getContext());
        RelativeLayout.LayoutParams reLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        reLayoutParams.setMargins(0, 0, 0, 0);
        listView.setLayoutParams(reLayoutParams);
        listView.setBackgroundColor(getResources().getColor(android.R.color.white));
        addView(listView);

        linearLayout = new LinearLayout(getContext());
        RelativeLayout.LayoutParams liLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        liLayoutParams.setMargins(0, MARGIN_TOP, 0, 0);
        linearLayout.setOrientation(LinearLayout.HORIZONTAL);
        linearLayout.setGravity(Gravity.CENTER);
        linearLayout.setLayoutParams(liLayoutParams);
        addView(linearLayout);

        imageArrow = new ImageView(getContext());
        imageArrow.setImageResource(R.drawable.arrowdown);
        LinearLayout.LayoutParams imgLayoutParams = new LinearLayout.LayoutParams(IMAGE_SIZE, IMAGE_SIZE);
        imageArrow.setLayoutParams(imgLayoutParams);
        linearLayout.addView(imageArrow);

        progressBar = new ProgressBar(getContext());
        LinearLayout.LayoutParams proLayoutParams = new LinearLayout.LayoutParams(IMAGE_SIZE, IMAGE_SIZE);
        progressBar.setIndeterminateDrawable(getResources().getDrawable(R.drawable.progressbar));
        progressBar.setLayoutParams(proLayoutParams);
        linearLayout.addView(progressBar);

        textViewTip = new TextView(getContext());
        LinearLayout.LayoutParams texLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        texLayoutParams.setMargins(20, 0, 0, 0);
        textViewTip.setText("正在重新整理...");
        textViewTip.setLayoutParams(texLayoutParams);
        linearLayout.addView(textViewTip);


        pullFlag = false;
        returnFlag = false;
        refreshFinishFlag = true;
        loadFinishFlag = true;

        oldY = 0;
        newY = 0;
        distance = 0;
        startIndex = 0;
        endIndex = pageSize;
        marginLayoutParams = (ViewGroup.MarginLayoutParams) listView.getLayoutParams();
        marginLayoutParamspro = (ViewGroup.MarginLayoutParams) linearLayout.getLayoutParams();

        //設定滑動事件
        listView.setOnTouchListener(new MyOnTouch());

        footer = new LinearLayout(getContext());
        footer.setGravity(Gravity.CENTER);

        progressBarFooter = new ProgressBar(getContext());
        LinearLayout.LayoutParams footerProLayoutParams = new LinearLayout.LayoutParams(IMAGE_SIZE, IMAGE_SIZE);
        progressBarFooter.setIndeterminateDrawable(getResources().getDrawable(R.drawable.progressbar));
        progressBarFooter.setLayoutParams(footerProLayoutParams);
        footer.addView(progressBarFooter);

        textViewTipFooter = new TextView(getContext());
        LinearLayout.LayoutParams footerTexLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        footerTexLayoutParams.setMargins(20, 0, 0, 0);
        textViewTipFooter.setText("正在載入...");
        textViewTipFooter.setLayoutParams(footerTexLayoutParams);
        footer.addView(textViewTipFooter);

        //設定分頁載入
        listView.setOnScrollListener(new ScrollListener());

        //這是點選事件
        listView.setOnItemClickListener(new MyItemClick());

    }

    //滑動事件
    class MyOnTouch implements View.OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    View firstChild = listView.getChildAt(0);
                    if (firstChild != null) {
                        //當前第一個是第幾項
                        int firstChildPosition = listView.getFirstVisiblePosition();
                        //第一項的座標為0
                        int firstChildTop = firstChild.getTop();
                        if (firstChildPosition == 0 && firstChildTop == 0 && refreshFinishFlag && loadFinishFlag) {
                            pullFlag = true;
                            Log.i(TAG, "---->ACTION_DOWN" + String.valueOf(pullFlag));
                        }
                        Log.i(TAG, "---->ACTION_DOWN" + String.valueOf(firstChildPosition));
                        Log.i(TAG, "---->ACTION_DOWN" + String.valueOf(firstChildTop));
                    }
                    returnFlag = false;
                    Log.i(TAG, "---->ACTION_DOWN");
                    oldY = (int) event.getRawY();
                    distance = 0;
                    break;
                case MotionEvent.ACTION_MOVE:
                    newY = (int) event.getRawY();
                    distance = newY - oldY;
                    if (pullFlag && distance > 0) {
                        returnFlag = true;
                        marginLayoutParams.topMargin = distance / 2;
                        listView.setLayoutParams(marginLayoutParams);
                        if (distance < 300) {
                            //正在下拉
                            downStatus();
                            marginLayoutParamspro.topMargin = (distance / 2) - 100;
                            linearLayout.setLayoutParams(marginLayoutParamspro);
                            //防止強迫症,拉完有放回來
                            refreshFinishFlag = true;
                        } else {
                            //下拉大於150,能夠執行重新整理動作
                            //更新標誌位,為完成下拉
                            refreshFinishFlag = false;
                            //顯示釋放
                            upStatus();
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    Log.i(TAG, "---->ACTION_UP");
                    if (pullFlag) {
                        if (distance < 300) {
                            //下拉沒有到位釋放
                            marginLayoutParams.topMargin = 0;
                            //隱藏上邊的部分
                            marginLayoutParamspro.topMargin = MARGIN_TOP;
                            linearLayout.setLayoutParams(marginLayoutParamspro);
                        } else {
                            marginLayoutParams.topMargin = 150;
                            //防止快速點拉
                            marginLayoutParamspro.topMargin = 50;
                            linearLayout.setLayoutParams(marginLayoutParamspro);
                            //顯示正在重新整理
                            refreshingStatus();
                            //下拉到位釋放,啟動重新整理執行緒
                            tempThreadRefresh = new Thread() {
                                @Override
                                public void run() {
                                    super.run();
                                    //插入重新整理事件
                                    refreshEvent.refresh();
                                    handler.obtainMessage(REFRESHMSG_CODE).sendToTarget();
                                }
                            };
                            tempThreadRefresh.start();
                        }
                        listView.setLayoutParams(marginLayoutParams);
                    }
                    pullFlag = false;
                    returnFlag = false;
                    break;
            }
            //true時listview不能進行滑動,false時能夠進行滑動
            return returnFlag;
        }
    }

    public void downStatus() {
        imageArrow.setVisibility(View.VISIBLE);
        progressBar.setVisibility(View.GONE);
        imageArrow.setImageResource(R.drawable.arrowdown);
        textViewTip.setText("下拉重新整理...");
    }

    public void upStatus() {
        imageArrow.setVisibility(View.VISIBLE);
        progressBar.setVisibility(View.GONE);
        imageArrow.setImageResource(R.drawable.arrowup);
        textViewTip.setText("釋放重新整理...");
    }

    public void refreshingStatus() {
        imageArrow.setVisibility(View.GONE);
        progressBar.setVisibility(View.VISIBLE);
        textViewTip.setText("正在重新整理...");
    }

    public void setAdapter(ArrayAdapter<String> adapter) {
        this.adapter = adapter;
        listView.setAdapter(adapter);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case REFRESHMSG_CODE:
                    //通知下拉重新整理
                    adapter.notifyDataSetChanged();
                    Toast.makeText(getContext(), "重新整理完成", Toast.LENGTH_SHORT).show();
                    refreshFinishFlag = true;
                    //隱藏上邊的部分
                    marginLayoutParamspro.topMargin = MARGIN_TOP;
                    linearLayout.setLayoutParams(marginLayoutParamspro);
                    //ListView回到原位
                    marginLayoutParams.topMargin = 0;
                    listView.setLayoutParams(marginLayoutParams);
                    //重新整理後,下拉載入重新開始
                    startIndex = 0;
                    endIndex = pageSize;
                    break;
                case LOADMORE_CODE:
                    //通知載入更多
                    adapter.notifyDataSetChanged();
                    listView.removeFooterView(footer);
                    loadFinishFlag = true;
                    break;
            }
        }
    };

    public void setRefreshEvent(CustomerListViewPullDownRefreshAndPageLoad.refreshEvent refreshEvent) {
        this.refreshEvent = refreshEvent;
    }

    public final class ScrollListener implements AbsListView.OnScrollListener {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            Log.i(TAG, "---->" + scrollState);
            switch (scrollState) {
                case SCROLL_STATE_IDLE:
                    break;
                case SCROLL_STATE_TOUCH_SCROLL:
                    break;
                case SCROLL_STATE_FLING:
                    break;
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            //獲取螢幕最後Item的ID
            int lastVisibleItem = listView.getLastVisiblePosition();
            if (lastVisibleItem + 1 == totalItemCount) {
                if (loadFinishFlag && refreshFinishFlag) {
                    //標誌位,防止多次載入
                    loadFinishFlag = false;
                    listView.addFooterView(footer);
                    //開執行緒載入資料
                    tempThreadLoadMore = new Thread() {
                        @Override
                        public void run() {
                            super.run();
                            startIndex += pageSize;
                            endIndex += pageSize;
                            //分頁載入
                            if (refreshEvent != null) {
                                refreshEvent.loadMore(startIndex, endIndex);
                            }
                            Message message = handler.obtainMessage(LOADMORE_CODE);
                            message.sendToTarget();
                        }
                    };
                    tempThreadLoadMore.start();
                }
            }
        }
    }

    class MyItemClick implements AdapterView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if(refreshFinishFlag&& loadFinishFlag){
                refreshEvent.onItemClick(parent, view, position, id);
            }
        }
    }

}