繁体   English   中英

圆形水平回收器视图适配器

[英]Circular horizontal Recycler View Adapter

我有一个水平的回收视图适配器,我试图让它在两个方向上都是圆形的。 我为此找到了多种解决方案,但在 Kotlin 中没有找到。 我的适配器的 getItemCount 和 onBindViewHolder 看起来像这样。

override fun onbindViewHolder(holder: ViewHolder<T>, position: Int){ 
    val Data = items[position]
    holder.bind(Data, position, viewHoldBindFunc)

override fun getItemCount(): Int = items.size 

我尝试将这两个功能更改为以下内容,但 Integer.MAX_VALUE 使整个屏幕崩溃。

    override fun getItemCount(): Int {return Integer.MAX_VALUE}
and 
    override fun onbindViewHolder(holder: ViewHolder<T>, position: Int){ 
        val NewPosition = position % items.size
        val Data = items[NewPosition]
        holder.bind(Data, NewPosition, viewHoldBindFunc)

谢谢

这是 Kotlin 中的一个似乎有效的解决方案。 我基于https://gist.github.com/nesquena/d09dc68ff07e845cc622中的一些代码。

事实证明,如果您调用回收器适配器的 notifyItemRemoved() 和 notifyItemInserted() 方法(对于您看不到的视图),它不会移动您当前正在查看的视图的 position,但它会改变RecyclerView 感知到的是您的右侧和左侧。

我得到了这个工作,所以我不妨分享结果:这个回收器适配器假装你显示的同一组项目有 5 个副本,并且每当显示左侧或右侧最远副本之一的项目时,它使用adapter.notifyItemRemoved() 和 notifyItemInserted() 将 RecyclerView 的感知转移到正在滚动的一侧。

您可能需要对此进行一些测试。 滚动几秒钟似乎对我来说效果很好。 为了安全起见,我总共放了 5 个副本(1 个在中间,两个在周围),但我敢打赌,如果你稍微弄乱了它,这将适用于 3 个副本。 :)

package com.github.ajsnarr98.testingplayground

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.ajsnarr98.testingplayground.databinding.ActivityCircularBinding

class CircularActivity : AppCompatActivity() {

    private val list = listOf<Int>(1,2,3,4,5,6,7,8,9,10,11,12)

    lateinit var binding: ActivityCircularBinding
    lateinit var recyclerAdapter: CircularAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityCircularBinding.inflate(layoutInflater)
        setContentView(binding.root)

        recyclerAdapter = CircularAdapter(list, binding.list)
        binding.list.apply {
            adapter = recyclerAdapter
            layoutManager = LinearLayoutManager(this@CircularActivity, RecyclerView.HORIZONTAL, false)
        }

        recyclerAdapter.init()
    }
}
package com.github.ajsnarr98.testingplayground

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class CircularAdapter(
        private val items: List<Int>,
        private val recyclerView: RecyclerView,
) : RecyclerView.Adapter<CircularAdapter.ViewHolder>() {

    var offset: Int = 0
    var numSets = 5

    val initialPosition = items.size * 2 // two sets of items before, two sets after

    fun init() {
        recyclerView.scrollToPosition(initialPosition)
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            // This happens many times a second during a scroll, so be wary of the code you place here.
            // We are given a few useful parameters to help us work out if we need to load some more data,
            // but first we check if we are waiting for the previous load to finish.'
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                // this example only supports LinearLayoutManager
                val layoutManager: LinearLayoutManager = recyclerView.layoutManager as? LinearLayoutManager ?: return
                val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
                val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()

                if (isInBoundarySet(firstVisibleItemPosition)) {
                    insertItemsLeft()
                }
                if (isInBoundarySet(lastVisibleItemPosition)) {
                    insertItemsRight()
                }
            }
        })
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
                LayoutInflater.from(parent.context).inflate(R.layout.item_number, parent, false)
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(itemForPosition(position))
    }

    override fun getItemCount(): Int = items.size * numSets

    /**
     * Returns true if the given position is within items.size from 0 or
     * getItemCount().
     */
    private fun isInBoundarySet(position: Int): Boolean {
        return position + items.size >= itemCount || position - items.size < 0
    }

    private fun itemForPosition(position: Int) = items[position % items.size]

    /**
     * Pretends a new set of items was inserted to the right, and a set was was removed to the left.
     */
    fun insertItemsRight() {
        numSets--
        notifyItemRangeRemoved(0, items.size)
        numSets++
        notifyItemRangeInserted(itemCount, items.size)
    }

    /**
     * Pretends a new set of items was inserted to the left, and a set was was removed to the right.
     */
    fun insertItemsLeft() {
        numSets--
        notifyItemRangeRemoved(itemCount-items.size, items.size)
        numSets++
        notifyItemRangeInserted(0, items.size)
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        fun bind(item: Int) {
            if (this.itemView is TextView) {
                this.itemView.text = item.toString()
            }
        }
    }

    companion object {
        private const val NUMBER_VIEW = 0
    }
}

item_number.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:background="@drawable/frame"
    android:textAlignment="center"
    android:textStyle="bold"
    android:textSize="40sp"
    tools:text="1"/>

activity_circular.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CircularActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Circular recycler view"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/list"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>

框架.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <!-- View background color -->
    <solid
        android:color="@color/white" >
    </solid>

    <!-- View border color and width -->
    <stroke
        android:width="3dp"
        android:color="@color/black" >
    </stroke>

</shape>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM