[PS] AE-7458 | Show top / recommended funds like Dashboard on fund listing page (#4696)
* [PS] added fund listing v2 widgets * [PS] implemented fund listing page changes * [PS] fix design issues * [PS] fix design issues Co-authored-by: shankar yadav <shankar.yadav@navi.com>
This commit is contained in:
committed by
GitHub Enterprise
parent
f7b34333bf
commit
94aeff96ba
@@ -25,6 +25,7 @@ import com.navi.amc.fundbuy.viewmodel.FundListViewModel
|
||||
import com.navi.amc.utils.AmcAnalytics
|
||||
import com.navi.amc.utils.AmcAnalytics.FUND_ID
|
||||
import com.navi.amc.utils.AmcAnalytics.ISIN
|
||||
import com.navi.amc.utils.Constant
|
||||
import com.navi.amc.utils.Constant.FUND_CATEGORY
|
||||
import com.navi.amc.utils.getValueFromActionData
|
||||
import com.navi.base.model.ActionData
|
||||
@@ -55,12 +56,20 @@ class FundListingFragment : AmcBaseFragment() {
|
||||
binding =
|
||||
DataBindingUtil.inflate(inflater, R.layout.fund_list_fragment_layout, container, false)
|
||||
initError(viewModel, showNewDesignSystemFragment = true)
|
||||
sendInitEvent()
|
||||
initRecyclerView()
|
||||
initObservers()
|
||||
fetchData()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun sendInitEvent() {
|
||||
sendEvent(
|
||||
AmcAnalytics.FUND_LIST,
|
||||
hashMapOf(Pair(FUND_CATEGORY, arguments?.getString(FUND_CATEGORY).orEmpty()))
|
||||
)
|
||||
}
|
||||
|
||||
private fun initObservers() {
|
||||
viewModel.fundListData.observe(viewLifecycleOwner) {
|
||||
hideLoader()
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.navi.amc.fundbuy.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
|
||||
import com.navi.amc.R
|
||||
import com.navi.amc.common.fragment.AmcBaseFragment
|
||||
import com.navi.amc.databinding.FundListFragmentV2LayoutBinding
|
||||
import com.navi.amc.fundbuy.viewmodel.FundListViewModel
|
||||
import com.navi.amc.utils.AmcAnalytics
|
||||
import com.navi.amc.utils.Constant
|
||||
import com.navi.amc.utils.SubPageStatusType
|
||||
import com.navi.amc.utils.getValueFromActionData
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.NaviClickAction
|
||||
import com.navi.base.model.NaviWidgetClickWithActionData
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.common.listeners.FragmentInterchangeListener
|
||||
import com.navi.common.listeners.HeaderInteractionListener
|
||||
import com.navi.design.utils.dpToPx
|
||||
import com.navi.naviwidgets.adapters.NaviAdapter
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.extensions.setVisibilityState
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.viewholder.DashboardHolderFactoryImpl
|
||||
import com.navi.naviwidgets.viewholder.ViewHolderFactoryImpl
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FundListingFragmentV2: AmcBaseFragment(), WidgetCallback {
|
||||
|
||||
private lateinit var binding: FundListFragmentV2LayoutBinding
|
||||
private val viewModel by lazy { ViewModelProvider(this).get(FundListViewModel::class.java) }
|
||||
private var naviAdapter: NaviAdapter<NaviWidget> =
|
||||
NaviAdapter(widgetCallback = this, factory = ViewHolderFactoryImpl())
|
||||
|
||||
override val screenName: String
|
||||
get() = AmcAnalytics.FUND_LIST
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = DataBindingUtil.inflate(inflater, R.layout.fund_list_fragment_v2_layout, container, false)
|
||||
sendInitEvent()
|
||||
initError(viewModel, showNewDesignSystemFragment = true)
|
||||
initRecyclerView()
|
||||
initObservers()
|
||||
fetchData()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun sendInitEvent() {
|
||||
val category = arguments?.getString(Constant.FUND_CATEGORY).orEmpty()
|
||||
val initEventName =
|
||||
if (category == SubPageStatusType.FUND_LANDING) AmcAnalytics.FUND_LANDING
|
||||
else if (category.isNotNullAndNotEmpty()) AmcAnalytics.FUND_CATEOGRY_LIST
|
||||
else AmcAnalytics.FUND_LIST
|
||||
sendEvent(
|
||||
initEventName,
|
||||
hashMapOf(Pair(Constant.FUND_CATEGORY, arguments?.getString(Constant.FUND_CATEGORY).orEmpty()))
|
||||
)
|
||||
}
|
||||
|
||||
private fun initRecyclerView() {
|
||||
binding.rvProducts.apply {
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||
adapter = naviAdapter
|
||||
addItemDecoration(object : ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
super.getItemOffsets(outRect, view, parent, state)
|
||||
parent.findContainingViewHolder(view)?.itemViewType?.let { itemViewType ->
|
||||
if(itemViewType == R.layout.layout_list_overlapping_header) {
|
||||
outRect.set(0, 0, 0, (-1 * dpToPx(50).toInt()))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun initObservers() {
|
||||
viewModel.fundListDataV2.observe(viewLifecycleOwner) { response ->
|
||||
hideLoader()
|
||||
response?.listOfWidgets?.let { list ->
|
||||
naviAdapter.setData(list)
|
||||
binding.rvProducts.visibility = View.VISIBLE
|
||||
} ?: run { binding.rvProducts.visibility = View.GONE }
|
||||
response?.header?.let { header ->
|
||||
headerInteractionListener?.setProperties(header)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchData() {
|
||||
showLoader()
|
||||
val fundCategory = arguments?.getString(Constant.FUND_CATEGORY)
|
||||
when(fundCategory) {
|
||||
SubPageStatusType.FUND_LANDING -> viewModel.fetchFundLandingData()
|
||||
else -> viewModel.fetchFundsDataV2(fundCategory)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(naviClickAction: NaviClickAction) {
|
||||
when (naviClickAction) {
|
||||
is NaviWidgetClickWithActionData -> {
|
||||
navigateToNextScreen(naviClickAction.actionData)
|
||||
}
|
||||
is ActionData -> {
|
||||
navigateToNextScreen(naviClickAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToNextScreen(actionData: ActionData?) {
|
||||
sendEvent(
|
||||
actionData?.metaData?.clickedData,
|
||||
hashMapOf(
|
||||
Pair(AmcAnalytics.FUND_ID, actionData?.getValueFromActionData(AmcAnalytics.ISIN).orEmpty()),
|
||||
Pair(Constant.FUND_CATEGORY, actionData?.getValueFromActionData(Constant.FUND_CATEGORY).orEmpty())
|
||||
)
|
||||
)
|
||||
fragmentInterchangeListener?.navigateToNextScreen(actionData)
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
headerInteractionListener = context as? HeaderInteractionListener
|
||||
fragmentInterchangeListener = context as? FragmentInterchangeListener
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
viewModel.clearData()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(bundle: Bundle): FundListingFragmentV2 {
|
||||
return FundListingFragmentV2().apply { arguments = bundle }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.navi.amc.fundbuy.models
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.common.model.Header
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.io.Serializable
|
||||
|
||||
@Parcelize
|
||||
data class FundListResponse(
|
||||
@SerializedName("content") val listOfWidgets: List<NaviWidget>? = null,
|
||||
@SerializedName("header") val header: Header? = null
|
||||
) : Serializable, Parcelable
|
||||
@@ -9,4 +9,10 @@ class FundListRepository @Inject constructor(private val retrofitService: Retrof
|
||||
|
||||
suspend fun fetchFundsData(fundCategory: String?) =
|
||||
apiResponseCallback(retrofitService.fetchFundListData(fundCategory))
|
||||
|
||||
suspend fun fetchFundsDataV2(fundCategory: String?) =
|
||||
apiResponseCallback(retrofitService.fetchFundListDataV2(fundCategory))
|
||||
|
||||
suspend fun fetchFundLandingData() =
|
||||
apiResponseCallback(retrofitService.fetchFundLandingData())
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.navi.amc.fundbuy.viewmodel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.navi.amc.fundbuy.models.FundListResponse
|
||||
import com.navi.amc.fundbuy.models.FundListScreen
|
||||
import com.navi.amc.fundbuy.repository.FundListRepository
|
||||
import com.navi.common.viewmodel.BaseVM
|
||||
@@ -17,6 +18,10 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
val fundListData: LiveData<FundListScreen?>
|
||||
get() = _fundListData
|
||||
|
||||
private val _fundListDataV2 = MutableLiveData<FundListResponse?>()
|
||||
val fundListDataV2: LiveData<FundListResponse?>
|
||||
get() = _fundListDataV2
|
||||
|
||||
fun fetchFundsData(fundCategory: String?) {
|
||||
viewModelScope.launch {
|
||||
val response = repository.fetchFundsData(fundCategory)
|
||||
@@ -26,6 +31,24 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
}
|
||||
}
|
||||
|
||||
fun fetchFundsDataV2(fundCategory: String?) {
|
||||
viewModelScope.launch {
|
||||
val response = repository.fetchFundsDataV2(fundCategory)
|
||||
if (response.error == null && response.errors.isNullOrEmpty()) {
|
||||
_fundListDataV2.value = response.data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun fetchFundLandingData() {
|
||||
viewModelScope.launch {
|
||||
val response = repository.fetchFundLandingData()
|
||||
if (response.error == null && response.errors.isNullOrEmpty()) {
|
||||
_fundListDataV2.value = response.data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearData() {
|
||||
errorResponse.value = null
|
||||
_fundListData.value = null
|
||||
|
||||
@@ -228,6 +228,14 @@ interface RetrofitService {
|
||||
@Query("fundCategory") fundCategory: String?
|
||||
): Response<GenericResponse<FundListScreen>>
|
||||
|
||||
@GET("/fund/fund-list/v2")
|
||||
suspend fun fetchFundListDataV2(
|
||||
@Query("fundCategory") fundCategory: String?
|
||||
): Response<GenericResponse<FundListResponse>>
|
||||
|
||||
@GET("/fund/fund-landing")
|
||||
suspend fun fetchFundLandingData(): Response<GenericResponse<FundListResponse>>
|
||||
|
||||
@GET("sip/sip-overview") suspend fun fetchSipDetails(): Response<GenericResponse<SipScreenData>>
|
||||
|
||||
@GET("/sip/sip-details")
|
||||
|
||||
@@ -37,6 +37,8 @@ object AmcAnalytics {
|
||||
const val CHECKER_ACTIVITY = "amc_checker_activity"
|
||||
const val BUY_ACTIVITY = "amc_buy_activity"
|
||||
const val FUND_LIST = "amc_init_fund_listing"
|
||||
const val FUND_CATEOGRY_LIST = "amc_init_fund_listing_category"
|
||||
const val FUND_LANDING = "amc_init_fund_landing"
|
||||
const val FUND_DETAILS = "amc_init_mf"
|
||||
const val AMC_RANDOM = "amc_random"
|
||||
const val FUND_BUY_SIP_LUMPSUM_SCREEN = "fund_buy_sip_lumpsum_screen"
|
||||
|
||||
@@ -169,6 +169,11 @@ fun getFragment(screen: String, bundle: Bundle): Fragment? {
|
||||
SubPageStatusType.FUND_SELL -> FundSellFragment.newInstance(bundle)
|
||||
SubPageStatusType.PORTFOLIO -> PortfolioFragment.newInstance(bundle)
|
||||
SubPageStatusType.FUND_LIST -> FundListingFragment.newInstance(bundle)
|
||||
SubPageStatusType.FUND_LIST_V2 -> FundListingFragmentV2.newInstance(bundle)
|
||||
SubPageStatusType.FUND_LANDING -> {
|
||||
bundle.putString(Constant.FUND_CATEGORY, SubPageStatusType.FUND_LANDING)
|
||||
FundListingFragmentV2.newInstance(bundle)
|
||||
}
|
||||
SubPageStatusType.MY_INVESTMENTS -> MyInvestmentsFragment.newInstance(bundle)
|
||||
SubPageStatusType.TRANSACTIONS_HISTORY -> TransactionHistoryFragment.newInstance(bundle)
|
||||
SubPageStatusType.INVESTMENT_DETAILS -> InvestmentDetailsFragment.newInstance(bundle)
|
||||
@@ -177,6 +182,7 @@ fun getFragment(screen: String, bundle: Bundle): Fragment? {
|
||||
SubPageStatusType.AUTO_PAY_SUCCESS -> AutoPaySuccessFragment.newInstance(bundle)
|
||||
SubPageStatusType.AUTO_PAY_MODIFY -> AutoPayModifyFragment.newInstance(bundle)
|
||||
SubPageStatusType.FUND_CATEGORY_LIST -> FundListingFragment.newInstance(bundle)
|
||||
SubPageStatusType.FUND_CATEGORY_LIST_V2 -> FundListingFragmentV2.newInstance(bundle)
|
||||
SubPageStatusType.FUND_INFORMATION -> FundInformationFragment.newInstance(bundle)
|
||||
SubPageStatusType.SIP_DETAILS_MODIFY -> ModifySipDetailsFragment.newInstance(bundle)
|
||||
SubPageStatusType.SIP_MODIFICATION -> SipModifyFragment.newInstance(bundle)
|
||||
|
||||
@@ -20,6 +20,8 @@ object SubPageStatusType {
|
||||
const val OTP = "otp"
|
||||
const val STATUS = "status"
|
||||
const val FUND_LIST = "fund_list"
|
||||
const val FUND_LANDING = "fund_landing"
|
||||
const val FUND_LIST_V2 = "fund_list_v2"
|
||||
const val FUND_DETAILS = "fund_details"
|
||||
const val FUND_BUY_SIP_LUMPSUM = "fund_buy_sip_lumpsum"
|
||||
const val ORDER_STATUS = "order_status"
|
||||
@@ -35,6 +37,7 @@ object SubPageStatusType {
|
||||
const val AUTO_PAY_SUCCESS = "auto_pay_success"
|
||||
const val AUTO_PAY_MODIFY = "auto_pay_modify"
|
||||
const val FUND_CATEGORY_LIST = "fund_category_list"
|
||||
const val FUND_CATEGORY_LIST_V2 = "fund_category_list_v2"
|
||||
const val FUND_INFORMATION = "fund_information"
|
||||
const val SIP_DETAILS_MODIFY = "sip_details_modify"
|
||||
const val CUTOFF_TIME_BOTTOMSHEET = "CUTOFF_TIME_BOTTOMSHEET"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ /*
|
||||
~ *
|
||||
~ * * Copyright © 2022 by Navi Technologies Private Limited
|
||||
~ * * All rights reserved. Strictly confidential
|
||||
~ *
|
||||
~ */
|
||||
-->
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvProducts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -113,9 +113,11 @@
|
||||
<dimen name="dp_122">122dp</dimen>
|
||||
<dimen name="dp_92">92dp</dimen>
|
||||
<dimen name="dp_202">202dp</dimen>
|
||||
<dimen name="dp_274">274dp</dimen>
|
||||
<dimen name="dp_278">278dp</dimen>
|
||||
<dimen name="dp_280">280dp</dimen>
|
||||
<dimen name="dp_300">300dp</dimen>
|
||||
<dimen name="dp_311">311dp</dimen>
|
||||
<dimen name="dp_332">332dp</dimen>
|
||||
<dimen name="dp_400">400dp</dimen>
|
||||
<dimen name="dp_510">510dp</dimen>
|
||||
|
||||
@@ -877,6 +877,9 @@ fun LottieAnimationView.showWhenDataIsAvailable(
|
||||
LottieEnums.AMC_OFFER_LOTTIE.name -> {
|
||||
setAnimation(R.raw.amc_offer_lottie)
|
||||
}
|
||||
LottieEnums.CONFETTI_FROM_ABOVE.name -> {
|
||||
setAnimation(R.raw.confetti_from_above)
|
||||
}
|
||||
}
|
||||
if (infiniteRepeat == true) {
|
||||
repeatCount = LottieDrawable.INFINITE
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.navi.naviwidgets.models.response.amc
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.Gradient
|
||||
import com.navi.naviwidgets.models.response.WidgetError
|
||||
|
||||
data class FundCardWidget(
|
||||
@SerializedName("widgetId") override val widgetId: String? = null,
|
||||
@SerializedName("widgetName") override var widgetNameForBaseAdapter: String? = WIDGET_NAME,
|
||||
@SerializedName("widgetData") val widgetData: FundCardWidgetData? = null,
|
||||
@SerializedName("isDependentWidget") override val isDependentWidget: Boolean?,
|
||||
@SerializedName("dependencyWidgetId") override val dependencyWidgetId: String?,
|
||||
override var isDependencyWidgetShowing: Boolean? = null,
|
||||
override var widgetError: WidgetError? = null
|
||||
) : NaviWidget() {
|
||||
companion object {
|
||||
const val WIDGET_NAME = "FUND_CARD_WIDGET"
|
||||
}
|
||||
}
|
||||
|
||||
data class FundCardWidgetData(
|
||||
@SerializedName("header") val header: FundCardWidgetHeader? = null,
|
||||
@SerializedName("items") val items: List<FundCardData>? = null,
|
||||
@SerializedName("gradient") val gradient: Gradient? = null
|
||||
)
|
||||
|
||||
data class FundCardData(
|
||||
@SerializedName("title") val title: TextWithStyle? = null,
|
||||
@SerializedName("iconCode") val iconCode: String? = 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("actionData") val action: ActionData? = null
|
||||
)
|
||||
|
||||
data class FundCardWidgetHeader(
|
||||
@SerializedName("title") val title: TextWithStyle? = null,
|
||||
@SerializedName("subtitle", alternate = ["subTitle"]) val subTitle: TextWithStyle? = null,
|
||||
@SerializedName("iconCode") val iconCode: String? = null
|
||||
)
|
||||
|
||||
data class SubItemData(
|
||||
@SerializedName("title") val title: TextWithStyle? = null,
|
||||
@SerializedName("subTitle", alternate = ["subtitle"]) val subtitle: TextWithStyle? = null,
|
||||
@SerializedName("iconCode") val iconCode: String? = null
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.navi.naviwidgets.models.response.amc
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.WidgetError
|
||||
|
||||
data class FundOptionsHorizontalListWidget(
|
||||
@SerializedName("widgetId") override val widgetId: String? = null,
|
||||
@SerializedName("widgetName") override var widgetNameForBaseAdapter: String? = WIDGET_NAME,
|
||||
@SerializedName("widgetData") val widgetData: IconHorizontalScrollData? = null,
|
||||
@SerializedName("isDependentWidget") override val isDependentWidget: Boolean?,
|
||||
@SerializedName("dependencyWidgetId") override val dependencyWidgetId: String?,
|
||||
override var isDependencyWidgetShowing: Boolean? = null,
|
||||
override var widgetError: WidgetError? = null
|
||||
): NaviWidget() {
|
||||
companion object {
|
||||
const val WIDGET_NAME = "FUND_OPTIONS_HORIZONTAL_LIST_WIDGET"
|
||||
}
|
||||
}
|
||||
|
||||
data class IconHorizontalScrollData(
|
||||
@SerializedName("title")
|
||||
val title: TextWithStyle? = null,
|
||||
@SerializedName("items")
|
||||
val items: List<IconTitleData>? = null,
|
||||
@SerializedName("bgColor")
|
||||
val bgColor: String? = null
|
||||
)
|
||||
|
||||
data class IconTitleData(
|
||||
@SerializedName("iconCode")
|
||||
val iconCode: String? = null,
|
||||
@SerializedName("title")
|
||||
val title: TextWithStyle? = null,
|
||||
@SerializedName("actionData")
|
||||
val action: ActionData? = null
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.navi.naviwidgets.models.response.amc
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.Gradient
|
||||
import com.navi.naviwidgets.models.response.WidgetError
|
||||
|
||||
data class ListOverlappingHeaderWidget(
|
||||
@SerializedName("widgetId") override val widgetId: String? = null,
|
||||
@SerializedName("widgetName") override var widgetNameForBaseAdapter: String? = WIDGET_NAME,
|
||||
@SerializedName("widgetData") val widgetData: ListOverlappingHeaderData? = null,
|
||||
@SerializedName("isDependentWidget") override val isDependentWidget: Boolean?,
|
||||
@SerializedName("dependencyWidgetId") override val dependencyWidgetId: String?,
|
||||
override var isDependencyWidgetShowing: Boolean? = null,
|
||||
override var widgetError: WidgetError? = null
|
||||
): NaviWidget() {
|
||||
companion object {
|
||||
const val WIDGET_NAME = "LIST_OVERLAPPING_HEADER_WIDGET"
|
||||
}
|
||||
}
|
||||
|
||||
data class ListOverlappingHeaderData(
|
||||
@SerializedName("title")
|
||||
val title: TextWithStyle? = null,
|
||||
@SerializedName("subtitle")
|
||||
val subTitle: TextWithStyle? = null,
|
||||
@SerializedName("iconCode")
|
||||
val iconCode: String? = null,
|
||||
@SerializedName("gradient")
|
||||
val gradient: Gradient? = null
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.navi.naviwidgets.models.response.amc
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.WidgetError
|
||||
|
||||
data class RewardsDetailWidget(
|
||||
@SerializedName("widgetId") override val widgetId: String? = null,
|
||||
@SerializedName("widgetName") override var widgetNameForBaseAdapter: String? = WIDGET_NAME,
|
||||
@SerializedName("widgetData") val widgetData: RewardsDetailWidgetData? = null,
|
||||
@SerializedName("isDependentWidget") override val isDependentWidget: Boolean?,
|
||||
@SerializedName("dependencyWidgetId") override val dependencyWidgetId: String?,
|
||||
override var isDependencyWidgetShowing: Boolean? = null,
|
||||
override var widgetError: WidgetError? = null
|
||||
): NaviWidget() {
|
||||
companion object {
|
||||
const val WIDGET_NAME = "REWARDS_DETAIL_WIDGET"
|
||||
}
|
||||
}
|
||||
|
||||
data class RewardsDetailWidgetData(
|
||||
@SerializedName("title")
|
||||
val title: TextWithStyle? = null,
|
||||
@SerializedName("label")
|
||||
val label: LabelData? = null,
|
||||
@SerializedName("icon")
|
||||
val icon: String? = null,
|
||||
@SerializedName("bgColor")
|
||||
val bgColor: String? = null,
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.navi.naviwidgets.models.response.amc
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.ImageDetails
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.Gradient
|
||||
import com.navi.naviwidgets.models.response.WidgetError
|
||||
|
||||
class TopProductHorizontalListWidget (
|
||||
@SerializedName("widgetId") override val widgetId: String? = null,
|
||||
@SerializedName("widgetName") override var widgetNameForBaseAdapter: String? = WIDGET_NAME,
|
||||
@SerializedName("widgetData") val widgetData: TopProductHorizontalListData? = null,
|
||||
@SerializedName("isDependentWidget") override val isDependentWidget: Boolean?,
|
||||
@SerializedName("dependencyWidgetId") override val dependencyWidgetId: String?,
|
||||
override var isDependencyWidgetShowing: Boolean? = null,
|
||||
override var widgetError: WidgetError? = null
|
||||
): NaviWidget() {
|
||||
companion object {
|
||||
const val WIDGET_NAME = "TOP_PRODUCT_HORIZONTAL_LIST_WIDGET"
|
||||
}
|
||||
}
|
||||
|
||||
data class TopProductHorizontalListData(
|
||||
@SerializedName("header") val header: TopProductHorizontalListHeader? = null,
|
||||
@SerializedName("items") val items: List<TopProductItem>? = null,
|
||||
)
|
||||
|
||||
data class TopProductHorizontalListHeader(
|
||||
@SerializedName("title") val title: TextWithStyle? = null,
|
||||
@SerializedName("iconCode") val iconCode: String? = null
|
||||
)
|
||||
|
||||
data class TopProductItem(
|
||||
@SerializedName("iconCode") val iconCode: String? = null,
|
||||
@SerializedName("imageDetails") val imageDetails: ImageDetails?,
|
||||
@SerializedName("gradient") val gradient: Gradient? = null,
|
||||
@SerializedName("title") val title: TextWithStyle? = null,
|
||||
@SerializedName("subTitle", alternate = ["subtitle"]) val subTitle: TextWithStyle? = null,
|
||||
@SerializedName("rightArrowIconCode") val rightArrowIconCode: String? = null,
|
||||
@SerializedName("footerIconCode") val footerIconCode: String? = null,
|
||||
@SerializedName("footerTitle") val footerTitle: TextWithStyle? = null,
|
||||
@SerializedName("footerBgColor") val footerBgColor: String? = null,
|
||||
@SerializedName("lottieFileName") val lottieFileName: String? = null,
|
||||
@SerializedName("label") val label: LabelData? = null,
|
||||
@SerializedName("actionTitle") val actionTitle: TextWithStyle? = null,
|
||||
@SerializedName("actionData") val actionData: ActionData? = null,
|
||||
)
|
||||
|
||||
data class LabelData(
|
||||
@SerializedName("title") val title: TextWithStyle? = null,
|
||||
@SerializedName("bgColor") val bgColor: String? = null
|
||||
)
|
||||
@@ -16,6 +16,7 @@ enum class LottieEnums {
|
||||
CARD_SHIMMER,
|
||||
ORANGE_GRADIENT_LOADER,
|
||||
GIFT_REWARD_LOTTIE,
|
||||
CONFETTI_FROM_ABOVE,
|
||||
AMC_REWARD_LOTTIE,
|
||||
SMALL_AMC_REWARD_LOTTIE,
|
||||
AMC_OFFER_LOTTIE
|
||||
|
||||
@@ -230,6 +230,8 @@ object NaviWidgetIconUtils {
|
||||
private const val ICON_INFO_SIMPLE = "ICON_INFO_SIMPLE"
|
||||
private const val ICON_OTHERS_SELECTED = "ICON_OTHERS_SELECTED"
|
||||
private const val CHEVRON = "CHEVRON"
|
||||
private const val CHEVRON_V2 = "CHEVRON_V2"
|
||||
private const val CHEVRON_V3 = "CHEVRON_V3"
|
||||
private const val CHEVRON_ICON_WITH_WHITE_BG = "CHEVRON_ICON_WITH_WHITE_BG"
|
||||
private const val TRENDING_ICON = "TRENDING_ICON"
|
||||
private const val ICON_BACK_ARROW = "ICON_BACK_ARROW"
|
||||
@@ -678,6 +680,8 @@ object NaviWidgetIconUtils {
|
||||
ICON_SECURITY_CHECK -> R.drawable.ic_security_check_svg
|
||||
ICON_INFO_SIMPLE -> R.drawable.ic_info_icon_svg
|
||||
CHEVRON -> R.drawable.ic_chevrons
|
||||
CHEVRON_V2-> R.drawable.ic_chevrons_v2
|
||||
CHEVRON_V3-> R.drawable.ic_chevron_v3
|
||||
CHEVRON_ICON_WITH_WHITE_BG -> R.drawable.ic_chevrons_with_white_bg_svg
|
||||
CHAT_NEW_ICON -> R.drawable.ic_new_chat_svg
|
||||
CALL_NEW_ICON -> R.drawable.ic_new_phone_call_svg
|
||||
|
||||
@@ -19,7 +19,9 @@ import com.navi.naviwidgets.interfaces.hospitalcard.HospitalCardWidgetInfo
|
||||
import com.navi.naviwidgets.interfaces.hospitalcard.HospitalCardWidgetV2Info
|
||||
import com.navi.naviwidgets.models.*
|
||||
import com.navi.naviwidgets.models.response.*
|
||||
import com.navi.naviwidgets.models.response.amc.*
|
||||
import com.navi.naviwidgets.models.response.callout.CalloutWidget
|
||||
import com.navi.naviwidgets.viewholder.amc.*
|
||||
import com.navi.naviwidgets.viewholder.callout.CalloutWidgetVH
|
||||
import com.navi.naviwidgets.viewholder.hospitalcard.HospitalCardV2VH
|
||||
import com.navi.naviwidgets.viewholder.hospitalcard.HospitalCardVH
|
||||
@@ -210,6 +212,11 @@ class ViewHolderFactoryImpl<T : NaviBaseAdapterModel> : ViewHolderTypeFactory<T>
|
||||
private val ICON_TITLE_WITH_CONSENT = R.layout.layout_icon_title_with_consent_widget
|
||||
private val AUTOPAY_STEPS_WIDGET = R.layout.widget_autopay_steps
|
||||
private val TITLE_END_ICON_WITH_GRADIENT = R.layout.layout_title_end_icon_with_gradient_widget
|
||||
private val FUND_CARD_WIDGET = R.layout.layout_fund_card_section
|
||||
private val FUND_OPTIONS_HORIZONTAL_LIST_WIDGET = R.layout.layout_fund_options_horizontal_list
|
||||
private val LIST_OVERLAPPING_HEADER_WIDGET = R.layout.layout_list_overlapping_header
|
||||
private val TOP_PRODUCT_HORIZONTAL_LIST_WIDGET = R.layout.layout_top_product_horizontal_list
|
||||
private val REWARDS_DETAIL_WIDGET = R.layout.layout_rewards_detail_widget
|
||||
private val PRODUCT_CLICK_CARD_CAROUSAL_WIDGET = R.layout.product_click_card_carousal_widget
|
||||
// Incase unknown/un-registered widget comes we need to handle that
|
||||
private val GENERIC_WIDGET = R.layout.dummy_content_view
|
||||
@@ -376,6 +383,11 @@ class ViewHolderFactoryImpl<T : NaviBaseAdapterModel> : ViewHolderTypeFactory<T>
|
||||
is IconTitleWithConsentWidget -> ICON_TITLE_WITH_CONSENT
|
||||
is AutopayStepsWidgetModel -> AUTOPAY_STEPS_WIDGET
|
||||
is TitleEndIconWithGradientWidget -> TITLE_END_ICON_WITH_GRADIENT
|
||||
is FundCardWidget -> FUND_CARD_WIDGET
|
||||
is FundOptionsHorizontalListWidget -> FUND_OPTIONS_HORIZONTAL_LIST_WIDGET
|
||||
is ListOverlappingHeaderWidget -> LIST_OVERLAPPING_HEADER_WIDGET
|
||||
is TopProductHorizontalListWidget -> TOP_PRODUCT_HORIZONTAL_LIST_WIDGET
|
||||
is RewardsDetailWidget -> REWARDS_DETAIL_WIDGET
|
||||
is ProductClickCardCarousalWidget -> PRODUCT_CLICK_CARD_CAROUSAL_WIDGET
|
||||
is BenefitExplainerWidgetBodyData -> BENEFIT_EXPLAINER_WIDGET
|
||||
// Default case, add all widgets above this
|
||||
@@ -553,6 +565,11 @@ class ViewHolderFactoryImpl<T : NaviBaseAdapterModel> : ViewHolderTypeFactory<T>
|
||||
ICON_TITLE_WITH_CONSENT -> IconTitleWithConsentWidgetVH(parent)
|
||||
AUTOPAY_STEPS_WIDGET -> AutopayStepWidgetVH(parent)
|
||||
TITLE_END_ICON_WITH_GRADIENT -> TitleEndIconWithGradientWidgetVH(parent)
|
||||
FUND_CARD_WIDGET -> FundCardWidgetVH(parent)
|
||||
FUND_OPTIONS_HORIZONTAL_LIST_WIDGET -> FundOptionsHorizontalListVH(parent)
|
||||
LIST_OVERLAPPING_HEADER_WIDGET -> ListOverlappingHeaderVH(parent)
|
||||
TOP_PRODUCT_HORIZONTAL_LIST_WIDGET -> TopProductHorizontalListVH(parent)
|
||||
REWARDS_DETAIL_WIDGET -> RewardsDetailWidgetVH(parent)
|
||||
PRODUCT_CLICK_CARD_CAROUSAL_WIDGET -> ProductClickCardCarousalWidgetVH(parent)
|
||||
CENTRE_TITLE_SUBTITLE_WIDGET -> CentreTitleSubtitleWidgetVH(parent)
|
||||
PRODUCT_INFO_WIDGET_V2 -> ProductInfoWidgetV2VH(parent)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.navi.naviwidgets.viewholder.amc
|
||||
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutFundCardSectionBinding
|
||||
import com.navi.naviwidgets.models.response.amc.FundCardWidget
|
||||
import com.navi.naviwidgets.viewholder.BaseViewHolder
|
||||
import com.navi.naviwidgets.widgets.amc.FundCardWidgetLayout
|
||||
|
||||
class FundCardWidgetVH(private val viewBinding: ViewDataBinding):
|
||||
BaseViewHolder<FundCardWidget>(view = viewBinding.root) {
|
||||
override fun bind(
|
||||
model: FundCardWidget,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int,
|
||||
totalItems: Int
|
||||
) {
|
||||
if(itemView is FundCardWidgetLayout) {
|
||||
itemView.update(model, viewBinding as LayoutFundCardSectionBinding, widgetCallback, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindError(errorData: Any?) {
|
||||
}
|
||||
|
||||
override fun bindWidgetStateChanged(payload: Any?) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.navi.naviwidgets.viewholder.amc
|
||||
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutFundOptionsHorizontalListBinding
|
||||
import com.navi.naviwidgets.models.response.amc.FundOptionsHorizontalListWidget
|
||||
import com.navi.naviwidgets.viewholder.BaseViewHolder
|
||||
import com.navi.naviwidgets.widgets.amc.FundOptionsHorizontalListLayout
|
||||
|
||||
class FundOptionsHorizontalListVH(private val viewBinding: ViewDataBinding)
|
||||
: BaseViewHolder<FundOptionsHorizontalListWidget>(view = viewBinding.root) {
|
||||
override fun bind(
|
||||
model: FundOptionsHorizontalListWidget,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int,
|
||||
totalItems: Int
|
||||
) {
|
||||
if(itemView is FundOptionsHorizontalListLayout) {
|
||||
itemView.update(model, viewBinding as LayoutFundOptionsHorizontalListBinding, widgetCallback, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindError(errorData: Any?) {
|
||||
}
|
||||
|
||||
override fun bindWidgetStateChanged(payload: Any?) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.navi.naviwidgets.viewholder.amc
|
||||
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutListOverlappingHeaderBinding
|
||||
import com.navi.naviwidgets.models.response.amc.ListOverlappingHeaderWidget
|
||||
import com.navi.naviwidgets.viewholder.BaseViewHolder
|
||||
import com.navi.naviwidgets.widgets.amc.ListOverlappingHeaderLayout
|
||||
|
||||
class ListOverlappingHeaderVH(
|
||||
private val viewBinding: ViewDataBinding
|
||||
): BaseViewHolder<ListOverlappingHeaderWidget>(view = viewBinding.root) {
|
||||
override fun bind(
|
||||
model: ListOverlappingHeaderWidget,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int,
|
||||
totalItems: Int
|
||||
) {
|
||||
if(itemView is ListOverlappingHeaderLayout) {
|
||||
itemView.update(model, viewBinding as LayoutListOverlappingHeaderBinding, widgetCallback, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindError(errorData: Any?) {
|
||||
}
|
||||
|
||||
override fun bindWidgetStateChanged(payload: Any?) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.navi.naviwidgets.viewholder.amc
|
||||
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutRewardsDetailWidgetBinding
|
||||
import com.navi.naviwidgets.models.response.amc.RewardsDetailWidget
|
||||
import com.navi.naviwidgets.viewholder.BaseViewHolder
|
||||
import com.navi.naviwidgets.widgets.amc.RewardsDetailWidgetLayout
|
||||
|
||||
class RewardsDetailWidgetVH(
|
||||
private val viewBinding: ViewDataBinding
|
||||
): BaseViewHolder<RewardsDetailWidget>(view = viewBinding.root) {
|
||||
override fun bind(
|
||||
model: RewardsDetailWidget,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int,
|
||||
totalItems: Int
|
||||
) {
|
||||
if(itemView is RewardsDetailWidgetLayout) {
|
||||
itemView.update(model, viewBinding as LayoutRewardsDetailWidgetBinding, widgetCallback, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindError(errorData: Any?) {
|
||||
}
|
||||
|
||||
override fun bindWidgetStateChanged(payload: Any?) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.navi.naviwidgets.viewholder.amc
|
||||
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutTopProductHorizontalListBinding
|
||||
import com.navi.naviwidgets.models.response.amc.TopProductHorizontalListWidget
|
||||
import com.navi.naviwidgets.viewholder.BaseViewHolder
|
||||
import com.navi.naviwidgets.widgets.amc.TopProductHorizontalListLayout
|
||||
|
||||
class TopProductHorizontalListVH(private val viewBinding: ViewDataBinding):
|
||||
BaseViewHolder<TopProductHorizontalListWidget>(view = viewBinding.root) {
|
||||
override fun bind(
|
||||
model: TopProductHorizontalListWidget,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int,
|
||||
totalItems: Int
|
||||
) {
|
||||
if(itemView is TopProductHorizontalListLayout) {
|
||||
itemView.update(model, viewBinding as LayoutTopProductHorizontalListBinding, widgetCallback, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindError(errorData: Any?) {
|
||||
}
|
||||
|
||||
override fun bindWidgetStateChanged(payload: Any?) {
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@ import android.view.LayoutInflater
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
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.ButtonViewBinding
|
||||
@@ -22,9 +25,13 @@ class ButtonViewLayout(context: Context, attributeSet: AttributeSet) :
|
||||
binding = DataBindingUtil.inflate(infater, R.layout.button_view, this, true)
|
||||
}
|
||||
|
||||
fun setProperties(actionData: ActionData?, widgetCallback: WidgetCallback?=null) {
|
||||
binding.title.text = actionData?.title
|
||||
binding.title.setTextColor(Color.parseColor(actionData?.titleColor))
|
||||
fun setProperties(actionData: ActionData?, widgetCallback: WidgetCallback?=null, title: TextWithStyle? = null) {
|
||||
if(title != null) {
|
||||
binding.title.setSpannableString(title)
|
||||
} else {
|
||||
binding.title.text = actionData?.title
|
||||
binding.title.setTextColor(Color.parseColor(actionData?.titleColor))
|
||||
}
|
||||
post {
|
||||
val radius = binding.rootLayout.height / 2.0
|
||||
binding.rootLayout.setCornerRadius(radius)
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.google.gson.JsonElement
|
||||
import com.navi.naviwidgets.models.*
|
||||
import com.navi.naviwidgets.models.ActionButtonWidget
|
||||
import com.navi.naviwidgets.models.response.*
|
||||
import com.navi.naviwidgets.models.response.amc.*
|
||||
import com.navi.naviwidgets.models.response.dashboard.*
|
||||
import com.navi.naviwidgets.models.response.esign.ApplicantESignWidgetModel
|
||||
import com.navi.naviwidgets.widgets.bottomsheetselector.LabeledOptionSelectorListWidgetModel
|
||||
@@ -218,6 +219,11 @@ class NaviWidgetJsonDeserializer : JsonDeserializer<NaviWidget> {
|
||||
IconTitleWithConsentWidget.WIDGET_NAME -> IconTitleWithConsentWidget::class.java
|
||||
AutopayStepsWidgetModel.WIDGET_NAME -> AutopayStepsWidgetModel::class.java
|
||||
TitleEndIconWithGradientWidget.WIDGET_NAME -> TitleEndIconWithGradientWidget::class.java
|
||||
FundCardWidget.WIDGET_NAME -> FundCardWidget::class.java
|
||||
FundOptionsHorizontalListWidget.WIDGET_NAME -> FundOptionsHorizontalListWidget::class.java
|
||||
ListOverlappingHeaderWidget.WIDGET_NAME -> ListOverlappingHeaderWidget::class.java
|
||||
TopProductHorizontalListWidget.WIDGET_NAME -> TopProductHorizontalListWidget::class.java
|
||||
RewardsDetailWidget.WIDGET_NAME -> RewardsDetailWidget::class.java
|
||||
else -> null
|
||||
}
|
||||
return if (className != null) {
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
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.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(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), LifecycleObserver {
|
||||
|
||||
private lateinit var binding: LayoutFundCardSectionBinding
|
||||
private lateinit var widgetCallback: WidgetCallback
|
||||
private var widgetPosition: Int = Int.MAX_VALUE
|
||||
private lateinit var widgetData: FundCardWidget
|
||||
private var lifecycle: Lifecycle? = null
|
||||
|
||||
fun update(
|
||||
widgetData: FundCardWidget,
|
||||
binding: LayoutFundCardSectionBinding,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int
|
||||
) {
|
||||
this.widgetData = widgetData
|
||||
this.binding = binding
|
||||
this.widgetCallback = widgetCallback
|
||||
this.widgetPosition = position
|
||||
this.lifecycle = widgetCallback.getLifeCycle()
|
||||
lifecycle?.addObserver(this)
|
||||
setProperties()
|
||||
}
|
||||
|
||||
private fun setProperties() {
|
||||
binding.apply {
|
||||
titleTv.setSpannableString(widgetData.widgetData?.header?.title)
|
||||
subtitleTv.setSpannableString(widgetData.widgetData?.header?.subTitle)
|
||||
iconIv.showWhenDataIsAvailable(widgetData.widgetData?.header?.iconCode)
|
||||
|
||||
widgetData.widgetData?.items?.let { list ->
|
||||
fundCardList.apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = FundCardAdapter(list, widgetCallback)
|
||||
}
|
||||
} ?: run {
|
||||
fundCardList.visibility = View.GONE
|
||||
}
|
||||
|
||||
widgetData.widgetData?.gradient?.let {
|
||||
root.setGradient(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.navi.naviwidgets.widgets.amc
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
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.LayoutFundOptionsHorizontalListBinding
|
||||
import com.navi.naviwidgets.databinding.TitleWithImageIconBinding
|
||||
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
|
||||
import com.navi.naviwidgets.models.response.amc.FundOptionsHorizontalListWidget
|
||||
|
||||
class FundOptionsHorizontalListLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), LifecycleObserver {
|
||||
|
||||
private lateinit var binding: LayoutFundOptionsHorizontalListBinding
|
||||
private lateinit var widgetCallback: WidgetCallback
|
||||
private var widgetPosition: Int = Int.MAX_VALUE
|
||||
private lateinit var widgetData: FundOptionsHorizontalListWidget
|
||||
private var lifecycle: Lifecycle? = null
|
||||
val inflater = LayoutInflater.from(context)
|
||||
|
||||
fun update(
|
||||
widgetData: FundOptionsHorizontalListWidget,
|
||||
binding: LayoutFundOptionsHorizontalListBinding,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int
|
||||
) {
|
||||
this.widgetData = widgetData
|
||||
this.binding = binding
|
||||
this.widgetCallback = widgetCallback
|
||||
this.widgetPosition = position
|
||||
this.lifecycle = widgetCallback.getLifeCycle()
|
||||
lifecycle?.addObserver(this)
|
||||
setProperties()
|
||||
}
|
||||
|
||||
private fun setProperties() {
|
||||
binding.apply {
|
||||
items.removeAllViews()
|
||||
root.setBackgroundColor(widgetData.widgetData?.bgColor.parseColorSafe())
|
||||
title.setSpannableString(widgetData.widgetData?.title)
|
||||
widgetData.widgetData?.items?.forEach { item ->
|
||||
val childBinding =
|
||||
DataBindingUtil.inflate<TitleWithImageIconBinding>(
|
||||
inflater,
|
||||
R.layout.title_with_image_icon,
|
||||
binding.container,
|
||||
false
|
||||
)
|
||||
childBinding.icon.showWhenDataIsAvailable(item.iconCode)
|
||||
childBinding.title.setSpannableString(item.title)
|
||||
childBinding.root.setOnClickListener {
|
||||
item.action?.let {
|
||||
widgetCallback.onClick(it)
|
||||
}
|
||||
}
|
||||
items.addView(childBinding.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.navi.naviwidgets.widgets.amc
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import com.navi.design.utils.setSpannableString
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutListOverlappingHeaderBinding
|
||||
import com.navi.naviwidgets.extensions.setGradient
|
||||
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
|
||||
import com.navi.naviwidgets.models.response.amc.ListOverlappingHeaderWidget
|
||||
|
||||
class ListOverlappingHeaderLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), LifecycleObserver {
|
||||
|
||||
private lateinit var binding: LayoutListOverlappingHeaderBinding
|
||||
private lateinit var widgetCallback: WidgetCallback
|
||||
private var widgetPosition: Int = Int.MAX_VALUE
|
||||
private lateinit var widgetData: ListOverlappingHeaderWidget
|
||||
private var lifecycle: Lifecycle? = null
|
||||
|
||||
fun update(
|
||||
widgetData: ListOverlappingHeaderWidget,
|
||||
binding: LayoutListOverlappingHeaderBinding,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int
|
||||
) {
|
||||
this.widgetData = widgetData
|
||||
this.binding = binding
|
||||
this.widgetCallback = widgetCallback
|
||||
this.widgetPosition = position
|
||||
this.lifecycle = widgetCallback.getLifeCycle()
|
||||
lifecycle?.addObserver(this)
|
||||
setProperties()
|
||||
}
|
||||
|
||||
private fun setProperties() {
|
||||
binding.apply {
|
||||
icon.showWhenDataIsAvailable(widgetData.widgetData?.iconCode)
|
||||
title.setSpannableString(widgetData.widgetData?.title)
|
||||
subtitle.setSpannableString(widgetData.widgetData?.subTitle)
|
||||
widgetData.widgetData?.gradient?.let { gradient ->
|
||||
root.setGradient(gradient)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.navi.naviwidgets.widgets.amc
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
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.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutRewardsDetailWidgetBinding
|
||||
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
|
||||
import com.navi.naviwidgets.models.response.amc.RewardsDetailWidget
|
||||
|
||||
class RewardsDetailWidgetLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), LifecycleObserver {
|
||||
|
||||
private lateinit var binding: LayoutRewardsDetailWidgetBinding
|
||||
private lateinit var widgetCallback: WidgetCallback
|
||||
private var widgetPosition: Int = Int.MAX_VALUE
|
||||
private lateinit var widgetData: RewardsDetailWidget
|
||||
private var lifecycle: Lifecycle? = null
|
||||
|
||||
fun update(
|
||||
widgetData: RewardsDetailWidget,
|
||||
binding: LayoutRewardsDetailWidgetBinding,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int
|
||||
) {
|
||||
this.widgetData = widgetData
|
||||
this.binding = binding
|
||||
this.widgetCallback = widgetCallback
|
||||
this.widgetPosition = position
|
||||
this.lifecycle = widgetCallback.getLifeCycle()
|
||||
lifecycle?.addObserver(this)
|
||||
setProperties()
|
||||
}
|
||||
|
||||
private fun setProperties() {
|
||||
binding.apply {
|
||||
title.setSpannableString(widgetData.widgetData?.title)
|
||||
icon.showWhenDataIsAvailable(widgetData.widgetData?.icon)
|
||||
label.setSpannableString(widgetData.widgetData?.label?.title)
|
||||
label.background = getNaviDrawable(
|
||||
radii = com.navi.design.utils.CornerRadius(
|
||||
leftBottom = dpToPx(8)
|
||||
), backgroundColor = widgetData.widgetData?.label?.bgColor.parseColorSafe()
|
||||
)
|
||||
root.setBackgroundColor(widgetData.widgetData?.bgColor.parseColorSafe())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.navi.naviwidgets.widgets.amc
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.LinearLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import com.navi.design.utils.*
|
||||
import com.navi.naviwidgets.R
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutTopProductHorizontalListBinding
|
||||
import com.navi.naviwidgets.databinding.TopProductHorizontalListItemBinding
|
||||
import com.navi.naviwidgets.extensions.setGradient
|
||||
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
|
||||
import com.navi.naviwidgets.models.response.amc.TopProductHorizontalListWidget
|
||||
import com.navi.naviwidgets.models.response.amc.TopProductItem
|
||||
|
||||
class TopProductHorizontalListLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), LifecycleObserver {
|
||||
|
||||
private lateinit var binding: LayoutTopProductHorizontalListBinding
|
||||
private lateinit var widgetCallback: WidgetCallback
|
||||
private var widgetPosition: Int = Int.MAX_VALUE
|
||||
private lateinit var widgetData: TopProductHorizontalListWidget
|
||||
private var lifecycle: Lifecycle? = null
|
||||
private val inflater = LayoutInflater.from(context)
|
||||
|
||||
fun update(
|
||||
widgetData: TopProductHorizontalListWidget,
|
||||
binding: LayoutTopProductHorizontalListBinding,
|
||||
widgetCallback: WidgetCallback,
|
||||
position: Int
|
||||
) {
|
||||
this.widgetData = widgetData
|
||||
this.binding = binding
|
||||
this.widgetCallback = widgetCallback
|
||||
this.widgetPosition = position
|
||||
this.lifecycle = widgetCallback.getLifeCycle()
|
||||
lifecycle?.addObserver(this)
|
||||
setProperties()
|
||||
}
|
||||
|
||||
private fun setProperties() {
|
||||
binding.apply {
|
||||
widgetData.widgetData?.items?.forEachIndexed { index, topProductItem ->
|
||||
bindItem(topProductItem, index, widgetData.widgetData?.items?.size ?: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindItem(item: TopProductItem, position: Int, totalItems: Int) {
|
||||
val view = inflater.inflate(R.layout.top_product_horizontal_list_item, binding.itemContainer, false)
|
||||
val itemBinding: TopProductHorizontalListItemBinding = DataBindingUtil.bind(view)!!
|
||||
itemBinding.productTitle.setSpannableString(item.title)
|
||||
itemBinding.productSubtitle.setSpannableString(item.subTitle)
|
||||
item.imageDetails?.let { imageDetails ->
|
||||
imageDetails.height?.let {
|
||||
itemBinding.productImage.layoutParams.height = dpToPxInInt(it)
|
||||
}
|
||||
imageDetails.width?.let {
|
||||
itemBinding.productImage.layoutParams.width = dpToPxInInt(it)
|
||||
}
|
||||
itemBinding.productImage.requestLayout()
|
||||
imageDetails.iconCode?.let {
|
||||
itemBinding.productImage.showWhenDataIsAvailable(it)
|
||||
}
|
||||
} ?: kotlin.run {
|
||||
itemBinding.productImage.showWhenDataIsAvailable(item.iconCode)
|
||||
}
|
||||
item.gradient?.let {
|
||||
itemBinding.productCard.setGradient(it)
|
||||
}
|
||||
itemBinding.productLabel.apply {
|
||||
background = getNaviDrawable(
|
||||
radii = CornerRadius(
|
||||
0f,
|
||||
0f,
|
||||
dpToPx(4),
|
||||
dpToPx(4)
|
||||
),
|
||||
backgroundColor = item.label?.bgColor.parseColorSafe()
|
||||
)
|
||||
setSpannableString(item.label?.title)
|
||||
}
|
||||
itemBinding.productStrategyTv.setSpannableString(item.footerTitle)
|
||||
itemBinding.productStrategyIv.showWhenDataIsAvailable(item.footerIconCode)
|
||||
itemBinding.productStrategyContainer.setBackgroundColor(item.footerBgColor.parseColorSafe())
|
||||
itemBinding.productLottie.showWhenDataIsAvailable(item.lottieFileName)
|
||||
|
||||
itemBinding.actionBtn.setProperties(item.actionData, widgetCallback, item.actionTitle)
|
||||
|
||||
if (totalItems == 1) {
|
||||
val layoutParams = LinearLayout.LayoutParams(
|
||||
deviceWidth() - resources.getDimension(R.dimen.dp_32).toInt(),
|
||||
resources.getDimension(R.dimen.dp_274).toInt()
|
||||
)
|
||||
layoutParams.rightMargin = dpToPx(16).toInt()
|
||||
layoutParams.leftMargin = dpToPx(16).toInt()
|
||||
layoutParams.bottomMargin = dpToPx(16).toInt()
|
||||
itemBinding.widgetContainer.layoutParams = layoutParams
|
||||
} else if (position == totalItems - 1) {
|
||||
val layoutParams = LinearLayout.LayoutParams(
|
||||
(deviceWidth() * 0.86).toInt(),
|
||||
resources.getDimension(R.dimen.dp_274).toInt()
|
||||
)
|
||||
layoutParams.rightMargin = dpToPx(16).toInt()
|
||||
layoutParams.leftMargin = dpToPx(16).toInt()
|
||||
layoutParams.bottomMargin = dpToPx(16).toInt()
|
||||
itemBinding.widgetContainer.layoutParams = layoutParams
|
||||
} else {
|
||||
val layoutParams = LinearLayout.LayoutParams(
|
||||
(deviceWidth() * 0.86).toInt(),
|
||||
resources.getDimension(R.dimen.dp_274).toInt()
|
||||
)
|
||||
layoutParams.leftMargin = dpToPx(16).toInt()
|
||||
layoutParams.bottomMargin = dpToPx(16).toInt()
|
||||
itemBinding.widgetContainer.layoutParams = layoutParams
|
||||
}
|
||||
itemBinding.root.setOnClickListener {
|
||||
item.actionData?.let { actionData ->
|
||||
widgetCallback.onClick(actionData)
|
||||
}
|
||||
}
|
||||
binding.itemContainer.addView(view)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size
|
||||
android:height="@dimen/dp_0"
|
||||
android:width="@dimen/dp_24"/>
|
||||
</shape>
|
||||
10
navi-widgets/src/main/res/drawable/ic_chevron_v3.xml
Normal file
10
navi-widgets/src/main/res/drawable/ic_chevron_v3.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M5.529,3.529C5.789,3.268 6.211,3.268 6.471,3.529L10.471,7.529C10.732,7.789 10.732,8.211 10.471,8.471L6.471,12.471C6.211,12.732 5.789,12.732 5.529,12.471C5.268,12.211 5.268,11.789 5.529,11.529L9.057,8L5.529,4.471C5.268,4.211 5.268,3.789 5.529,3.529Z"
|
||||
android:fillColor="#FF5732"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
9
navi-widgets/src/main/res/drawable/ic_chevrons_v2.xml
Normal file
9
navi-widgets/src/main/res/drawable/ic_chevrons_v2.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16.465,12.019C16.465,12.368 16.316,12.667 16.066,12.867L10.529,17.806C10.13,18.105 9.531,18.055 9.232,17.656C8.932,17.257 8.932,16.708 9.331,16.409L14.22,12.118C14.27,12.068 14.27,12.019 14.22,11.919L9.331,7.628C8.932,7.279 8.882,6.73 9.232,6.331C9.581,5.932 10.13,5.882 10.529,6.232C10.529,6.232 10.529,6.232 10.579,6.281L16.116,11.17C16.316,11.37 16.465,11.719 16.465,12.019Z"
|
||||
android:fillColor="#FF5732"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/title_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="start"
|
||||
tools:text="Expense ratio" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/title_icon"
|
||||
android:layout_width="@dimen/dp_16"
|
||||
android:layout_height="@dimen/dp_16"
|
||||
android:layout_marginStart="@dimen/dp_4"
|
||||
android:layout_gravity="bottom"
|
||||
tools:src="@drawable/arrow_forward_black" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/dp_24"
|
||||
android:layout_height="@dimen/dp_24"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:src="@drawable/arrow_forward_black" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_2"
|
||||
android:gravity="start"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title_container"
|
||||
tools:text="0.50%" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
110
navi-widgets/src/main/res/layout/layout_fund_card.xml
Normal file
110
navi-widgets/src/main/res/layout/layout_fund_card.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?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/fund_title"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_24"
|
||||
app:layout_constraintBottom_toTopOf="@id/fund_size"
|
||||
app:layout_constraintEnd_toStartOf="@id/icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Nifty India Manufacturing Index Fund" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/dp_24"
|
||||
android:layout_height="@dimen/dp_24"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
app:layout_constraintBottom_toBottomOf="@id/fund_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/fund_title"
|
||||
tools:src="@drawable/arrow_forward_black" />
|
||||
|
||||
<include
|
||||
android:id="@+id/fund_size"
|
||||
layout="@layout/item_title_subtitle_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_16"
|
||||
app:layout_constraintBottom_toTopOf="@id/product_strategy_container"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<include
|
||||
android:id="@+id/returns"
|
||||
layout="@layout/item_title_subtitle_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/dp_16"
|
||||
app:layout_constraintBottom_toTopOf="@id/product_strategy_container"
|
||||
app:layout_constraintEnd_toStartOf="@id/cta"
|
||||
app:layout_constraintStart_toEndOf="@id/fund_size" />
|
||||
|
||||
<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_constraintBottom_toTopOf="@id/product_strategy_container"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/product_strategy_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_32"
|
||||
android:layout_marginHorizontal="@dimen/dp_1"
|
||||
android:layout_marginBottom="@dimen/dp_1"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/product_strategy_iv"
|
||||
android:layout_width="@dimen/dp_16"
|
||||
android:layout_height="@dimen/dp_16"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/dp_16" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/product_strategy_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/dp_8"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
tools:text="20k+ investors have invested in this fund" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</layout>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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">
|
||||
|
||||
<com.navi.naviwidgets.widgets.amc.FundCardWidgetLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon_iv"
|
||||
android:layout_width="@dimen/dp_24"
|
||||
android:layout_height="@dimen/dp_24"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:src="@drawable/ic_new_launch_svg"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_8"
|
||||
app:layout_constraintStart_toEndOf="@id/icon_iv"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Highest returns" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/subtitle_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_4"
|
||||
android:layout_marginBottom="@dimen/dp_20"
|
||||
app:layout_constraintStart_toStartOf="@id/title_tv"
|
||||
app:layout_constraintTop_toBottomOf="@id/title_tv"
|
||||
app:layout_constraintBottom_toTopOf="@id/fund_card_list"
|
||||
tools:text="Start investing with ₹10" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/fund_card_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
</com.navi.naviwidgets.widgets.amc.FundCardWidgetLayout>
|
||||
|
||||
</layout>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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">
|
||||
|
||||
<com.navi.naviwidgets.widgets.amc.FundOptionsHorizontalListLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/dp_16"
|
||||
android:paddingBottom="@dimen/dp_24">
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Looking for specific funds?"/>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_24"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="@dimen/dp_16"
|
||||
android:paddingEnd="@dimen/dp_16"
|
||||
android:scrollbars="none"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/items"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@drawable/divider_horizontal_24"
|
||||
android:orientation="horizontal"
|
||||
android:showDividers="middle" />
|
||||
</HorizontalScrollView>
|
||||
</com.navi.naviwidgets.widgets.amc.FundOptionsHorizontalListLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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">
|
||||
|
||||
<com.navi.naviwidgets.widgets.amc.ListOverlappingHeaderLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/dp_88">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/dp_56"
|
||||
android:layout_height="@dimen/dp_56"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_36"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_32"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Low cost Index Funds" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
tools:text="Funds that mimic financial market indices
|
||||
like Nifty 50 Index subject to tracking error" />
|
||||
</com.navi.naviwidgets.widgets.amc.ListOverlappingHeaderLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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">
|
||||
|
||||
<com.navi.naviwidgets.widgets.amc.RewardsDetailWidgetLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_16"
|
||||
android:lineSpacingExtra="@dimen/dp_4"
|
||||
app:layout_constraintBottom_toTopOf="@id/divider"
|
||||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Win instant ₹100 cashback\non completing KYC" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/dp_8"
|
||||
android:paddingTop="@dimen/dp_2"
|
||||
android:paddingEnd="@dimen/dp_8"
|
||||
android:paddingBottom="@dimen/dp_2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="2 days left" />
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_4"
|
||||
android:background="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</com.navi.naviwidgets.widgets.amc.RewardsDetailWidgetLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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">
|
||||
|
||||
<com.navi.naviwidgets.widgets.amc.TopProductHorizontalListLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_32"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/item_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal" />
|
||||
</HorizontalScrollView>
|
||||
</com.navi.naviwidgets.widgets.amc.TopProductHorizontalListLayout>
|
||||
</layout>
|
||||
29
navi-widgets/src/main/res/layout/title_with_image_icon.xml
Normal file
29
navi-widgets/src/main/res/layout/title_with_image_icon.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?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.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/dp_56"
|
||||
android:layout_height="@dimen/dp_56"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:gravity="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/icon"
|
||||
tools:text="Index" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,127 @@
|
||||
<?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/widget_container"
|
||||
android:layout_width="@dimen/dp_311"
|
||||
android:layout_height="@dimen/dp_274"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:outlineSpotShadowColor="@color/outlineSpotShadowColor"
|
||||
app:cardCornerRadius="@dimen/dp_8"
|
||||
app:cardElevation="@dimen/dp_8">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/product_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/product_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/black"
|
||||
android:textColor="@color/white"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:paddingHorizontal="@dimen/dp_10"
|
||||
android:paddingVertical="@dimen/dp_4"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Our recommendation" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/product_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_32"
|
||||
android:layout_marginTop="@dimen/dp_72"
|
||||
android:gravity="center_vertical"
|
||||
android:lineSpacingExtra="@dimen/dp_4"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="US Total Stock Market Fund of Fund" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/product_subtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintStart_toStartOf="@id/product_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/product_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/product_title"
|
||||
tools:text="Invest in India’s 50 largest companies" />
|
||||
|
||||
<com.navi.naviwidgets.views.ButtonViewLayout
|
||||
android:id="@+id/action_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_32"
|
||||
android:layout_marginBottom="@dimen/dp_16"
|
||||
app:layout_constraintBottom_toTopOf="@id/product_strategy_container"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/product_subtitle"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/product_image"
|
||||
android:layout_width="@dimen/dp_100"
|
||||
android:layout_height="@dimen/dp_82"
|
||||
app:layout_constraintBottom_toTopOf="@id/divider"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/product_lottie"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_loop="true" />
|
||||
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_2"
|
||||
android:background="@color/white"
|
||||
app:layout_constraintBottom_toTopOf="@+id/product_strategy_container"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/product_strategy_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_40"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/product_strategy_iv"
|
||||
android:layout_width="@dimen/dp_16"
|
||||
android:layout_height="@dimen/dp_16"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/dp_16" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/product_strategy_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/dp_8"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="20k+ investors have invested in this fund" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</layout>
|
||||
1
navi-widgets/src/main/res/raw/confetti_from_above.json
Normal file
1
navi-widgets/src/main/res/raw/confetti_from_above.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user