Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.launch
import ru.otus.cryptosample.CoinsSampleApp
import ru.otus.cryptosample.coins.feature.adapter.CoinsAdapter
Expand All @@ -30,6 +31,8 @@ class CoinListFragment : Fragment() {

private lateinit var coinsAdapter: CoinsAdapter

private val sharedPool = RecyclerView.RecycledViewPool()

override fun onAttach(context: Context) {
super.onAttach(context)

Expand Down Expand Up @@ -59,14 +62,15 @@ class CoinListFragment : Fragment() {
}

private fun setupRecyclerView() {
coinsAdapter = CoinsAdapter()
coinsAdapter = CoinsAdapter(sharedPool)

val gridLayoutManager = GridLayoutManager(requireContext(), 2)
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return when (coinsAdapter.getItemViewType(position)) {
0 -> 2 // Category header spans full width
1 -> 1 // Coin item spans half width
2 -> 2
else -> 1
}
}
Expand All @@ -75,6 +79,7 @@ class CoinListFragment : Fragment() {
binding.recyclerView.apply {
layoutManager = gridLayoutManager
adapter = coinsAdapter
setRecycledViewPool(sharedPool)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ru.otus.cryptosample.coins.feature.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ru.otus.cryptosample.coins.feature.CoinState
import ru.otus.cryptosample.databinding.ItemCoinBinding
import ru.otus.cryptosample.databinding.ItemCoinHorizontalListBinding

class CoinHorizontalAdapter :
ListAdapter<CoinState, CoinViewHolder>(DiffCallback) {

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

override fun onBindViewHolder(holder: CoinViewHolder, position: Int) {
holder.bind(getItem(position))
}
}

object DiffCallback : DiffUtil.ItemCallback<CoinState>() {

override fun areItemsTheSame(oldItem: CoinState, newItem: CoinState): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: CoinState, newItem: CoinState): Boolean {
return oldItem == newItem
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import ru.otus.cryptosample.coins.feature.CoinCategoryState
import ru.otus.cryptosample.coins.feature.CoinState
import ru.otus.cryptosample.databinding.ItemCategoryHeaderBinding
import ru.otus.cryptosample.databinding.ItemCoinBinding
import ru.otus.cryptosample.databinding.ItemCoinHorizontalListBinding

class CoinsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
class CoinsAdapter(
private val sharedPool: RecyclerView.RecycledViewPool
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

companion object {
private const val VIEW_TYPE_CATEGORY = 0
private const val VIEW_TYPE_COIN = 1

private const val VIEW_TYPE_COINS_HORIZONTAL = 2
}

private var items = listOf<CoinsAdapterItem>()
Expand All @@ -21,8 +27,14 @@ class CoinsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

categories.forEach { category ->
adapterItems.add(CoinsAdapterItem.CategoryHeader(category.name))
category.coins.forEach { coin ->
adapterItems.add(CoinsAdapterItem.CoinItem(coin))
if (category.coins.size > 10) {
adapterItems.add(
CoinsAdapterItem.CoinItemsHorizontalRV(category.coins)
)
} else {
category.coins.forEach { coin ->
adapterItems.add(CoinsAdapterItem.CoinItem(coin))
}
}
}

Expand All @@ -36,6 +48,7 @@ class CoinsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
return when (items[position]) {
is CoinsAdapterItem.CategoryHeader -> VIEW_TYPE_CATEGORY
is CoinsAdapterItem.CoinItem -> VIEW_TYPE_COIN
is CoinsAdapterItem.CoinItemsHorizontalRV -> VIEW_TYPE_COINS_HORIZONTAL
}
}

Expand All @@ -55,10 +68,18 @@ class CoinsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
false
)
)
VIEW_TYPE_COINS_HORIZONTAL -> CoinsHorizontalViewHolder( binding =
ItemCoinHorizontalListBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
),
sharedPool = sharedPool
)
else -> throw IllegalArgumentException("Unknown view type: $viewType")
}
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (val item = items[position]) {
is CoinsAdapterItem.CategoryHeader -> {
Expand All @@ -67,6 +88,10 @@ class CoinsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
is CoinsAdapterItem.CoinItem -> {
(holder as CoinViewHolder).bind(item.coin)
}

is CoinsAdapterItem.CoinItemsHorizontalRV -> {
(holder as CoinsHorizontalViewHolder).bind(item.coinsList)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import ru.otus.cryptosample.coins.feature.CoinState

sealed class CoinsAdapterItem {
data class CategoryHeader(val categoryName: String) : CoinsAdapterItem()
data class CoinItemsHorizontalRV(val coinsList: List<CoinState>) : CoinsAdapterItem()
data class CoinItem(val coin: CoinState) : CoinsAdapterItem()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ru.otus.cryptosample.coins.feature.adapter

import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.load
import ru.otus.cryptosample.R
import ru.otus.cryptosample.coins.feature.CoinState
import ru.otus.cryptosample.databinding.ItemCoinBinding
import ru.otus.cryptosample.databinding.ItemCoinHorizontalListBinding

class CoinsHorizontalViewHolder(
private val binding: ItemCoinHorizontalListBinding,
private val sharedPool: RecyclerView.RecycledViewPool
) : RecyclerView.ViewHolder(binding.root) {

private val adapter = CoinHorizontalAdapter()

init {
binding.recyclerHorizontal.layoutManager =
LinearLayoutManager(binding.root.context, LinearLayoutManager.HORIZONTAL, false)

binding.recyclerHorizontal.adapter = adapter
//binding.recyclerHorizontal.setRecycledViewPool(sharedPool) тут краш ClassCastException
}

fun bind(items: List<CoinState>) {
adapter.submitList(items)
}
}
6 changes: 6 additions & 0 deletions app/src/main/res/layout/item_coin_horizontal_list.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_horizontal"
android:layout_width="wrap_content"
android:layout_marginTop="12dp"
android:layout_height="wrap_content" />