Android开发之细说ListView上拉加载,下拉刷新过程

来源:互联网 发布:新笔下文学软件 编辑:程序博客网 时间:2024/06/06 11:42
摘要
学习记下的笔记

下拉刷新-------
    1.addHeaderView必须在setAdapter之前调用
    2.将paddingTop设置一个headerView高度的负值去隐藏它
   
    getHeight()和getMeasuredHeight()的区别:
    getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用
                        它获取到宽高,在自定义控件内部多使用这个
                        使用view.measure(0,0)方法可以主动通知系统去测量,然后就
                        可以直接使用它获取宽高
    getHeight():必须在onLayout方法执行完后,才能获得宽高
                view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                    headerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    int headerViewHeight = headerView.getHeight();
                    //直接可以获取宽高
            }
        });
    3.setSelection(position);将对应位置的item放置到屏幕顶端

 

第一步:制作一个旋转的箭头动画indeterminate_drawable.xml

<?xml version="1.0" encoding="utf-8"?><rotate xmlns:android="http://schemas.android.com/apk/res/android"android:drawable="@drawable/indicate_rotate"android:fromDegrees="0"0度开始旋转android:pivotX="50%"     参照点自身X轴一半android:pivotY="50%"     自身Y轴一半android:toDegrees="360"/>   旋转360度
第二步:下拉加载布局文件layout_header.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:gravity="center_horizontal"    android:orientation="horizontal" >        <RelativeLayout android:layout_width="wrap_content"        android:layout_marginTop="10dp"        android:layout_marginBottom="10dp"        android:layout_height="wrap_content">                <ImageView android:layout_width="wrap_content"            android:layout_centerInParent="true"            android:id="@+id/iv_arrow"            android:background="@drawable/indicator_arrow"            android:layout_height="wrap_content"/>                <ProgressBar android:layout_width="30dp"            android:layout_centerInParent="true"            android:layout_height="30dp"            android:visibility="invisible"    初始化不可见            android:id="@+id/pb_rotate"            android:indeterminateDuration="1000"    旋转周期1秒               android:indeterminateDrawable="@drawable/indeterminate_drawable"   设置刚刚自定义的旋转箭头动画            />            </RelativeLayout>        <LinearLayout android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:layout_marginBottom="10dp"        android:gravity="center"        android:layout_marginLeft="15dp"        android:orientation="vertical">        <TextView android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="20sp"            android:id="@+id/tv_state"            android:textColor="#aa000000"            android:text="下拉刷新"/>        <TextView android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="14sp"            android:id="@+id/tv_time"            android:textColor="@android:color/darker_gray"            android:text="最后刷新:"/>            </LinearLayout></LinearLayout>
 
第三步:上拉加载布局文件layout_footer.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:gravity="center_horizontal"    android:orientation="horizontal" >        <RelativeLayout android:layout_width="wrap_content"        android:layout_marginTop="10dp"        android:layout_marginBottom="10dp"        android:layout_height="wrap_content">                <ImageView android:layout_width="wrap_content"            android:layout_centerInParent="true"            android:id="@+id/iv_arrow"            android:background="@drawable/indicator_arrow"            android:layout_height="wrap_content"/>                <ProgressBar android:layout_width="30dp"            android:layout_centerInParent="true"            android:layout_height="30dp"            android:visibility="invisible"            android:id="@+id/pb_rotate"            android:indeterminateDuration="1000"               android:indeterminateDrawable="@drawable/indeterminate_drawable"            />            </RelativeLayout>        <LinearLayout android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:layout_marginBottom="10dp"        android:gravity="center"        android:layout_marginLeft="15dp"        android:orientation="vertical">        <TextView android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="20sp"            android:id="@+id/tv_state"            android:textColor="#aa000000"            android:text="下拉刷新"/>        <TextView android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="14sp"            android:id="@+id/tv_time"            android:textColor="@android:color/darker_gray"            android:text="最后刷新:"/>            </LinearLayout></LinearLayout>
第四步:R.layout.activity_main
<?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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.zd.listviewtest.MainActivity">    <com.zd.listviewtest.RefreshListView        android:id="@+id/refreshListView"        android:layout_height="match_parent"        android:layout_width="match_parent" /></RelativeLayout>


第五步:自定义一个带下拉刷新,上拉加载的listView
package com.zaizai.dropdownrefresh.view;import java.text.SimpleDateFormat;import java.util.Date;import android.widget.AbsListView.OnScrollListener;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.animation.RotateAnimation;import android.widget.AbsListView;import android.widget.ImageView;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;import com.zaizai.dropdownrefresh.R;public class RefreshListView extends ListView implements OnScrollListener {    private View headerView;//headerView    private ImageView ivArrow;    private ProgressBar pbRotate;    private TextView tvState, tvTime;    private View footerView;    private int footerViewHeight;    private int headerViewHeight;//headerView高    private int downY;//按下时y坐标    private final int PULL_REFRESH = 0;//下拉刷新的状态    private final int RELEASE_REFRESH = 1;//松开刷新的状态    private final int REFRESHING = 2;//正在刷新的状态    private int currentState = PULL_REFRESH;    private RotateAnimation upAnimation, downAnimation;    private boolean isLoadingMore = false;//当前是否正在处于加载更多    public RefreshListView(Context context) {        super(context);        init();    }    public RefreshListView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    private void init() {        //设置滚动监听事件        setOnScrollListener(this);        initHeaderView();        initRotateAnimation();        initFooterView();    }    /**     * 初始化headerView     */    private void initHeaderView() {        headerView = View.inflate(getContext(), R.layout.layout_header, null);        ivArrow = (ImageView) headerView.findViewById(R.id.iv_arrow);        pbRotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate);        tvState = (TextView) headerView.findViewById(R.id.tv_state);        tvTime = (TextView) headerView.findViewById(R.id.tv_time);        headerView.measure(0, 0);//主动通知系统去测量该view;        headerViewHeight = headerView.getMeasuredHeight(); //获得View的高度        headerView.setPadding(0, -headerViewHeight, 0, 0);  //将View隐藏,在下拉时在显示        //将其放在第一个view位置        addHeaderView(headerView);    }    /**     * 初始化旋转动画     */    private void initRotateAnimation() {        upAnimation = new RotateAnimation(0, -180,                RotateAnimation.RELATIVE_TO_SELF, 0.5f,                RotateAnimation.RELATIVE_TO_SELF, 0.5f);        upAnimation.setDuration(300);        upAnimation.setFillAfter(true);        downAnimation = new RotateAnimation(-180, -360,                RotateAnimation.RELATIVE_TO_SELF, 0.5f,                RotateAnimation.RELATIVE_TO_SELF, 0.5f);        downAnimation.setDuration(300);        downAnimation.setFillAfter(true);    }    private void initFooterView() {        footerView = View.inflate(getContext(), R.layout.layout_footer, null);        footerView.measure(0, 0);//主动通知系统去测量该view;        footerViewHeight = footerView.getMeasuredHeight(); //获得底部view的高度        footerView.setPadding(0, -footerViewHeight, 0, 0);   //将其隐藏        addFooterView(footerView);  //设置为最底部的View    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN: {                //获得按下的Y值                downY = (int) ev.getY();                break;            }            case MotionEvent.ACTION_MOVE: {                if (currentState == REFRESHING) {                    //正在加载数据未完成,此时拖动不处理                    break;                }                //下拉的距离                int deltaY = (int) (ev.getY() - downY);                int paddingTop = -headerViewHeight + deltaY;                //下拉的距离大于0且第一个条目已经出现                if (paddingTop > -headerViewHeight && getFirstVisiblePosition() == 0) {                    /*根据下拉的距离重新定位headerView*/                    headerView.setPadding(0, paddingTop, 0, 0);//          Log.e("RefreshListView", "paddingTop: "+paddingTop);                    if (paddingTop >= 0 && currentState == PULL_REFRESH) {                        //从下拉刷新进入松开刷新状态                        currentState = RELEASE_REFRESH;                        //更新headerView状态                        refreshHeaderView();                    } else if (paddingTop < 0 && currentState == RELEASE_REFRESH) {                        //进入下拉刷新状态                        currentState = PULL_REFRESH;                        refreshHeaderView();                    }                    return true;//拦截TouchMove。不让listview处理该次move事件,会造成listview无法滑动                }                break;            }            case MotionEvent.ACTION_UP: {                if (currentState == PULL_REFRESH) {                    //隐藏headerView                    headerView.setPadding(0, -headerViewHeight, 0, 0);                } else if (currentState == RELEASE_REFRESH) {                    headerView.setPadding(0, 0, 0, 0);                    currentState = REFRESHING;                    refreshHeaderView();                    if (listener != null) {                        listener.onPullRefresh();                    }                }                break;            }            default: {                break;            }        }        return super.onTouchEvent(ev);    }    /**     * 根据currentState来更新headerView状态     */    private void refreshHeaderView() {        switch (currentState) {            case PULL_REFRESH:                tvState.setText("下拉刷新");                ivArrow.startAnimation(downAnimation);                break;            case RELEASE_REFRESH:                tvState.setText("松开刷新");                ivArrow.startAnimation(upAnimation);                break;            case REFRESHING:                ivArrow.clearAnimation();//因为向上的旋转动画有可能没有执行完                ivArrow.setVisibility(View.INVISIBLE);                pbRotate.setVisibility(View.VISIBLE);                tvState.setText("正在刷新...");                break;        }    }    /**     * 完成刷新操作,重置状态,在你获取完数据并更新完adater之后,去在UI线程中调用该方法     */    public void completeRefresh() {        if (isLoadingMore) {            //重置footerView状态            footerView.setPadding(0, -footerViewHeight, 0, 0);            isLoadingMore = false;        } else {            //重置headerView状态            headerView.setPadding(0, -headerViewHeight, 0, 0);            currentState = PULL_REFRESH;            pbRotate.setVisibility(View.INVISIBLE);            ivArrow.setVisibility(View.VISIBLE);            tvState.setText("下拉刷新");            tvTime.setText("最后刷新:" + getCurrentTime());        }    }    /**     * 获取当前系统时间,并格式化     *     * @return     */    private String getCurrentTime() {        SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");        return format.format(new Date());    }    private OnRefreshListener listener;    public void setOnRefreshListener(OnRefreshListener listener) {        this.listener = listener;    }    public interface OnRefreshListener {        void onPullRefresh();        void onLoadingMore();    }    /**     * SCROLL_STATE_IDLE:闲置状态,就是手指松开     * SCROLL_STATE_TOUCH_SCROLL:手指触摸滑动,就是按着来滑动     * SCROLL_STATE_FLING:快速滑动后松开     */    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        if (scrollState == OnScrollListener.SCROLL_STATE_IDLE                && getLastVisiblePosition() == (getCount() - 1) && !isLoadingMore) {            isLoadingMore = true;            footerView.setPadding(0, 0, 0, 0);//显示出footerView            setSelection(getCount());//让listview最后一条显示出来            if (listener != null) {                listener.onLoadingMore();            }        }    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem,                         int visibleItemCount, int totalItemCount) {    }}
第五步:自定义listView使用
package com.zaizai.dropdownrefresh;import android.os.Handler;import android.os.SystemClock;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.widget.BaseAdapter;import android.widget.TextView;import com.zaizai.dropdownrefresh.view.RefreshListView;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {    private RefreshListView refreshListView;    private ArrayList<String> list = new ArrayList<String>();    private MyAdapter adapter;    private Handler handler = new Handler() {        public void handleMessage(android.os.Message msg) {            //更新UI            adapter.notifyDataSetChanged();            refreshListView.completeRefresh();        }        ;    };    @Override    protected void onCreate(Bundle savedInstanceState) {        requestWindowFeature(Window.FEATURE_NO_TITLE);        super.onCreate(savedInstanceState);        initView();        initData();    }    private void initView() {        setContentView(R.layout.activity_main);        refreshListView = (RefreshListView) findViewById(R.id.refreshListView);    }    private void initData() {        for (int i = 0; i < 15; i++) {            list.add("listview原来的数据 - " + i);        }//    final View headerView = View.inflate(this, R.layout.layout_header, null);        //第一种方法//    headerView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {//       @Override//       public void onGlobalLayout() {//          headerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);//          int headerViewHeight = headerView.getHeight();//////          Log.e("MainActivity", "headerViewHeight: "+headerViewHeight);//          headerView.setPadding(0, -headerViewHeight, 0, 0);//          refreshListView.addHeaderView(headerView);////       }//    });        //第二种方法//    headerView.measure(0, 0);//主动通知系统去测量//    int headerViewHeight = headerView.getMeasuredHeight();//    Log.e("MainActivity", "headerViewHeight: "+headerViewHeight);//    headerView.setPadding(0, -headerViewHeight, 0, 0);//    refreshListView.addHeaderView(headerView);//        adapter = new MyAdapter();        refreshListView.setAdapter(adapter);        refreshListView.setOnRefreshListener(new RefreshListView.OnRefreshListener() {            @Override            public void onPullRefresh() {                //需要联网请求服务器的数据,然后更新UI                requestDataFromServer(false);            }            @Override            public void onLoadingMore() {                requestDataFromServer(true);            }        });    }    /**     * 模拟向服务器请求数据     */    private void requestDataFromServer(final boolean isLoadingMore) {        new Thread() {            public void run() {                SystemClock.sleep(3000);//模拟请求服务器的一个时间长度                if (isLoadingMore) {                    list.add("加载更多的数据-1");                    list.add("加载更多的数据-2");                    list.add("加载更多的数据-3");                } else {                    list.add(0, "下拉刷新的数据");                }                //在UI线程更新UI                handler.sendEmptyMessage(0);            }            ;        }.start();    }    class MyAdapter extends BaseAdapter {        @Override        public int getCount() {            return list.size();        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            TextView textView = new TextView(MainActivity.this);            textView.setPadding(20, 20, 20, 20);            textView.setTextSize(18);            textView.setText(list.get(position));            return textView;        }    }}
1 0
原创粉丝点击