ListView下拉刷新

下拉刷新-------
    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放置到屏幕顶端

    4. 有时listview在滑动的时候背景会变黑,这是Listview默认的背景色  可以将其默认背景色改成白色的   android:cacheColorHint="#fff"

其中headerView的布局文件

<?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_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp" >

        <ImageView
            android:id="@+id/iv_arrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/indicator_arrow"
            android:contentDescription="@null" />

        <ProgressBar
            android:id="@+id/pb_rotate"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:visibility="invisible"
            android:layout_centerInParent="true"
            android:indeterminateDrawable="@drawable/indeterminate_drawable"
            android:indeterminateDuration="2000" />
    </RelativeLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:orientation="vertical" >

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

        <TextView
            android:id="@+id/tv_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="最后刷新:"
            android:textColor="@android:color/darker_gray"
            android:textSize="14sp" />
    </LinearLayout>

</LinearLayout>
View Code

其中footerView的布局文件

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

    <ProgressBar
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:indeterminate="true"
        android:indeterminateDrawable="@drawable/indeterminate_drawable"
        android:indeterminateDuration="1000" />

    <TextView android:layout_width="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_height="wrap_content"
        android:textColor="#aa000000"
        android:layout_marginLeft="15dp"
        android:textSize="20sp"
        android:text="加载更多..."/>
</LinearLayout>
View Code

android:indeterminateDrawable="@drawable/indeterminate_drawable"

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:drawable="@drawable/indicate_rotate"
    android:toDegrees="360">
    

</rotate>

RefreshListView的主代码

package com.demo.pullrefresh.view;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.demo.pullrefresh.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
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 android.widget.AbsListView.OnScrollListener;

public class RefreshListView extends ListView implements OnScrollListener {

    private View headerView;// headerView
    private ImageView iv_arrow;
    private ProgressBar pb_rotate;
    private TextView tv_state, tv_time;

    private int downY;// 按下时y的坐标
    private int headerViewHeight;// headerView高

    private View footerView;
    private int footerViewHeight;

    private final int PULL_REFRESH = 0;// 下拉刷新的状态
    private final int RELEASE_REFRESH = 1;// 松开刷新的状态
    private final int REFRESHING = 2;// 正在刷新的状态
    private int currentState = PULL_REFRESH;// headerView的默认位置

    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();
        initFooterView();
        initRotateAnimation();
    }

    /**
     * 初始化headerView
     */
    private void initHeaderView() {
        headerView = View.inflate(getContext(), R.layout.layout_header, null);
        // headerView
        // =LayoutInflater.from(getContext()).inflate(R.layout.layout_header,
        // null);
        iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
        pb_rotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate);
        tv_state = (TextView) headerView.findViewById(R.id.tv_state);
        tv_time = (TextView) headerView.findViewById(R.id.tv_time);
        // 第一种方法
        // 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);// 主动通知系统去测量
        headerViewHeight = headerView.getMeasuredHeight();
        Log.e("MainActivity", "headerViewHeight: " + headerViewHeight);
        headerView.setPadding(0, -headerViewHeight, 0, 0);
        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);
    }

    /**
     * 初始化footerView
     */
    private void initFooterView() {
        footerView = View.inflate(getContext(), R.layout.layout_footer, null);
        footerView.measure(0, 0);// 主动通知系统去测量该View
        footerViewHeight = footerView.getMeasuredHeight();
        footerView.setPadding(0, -footerViewHeight, 0, 0);
        addFooterView(footerView);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downY = (int) ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:

            int deltaY = (int) (ev.getY() - downY);
            int paddingTop = -headerViewHeight + deltaY;
            if (paddingTop > -headerViewHeight
                    && getFirstVisiblePosition() == 0) {
                headerView.setPadding(0, paddingTop, 0, 0);
                Log.d("jiejie", "paddingtop" + paddingTop);

                if (paddingTop >= 0 && currentState == PULL_REFRESH) {
                    // 从下拉刷新进入松开刷新的状态
                    currentState = RELEASE_REFRESH;
                    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.onPullRefersh();
                }
            }
            break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 根据currentState来更新headerView
     */
    private void refreshHeaderView() {
        switch (currentState) {

        case PULL_REFRESH:
            tv_state.setText("下拉刷新");
            iv_arrow.startAnimation(downAnimation);
            break;

        case RELEASE_REFRESH:
            tv_state.setText("松开刷新");
            iv_arrow.startAnimation(upAnimation);
            break;

        case REFRESHING:
            iv_arrow.clearAnimation();// 因为向上的旋转动画有可能没有执行完
            iv_arrow.setVisibility(View.INVISIBLE);
            pb_rotate.setVisibility(View.VISIBLE);
            tv_state.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;
            pb_rotate.setVisibility(View.INVISIBLE);
            iv_arrow.setVisibility(View.VISIBLE);
            tv_state.setText("下拉刷新");
            tv_time.setText("最后刷新:" + getCurrentTime());
        }
    }

    /**
     * 取得当前系统的时间,并格式化
     */
    @SuppressLint("SimpleDateFormat")
    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 onPullRefersh();

        void onLoadingMore();
    }

    /**
     * SCROLL_STATE_IDLE:闲置状态,就是手指松开 SCROLL_STATE_TOUCH_SCROLL:手指触摸滑动,就是按着来滑动
     * SCROLL_STATE_FLING:快速滑动后松开
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        // TODO Auto-generated method stub

    }

    @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();
            }
        }
    }
}

MainActivity的主代码

package com.demo.pullrefresh;

import java.util.ArrayList;
import java.util.List;

import com.demo.pullrefresh.view.RefreshListView;
import com.demo.pullrefresh.view.RefreshListView.OnRefreshListener;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnItemClickListener {
    private RefreshListView refreshListView;
    private MyAdapter adapter;

    private List<String> list ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        initView();
        initData();
    }

    private void initView() {
        // TODO Auto-generated method stub
        // requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.mainactivity);
        refreshListView = (RefreshListView) findViewById(R.id.rf_mainlistview);
    }

    private void initData() {
        list = new ArrayList<String>();
        for (int i = 0; i < 30; i++) {
            list.add("ListView原来的数据——   " + i);
        }

        adapter = new MyAdapter();
        refreshListView.setAdapter(adapter);
        refreshListView.setOnRefreshListener(new OnRefreshListener() {

            @Override
            public void onPullRefersh() {
                // TODO Auto-generated method stub
                // 需要联网请求服务器的数据,然后更新UI
                requestDataFromServer(false);
            }

            @Override
            public void onLoadingMore() {
                // TODO Auto-generated method stub
                requestDataFromServer(true);
            }
        });
        refreshListView.setOnItemClickListener(this);
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // 跟新UI
            adapter.notifyDataSetChanged();
            refreshListView.completeRefresh();
        }

    };

    /**
     * 模拟向服务器请求数据
     * 
     * @param isLoadingMore
     */
    private void requestDataFromServer(final boolean isLoadingMore) {
        new Thread() {
            public void run() {
                SystemClock.sleep(3000);// 模拟请求服务器的一个时间长度
                Log.d("jiejie", isLoadingMore + "");
                if (isLoadingMore) {
                    list.add("加载了更多的数据  ————1");
                    list.add("加载了更多的数据  ————2");
                    list.add("加载了更多的数据  ————3");
                } else {

                }
                handler.sendEmptyMessage(0);
            };
        }.start();
    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // TODO Auto-generated method stub
        Toast.makeText(MainActivity.this, "第" + arg2 + "个条目== " + list.get(arg2-1),
                Toast.LENGTH_SHORT).show();

    }

    private class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return list.size();
        }

        @Override
        public Object getItem(int arg0) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public View getView(int arg0, View arg1, ViewGroup arg2) {
            // TODO Auto-generated method stub
            TextView textView = new TextView(MainActivity.this);
            textView.setPadding(20, 20, 20, 20);
            textView.setTextSize(18);
            textView.setText(list.get(arg0));
            return textView;
        }

    }

}

 

你可能感兴趣的:(ListView下拉刷新)