개발 공부/안드로이드

android recyclerview 화면에 보이는 아이템 위치와 activity에서 수정하기

yong_DD 2022. 7. 5. 21:34

목표 : 스크롤 할 때마다 현재 recyclerview에서 보이는 위치를 가져와서  activity에서 recyclerview item의 백그라운드 색을 수정


1. 현재 보이는 아이템 위치 가져오기

  • findFirstVisibleItemPosition() 
  • findFirstCompletelyVisibleItemPosition()
  • findLastCompletelyVisibleItemPosition()
  • findLastVisibleItemPosition()
findFirstVisibleItemPosition, findLastVisibleItemPosition은 화면에서 가장 상단, 하단에 보이는 아이템의 위치로서 전체가 온전히 보이지 않고 일부만 보이는 상태이다.
findFirstCompletelyVisibleItemPosition,findLastCompletelyVisibleItemPosition은 온전히 보이는 아이템 중 가장 상단, 가장하단에 보이는 아이템의 위치를 가져온다.

 

스크롤 할 때마다 변경이 되어야하므로 스크롤 리스너에 달아서 값을 전달해준다.

* 상단의 글자색으로 배경이 바뀐다!

 

 binding.recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener(){
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val firstVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager)
                    .findFirstVisibleItemPosition()
                val firstCompleteVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager)
                    .findFirstCompletelyVisibleItemPosition()
                val lastCompleteVisibleItemPosition =  (recyclerView.layoutManager as LinearLayoutManager)
                    .findLastCompletelyVisibleItemPosition()
                val lastVisibleItemPosition =  (recyclerView.layoutManager as LinearLayoutManager)
                    .findLastVisibleItemPosition()

                changeFirstItemBackground(firstVisibleItemPosition)
                changeFirstCompleteItemBackground(firstCompleteVisibleItemPosition)
                changeLastCompleteItemBackground(lastCompleteVisibleItemPosition)
                changeLastItemBackground(lastVisibleItemPosition)

            }
        })

 

 

2. activity에서 recyclerview viewHolder 가져오기(findViewHolderForAdapterPosition)

position을 통해 findViewHolderForAdapterPosition로 해당 아이템의 viewHolder를 가져오고, 그 viewholder를 통해 값을 변경한다. (여기서는 백그라운드 변경)

    private fun changeFirstItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color1,null))
    }

    private fun changeFirstCompleteItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color2,null))
    }

    private fun changeLastItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color3,null))
    }

    private fun changeLastCompleteItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color4,null))
    }

 


[완성 화면]

 

 


[전체 코드]

class RecyclerViewItemActivity : AppCompatActivity() {

    private lateinit var binding : ActivityRecyclerviewBinding
    private val adapter = PersonAdapter()

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

    private fun setRecyclerView(){
    
        binding.recyclerView.adapter = adapter
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener(){
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val firstVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager)
                    .findFirstVisibleItemPosition()
                val firstCompleteVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager)
                    .findFirstCompletelyVisibleItemPosition()
                val lastCompleteVisibleItemPosition =  (recyclerView.layoutManager as LinearLayoutManager)
                    .findLastCompletelyVisibleItemPosition()
                val lastVisibleItemPosition =  (recyclerView.layoutManager as LinearLayoutManager)
                    .findLastVisibleItemPosition()

                changeFirstItemBackground(firstVisibleItemPosition)
                changeFirstCompleteItemBackground(firstCompleteVisibleItemPosition)
                changeLastCompleteItemBackground(lastCompleteVisibleItemPosition)
                changeLastItemBackground(lastVisibleItemPosition)

            }
        })

        initList()
    }

    private fun changeFirstItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color1,null))
    }

    private fun changeFirstCompleteItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color2,null))
    }

    private fun changeLastItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color3,null))
    }

    private fun changeLastCompleteItemBackground(position:Int){
        val holder = binding.recyclerView.findViewHolderForAdapterPosition(position) as PersonAdapter.ViewHolder
        holder.binding.personBackView.setBackgroundColor(resources.getColor(R.color.color4,null))
    }


    private fun initList(){
        val list = mutableListOf<Person>()
        list.add(Person(0,"이름 0"))
        list.add(Person(1,"이름 1"))
        list.add(Person(2,"이름 2"))
        list.add(Person(3,"이름 3"))
        list.add(Person(4,"이름 4"))
        list.add(Person(5,"이름 5"))
        list.add(Person(6,"이름 6"))
        list.add(Person(7,"이름 7"))
        list.add(Person(8,"이름 8"))
        list.add(Person(9,"이름 9"))
        list.add(Person(10,"이름 10"))
        list.add(Person(11,"이름 11"))
        list.add(Person(12,"이름 12"))
        list.add(Person(13,"이름 13"))
        list.add(Person(14,"이름 14"))
        list.add(Person(15,"이름 15"))
        list.add(Person(16,"이름 16"))
        list.add(Person(17,"이름 17"))
        list.add(Person(18,"이름 18"))
        list.add(Person(19,"이름 19"))
        
        adapter.lists = list
        adapter.notifyItemRangeInserted(0,adapter.itemCount)

    }
}
class PersonAdapter: RecyclerView.Adapter<PersonAdapter.ViewHolder>()  {

    var lists = mutableListOf<Person>()
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonAdapter.ViewHolder {
        val binding  = ItemPersonBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: PersonAdapter.ViewHolder, position: Int) {
        holder.setItem(lists[position])
    }

    override fun getItemCount(): Int {
        return lists.size
    }

    inner class ViewHolder(val binding: ItemPersonBinding) : RecyclerView.ViewHolder(binding.root) {

        fun setItem(list:Person){
            binding.idTextView.text = list.id.toString()
            binding.nameTextView.text = list.name
        }
    }
}
<?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">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="1dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="1dp"
        android:layout_marginBottom="1dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="wrap_content"
    android:layout_margin="10dp"
    app:cardCornerRadius="15dp">

    <LinearLayout
        android:id="@+id/personBackView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="20dp">

        <TextView
            android:id="@+id/idTextView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            tools:text="0"
            android:gravity="center"/>
        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="#1A000000"/>

        <TextView
            android:id="@+id/nameTextView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            tools:text="김땡땡"
            android:layout_weight="1"
            android:gravity="center"/>
    </LinearLayout>
</androidx.cardview.widget.CardView>

 

 

[참고 자료]

https://developer.android.com/reference/androidx/recyclerview/widget/LinearLayoutManager#findFirstCompletelyVisibleItemPosition()

 

LinearLayoutManager  |  Android Developers

androidx.wear.watchface.complications.rendering

developer.android.com

https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView#findViewHolderForAdapterPosition(int)

 

RecyclerView  |  Android Developers

androidx.wear.watchface.complications.rendering

developer.android.com