안드로이드 RecyclerView에서 SectionIndexer를 구현해보자(카카오톡 메인화면 드래그 시 사이드바st)

·2022년 2월 21일
0

카카오나 연락처를 보면

사진처럼 sectionindexer가 있는 것을 볼 수 있다.
클릭하면 해당 초성그룹이 있는 곳으로 이동한다. 한번 만들어보자.

나는 1~1000까지의 숫자를 리사이클러뷰에 넣었고 indexer는 100단위로 만들었다.

나는 리사이클러뷰로 전체 화면을 잡았고 indexer부분은 LinearLayout안에 Butten을 넣어 구현했다. 다른 레이아웃써도 된다.

데이터바인딩을 사용하였음.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="click"
            type="android.view.View.OnClickListener" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rc"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
        <LinearLayout
            android:id="@+id/layout"
            android:background="#25000000"
            android:layout_width="60dp"
            android:layout_height="0dp"
            android:visibility="invisible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:orientation="vertical"
            android:gravity="center_vertical">
            <Button
                android:id="@+id/btn_0"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="0"
                android:onClick="@{click}"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:layout_marginTop="20dp"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_100"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="100"
                android:textSize="10dp"
                android:onClick="@{click}"
                android:textColor="@color/black"
                android:layout_marginTop="20dp"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_200"
                android:onClick="@{click}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="200"
                android:layout_marginTop="20dp"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_300"
                android:onClick="@{click}"
                android:layout_marginTop="20dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="300"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_400"
                android:onClick="@{click}"
                android:layout_marginTop="20dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="400"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_500"
                android:layout_marginTop="20dp"
                android:onClick="@{click}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="500"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_600"
                android:layout_marginTop="20dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="600"
                android:onClick="@{click}"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_700"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:text="700"
                android:textSize="10dp"
                android:onClick="@{click}"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_800"
                android:onClick="@{click}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:text="800"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>
            <Button
                android:id="@+id/btn_900"
                android:onClick="@{click}"
                android:layout_width="wrap_content"
                android:layout_marginTop="20dp"
                android:layout_height="wrap_content"
                android:text="900"
                android:textSize="10dp"
                android:textColor="@color/black"
                android:background="@android:color/transparent"/>

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

이때 LinearLayout을 invisible로 해줘서 시작할 땐 안보이도록 해주었다.

리사이클러뷰에서 스크롤 이벤트가 발생하면 LinearLayout이 생겼다가 사라지게 만들어야하는데 애니메이션을 사용하였다.

스크롤 부분(터치이벤트는 클릭할때마다 이벤트가 적용되는데 나는 드래그를 할때만 layout이 생기길 원해서 스크롤 이벤트를 사용하였다.)

이제 애니메이션으로 생긴 indexer를 클릭했을 때 로직이다.
scrollToPosition을 하면 해당 위치가 맨 밑으로 가게 되어서 scrollToPositionWithOffset을 사용하였다.offset을 0으로 주게 되면 화면 맨위에와의 거리가 0이 되어서 맨위로 자리잡는다.

나머지 버튼은 생략

전체 코드
MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.animation.*
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView.*
import com.example.kakaoexample.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity(), View.OnClickListener {
    lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.click = this@MainActivity

        var itemList = mutableListOf<Int>()

        for (i in 1..1000) {
            itemList.add(i)
        }

        val recyclerAdapter = RecyclerViewAdapter(itemList)
        binding.rc.adapter = recyclerAdapter
        binding.rc.layoutManager = LinearLayoutManager(this)

        //애니메이션 설정
        val fadeIn = AlphaAnimation(0f, 1f)
        fadeIn.interpolator = DecelerateInterpolator()
        fadeIn.duration = 300

        val fadeOut = AlphaAnimation(1f, 0f)
        fadeOut.interpolator = AccelerateInterpolator()
        fadeOut.startOffset = 300
        fadeOut.duration = 1500

        //300ms동안 layout이 생겼다가 1500ms동안 사라지는 애니메이션
        val animation = AnimationSet(false)
        animation.addAnimation(fadeIn)
        animation.addAnimation(fadeOut)

        binding.rc.setOnScrollChangeListener { view, i, i2, i3, i4 ->
            if (binding.rc.scrollState == SCROLL_STATE_DRAGGING) {
                binding.layout.startAnimation(animation)
            }
        }
    }

    override fun onClick(view: View?) {
        when (view?.id) {
            R.id.btn_0 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(0, 0)
            }
            R.id.btn_100 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(100, 0)
            }
            R.id.btn_200 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(200, 0)
            }
            R.id.btn_300 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(300, 0)
            }
            R.id.btn_400 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(400, 0)
            }
            R.id.btn_500 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(500, 0)
            }
            R.id.btn_600 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(600, 0)
            }
            R.id.btn_700 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(700, 0)
            }
            R.id.btn_800 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(800, 0)
            }
            R.id.btn_900 -> {
                (binding.rc.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(900, 0)
            }
        }
    }
}

RecyclerViewAdapter.kt

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.kakaoexample.databinding.ItemlistBinding


class RecyclerViewAdapter(private val list: MutableList<Int>) : RecyclerView.Adapter<RecyclerViewAdapter.Holder>() {

    class Holder(val binding: ItemlistBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val binding = ItemlistBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.binding.itemname = list[position].toString()
    }

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

성공!

profile
가보자고

0개의 댓글

관련 채용 정보