文档章节

自定义控件-RefreshListview

IceFrost
 IceFrost
发布于 2015/02/02 19:51
字数 1287
阅读 69
收藏 4

自定义RefreshListView

public class RefreshListView extends ListView implements OnScrollListener{

    private LinearLayout refresh_header_root;

    private LinearLayout refresh_header_view;

    private ProgressBar refresh_header_progressbar;

    private ImageView refresh_header_imageview;

    private TextView refresh_header_text;

    private TextView refresh_header_time;

    private int headerHeight;

    private View customerView;

    private RotateAnimation rotateAnimationUp;

    private RotateAnimation rotateAnimationDown;

    private int downY = -1;

    private int mfirstVisibleItem = -1;

    

    private int currentState = PULL_REFRESH;

    //onRefreshListener传递进来的对象(刷新,加载)

    private OnRefreshListener onRefreshListener;

    

    //下拉刷新

    private static final int PULL_REFRESH = 0;

    //释放刷新

    private static final int RELEASE_REFRESH = 1;

    //正在刷新

    private static final int IS_REFRESHING = 2;

   

    private LinearLayout refresh_footer_root;

    private int footerHeight;

    //默认为没有加载更多

    private boolean isload = false;

    //控件一被创建,便添加头控件,底控件,设置滚动状态的监听器

    public RefreshListView(Context context, AttributeSet attrs) {

        super(context, attrs);

        //添加刷新头,放置在ListView最顶部

        initHeader();

        initFooter();

        setOnScrollListener(this);

    }

    public RefreshListView(Context context) {

        super(context);

        initHeader();

        initFooter();

        setOnScrollListener(this);

    }

    

    private void initFooter() {

        View viewFooter = View.inflate(getContext(), R.layout.refresh_footernull);

        

        refresh_footer_root = (LinearLayout) viewFooter.findViewById(R.id.refresh_footer_root);

        refresh_footer_root.measure(0, 0);

        footerHeight = refresh_footer_root.getMeasuredHeight();

        refresh_footer_root.setPadding(0,-footerHeight, 0, 0);

        

        this.addFooterView(viewFooter);

        }

      private void initHeader() {

        View view = View.inflate(getContext(), R.layout.refresh_headernull);

        

        refresh_header_root = (LinearLayout) view.findViewById(R.id.refresh_header_root);

        

        //刷新头对应控件

        refresh_header_view = (LinearLayout) view.findViewById(R.id.refresh_header_view);

        

        refresh_header_progressbar = (ProgressBar) view.findViewById(R.id.refresh_header_progressbar);

        refresh_header_imageview = (ImageView) view.findViewById(R.id.refresh_header_imageview);

        

        refresh_header_text = (TextView) view.findViewById(R.id.refresh_header_text);

        refresh_header_time = (TextView) view.findViewById(R.id.refresh_header_time);

        

        refresh_header_view.measure(0, 0);

        headerHeight = refresh_header_view.getMeasuredHeight();

        refresh_header_view.setPadding(0, -headerHeight, 0, 0);

        

        this.addHeaderView(view);

        //初始化箭头的选择动画

        initAnimation();

    }

//上拉刷新和下拉加载的方法,只有使用者知道该如何实现,因此给使用者暴露接口,让使用者实现其中的方法

    public interface OnRefreshListener{

        //下拉刷新的方法

        public void pullDownRefresh();

        //上拉加载的方法

        public void loadMore();

    } 

//提供将接口实现类传递进来的方法 

    public void setOnRefreshListener(OnRefreshListener onRefreshListener){

        this.onRefreshListener = onRefreshListener;

    }

 //初始化箭头旋转的动画

    private void initAnimation() {

        //逆时针选择180度  箭头由下向上旋转

        rotateAnimationUp = new RotateAnimation(

                0, -180, 

                Animation.RELATIVE_TO_SELF, 0.5f, 

                Animation.RELATIVE_TO_SELF, 0.5f);

        rotateAnimationUp.setDuration(500);

       //使动画停留在最后一帧

        rotateAnimationUp.setFillAfter(true);

        

        //逆时针选择180度 箭头由上向下选择

        rotateAnimationDown = new RotateAnimation(

                -180,-360 ,

                Animation.RELATIVE_TO_SELF, 0.5f, 

                Animation.RELATIVE_TO_SELF, 0.5f);

        rotateAnimationDown.setDuration(500);

        rotateAnimationDown.setFillAfter(true);

    }

//刷新或加载完毕后,调用此方法,隐藏头控件或底控件

    public void finish(){

        //刷新完毕后的业务逻辑

        if(currentState == IS_REFRESHING){

            refresh_header_progressbar.setVisibility(View.INVISIBLE);

            refresh_header_imageview.setVisibility(View.VISIBLE);

            refresh_header_text.setText("下拉刷新");

            currentState = PULL_REFRESH;

            refresh_header_view.setPadding(0, -headerHeight, 0, 0);

        }

        

        //加载完毕后的逻辑

        if(isload){

            //隐藏脚底

            refresh_footer_root.setPadding(0, -footerHeight, 0, 0);

            isload = false;

        }

    }

    

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

        case MotionEvent.ACTION_DOWN:

            downY = (int) ev.getY();

            break;

        case MotionEvent.ACTION_MOVE:

            //当前downY的值是无限趋近与downY的值

            if(downY == -1){

                downY = (int) ev.getY();

            }

            int moveY = (int) ev.getY();

            

            //当前的刷新头还隐藏的距离

            int padding = -headerHeight+moveY-downY;

            

            //获取轮播图图片左上角的位置

            int [] locationCustomerView = new int[2];

            //就将当前view的左上角的(x,y)的坐标赋值给locationCustomerView

            customerView.getLocationOnScreen(locationCustomerView);

            int customerViewY = locationCustomerView[1];

            //listView左上角的位置

            

            int[] locationListView = new int[2];

            this.getLocationOnScreen(locationListView);

            int listY = locationListView[1];

            

            if(listY>customerViewY){

                break;

            }

//显示头控件的条件,第一个可见item为第零个itemm

            if(padding>-headerHeight && mfirstVisibleItem==0){

                //向下滑动并且第一个条目可见,做下拉刷新操作

                //下拉刷新

                //释放刷新

                //正在刷新

                if(padding>0 && currentState == PULL_REFRESH){

                    currentState = RELEASE_REFRESH;

                    setCurrentOption();

                }

                if(padding<0 && currentState == RELEASE_REFRESH){

                    currentState = PULL_REFRESH;

                    setCurrentOption();

                }

                refresh_header_view.setPadding(0, padding, 0, 0);

                //保证后续的事件去做响应,up事件做响应

                return true;

            }

            break;

        case MotionEvent.ACTION_UP:

//手指抬起,如果状态为释放刷新,就要进行刷新操作,显示正在刷新的界面,并调用刷新的方法,改变状态为正在刷新。调用finish方法时,如果状态为正在刷新,会重新隐藏头控件,并将状态初始化为下拉刷新。

如果状态为下拉刷新,则隐藏头控件,不执行刷新的业务逻辑

            if(currentState == RELEASE_REFRESH){

                //如果手指放开,就真的要去做刷新操作,改为刷新操作的状态

                currentState = IS_REFRESHING;

                //完整的显示刷新头

                refresh_header_view.setPadding(0, 0, 0, 0);

                setCurrentOption();

                //刷新的逻辑,回调(定义一个接口,为实现的方法(刷新逻辑的方法),谁用谁实现,在合理的地方调用当前方法)

                if(onRefreshListener!=null){

                    //刷新逻辑

                    onRefreshListener.pullDownRefresh();

                }

                //模拟网络请求操作

                if(handler!=null){

                    handler.sendEmptyMessageDelayed(0,3000);

                }

            }else if(currentState == PULL_REFRESH){

                //弹回操作

                refresh_header_view.setPadding(0, -headerHeight, 0, 0);

            }

            break;

        }

        return super.onTouchEvent(ev);

    }

 //根据刷新状态改变刷新界面的方法

    private void setCurrentOption() {

        switch (currentState) {

        case RELEASE_REFRESH:

            //修改下拉刷新文字为释放刷新

            refresh_header_text.setText("释放刷新");

            refresh_header_imageview.startAnimation(rotateAnimationUp);

            break;

        case PULL_REFRESH:

            //修改下拉刷新文字为释放刷新

            refresh_header_text.setText("下拉刷新");

            refresh_header_imageview.startAnimation(rotateAnimationDown);

            break;

        case IS_REFRESHING:

            refresh_header_text.setText("正在刷新");

            refresh_header_imageview.clearAnimation();

            refresh_header_imageview.setVisibility(View.GONE);

            refresh_header_progressbar.setVisibility(View.VISIBLE);

            refresh_header_time.setText(getTime());

            break;

        }

    }

//获取当前时间的方法

    private String getTime() {

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date date = new Date();

        return dateFormat.format(date);

    }

//将轮播图添加到头控件的底部的方法

    public void addCustomerView(View view){

        customerView = view;

        refresh_header_root.addView(view);

    }

    @Override

    public void onScroll(AbsListView view, int firstVisibleItem,

            int visibleItemCount, int totalItemCount) {

        mfirstVisibleItem  = firstVisibleItem;

    }

//滚动到最后一个条目时,调用加载数据的方法,显示加载数据的界面,加载完后,隐藏界面

    public void onScrollStateChanged(AbsListView view, int scrollState) {

        //OnScrollListener.SCROLL_STATE_FLING  飞速滚动

        //OnScrollListener.SCROLL_STATE_TOUCH_SCROLL  慢慢的滚动

        //OnScrollListener.SCROLL_STATE_IDLE 滚动状态改变

        if(scrollState == OnScrollListener.SCROLL_STATE_FLING 

                || scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){

            if((getLastVisiblePosition() == getCount()-1) && !isload){

                //加载逻辑

                //底部的脚,显示出来

                refresh_footer_root.setPadding(0, 0, 0, 0);

                isload = true;

                if(onRefreshListener!=null){

                    onRefreshListener.loadMore();

                }

                handler.sendEmptyMessageDelayed(0, 2000);

            }

        }

        

    }

 private Handler handler = new Handler(){

        public void handleMessage(android.os.Message msg) {

            finish();

        };

    };

}


© 著作权归作者所有

IceFrost
粉丝 0
博文 1
码字总数 1287
作品 0
深圳
私信 提问
仿美团下拉刷新控件(二)

如果想学习更多进阶知识,可以关注我的微信公众号:Android小菜。 也可以直接扫描二维码关注: 转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客 本篇是实现仿美团下拉刷新...

qq_32059827
2017/10/28
0
0
上拉、下拉刷新组件--react-native-refresh-list-view

初学 React Native,看到 Github 上现有的相关控件实现都较为复杂,又不太符合自己心中想要的样子。于是自己做了一个简单的列表下拉、上拉刷新控件。列表使用的是 FlatList。 控件的实现非常...

素敌
2017/08/16
1K
0
Wang丶Yan/YanRefreshListView

YanRefreshListView Listview的下拉刷新和上啦加载更多,以及上啦的开关 已经做android很久了,前几天感觉到现在还没自己写过ListView的下拉刷新和上啦加载更多 于是就看了一下网上的某个视频...

Wang丶Yan
2017/07/18
0
0
Jaynm/PullToRefreshListView

PullToRefreshScrollViewDemo Android使用PullToRefresh完成ListView下拉刷新和左滑删除 一、本文主要内容: 使用PullToRefresh完成ListView下拉、上拉刷新; 扩展PullToRefresh完美的实现L...

Jaynm
2016/11/03
0
0
c#Winform自定义控件-目录

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 开源地址:https://gitee.com/kwwwvagaa/netwinformcustom_control 如果觉得写的还行,请点个 star 支持一下...

冰封一夏
08/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
今天
10
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
今天
7
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
今天
6
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
今天
11
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部