PullToRefreshListView下拉刷新

搞了好几天,各种bug,现在终于搞定了!!赶紧开一篇blog,废话不说了 上代码记录一下,方便以后查看~~
MainActivity代码:

package com.example.lenovo.pulltorefreshlistview;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.google.gson.Gson;
import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.x;
import java.util.ArrayList;
import java.util.List;
import Adapter.MyBaseAdapter;
import Adapter.MyViewPagerAdapter;
import Bean.NewsBean;

public class MainActivity extends Activity {
    private PullToRefreshListView listView;
    private ViewPager viewPager;
    private LinearLayout linearLayout;
    private ImageView[] points;
    private String jsonStr = "http://www.imooc.com/api/teacher?type=4&num=30";
    private List<NewsBean.DataBean> listData = new ArrayList<>();
    private String[] imagesUrl = {
            "http://bbs.uc.cn/data/attachment/forum/201302/17/163510xsv14x35i9ix41i0.jpg",
            "http://p3.so.qhimg.com/t0121ddd5bc66dcc9e8.jpg",
            "http://p3.so.qhimg.com/t0181e8d7355386f79d.jpg",
            "http://bbs.liebao.cn/data/attachment/forum/201210/25/182447qee2e922myyw8y8m.jpg"};
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
            handler.sendEmptyMessageDelayed(1, 3000);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initPoint();
        //下面这2句一定要在ViewPager.setAdapter之前调用,否则出现先加载最后一张图片的问题
        viewPager.setCurrentItem(Integer.MAX_VALUE / 2);
        handler.sendEmptyMessageDelayed(1, 3000);
        viewPager.setAdapter(new MyViewPagerAdapter(this, imagesUrl));
        requestNet();
        //viewpager页面滑动监听
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                for (int i = 0; i < points.length; i++) {
                    if (position % imagesUrl.length == i) {
                        points[i].setImageResource(R.drawable.point_focus);
                    } else {
                        points[i].setImageResource(R.drawable.point_noraml);
                    }
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
        listView.setOnRefreshListener(new PullToRefreshListView.onRefreshListener() {
            @Override
            public void onRefresh() {
                //请求服务器获取数据,刷新完成调用这句
                //别忘了mAdapter.notifyDataSetChanged();
                listView.onRefreshComplete(true);
            }

            @Override
            public void onLandmore() {
                //请求服务器获取数据,加载完成调用这句
                //别忘了mAdapter.notifyDataSetChanged();
                 listView.onRefreshComplete(true);
            }
        });
        //listview中item的点事件
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //listview真正的position
                position = position-listView.getHeaderViewsCount();
                Toast.makeText(MainActivity.this, "当前位置:"+position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /** * 模拟请求服务器数据 */
    private void requestNet() {
        RequestParams params = new RequestParams(jsonStr);
        x.http().get(params, new Callback.CommonCallback<String>() {
            @Override
            public void onSuccess(String s) {
                NewsBean news = new Gson().fromJson(s,NewsBean.class);
                listData.addAll(news.getData());
                //一请求完数据就更新UI
                listView.setAdapter(new MyBaseAdapter(MainActivity.this,listData));
            }

            @Override
            public void onError(Throwable throwable, boolean b) {

            }

            @Override
            public void onCancelled(CancelledException e) {

            }

            @Override
            public void onFinished() {

            }
        });
    }

    /** * 初始化小圆点 */
    private void initPoint() {
        points = new ImageView[imagesUrl.length];
        for(int i=0;i<points.length;i++){
            points[i] = (ImageView) linearLayout.getChildAt(i);
        }
        points[0].setImageResource(R.drawable.point_focus);
    }

    private void initView() {
        listView = (PullToRefreshListView) findViewById(R.id.listview);
        View view = View.inflate(this,R.layout.headerview,null);
        linearLayout = (LinearLayout) view.findViewById(R.id.linearlayout);
        viewPager = (ViewPager) view.findViewById(R.id.viewpager);
        listView.addHeaderView(view);
    }
}

ListView的数据Adapter代码:

package Adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.lenovo.pulltorefreshlistview.R;
import org.xutils.x;
import java.util.List;
import Bean.NewsBean;

/** * Created by shan on 2016/6/28. */
public class MyBaseAdapter extends BaseAdapter {
    private Context context;
    private List<NewsBean.DataBean> listData;

    public MyBaseAdapter(Context context, List<NewsBean.DataBean> listData) {
        this.context = context;
        this.listData = listData;
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView==null){
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.news_item,parent,false);
            holder.news_icon = (ImageView) convertView.findViewById(R.id.news_icon);
            holder.news_title = (TextView) convertView.findViewById(R.id.news_title);
            holder.news_description = (TextView) convertView.findViewById(R.id.news_description);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }
        x.image().bind(holder.news_icon,listData.get(position).getPicBig());
        holder.news_title.setText(listData.get(position).getName());
        holder.news_description.setText(listData.get(position).getDescription());
        return convertView;
    }

    private class ViewHolder{
        private ImageView news_icon;
        private TextView news_title,news_description;
    }
}

ViewPager的数据Adapter代码:

package Adapter;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import org.xutils.x;
import Utils.ToastUtil;

/** * Created by shan on 2016/6/28. */
public class MyViewPagerAdapter extends PagerAdapter {
    private Context context;
    private String[] imagesUrl;

    public MyViewPagerAdapter(Context context, String[] imagesUrl) {
        this.context = context;
        this.imagesUrl = imagesUrl;
    }

    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view==object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        ImageView view = new ImageView(context);
        view.setScaleType(ImageView.ScaleType.CENTER_CROP);
        container.addView(view);
        //轮播图中图片的监听
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switch(position%imagesUrl.length){
                    case 0:
                        ToastUtil.showShort(context,"点击了图片1");
                        break;
                    case 1:
                        ToastUtil.showShort(context,"点击了图片2");
                        break;
                    case 2:
                        ToastUtil.showShort(context,"点击了图片3");
                        break;
                    case 3:
                        ToastUtil.showShort(context,"点击了图片4");
                        break;
                }
            }
        });
        x.image().bind(view,imagesUrl[position%imagesUrl.length]);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

ListView的新闻列表item样式代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="8dp" android:paddingBottom="8dp" android:paddingRight="10dp">
    <ImageView  android:id="@+id/news_icon" android:layout_width="100dp" android:layout_height="70dp" android:scaleType="centerCrop" android:layout_marginLeft="10dp" android:src="@drawable/ic_launcher"/>
    <TextView  android:id="@+id/news_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="新闻标题" android:maxLines="1" android:textSize="16sp" android:layout_marginLeft="5dp" android:textColor="#000" android:layout_toRightOf="@+id/news_icon"/>
    <TextView  android:id="@+id/news_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/news_icon" android:layout_below="@+id/news_title" android:layout_alignLeft="@+id/news_title" android:layout_marginTop="3dp" android:maxLines="2" android:text="新闻内容介绍"/>
</RelativeLayout>

ListView的HeaderView(ViewPager+圆点)的xml代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
    <android.support.v4.view.ViewPager  android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="150dp">
    </android.support.v4.view.ViewPager>
    <LinearLayout  android:id="@+id/linearlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_horizontal" android:layout_marginTop="130dp">
        <ImageView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/point_noraml"/>
        <ImageView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/point_noraml"/>
        <ImageView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/point_noraml"/>
        <ImageView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/point_noraml"/>
    </LinearLayout>
</RelativeLayout>

接下来是刷新头view和加载脚view的xml代码:
刷新头xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pull_to_refresh_header" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
    <RelativeLayout  android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent" android:paddingTop="8dp" android:paddingBottom="8dp" android:gravity="center_horizontal">
        <RelativeLayout  android:id="@+id/refresh_progress" android:layout_width="wrap_content" android:layout_height="wrap_content">
            <ProgressBar  android:id="@+id/pulldown_progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminateDrawable="@drawable/custom_progressbar" android:visibility="invisible"/>
            <ImageView  android:id="@+id/arrow_down" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/arrow" android:layout_centerInParent="true" android:visibility="visible" />
        </RelativeLayout>
        <RelativeLayout  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_centerInParent="true" android:layout_toRightOf="@+id/refresh_progress">
            <TextView  android:id="@+id/pulldown_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新" android:textColor="#969696" android:textSize="16sp" />
            <TextView  android:id="@+id/pulldown_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="最近更新:12:00" android:layout_below="@+id/pulldown_text"/>
        </RelativeLayout>
    </RelativeLayout>
</LinearLayout>

加载脚view代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pull_to_refresh_header" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center">

    <ProgressBar  android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminateDrawable="@drawable/custom_progressbar" android:visibility="visible"/>

    <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正在加载..." android:layout_marginLeft="15dp" android:textColor="#969696" android:textSize="16sp" />

</LinearLayout>

说明一下:这里用的自定义的Progressbar,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%">
    <shape  android:shape="ring" android:useLevel="false" android:innerRadius="10dp" android:thickness="3dp">
        <!--sweep横扫而过的方式-->
        <gradient android:startColor="#fff" android:endColor="#00ffff" android:centerColor="#9f00" android:type="sweep"></gradient>

    </shape>
</rotate>

引用方式:android:indeterminateDrawable=”@drawable/custom_progressbar

最后,PullToRefreshListView:

package com.example.lenovo.pulltorefreshlistview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
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 java.text.SimpleDateFormat;
import java.util.Date;

/** * Created by shan on 2016/6/26. * * 下拉刷新的listview */
public class PullToRefreshListView extends ListView implements AbsListView.OnScrollListener{
    private static final int STATE_PULL_TO_REFRESH = 1;
    private static final int STATE_RELEASE_TO_REFRESH = 2;
    private static final int STATE_REFRESHING = 3;
    private int mCurrentState = STATE_PULL_TO_REFRESH;//当前状态
    //下拉刷新的头view
    private View headerview;
    private int headerviewHeight;//下拉刷新view的高度
    private int startY = -1;//起始Y坐标
    private int endY;//终点坐标
    //下拉刷新布局中的子view
    private TextView pulldown_text;
    private TextView pulldown_time;
    private ImageView arrow_down;
    private ProgressBar pulldown_progressbar;
    private RotateAnimation animUp; //向上的箭头
    private RotateAnimation animDown;//向下的箭头
    //上拉加载更多的脚view
    private View footerview;
    private int footerviewHeight;//下拉刷新view的高度
    //上拉加载布局中的子view


    public PullToRefreshListView(Context context) {
        super(context);
        initHeaderView();
        initFooterView();
    }

    public PullToRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeaderView();
        initFooterView();
    }

    public PullToRefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initHeaderView();
        initFooterView();
    }

    public PullToRefreshListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initHeaderView();
        initFooterView();
    }

    /** * 初始化头布局 */
    private void initHeaderView(){
        headerview = View.inflate(getContext(), R.layout.refresh_header, null);
        this.addHeaderView(headerview);
        pulldown_text = (TextView) headerview.findViewById(R.id.pulldown_text);
        pulldown_time = (TextView) headerview.findViewById(R.id.pulldown_time);
        arrow_down = (ImageView) headerview.findViewById(R.id.arrow_down);
        pulldown_progressbar = (ProgressBar) headerview.findViewById(R.id.pulldown_progressbar);
        //隐藏下拉刷新布局
        headerview.measure(0, 0);
        //获得下拉刷新view的高度
        headerviewHeight = headerview.getMeasuredHeight();
        //隐藏下拉刷新view
        headerview.setPadding(0, -headerviewHeight, 0, 0);
        //初始化箭头的动画
        initAnimation();
        setCurrentTime();
    }

    /** * 初始化脚view */
    private void initFooterView(){
        footerview = View.inflate(getContext(), R.layout.refresh_footer, null);
        this.addFooterView(footerview);
        footerviewHeight = getMeasuredHeight();
        footerview.measure(0, 0);
        footerview.setPadding(0, -footerviewHeight, 0, 0);
        this.setOnScrollListener(this);//滑动监听
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch(ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                startY = (int) ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                //当用户按住viewpager进行下拉时,ACTION_DOWN会被viewpager消费掉,导致startY没有赋值,
                // 此处需要重新获取一下
                if(startY == -1){
                    startY = (int) ev.getY();
                }
                if(mCurrentState==STATE_REFRESHING){
                    //如果是正在刷新,跳出循环
                    break;
                }
                endY = (int) ev.getY();
                //计算滑动【偏移量
                int dy = endY - startY;
                int firstVisiblePositin = getFirstVisiblePosition();//当前显示的第一个item的位置
                //如果当前显示的位置是ListView的第一项并且偏移量>0 再执行下拉操作
                if(dy>0&&firstVisiblePositin==0){
                    //计算下拉刷新view被拉下来的高度
                    int padding = dy-headerviewHeight;
                    headerview.setPadding(0,padding,0,0);
                    if(padding>0&&mCurrentState!=STATE_RELEASE_TO_REFRESH){
                        //改为松开刷新
                        mCurrentState = STATE_RELEASE_TO_REFRESH;
                        refreshState();
                    }else if(padding<0&&mCurrentState!=STATE_PULL_TO_REFRESH){
                        //改为下拉刷新
                        mCurrentState = STATE_PULL_TO_REFRESH;
                        refreshState();
                    }
                    super.onTouchEvent(ev);
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                startY = -1;
                if(mCurrentState==STATE_RELEASE_TO_REFRESH){
                    mCurrentState = STATE_REFRESHING;
                    refreshState();
                    //完整展示头view
                    headerview.setPadding(0, 0, 0, 0);
                    //4.进行回调
                    if(mListener!=null){
                        mListener.onRefresh();
                    }
                }else if(mCurrentState==STATE_PULL_TO_REFRESH){
                    headerview.setPadding(0,-headerviewHeight,0,0);
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    /** * 根据当前状态刷新界面 */
    private void refreshState() {
        switch(mCurrentState){
            case STATE_PULL_TO_REFRESH:
                pulldown_text.setText("下拉刷新");
                pulldown_progressbar.setVisibility(View.INVISIBLE);
                arrow_down.setVisibility(View.VISIBLE);
                arrow_down.startAnimation(animDown);
                break;
            case STATE_RELEASE_TO_REFRESH:
                pulldown_text.setText("释放立即刷新");
                pulldown_progressbar.setVisibility(View.INVISIBLE);
                arrow_down.setVisibility(View.VISIBLE);
                arrow_down.startAnimation(animUp);
                break;
            case STATE_REFRESHING:
                pulldown_text.setText("正在刷新...");
                arrow_down.clearAnimation();//清除箭头动画,否则无法隐藏
                pulldown_progressbar.setVisibility(View.VISIBLE);
                arrow_down.setVisibility(View.INVISIBLE);
                break;
        }
    }

    /** * 设置刷新当前时间 */
    private void setCurrentTime(){
        SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm");
        String time = format.format(new Date());
        pulldown_time.setText("上次更新:"+time);
    }

    /** * 初始化箭头动画 */
    private void initAnimation(){
        animUp = new RotateAnimation(0,-180,
                Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
        animUp.setDuration(200);
        animUp.setFillAfter(true);
        animDown = new RotateAnimation(-180,0,
                Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
        animDown.setDuration(200);
        animDown.setFillAfter(true);
    }

    /** * 刷新完毕,收起刷新view,在网络请求结束刷新完毕后调用该方法,复原状态 * * 即使网络请求失败导致刷新失败,也要执行此步骤,以便再刷新 * * */
    public void onRefreshComplete(boolean success){
        if(!isLoadingMore){
            headerview.setPadding(0,-headerviewHeight,0,0);
            mCurrentState = STATE_PULL_TO_REFRESH;
            pulldown_text.setText("下拉刷新");
            pulldown_progressbar.setVisibility(View.INVISIBLE);
            arrow_down.setVisibility(View.VISIBLE);
            //刷新success了再更新上次刷新时间,刷新失败的话,不需要更新本次刷新时间
            if(success){
                setCurrentTime();
            }
        }else{
            //加载更多
            footerview.setPadding(0,-footerviewHeight,0,0);//隐藏脚view
            isLoadingMore = false;
        }
    }



    public onRefreshListener mListener;//3.定义成员变量,接收监听对象

    /** * 2.暴露接口,设置监听 */
    public void setOnRefreshListener(onRefreshListener listener){
        mListener = listener;
    }



    private boolean isLoadingMore;//标记是否正在加载动作


    /** * 滑动状态发生变化 */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if(scrollState==SCROLL_STATE_IDLE){//空闲状态
            int lastVisiblePositin = getLastVisiblePosition();
            //表示滑到底,而且没有正在加载更多
            if(lastVisiblePositin==getCount()-1&&!isLoadingMore){
                isLoadingMore = true;
                footerview.setPadding(0,0,0,0);//到底了,显示脚view
                setSelection(getCount()-1);//将footerview显示在最后的一个位置上
                //通知主界面加载下一页
                if(mListener!=null){
                    mListener.onLandmore();
                }
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }


    /** * 1.下拉刷新 上拉加载回调接口 */
    public interface onRefreshListener{
        public void onRefresh();
        public void onLandmore();
    }
}

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