一起撸个朋友圈吧(step1) - ListView(完结)篇

项目地址:https://github.com/razerdp/FriendCircle
一起撸个朋友圈吧这是本文所处文集,所有更新都会在这个文集里面哦,欢迎关注

上篇链接:http://www.jianshu.com/p/94e1e267b3b3
下篇链接:http://www.jianshu.com/p/94403e45fbef

在上一篇里面,最后我留下了一个问题,就是关于耦合度的问题。
经过思考后,个人认为,原框架留下了PtrHandler和PtrUIHandler为的就是解耦,我们要实现一个别的下拉header,只需要实现这两个接口就可以联调控制了,也就是ptrframelayout和这两个接口必定是相互依赖的,而不能说我们脱离框架来进行扩展。

同样,我们外部添加的刷新icon其实是可有可无,内部做好空引用判断防止崩溃,这个刷新icon是可有可无的,而且icon由下拉header控制的好处是外部不需要执行什么回调来控制(毕竟回调地狱你懂的),对外部来说,我需要做的,只是在布局文件中放好imageview,然后set进去就完了,其他不管。


今天这篇文章将会是ListView定制的最后一篇。今天要实现的是昨天留下的手尾:上拉加载更多。

不多说,先上图:

加载更多预览

事实上,个人觉得加载更多是实现最简单的。。。特别是对listview来说。

因为listview自带footerView,有了这个footerview,我们就可以定义我们的加载更多布局来实现各种各样的加载更多了。

吹逼吹完了,我们就开工吧(←_←)

首先,依然是布局文件入手,我们的布局文件也是十分简单,只有两个view

footer布局

其中因为某些原因,我们的加载那朵菊花需要特别定制一下。为何?
如果细心观察,可以看到那朵小菊花其实是在转动的时候有明暗变化的,ios因为自带有,所以不用管,可android的原生progressbar是个圆环啊,要变成菊花,只好兼职一回设计师,拉出我们的AE(在下不会PS)

菊花

用形状图层画一个明暗变化的棍子,在旋转属性上打上index30和透明度属性上打上100-(index5),然后不断地复制图层就有了一朵菊花了。

播放起来是这样的,转起来是不是有模有样←_←(看久了会晕的)


菊花

扯回来我们的as,布局弄好后就是写java了

构造器什么的我们就不管了,我们的footer依然使用PtrUIHandler,虽然这个回调不需要在ptrframelayout注册,但为了方便我们还是用它吧。

  //=============================================================ptr:
    private PtrUIHandler mPtrUIHandler = new PtrUIHandler() {
        /**回到初始位置*/
        @Override
        public void onUIReset(PtrFrameLayout frame) {
            if (mRotateIcon==null)return;
            mRotateIcon.setVisibility(GONE);
            mRotateIcon.clearAnimation();
            loadingText.setText(LOAD_MORE);
        }

        /**离开初始位置*/
        @Override
        public void onUIRefreshPrepare(PtrFrameLayout frame) {

        }

        /**开始刷新动画*/
        @Override
        public void onUIRefreshBegin(PtrFrameLayout frame) {
            loadingText.setText(LOADING);
            if (mRotateIcon.getAnimation() != null) {
                mRotateIcon.setVisibility(VISIBLE);
                mRotateIcon.clearAnimation();
            }
            mRotateIcon.startAnimation(rotateAnimation);
        }

        /**刷新完成*/
        @Override
        public void onUIRefreshComplete(PtrFrameLayout frame) {
            mRotateIcon.setVisibility(GONE);
            mRotateIcon.clearAnimation();
            loadingText.setText(LOAD_MORE);
        }

        /**位移更新重载*/
        @Override
        public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {
        }
    };

这回相比于header,我们只需要定义几个地方:

  • 初始状态:菊花隐藏,文字定义为“加载更多”
  • 刷新状态:菊花显示,同时播放动画,文字定义为“正在加载”
  • 完成状态:菊花隐藏,文字定义为“加载更多”

大概就是这三个地方。

然后就是针对是否还有更多数据加载,我们用的是一个布尔值,这个值应该是由服务器下发的,因为只有服务器才知道有没有更多的数据。
所以我们预留一个接口:

    public void setHasMore(boolean loadMore){
        if (loadMore){
            mRotateIcon.clearAnimation();
        }else {
            mRotateIcon.clearAnimation();
            mRotateIcon.setVisibility(GONE);
            loadingText.setText(LOAD_ALL);
        }
    }

当loadmore有的时候,意味着还有更多数据加载,我们就清掉菊花的动画,如果没有,我们就隐藏菊花,文字定义为“已经全部加载”提示用户后面没有数据了。

footer大概就是这么多内容,接下来就是回到我们的listview进行联调了

在昨天,我们setScrollListener方法里面预留了位置,但未处理,哪个地方就是用来加载更多的,那么今天我们就把它完成了

回到我们的setScrollListener

   private void setScrollListener() {
        mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (mOnLoadMoreRefreshListener != null) {
                    if (SCROLL_STATE_IDLE == scrollState &&
                            0 != mListView.getFirstVisiblePosition() && lastItem == mListView.getCount()) {
                        if (hasMore && loadmoreState != PullState.REFRESHING) {
                            //当有更多同时当前加载更多布局不在刷新状态,则执行刷新
                            curMode = PullMode.FROM_BOTTOM;
                            changeLoadMoreState(PullState.REFRESHING);
                        }
                    }
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                lastItem = firstVisibleItem + visibleItemCount;
            }
        });
    }

在if条件里面我们把模式换位frombottom,同时调用changeLoadMoreState来更改footer的状态。

因为执行到这个if里面,此刻的状态必定是有更多数据加载,用户滑到了底部,同时footer处于非刷新状态,所以我们直接更改为刷新状态就可以了。

接下来看看changeLoadMoreState方法

    private void changeLoadMoreState(PullState curLoadMoreState) {
        final PtrUIHandler footerHandler = mFooter.getPtrUIHandler();
        switch (curLoadMoreState) {
            case NORMAL:
                footerHandler.onUIReset(this);
                break;
            case REFRESHING:
                footerHandler.onUIRefreshBegin(this);
                if (mOnLoadMoreRefreshListener != null) mOnLoadMoreRefreshListener.onRefreshing(this);
                break;
            default:
                break;
        }
        loadmoreState = curLoadMoreState;
    }

这个方法里面我们只需要根据状态调用footer的ptruihandler就好了,同时在刷新的时候把刷新接口回调出去,其他不用管。

这时候也许有疑问了,我们的footer没有看到相关的addview操作啊。
其实文章写到这里的时候我也发现了- - 我也忘记footer还没弄到listview里面了。
思考一番后,我打算将footer在setHasMore方法里面添加

   public void setHasMore(boolean hasMore) {
        if (mOnLoadMoreRefreshListener == null) return;
        if (mListView.getFooterViewsCount() == 0 && hasMore) {
            mListView.addFooterView(mFooter);
        }
        mFooter.setHasMore(hasMore);
        this.hasMore = hasMore;
    }

也就是如果有更多数据的时候,添加我们的footer
至此,我们的加载更多就完成了,最后还要做的,就是将加载完成的方法暴露,毕竟框架只有下拉刷新的完成回调而没有加载更多的回调啊。

    public void loadmoreCompelete() {
        changeLoadMoreState(PullState.NORMAL);
    }

这样,我们在activity就可以这么使用了:

        mFriendCirclePtrListView.setOnPullDownRefreshListener(new OnPullDownRefreshListener() {
            @Override
            public void onRefreshing(PtrFrameLayout frame) {
                frame.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mFriendCirclePtrListView.refreshComplete();
                    }
                },1800);
            }
        });
        mFriendCirclePtrListView.setOnLoadMoreRefreshListener(new OnLoadMoreRefreshListener() {
            @Override
            public void onRefreshing(PtrFrameLayout frame) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        SystemClock.sleep(1500);
                        for (int i=0,size=test.size();i<20;i++){
                            test.add("test"+(size+i));
                        }
                    }
                }).start();

                frame.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mFriendCirclePtrListView.refreshComplete();
                        adapter.notifyDataSetChanged();
                        mFriendCirclePtrListView.setHasMore(false);
                    }
                },3000);
            }
        });
    }

当然,我们以后会进行一下封装
ps:因为在下没有服务器,所以只能靠本地模拟网络延迟和数据更新了,所以只能手动设置setHasMore,这些操作其实应该是靠请求完成的。

OK,我们撸个朋友圈的计划已经踏出了一步了,起码把listview框架搭建好,那么下一篇,我们将担任一下后端,来设计一下我们的数据结构吧(JSON结构)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容