TP-32006 | PS | index return card design (#7165)

This commit is contained in:
Prakhar Saxena
2023-07-20 11:30:35 +05:30
committed by GitHub
parent 373dd086f5
commit 8773024a41
5 changed files with 372 additions and 127 deletions

View File

@@ -36,12 +36,15 @@ data class FundCardWidgetData(
data class FundCardData(
@SerializedName("title") val title: TextWithStyle? = null,
@SerializedName("subtitle", alternate = ["subTitle"]) val subtitle: TextWithStyle? = null,
@SerializedName("iconCode") val iconCode: String? = null,
@SerializedName("tagData") val tagData: TagData? = null,
@SerializedName("footerIconCode") val footerIconCode: String? = null,
@SerializedName("footerBgColor") val footerBgColor: String? = null,
@SerializedName("footerTitle") val footerTitle: TextWithStyle? = null,
@SerializedName("items") val items: List<SubItemData>? = null,
@SerializedName("cta") val cta: SubItemData? = null,
@SerializedName("variantName") val variantName: String? = null,
@SerializedName("actionData") val action: ActionData? = null
)

View File

@@ -0,0 +1,223 @@
package com.navi.naviwidgets.widgets.amc
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.navi.base.utils.isNotNullAndNotEmpty
import com.navi.design.utils.CornerRadius
import com.navi.design.utils.dpToPx
import com.navi.design.utils.getNaviDrawable
import com.navi.design.utils.parseColorSafe
import com.navi.design.utils.setSpannableString
import com.navi.naviwidgets.R
import com.navi.naviwidgets.callbacks.WidgetCallback
import com.navi.naviwidgets.databinding.LayoutFundCardBinding
import com.navi.naviwidgets.databinding.LayoutFundCardIndexReturnBinding
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
import com.navi.naviwidgets.models.response.amc.FundCardData
class FundCardAdapter(
private val list: List<FundCardData> = emptyList(),
private val widgetCallback: WidgetCallback
) : RecyclerView.Adapter<FundCardViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FundCardViewHolder {
return when(viewType) {
INDEX_RETURN_TOP_CTA -> {
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
val itemBinding: LayoutFundCardIndexReturnBinding = DataBindingUtil.bind(view)!!
IndexReturnFundCardViewHolder(itemBinding, widgetCallback)
}
else -> {
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
val itemBinding: LayoutFundCardBinding = DataBindingUtil.bind(view)!!
DefaultFundCardViewHolder(itemBinding, widgetCallback)
}
}
}
override fun getItemViewType(position: Int): Int {
return when(list[position].variantName) {
VARIANT_INDEX_RETURN_TOP_CTA -> INDEX_RETURN_TOP_CTA
else -> DEFAULT_FUND_CARD
}
}
override fun onBindViewHolder(holder: FundCardViewHolder, position: Int) {
holder.bind(list[position], position)
}
override fun getItemCount() =
list.size
companion object {
private const val VARIANT_INDEX_RETURN_TOP_CTA = "INDEX_RETURN_TOP_CTA"
private val INDEX_RETURN_TOP_CTA = R.layout.layout_fund_card_index_return
private val DEFAULT_FUND_CARD = R.layout.layout_fund_card
}
}
sealed class FundCardViewHolder(private val viewBinding: ViewBinding): RecyclerView.ViewHolder(viewBinding.root) {
abstract fun bind(card: FundCardData, position: Int)
}
class DefaultFundCardViewHolder(
private val viewBinding: LayoutFundCardBinding,
private val widgetCallback: WidgetCallback
) : FundCardViewHolder(viewBinding) {
override fun bind(card: FundCardData, position: Int) {
viewBinding.apply {
fundCard.background = getNaviDrawable(
cornerRadius = dpToPx(8).toInt(),
strokeColor = ContextCompat.getColor(
itemView.context,
R.color.border_grey_color
),
strokeWidth = dpToPx(1).toInt(),
backgroundColor = ContextCompat.getColor(
itemView.context,
R.color.white
)
)
fundTitle.setSpannableString(card.title)
icon.showWhenDataIsAvailable(card.iconCode)
card.tagData?.let {
fundTagContainer.isVisible = true
fundTagTitle.setSpannableString(it.title)
fundTagIcon.showWhenDataIsAvailable(it.iconCode)
} ?: kotlin.run {
fundTagContainer.isVisible = false
}
card.items?.forEachIndexed { index, subItemData ->
when(index) {
0 -> {
fundSize.title.setSpannableString(subItemData.title)
fundSize.subtitle.setSpannableString(subItemData.subtitle)
if(subItemData.title?.text.isNotNullAndNotEmpty()) {
fundSize.titleIcon.showWhenDataIsAvailable(subItemData.iconCode)
fundSize.icon.visibility = View.GONE
}
else {
fundSize.icon.showWhenDataIsAvailable(subItemData.iconCode)
fundSize.title.visibility = View.GONE
}
}
1 -> {
returns.title.setSpannableString(subItemData.title)
returns.subtitle.setSpannableString(subItemData.subtitle)
if(subItemData.title?.text.isNotNullAndNotEmpty()) {
returns.titleIcon.showWhenDataIsAvailable(subItemData.iconCode)
returns.icon.visibility = View.GONE
}
else {
returns.icon.showWhenDataIsAvailable(subItemData.iconCode)
returns.title.visibility = View.GONE
}
}
2 -> {
cta.title.setSpannableString(subItemData.title)
cta.subtitle.setSpannableString(subItemData.subtitle)
if(subItemData.title?.text.isNotNullAndNotEmpty()) {
cta.titleIcon.showWhenDataIsAvailable(subItemData.iconCode)
cta.icon.visibility = View.GONE
}
else {
cta.icon.showWhenDataIsAvailable(subItemData.iconCode)
cta.title.visibility = View.GONE
}
}
}
}
if(card.footerTitle?.text.isNotNullAndNotEmpty()) {
productStrategyContainer.background = getNaviDrawable(
radii = CornerRadius(
leftBottom = dpToPx(8),
rightBottom = dpToPx(8)
),
backgroundColor = card.footerBgColor.parseColorSafe()
)
productStrategyTv.setSpannableString(card.footerTitle)
productStrategyIv.showWhenDataIsAvailable(card.footerIconCode)
} else {
productStrategyContainer.visibility = View.GONE
}
fundCard.setOnClickListener {
card.action?.let { actionData ->
widgetCallback.onClick(actionData)
}
}
}
}
}
class IndexReturnFundCardViewHolder(
private val viewBinding: LayoutFundCardIndexReturnBinding,
private val widgetCallback: WidgetCallback
) : FundCardViewHolder(viewBinding) {
override fun bind(card: FundCardData, position: Int) {
viewBinding.apply {
fundCard.background = getNaviDrawable(
cornerRadius = dpToPx(8).toInt(),
strokeColor = ContextCompat.getColor(
itemView.context,
R.color.border_grey_color
),
strokeWidth = dpToPx(1).toInt(),
backgroundColor = ContextCompat.getColor(
itemView.context,
R.color.white
)
)
title.setSpannableString(card.title)
subtitle.setSpannableString(card.subtitle)
cta.apply {
title.setSpannableString(card.cta?.title)
subtitle.setSpannableString(card.cta?.subtitle)
if (card.cta?.title?.text.isNotNullAndNotEmpty()) {
titleIcon.showWhenDataIsAvailable(card.cta?.iconCode)
icon.visibility = View.GONE
} else {
icon.showWhenDataIsAvailable(card.cta?.iconCode)
title.visibility = View.GONE
}
}
card.tagData?.let {
fundTagContainer.isVisible = true
fundTagTitle.setSpannableString(it.title)
fundTagIcon.showWhenDataIsAvailable(it.iconCode)
} ?: kotlin.run {
fundTagContainer.isVisible = false
}
card.items?.forEachIndexed { index, subItemData ->
when(index) {
0 -> {
fundTitle.setSpannableString(subItemData.title)
fundSubtitle.setSpannableString(subItemData.subtitle)
fundIcon.showWhenDataIsAvailable(subItemData.iconCode)
}
}
}
fundCard.setOnClickListener {
card.action?.let { actionData ->
widgetCallback.onClick(actionData)
}
}
}
}
}

View File

@@ -9,26 +9,16 @@ package com.navi.naviwidgets.widgets.amc
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.navi.base.utils.isNotNullAndNotEmpty
import com.navi.design.utils.*
import com.navi.naviwidgets.R
import com.navi.naviwidgets.callbacks.WidgetCallback
import com.navi.naviwidgets.databinding.LayoutFundCardBinding
import com.navi.naviwidgets.databinding.LayoutFundCardSectionBinding
import com.navi.naviwidgets.extensions.setGradient
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
import com.navi.naviwidgets.models.response.amc.FundCardData
import com.navi.naviwidgets.models.response.amc.FundCardWidget
class FundCardWidgetLayout @JvmOverloads constructor(
@@ -78,118 +68,4 @@ class FundCardWidgetLayout @JvmOverloads constructor(
}
}
}
}
class FundCardAdapter(
private val list: List<FundCardData> = emptyList(),
private val widgetCallback: WidgetCallback
) : RecyclerView.Adapter<CardViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.layout_fund_card, parent, false)
val itemBinding: LayoutFundCardBinding = DataBindingUtil.bind(view)!!
return CardViewHolder(itemBinding, widgetCallback)
}
override fun onBindViewHolder(holder: CardViewHolder, position: Int) {
holder.bind(list[position], position)
}
override fun getItemCount() =
list.size
}
class CardViewHolder(
private val viewBinding: LayoutFundCardBinding,
private val widgetCallback: WidgetCallback
) : RecyclerView.ViewHolder(viewBinding.root) {
fun bind(card: FundCardData, position: Int) {
viewBinding.apply {
fundCard.background = getNaviDrawable(
cornerRadius = dpToPx(8).toInt(),
strokeColor = ContextCompat.getColor(
itemView.context,
R.color.border_grey_color
),
strokeWidth = dpToPx(1).toInt(),
backgroundColor = ContextCompat.getColor(
itemView.context,
R.color.white
)
)
fundTitle.setSpannableString(card.title)
icon.showWhenDataIsAvailable(card.iconCode)
card.tagData?.let {
fundTagContainer.isVisible = true
fundTagTitle.setSpannableString(it.title)
fundTagIcon.showWhenDataIsAvailable(it.iconCode)
} ?: kotlin.run {
fundTagContainer.isVisible = false
}
card.items?.forEachIndexed { index, subItemData ->
when(index) {
0 -> {
fundSize.title.setSpannableString(subItemData.title)
fundSize.subtitle.setSpannableString(subItemData.subtitle)
if(subItemData.title?.text.isNotNullAndNotEmpty()) {
fundSize.titleIcon.showWhenDataIsAvailable(subItemData.iconCode)
fundSize.icon.visibility = View.GONE
}
else {
fundSize.icon.showWhenDataIsAvailable(subItemData.iconCode)
fundSize.title.visibility = View.GONE
}
}
1 -> {
returns.title.setSpannableString(subItemData.title)
returns.subtitle.setSpannableString(subItemData.subtitle)
if(subItemData.title?.text.isNotNullAndNotEmpty()) {
returns.titleIcon.showWhenDataIsAvailable(subItemData.iconCode)
returns.icon.visibility = View.GONE
}
else {
returns.icon.showWhenDataIsAvailable(subItemData.iconCode)
returns.title.visibility = View.GONE
}
}
2 -> {
cta.title.setSpannableString(subItemData.title)
cta.subtitle.setSpannableString(subItemData.subtitle)
if(subItemData.title?.text.isNotNullAndNotEmpty()) {
cta.titleIcon.showWhenDataIsAvailable(subItemData.iconCode)
cta.icon.visibility = View.GONE
}
else {
cta.icon.showWhenDataIsAvailable(subItemData.iconCode)
cta.title.visibility = View.GONE
}
}
}
}
if(card.footerTitle?.text.isNotNullAndNotEmpty()) {
productStrategyContainer.background = getNaviDrawable(
radii = CornerRadius(
leftBottom = dpToPx(8),
rightBottom = dpToPx(8)
),
backgroundColor = card.footerBgColor.parseColorSafe()
)
productStrategyTv.setSpannableString(card.footerTitle)
productStrategyIv.showWhenDataIsAvailable(card.footerIconCode)
} else {
productStrategyContainer.visibility = View.GONE
}
fundCard.setOnClickListener {
card.action?.let { actionData ->
widgetCallback.onClick(actionData)
}
}
}
}
}
}

View File

@@ -109,7 +109,8 @@
<LinearLayout
android:id="@+id/product_strategy_container"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_32"
android:layout_height="wrap_content"
android:paddingVertical="@dimen/dp_10"
android:layout_marginHorizontal="@dimen/dp_1"
android:layout_marginBottom="@dimen/dp_1"
android:orientation="horizontal"
@@ -130,9 +131,9 @@
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_16"
android:lineSpacingExtra="@dimen/sp_4"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
tools:text="20k+ investors have invested in this fund" />
</LinearLayout>

View File

@@ -0,0 +1,142 @@
<?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"
xmlns:tools="http://schemas.android.com/tools">
<androidx.cardview.widget.CardView
android:id="@+id/fund_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_16"
android:layout_marginBottom="@dimen/dp_16"
android:outlineSpotShadowColor="@color/outlineSpotShadowColor"
app:cardCornerRadius="@dimen/dp_8"
app:cardElevation="@dimen/dp_8"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/fund_card2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/dp_16"
app:layout_constraintBottom_toBottomOf="parent">
<com.navi.design.textview.NaviTextView
android:id="@+id/title"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_16"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@id/cta"
app:layout_constraintStart_toStartOf="parent"
tools:text="Nifty 50 Index" />
<com.navi.design.textview.NaviTextView
android:id="@+id/subtitle"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_4"
app:layout_constraintTop_toBottomOf="@id/title"
app:layout_constraintEnd_toStartOf="@id/cta"
app:layout_constraintStart_toStartOf="parent"
tools:text="3Y returns : +26.57%" />
<include
android:id="@+id/cta"
layout="@layout/item_title_subtitle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_16"
android:layout_marginBottom="@dimen/dp_16"
app:layout_constraintTop_toTopOf="@id/title"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/fund_tag_container"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_8"
android:orientation="horizontal"
android:gravity="center_vertical"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/subtitle"
app:layout_constraintEnd_toStartOf="@id/cta"
app:layout_constraintStart_toStartOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/fund_tag_icon"
android:layout_width="@dimen/dp_16"
android:layout_height="@dimen/dp_16"
android:layout_marginEnd="@dimen/dp_8"
tools:src="@drawable/ic_star_with_grey_bg" />
<com.navi.design.textview.NaviTextView
android:id="@+id/fund_tag_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="5K+ investors" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="subtitle, cta, fund_tag_container" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_2"
android:layout_marginTop="@dimen/dp_12"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginEnd="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier"
android:background="@drawable/dotted_line" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/fund_icon"
android:layout_width="@dimen/dp_16"
android:layout_height="@dimen/dp_16"
android:layout_marginStart="@dimen/dp_16"
app:layout_constraintTop_toTopOf="@id/fund_title"
app:layout_constraintStart_toStartOf="parent"
tools:src="@drawable/ic_rewards_navi" />
<com.navi.design.textview.NaviTextView
android:id="@+id/fund_title"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_16"
app:layout_constraintTop_toBottomOf="@id/divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/fund_icon"
tools:text="3Y returns : +26.57%" />
<com.navi.design.textview.NaviTextView
android:id="@+id/fund_subtitle"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="@dimen/dp_16"
android:layout_marginBottom="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_8"
android:gravity="center_vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/fund_title"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="20k+ investors have invested in this fund" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>