首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >具有多个viewType的适配器是否与SwipeRefreshLayout兼容?

具有多个viewType的适配器是否与SwipeRefreshLayout兼容?
EN

Stack Overflow用户
提问于 2019-06-11 23:23:51
回答 3查看 224关注 0票数 0

我正在做一个列表,当我进入列表的底部时,它会得到更多的项目。我也希望这个列表是可刷新的,所以我需要一个SwipeRefreshLayout

假设我有一个这样的适配器:

class OrdersListAdapter(val selected : (Order) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    fun addOrders(orders: ArrayList<Order>) {
        this.orders.addAll(orders)
        notifyItemRangeInserted(this.orders.size - orders.size + FIRST_ITEM_INDEX, orders.size)
    }

    fun setFirstOrders(orders: ArrayList<Order>) {
        this.orders = orders
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return (orders.size + 1 + FIRST_ITEM_INDEX)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            TYPE_ORDERS -> OrdersViewHolder(DataBindingUtil.inflate<OrdersItemBinding>(LayoutInflater.from(parent.context),
                R.layout.orders_item, parent, false).apply {
                viewModel = OrdersViewModel()
            })
            else -> LoadingMoreOrdersViewHolder(DataBindingUtil.inflate<LoadingMoreOrdersItemBinding>(LayoutInflater.from(parent.context),
                    R.layout.loading_more_orders_item, parent, false).apply {
                viewModel = LoadingMoreOrdersViewModel()
            })
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (getItemViewType(position)) {
            TYPE_ORDERS -> (holder as? OrdersViewHolder)?.setData(orders[position - FIRST_ITEM_INDEX])
            TYPE_LOADING -> (holder as? LoadingMoreOrdersViewHolder)?.setState(loading, error, noMoreItems)
        }
    }

    override fun getItemViewType(position: Int): Int =
            if (position == FIRST_ITEM_INDEX - 1) TYPE_HEADER else if (position == itemCount - 1) TYPE_LOADING else TYPE_ORDERS

好的,如果我把我的RecyclerView放在一个SwipeRefreshLayout里面:

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/orders_rv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layoutManager="android.support.v7.widget.LinearLayoutManager" />

    </android.support.v4.widget.SwipeRefreshLayout>

这将显示所有项目,但refreshLayout将不起作用:如果我拉出我的视图,什么也不会发生。

但是如果我没有在我的适配器中设置任何加载布局(列表底部的那个,用来加载更多的项目,从R.layout.loading_more_orders_item扩展),那么SwipeRefreshLayout将会正常工作。

如何在适配器中有两个视图类型,并在SwipeRefreshLayout中设置我的RecyclerView?

编辑:

这是我的onRefreshListener:

refreshLayout = binding.swipeRefreshLayout

refreshLayout?.setOnRefreshListener { reloadOrders() }

在reloadOrders()中:

private fun reloadOrders() {
    viewModel.setLoading()
    refreshLayout?.isRefreshing = false
    Observable.timer(1, TimeUnit.SECONDS)
            .subscribe { getOrders() }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-06-12 16:22:27

好的,多亏了@r2rek,我找到了一个适合我的解决方案:

在代码中,我们创建了一个类,该类扩展了LinearLayoutManager并覆盖了方法canScrollVertically()以始终返回false:

inner class MyLinearLayout(context: Context) : LinearLayoutManager(context) {
    override fun canScrollVertically(): Boolean {
        return (false)
    }
}

然后,当我们初始化RecyclerView时,我们将这个类应用到layoutManager

ordersRv?.layoutManager = MyLinearLayout(this)

这将允许您刷新,但您将无法在您的RecyclerView中滚动(duh)。

要解决此问题,请在xml中添加一个NestedScrollView,如下所示:

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/refresh_layout"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginTop="8dp"
    android:layout_marginBottom="8dp"
    android:visibility="@{viewModel.ordersVisibility}"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/toolbar">

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/orders_rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    </android.support.v4.widget.NestedScrollView>

</android.support.v4.widget.SwipeRefreshLayout>

现在,您可以在RecyclerView中滚动,并使用SwipeRefreshLayout进行拉动以刷新。

我认为这种方法有点老套,所以如果有人有更好的解决方案,请随时告诉我们!

票数 0
EN

Stack Overflow用户

发布于 2019-06-12 03:32:16

您可以尝试覆盖linearlayout及其canScrollVertically()方法以返回false。干杯!

票数 1
EN

Stack Overflow用户

发布于 2019-06-11 23:57:49

回答你的问题,兼容性不是你遇到的问题。不确定布局的大小,因为其高度为0dp。我会玩弄视图大小和视图层次结构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56546979

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档