From 7d4432278ef5819d293b7a038f0253a875917163 Mon Sep 17 00:00:00 2001 From: Carlos Martinez Date: Sun, 2 Feb 2020 22:35:44 -0300 Subject: [PATCH] implement recycler view for userlist --- .../base/extensions/ApplicationExtension.kt | 8 +++ .../hako/base/extensions/ListExtensions.kt | 23 +++++++ .../hako/base/extensions/ViewExtensions.kt | 3 +- .../friendlist/feature/UserlistFragment.kt | 57 +++++++++++++-- .../com/hako/friendlist/model/UserModels.kt | 38 +++------- .../hako/friendlist/widget/UserlistAdapter.kt | 69 +++++++++++++++++++ .../src/main/res/layout/fragment_userlist.xml | 10 ++- .../src/main/res/layout/item_user_card.xml | 4 ++ 8 files changed, 176 insertions(+), 36 deletions(-) create mode 100644 base/src/main/java/com/hako/base/extensions/ApplicationExtension.kt create mode 100644 base/src/main/java/com/hako/base/extensions/ListExtensions.kt create mode 100644 userlist/src/main/java/com/hako/friendlist/widget/UserlistAdapter.kt diff --git a/base/src/main/java/com/hako/base/extensions/ApplicationExtension.kt b/base/src/main/java/com/hako/base/extensions/ApplicationExtension.kt new file mode 100644 index 0000000..cd7e477 --- /dev/null +++ b/base/src/main/java/com/hako/base/extensions/ApplicationExtension.kt @@ -0,0 +1,8 @@ +package com.hako.base.extensions + +import android.content.Context +import android.widget.Toast + +fun Context.toast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() +} \ No newline at end of file diff --git a/base/src/main/java/com/hako/base/extensions/ListExtensions.kt b/base/src/main/java/com/hako/base/extensions/ListExtensions.kt new file mode 100644 index 0000000..61a3ded --- /dev/null +++ b/base/src/main/java/com/hako/base/extensions/ListExtensions.kt @@ -0,0 +1,23 @@ +package com.hako.base.extensions + +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView + +fun RecyclerView.Adapter<*>.autoNotify(oldList: List, newList: List, compare: (T, T) -> Boolean) { + val diff = DiffUtil.calculateDiff(object : DiffUtil.Callback() { + + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return compare(oldList[oldItemPosition], newList[newItemPosition]) + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return oldList[oldItemPosition] == newList[newItemPosition] + } + + override fun getOldListSize() = oldList.size + + override fun getNewListSize() = newList.size + }) + + diff.dispatchUpdatesTo(this) +} \ No newline at end of file diff --git a/base/src/main/java/com/hako/base/extensions/ViewExtensions.kt b/base/src/main/java/com/hako/base/extensions/ViewExtensions.kt index 93700d1..5bd84f8 100644 --- a/base/src/main/java/com/hako/base/extensions/ViewExtensions.kt +++ b/base/src/main/java/com/hako/base/extensions/ViewExtensions.kt @@ -1,10 +1,11 @@ package com.hako.base.extensions import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.annotation.LayoutRes -fun ViewGroup.inflate(@LayoutRes layout: Int, attachToRoot: Boolean = false) = +fun ViewGroup.inflate(@LayoutRes layout: Int, attachToRoot: Boolean = false): View = LayoutInflater .from(context) .inflate(layout, this, attachToRoot) diff --git a/userlist/src/main/java/com/hako/friendlist/feature/UserlistFragment.kt b/userlist/src/main/java/com/hako/friendlist/feature/UserlistFragment.kt index ad27523..f83776b 100644 --- a/userlist/src/main/java/com/hako/friendlist/feature/UserlistFragment.kt +++ b/userlist/src/main/java/com/hako/friendlist/feature/UserlistFragment.kt @@ -5,16 +5,63 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.hako.base.extensions.toast +import com.hako.friendlist.model.UserViewable +import com.hako.friendlist.widget.UserlistAdapter import com.hako.friendlist_userlist.R +import kotlinx.android.synthetic.main.fragment_userlist.* class UserlistFragment : Fragment() { + private val chatAdapter by lazy { UserlistAdapter() } + override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return inflater.inflate(R.layout.fragment_userlist, container, false) + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? + ): View = inflater.inflate(R.layout.fragment_userlist, container, false) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setRecycler() } + private fun setRecycler() { + fragment_userlist_recycler_container.apply { + layoutManager = LinearLayoutManager(context) + adapter = chatAdapter.apply { + addAll( + listOf( + UserViewable(1, "Carlos Martinez", "carlitos"), + UserViewable(2, "Carlos Martinez", "carlitos"), + UserViewable(3, "Carlos Martinez", "carlitos"), + UserViewable(4, "Carlos Martinez", "carlitos"), + UserViewable(5, "Carlos Martinez", "carlitos"), + UserViewable(6, "Carlos Martinez", "carlitos"), + UserViewable(7, "Carlos Martinez", "carlitos"), + UserViewable(8, "Carlos Martinez", "carlitos"), + UserViewable(9, "Carlos Martinez", "carlitos"), + UserViewable(10, "Carlos Martinez", "carlitos"), + UserViewable(11, "Carlos Martinez", "carlitos"), + UserViewable(12, "Carlos Martinez", "carlitos"), + UserViewable(13, "Carlos Martinez", "carlitos"), + UserViewable(14, "Carlos Martinez", "carlitos"), + UserViewable(15, "Carlos Martinez", "carlitos"), + UserViewable(16, "Carlos Martinez", "carlitos"), + UserViewable(17, "Carlos Martinez", "carlitos"), + UserViewable(18, "Carlos Martinez", "carlitos"), + UserViewable(19, "Carlos Martinez", "carlitos"), + UserViewable(20, "Carlos Martinez", "carlitos") + ) + ) + + onItemClick = { + context.toast(it.realName) + } + + onFavoriteClick = { + context.toast(it.userName) + } + } + } + } } \ No newline at end of file diff --git a/userlist/src/main/java/com/hako/friendlist/model/UserModels.kt b/userlist/src/main/java/com/hako/friendlist/model/UserModels.kt index f2d3428..6c6992a 100644 --- a/userlist/src/main/java/com/hako/friendlist/model/UserModels.kt +++ b/userlist/src/main/java/com/hako/friendlist/model/UserModels.kt @@ -2,6 +2,7 @@ package com.hako.friendlist.model import android.os.Parcelable import com.google.gson.annotations.SerializedName +import com.hako.base.room.entities.UserEntity import kotlinx.android.parcel.Parcelize @Parcelize @@ -10,35 +11,18 @@ data class User( @SerializedName("name") val realName: String, @SerializedName("username") val userName: String, @SerializedName("email") val email: String, - @SerializedName("amount") val balance: Address, @SerializedName("phone") val phone: String, - @SerializedName("website") val website: String, - @SerializedName("company") val company: Company -) : Parcelable { + @SerializedName("website") val website: String +) : Parcelable - @Parcelize - data class Address( - @SerializedName("street") val street: String, - @SerializedName("suite") val realName: String, - @SerializedName("city") val userName: String, - @SerializedName("zipcode") val email: String, - @SerializedName("geo") val geoLocation: GeoLocation - ) : Parcelable { +data class UserViewable( + val id: Int, + val realName: String, + val userName: String, + var isFavorite: Boolean = false +) { + fun User.toUserViewable() = UserViewable(this.id, this.realName, this.userName) - @Parcelize - data class GeoLocation( - @SerializedName("lat") val latitude: String, - @SerializedName("lng") val longitude: String - ) : Parcelable - } - - @Parcelize - data class Company( - @SerializedName("name") val name: String, - @SerializedName("catchPhrase") val catchPhrase: String, - @SerializedName("bs") val keywords: String - ) : Parcelable { - fun getKeywordList() = keywords.split(" ") - } + fun UserEntity.toUserViewable() = UserViewable(this.id, this.realName, this.userName) } diff --git a/userlist/src/main/java/com/hako/friendlist/widget/UserlistAdapter.kt b/userlist/src/main/java/com/hako/friendlist/widget/UserlistAdapter.kt new file mode 100644 index 0000000..a6bfe05 --- /dev/null +++ b/userlist/src/main/java/com/hako/friendlist/widget/UserlistAdapter.kt @@ -0,0 +1,69 @@ +package com.hako.friendlist.widget + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.hako.base.extensions.autoNotify +import com.hako.friendlist.model.UserViewable +import com.hako.friendlist_userlist.R +import kotlinx.android.synthetic.main.item_user_card.view.* +import kotlin.properties.Delegates + +class UserlistAdapter : RecyclerView.Adapter() { + + private var items by Delegates.observable(emptyList()) { _, oldList, newList -> + autoNotify(oldList, newList) { old, new -> old.id == new.id } + notifyDataSetChanged() + } + + var onItemClick: (UserViewable) -> Unit = { } + var onFavoriteClick: (UserViewable) -> Unit = { } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = + UserViewHolder( + LayoutInflater + .from(parent.context) + .inflate(R.layout.item_user_card, parent, false), + onItemClick, + onFavoriteClick + ) + + fun getItem(position: Int) = items[position] + + fun addAll(list: List) { + items = list + } + + override fun getItemCount() = items.size + + override fun onBindViewHolder(viewholder: RecyclerView.ViewHolder, position: Int) = + when (viewholder) { + is UserViewHolder -> viewholder.bind(items[position]) + else -> throw NoWhenBranchMatchedException("Undefined viewholder") + } +} + +class UserViewHolder(private val view: View, + private val onItemClick: (UserViewable) -> Unit, + private val onFavoriteClick: (UserViewable) -> Unit) : + RecyclerView.ViewHolder(view) { + + fun bind(user: UserViewable) = with(view) { + item_user_card_real_name.text = user.realName + item_user_card_user_name.text = user.userName + item_user_card_container.setOnClickListener { + onItemClick(user) + } + item_user_card_like_button.setOnClickListener { + onFavoriteClick(user) + } + } + + private fun setFavorite(status: Boolean) { + when (status) { + true -> view.item_user_card_like_button.like() + false -> view.item_user_card_like_button.dislike() + } + } +} \ No newline at end of file diff --git a/userlist/src/main/res/layout/fragment_userlist.xml b/userlist/src/main/res/layout/fragment_userlist.xml index d67170b..a208918 100644 --- a/userlist/src/main/res/layout/fragment_userlist.xml +++ b/userlist/src/main/res/layout/fragment_userlist.xml @@ -3,10 +3,14 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"> + android:orientation="vertical" + android:id="@+id/fragment_userlist_base"> - diff --git a/userlist/src/main/res/layout/item_user_card.xml b/userlist/src/main/res/layout/item_user_card.xml index f838949..524ef91 100644 --- a/userlist/src/main/res/layout/item_user_card.xml +++ b/userlist/src/main/res/layout/item_user_card.xml @@ -2,8 +2,12 @@