카카오나 연락처를 보면
사진처럼 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
}
}
성공!