1. 뷰 타입
companion object {
const val VIEW_TYPE_1 = 1
const val VIEW_TYPE_2 = 2
const val VIEW_TYPE_3 = 3
}
private var list = mutableListOf<UserModel>()
private var viewTypeState = VIEW_TYPE_1
fun typeChange(newType: Int) {
viewTypeState = newType
notifyDataSetChanged()
}
어뎁터 추가문구
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
VIEW_TYPE_1 -> {
ContactViewHolder(
ContactItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
VIEW_TYPE_2 -> {
Type2ViewHolder(
ContactItem2Binding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
else -> {
Type3ViewHolder(
ContactItem3Binding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = list[position]
when (viewTypeState) {
VIEW_TYPE_1 -> {
(holder as ContactViewHolder).onBind(item)
holder.itemView.setOnLongClickListener(){
itemLongClick?.onLongClick(it,position)
true
}
}
VIEW_TYPE_2 -> {
(holder as Type2ViewHolder).onBind(item)
holder.itemView.setOnLongClickListener(){
itemLongClick?.onLongClick(it,position)
true
}
}
VIEW_TYPE_3 -> {
(holder as Type3ViewHolder).onBind((item))
holder.itemView.setOnLongClickListener(){
itemLongClick?.onLongClick(it,position)
true
}
}
}
}
액티비티
interface ViewTypeChangeLisener{
fun onViewTypeChanged(type:Int)
}
mainFabViewTypeChange.setOnClickListener {
if (viewTypeState == ContactAdapter.VIEW_TYPE_1) {
mainFabViewTypeChange.foreground =
ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_pikachu)
viewTypeState = ContactAdapter.VIEW_TYPE_2
lisener?.onViewTypeChanged(viewTypeState)
} else if(viewTypeState == ContactAdapter.VIEW_TYPE_2) {
mainFabViewTypeChange.foreground =
ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_evee)
viewTypeState = ContactAdapter.VIEW_TYPE_3
lisener?.onViewTypeChanged(viewTypeState)
} else {
mainFabViewTypeChange.foreground =
ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_ditto)
viewTypeState = ContactAdapter.VIEW_TYPE_1
lisener?.onViewTypeChanged(viewTypeState)
}
}
흐름은 이러하다
메인 액티비티에서 정의된 typestate를 인터페이스에 실어 날라서 fragment에서 받고
정의된 인터페이스에서 adapter에서 정의된 메소드를 이용하여 state를 조절해준다.
뷰 타입의 변화가 일어나는 부분에서 레이아웃 매니저를 통해 그리드/리니어 형태를 정의해준다.
그리드 타입 제어 시
GridLayoutManager(requireContext(), 2)
이 부분을 통해 2개의 아이템씩 정의할 수 있다.
프래그먼트
override fun onViewTypeChanged(type: Int) {
contactAdapter.typeChange(type)
if (type == ContactAdapter.VIEW_TYPE_3) {
contactRecycerview.layoutManager = GridLayoutManager(requireContext(), 2)
Log.d("타입", contactAdapter.getViewTypeState().toString())
} else {
contactRecycerview.layoutManager = LinearLayoutManager(requireContext())
}
}
2. 북 마크
<?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=".contact.ContactFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contact_recycerview_bookmark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/contact_recycerview"
/>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#8C8C8C"
android:elevation="0dp"
app:layout_constraintTop_toBottomOf="@+id/contact_recycerview_bookmark"
app:layout_constraintBottom_toTopOf="@id/contact_recycerview"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contact_recycerview"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@+id/contact_recycerview_bookmark"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
두 개의 리사이클리어뷰로 북마크/기본 아이템의 리사이클리어뷰를 만들고
북마크 프래그먼트의 어뎁터를 만든 뒤 그려준다.
북 마크 프래그 먼트에서 사용되는 메소드
fun setItem(item: UserModel) {
if (item == null) return
if (!item.isBookMark) {
bookMarkList.add(item)
notifyDataSetChanged()
}
}
fun removeItem(item: UserModel) {
if (item == null) return
val removeItem = bookMarkList.find { it == item }
bookMarkList.remove(removeItem)
notifyDataSetChanged()
}
fun removePositionItem(position: Int) {
if (position == null) return
bookMarkList.removeAt(position)
notifyDataSetChanged()
}
fun getItemPosition(position: Int):UserModel{
return bookMarkList[position]
}
컨택트 어뎁터에서 사용되는 메소드
fun getViewTypeState(): Int {
return viewTypeState
}
fun typeChange(newType: Int) {
viewTypeState = newType
notifyDataSetChanged()
}
fun getItemPosition(position: Int):UserModel{
return list[position]
}
fun setBookMark(isBookMark : Boolean,position: Int){
list[position].isBookMark = isBookMark
notifyDataSetChanged()
}
프래그먼트에서 제어해주는 인터페이스
contactAdapter.itemLongClick = object : ContactAdapter.ItemLongClick {
override fun onLongClick(view: View, position: Int) {
val item = contactAdapter.getItemPosition(position)
if (!item.isBookMark) {
//북마크 추가
bookMarkAdapter.setItem(item)
item.isBookMark = true
contactAdapter.setBookMark(item.isBookMark,position)
}else{
//북마크 해제
bookMarkAdapter.removeItem(item)
item.isBookMark = false
contactAdapter.setBookMark(item.isBookMark,position)
}
}
}
contactRecycerviewBookmark.adapter = bookMarkAdapter
bookMarkAdapter.onItemLongClick = object :BookMarkAdapter.ItemLongClick{
override fun onLongClick(view: View, position: Int) {
val item = bookMarkAdapter.getItemPosition(position)
bookMarkAdapter.removePositionItem(position)
item.isBookMark = false
contactAdapter.setBookMark(item.isBookMark,position)
}
}
이 흐름을 통해 롱 클릭 시 북마크가 온/오프가 되며
val item = list[position]
when (viewTypeState) {
VIEW_TYPE_1 -> {
(holder as ContactViewHolder).onBind(item)
holder.itemView.setOnLongClickListener(){
itemLongClick?.onLongClick(it,position)
true
}
}
VIEW_TYPE_2 -> {
(holder as Type2ViewHolder).onBind(item)
holder.itemView.setOnLongClickListener(){
itemLongClick?.onLongClick(it,position)
true
}
}
VIEW_TYPE_3 -> {
(holder as Type3ViewHolder).onBind((item))
holder.itemView.setOnLongClickListener(){
itemLongClick?.onLongClick(it,position)
true
}
}
}
인터페이스로 구현되었기 때문에 각각의 홀더에만 들어가면 된다.
3. 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="100dp"
android:background="?attr/selectableItemBackground"
tools:ignore="contentDescription">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/contact_book_mark_behind"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#40C057"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/contact_book_mark_iv_call"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_call" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/contactbook_mark__swipe"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:foreground="?attr/selectableItemBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/contact_book_mark_iv_bookmark"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="30dp"
android:src="@drawable/ic_book_mark_ball_on"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/contact_book_mark_iv_profile"
android:layout_width="80dp"
android:layout_height="89dp"
android:layout_marginStart="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView
android:id="@+id/contact_book_mark_tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="35dp"
android:text=""
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/contact_book_mark_iv_profile"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:elevation="4dp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
여기서 view부분이 삭제되면 해당 xml자체거 어그러지는 이상한 오류가 발생했다.
이에 대한 원인규명중이기는 하나 이유는 모르겠다
'개발노트 > Kotlin' 카테고리의 다른 글
9주차를 돌아보며 (0) | 2023.09.11 |
---|---|
9주차 5일 (0) | 2023.09.08 |
8주차를 돌아보며 (0) | 2023.09.04 |
9주차 1일 팀프로젝트-xml과 drawableResource 그리고 color (0) | 2023.09.04 |
8주차 5일 fragment와 액티비티등 (0) | 2023.09.01 |