耳朵(四)常见的上下拉列表

耳朵(四)常见的上下拉列表

tags: 耳朵_android


本节来实现一个常见的带下拉刷新, 上拉加载更多的列表界面.
最后完成的效果图:


首先分析一下我们的web端,安利一下ear.life, 有很多分类目录, 而每个目录下的样式都是一样的,


所以可以想像我们的APP也只需要一个界面, 根据不同的分类id来加载不同的内容(这里可以脑补一下今日头条).

首先在ui包下添加article包,并创建一个ArticleListFragment,



继承自BaseListFragment, 这里的两个泛型T和H先暂时不管吧.

接着需要分析接口交互了, 上一节已经介绍并测试成功了的, 这里公布下API地址吧:

文章列表API: http://ear.life/?json=get_posts

创建对应的Model类, 暂时只需要有几个演示的字段:

    class HttpPostListModel(var posts: ArrayList<PostModel>) : BaseModel() {
        class PostModel(var id: Int, var url: String, var title: String, var excerpt: String)
    }

可以看到只取了posts字段, 而在posts集合中的对象也只取了id、h5地址、标题和简短的内容摘要,已经完全够用了。
现在回到ArticleListFragment中声明一个ViewHolder继承自BaseViewHolder:

    inner class ArticleHolder(itemView: View) : BaseViewHolder<PostModel>(itemView) {
        override fun setContent(position: Int) {
            //一会来设置
        }
    }

inner的作用相当于java中的内部类, 如果不用inner的话, 跟Context交互起来相对来说稍微复杂一些, 这里自行考虑.
现在可以指定之前BaseListFragment的T和H两个泛型了, 并实现BaseListFragment中的抽象方法:

class ArticleListFragment : BaseListFragment<PostModel, ArticleHolder>(){
    override fun getView(parent: ViewGroup?, position: Int): ArticleHolder {
    }
    //...
}

好了, 到现在为止, BaseListFragment这边差不多配置完了, 我们去建个简单的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="130dp">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="#565656"
                android:textSize="16sp"/>
    
            <TextView
                android:id="@+id/tv_excerpt"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/tv_title"
                android:layout_marginTop="5dp"
                android:ellipsize="marquee"
                android:maxLines="3"
                android:textColor="#717171"
                android:textSize="12sp"/>
    
            <View
                android:layout_width="match_parent"
                android:layout_height="0.5dp"
                android:layout_alignParentBottom="true"
                android:background="@color/subscribe_item_drag_stroke"/>
    
        </RelativeLayout>
    </RelativeLayout>

样子可能有点丑, 那不重要. 回到Fragment, 为其设置item的资源ID, 同时给ViewHolder中的控件也用起来:

    class ArticleListFragment(override var itemResID: Int = R.layout.item_article) : BaseListFragment<PostModel, ArticleHolder>()
    ...
    inner class ArticleHolder(itemView: View) : BaseViewHolder<PostModel>(itemView) {
        override fun setContent(position: Int) {
            itemView.tv_title.text = data.title
            itemView.tv_excerpt.text = data.excerpt

            itemView.onClick { showToast(data.url) }
        }
    }

ok, 现在是最后一步, 请求数据. BaseListFragment对此进行了很好的封装, 我们只需要实现其中的loadData方法即可, 下拉刷新及下拉加载更多,还有空数据友好提示等等的功能,完全不需要再操心了:

override fun loadData() {
    val params = HashMap<String, Any>()
    params.put("json", "get_posts")

    HMRequest.go<HttpPostListModel>(params = params, needCallBack = true) {
        //仅需要调用这一个方法完成上下拉功能
        loadCompleted(it?.posts)
    }
}

运行前不要忘记去MainTabActivity把第一个BlankFragment换成刚刚的ArticleListFragment


ok,效果已经出来了, 不过细心的同学一定会发现, 怎么每一页的内容都是一样的呢? 是的, 我们还没有添加类似count和page这样的参数呢.
将loadData方法中val params = HashMap<String, Any>()改为BaseListFragment内置的val params = listParams, 这样如果你的服务器需要的参数正好是pagepageSize的话, 那不需要多余的代码, 现在完全可以正常显示了, 不过我们正在演示的这个项目, 需要的是pagecount这两个参数, 我们需要将默认的pageSize修改为当前项目的count:

override fun setUIParams() {
    default_params_pageSize = "count"
}

要是不想重写setUIParams方法的话, 也可以直接在itemResID后面跟上也是可以的。 除了默认的参数名之外, 还有默认的count、index、拖拽排序、侧滑删除、滑动菜单等等,要是你不需要刷新或者加载更多功能也是一个属性的事儿,非常简单。另外,BaseListFragment用的列表控件是RecyclerView, 所以即使你想要把列表换成两行三行的, 也是可以直接row = 2 就能实现。这正是HMLibrary的目的,将繁琐的一成不变的东西装起来,换成简单的直观的暴露出来,让UI层的代码更清晰明了,更便于维护升级。
最后奉上完整的代码:

class ArticleListFragment(override var itemResID: Int = R.layout.item_article) : BaseListFragment<PostModel, ArticleHolder>() {

    override fun setUIParams() {
        default_params_pageSize = "count"
    }

    override fun loadData() {
        val params = listParams
        params.put("json", "get_posts")

        HMRequest.go<HttpPostListModel>(params = params, needCallBack = true) {
            //仅需要调用这一个方法完成上下拉功能
            loadCompleted(it?.posts)
        }
    }

    override fun getView(parent: ViewGroup?, position: Int): ArticleHolder = ArticleHolder(getItemView(parent))

    inner class ArticleHolder(itemView: View) : BaseViewHolder<PostModel>(itemView) {
        override fun setContent(position: Int) {
            itemView.tv_title.text = data.title
            itemView.tv_excerpt.text = data.excerpt

            itemView.onClick { showToast(data.url) }
        }
    }

    class HttpPostListModel(var posts: ArrayList<PostModel>) : BaseModel() {
        class PostModel(var id: Int, var url: String, var title: String, var excerpt: String)
    }

}

item界面还是非常丑的, 不知道有没有美工同志... 优化的事儿就当家庭作业吧.

github: https://github.com/bxcx/ear
本节分支: https://github.com/bxcx/ear/tree/list

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,045评论 25 707
  • iOS网络架构讨论梳理整理中。。。 其实如果没有APIManager这一层是没法使用delegate的,毕竟多个单...
    yhtang阅读 5,144评论 1 23
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,493评论 18 399
  • 项目设置 DEBUG 一个布尔型用来开启或关闭项目的debug模式。如果设置为True,当你的应用抛出一个未...
    lijun_m阅读 737评论 0 0
  • 清风抚面鸟吹笛 孩童戏水鱼争食 一抹斜阳迟不归 回家犹恐怕天黑
    冰若风阅读 303评论 6 3