diff --git a/app/build.gradle b/app/build.gradle index 2af7f8df9b..c731f85b65 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-kapt' apply plugin: 'com.google.firebase.appdistribution' apply plugin: "com.github.triplet.play" @@ -156,6 +156,12 @@ android { packagingOptions { resources.excludes.add("META-INF/versions/9/previous-compilation-data.bin") resources.excludes.add("META-INF/DEPENDENCIES") + resources.excludes.add("META-INF/NOTICE.md") + } + + + buildFeatures { + viewBinding true } } @@ -262,6 +268,7 @@ dependencies { implementation biometricDep + implementation androidDep implementation constraintDep diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/BackDelayedNavigation.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/BackDelayedNavigation.kt index cd3e9f10e1..0c2686d734 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/BackDelayedNavigation.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/BackDelayedNavigation.kt @@ -1,7 +1,7 @@ package io.novafoundation.nova.app.root.navigation.delayedNavigation import io.novafoundation.nova.common.navigation.DelayedNavigation -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize @Parcelize object BackDelayedNavigation : DelayedNavigation diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/NavComponentDelayedNavigation.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/NavComponentDelayedNavigation.kt index 55871c35eb..5eedeb62b3 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/NavComponentDelayedNavigation.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/delayedNavigation/NavComponentDelayedNavigation.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.app.root.navigation.delayedNavigation import android.os.Bundle import io.novafoundation.nova.common.navigation.DelayedNavigation -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize @Parcelize class NavComponentDelayedNavigation(val globalActionId: Int, val extras: Bundle? = null) : DelayedNavigation diff --git a/app/src/main/java/io/novafoundation/nova/app/root/presentation/RootActivity.kt b/app/src/main/java/io/novafoundation/nova/app/root/presentation/RootActivity.kt index 8b54a4de3f..279367c2e7 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/presentation/RootActivity.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/presentation/RootActivity.kt @@ -2,9 +2,12 @@ package io.novafoundation.nova.app.root.presentation import android.content.Intent import android.os.Bundle +import android.view.LayoutInflater import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment + import io.novafoundation.nova.app.R +import io.novafoundation.nova.app.databinding.ActivityRootBinding import io.novafoundation.nova.app.root.di.RootApi import io.novafoundation.nova.app.root.di.RootComponent import io.novafoundation.nova.app.root.navigation.holders.RootNavigationHolder @@ -18,10 +21,10 @@ import io.novafoundation.nova.common.utils.systemCall.SystemCallExecutor import io.novafoundation.nova.common.utils.updatePadding import io.novafoundation.nova.common.view.bottomSheet.action.observeActionBottomSheet import io.novafoundation.nova.splash.presentation.SplashBackgroundHolder -import kotlinx.android.synthetic.main.activity_root.rootNetworkBar + import javax.inject.Inject -class RootActivity : BaseActivity(), SplashBackgroundHolder { +class RootActivity : BaseActivity(), SplashBackgroundHolder { @Inject lateinit var rootNavigationHolder: RootNavigationHolder @@ -32,6 +35,10 @@ class RootActivity : BaseActivity(), SplashBackgroundHolder { @Inject lateinit var contextManager: ContextManager + override fun createBinding(): ActivityRootBinding { + return ActivityRootBinding.inflate(LayoutInflater.from(this)) + } + override fun inject() { FeatureUtils.getFeature(this, RootApi::class.java) .mainActivityComponentFactory() @@ -59,7 +66,7 @@ class RootActivity : BaseActivity(), SplashBackgroundHolder { contextManager.attachActivity(this) - rootNetworkBar.setOnApplyWindowInsetsListener { view, insets -> + binder.rootNetworkBar.setOnApplyWindowInsetsListener { view, insets -> view.updatePadding(top = insets.systemWindowInsetTop) insets @@ -78,10 +85,6 @@ class RootActivity : BaseActivity(), SplashBackgroundHolder { rootNavigationHolder.detach() } - override fun layoutResource(): Int { - return R.layout.activity_root - } - override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) @@ -107,7 +110,7 @@ class RootActivity : BaseActivity(), SplashBackgroundHolder { observeActionBottomSheet(viewModel) viewModel.showConnectingBarLiveData.observe(this) { show -> - rootNetworkBar.setVisible(show) + binder.rootNetworkBar.setVisible(show) } viewModel.messageLiveData.observe( diff --git a/app/src/main/java/io/novafoundation/nova/app/root/presentation/main/MainFragment.kt b/app/src/main/java/io/novafoundation/nova/app/root/presentation/main/MainFragment.kt index 9eecc413db..eda9cfc885 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/presentation/main/MainFragment.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/presentation/main/MainFragment.kt @@ -1,16 +1,14 @@ package io.novafoundation.nova.app.root.presentation.main import android.graphics.RectF -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup import androidx.activity.OnBackPressedCallback import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.setupWithNavController + import io.novafoundation.nova.app.R +import io.novafoundation.nova.app.databinding.FragmentMainBinding import io.novafoundation.nova.app.root.di.RootApi import io.novafoundation.nova.app.root.di.RootComponent import io.novafoundation.nova.app.root.navigation.navigators.staking.StakingDashboardNavigator @@ -19,11 +17,12 @@ import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.utils.blur.SweetBlur import io.novafoundation.nova.common.utils.setBackgroundColorRes import io.novafoundation.nova.common.utils.updatePadding -import kotlinx.android.synthetic.main.fragment_main.bottomNavHost -import kotlinx.android.synthetic.main.fragment_main.bottomNavigationView + import javax.inject.Inject -class MainFragment : BaseFragment() { +class MainFragment : BaseFragment() { + + override fun createBinding() = FragmentMainBinding.inflate(layoutInflater) @Inject lateinit var stakingDashboardNavigator: StakingDashboardNavigator @@ -36,10 +35,6 @@ class MainFragment : BaseFragment() { } } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_main, container, false) - } - override fun onDestroyView() { super.onDestroyView() @@ -48,17 +43,17 @@ class MainFragment : BaseFragment() { } override fun initViews() { - bottomNavigationView.setOnApplyWindowInsetsListener { _, insets -> + binder.bottomNavigationView.setOnApplyWindowInsetsListener { _, insets -> // overwrite BottomNavigation behavior and ignore insets insets } - bottomNavHost.setOnApplyWindowInsetsListener { v, insets -> + binder.bottomNavHost.setOnApplyWindowInsetsListener { v, insets -> val systemWindowInsetBottom = insets.systemWindowInsetBottom // post to prevent bottomNavigationView.height being 0 if callback is called before view has been measured v.post { - val padding = (systemWindowInsetBottom - bottomNavigationView.height).coerceAtLeast(0) + val padding = (systemWindowInsetBottom - binder.bottomNavigationView.height).coerceAtLeast(0) v.updatePadding(bottom = padding) } @@ -70,8 +65,8 @@ class MainFragment : BaseFragment() { navController = nestedNavHostFragment.navController stakingDashboardNavigator.setStakingTabNavController(navController!!) - bottomNavigationView.setupWithNavController(navController!!) - bottomNavigationView.itemIconTintList = null + binder.bottomNavigationView.setupWithNavController(navController!!) + binder.bottomNavigationView.itemIconTintList = null requireActivity().onBackPressedDispatcher.addCallback(backCallback) @@ -102,9 +97,9 @@ class MainFragment : BaseFragment() { .captureExtraSpace(RectF(0f, offset, 0f, 0f)) .cutSpace(RectF(0f, offset, 0f, offset)) .radius(radiusInPx) - .captureFrom(bottomNavHost) - .toTarget(bottomNavigationView) - .catchException { bottomNavigationView.setBackgroundColorRes(R.color.solid_navigation_background) } + .captureFrom(binder.bottomNavHost) + .toTarget(binder.bottomNavigationView) + .catchException { binder.bottomNavigationView.setBackgroundColorRes(R.color.solid_navigation_background) } .build() // .start() } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/presentation/splitScreen/SplitScreenFragment.kt b/app/src/main/java/io/novafoundation/nova/app/root/presentation/splitScreen/SplitScreenFragment.kt index acd69c525a..42764aa12e 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/presentation/splitScreen/SplitScreenFragment.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/presentation/splitScreen/SplitScreenFragment.kt @@ -2,9 +2,7 @@ package io.novafoundation.nova.app.root.presentation.splitScreen import android.graphics.Rect import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup import androidx.core.graphics.Insets import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat @@ -14,6 +12,7 @@ import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import coil.ImageLoader import io.novafoundation.nova.app.R +import io.novafoundation.nova.app.databinding.FragmentSplitScreenBinding import io.novafoundation.nova.app.root.di.RootApi import io.novafoundation.nova.app.root.di.RootComponent import io.novafoundation.nova.app.root.navigation.holders.SplitScreenNavigationHolder @@ -27,13 +26,8 @@ import io.novafoundation.nova.common.utils.letOrHide import io.novafoundation.nova.common.utils.payloadOrElse import io.novafoundation.nova.feature_dapp_impl.presentation.tab.setupCloseAllDappTabsDialogue import javax.inject.Inject -import kotlinx.android.synthetic.main.fragment_split_screen.dappEntryPoint -import kotlinx.android.synthetic.main.fragment_split_screen.dappEntryPointClose -import kotlinx.android.synthetic.main.fragment_split_screen.dappEntryPointIcon -import kotlinx.android.synthetic.main.fragment_split_screen.dappEntryPointText -import kotlinx.android.synthetic.main.fragment_split_screen.mainNavHost -class SplitScreenFragment : BaseFragment() { +class SplitScreenFragment : BaseFragment() { companion object : PayloadCreator by FragmentPayloadCreator() @@ -49,9 +43,7 @@ class SplitScreenFragment : BaseFragment() { navHostFragment.navController } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_split_screen, container, false) - } + override fun createBinding() = FragmentSplitScreenBinding.inflate(layoutInflater) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -76,25 +68,25 @@ class SplitScreenFragment : BaseFragment() { override fun initViews() { val outlineMargin = Rect(0, (-12).dp, 0, 0) // To avoid round corners at top - mainNavHost.outlineProvider = RoundCornersOutlineProvider(12.dpF, margin = outlineMargin) + binder.mainNavHost.outlineProvider = RoundCornersOutlineProvider(12.dpF, margin = outlineMargin) - dappEntryPoint.setOnClickListener { viewModel.onTabsClicked() } - dappEntryPointClose.setOnClickListener { viewModel.onTabsCloseClicked() } + binder.dappEntryPoint.setOnClickListener { viewModel.onTabsClicked() } + binder.dappEntryPointClose.setOnClickListener { viewModel.onTabsCloseClicked() } } override fun subscribe(viewModel: SplitScreenViewModel) { setupCloseAllDappTabsDialogue(viewModel.closeAllTabsConfirmation) viewModel.dappTabsVisible.observe { shouldBeVisible -> - mainNavHost.clipToOutline = shouldBeVisible - dappEntryPoint.isVisible = shouldBeVisible + binder.mainNavHost.clipToOutline = shouldBeVisible + binder.dappEntryPoint.isVisible = shouldBeVisible } viewModel.tabsTitle.observe { model -> - dappEntryPointIcon.letOrHide(model.icon) { - dappEntryPointIcon.setIcon(it, imageLoader) + binder.dappEntryPointIcon.letOrHide(model.icon) { + binder.dappEntryPointIcon.setIcon(it, imageLoader) } - dappEntryPointText.text = model.title + binder.dappEntryPointText.text = model.title } manageImeInsets() } @@ -108,7 +100,7 @@ class SplitScreenFragment : BaseFragment() { var dappEntryPointHeight = 0 // Inset listener that provides a custom insets to its children - ViewCompat.setOnApplyWindowInsetsListener(mainNavHost) { _, insets -> + ViewCompat.setOnApplyWindowInsetsListener(binder.mainNavHost) { _, insets -> val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()) val changedImeInsets = Insets.of( @@ -125,13 +117,13 @@ class SplitScreenFragment : BaseFragment() { // Subscribe to get dAppEntryPoint height viewModel.dappTabsVisible.observe { - dappEntryPoint.post { - dappEntryPointHeight = if (dappEntryPoint.isVisible) { - dappEntryPoint.height + dappEntryPoint.marginTop + binder.dappEntryPoint.post { + dappEntryPointHeight = if (binder.dappEntryPoint.isVisible) { + binder.dappEntryPoint.height + binder.dappEntryPoint.marginTop } else { 0 } - ViewCompat.requestApplyInsets(mainNavHost) // Request new insets to trigger inset listener + ViewCompat.requestApplyInsets(binder.mainNavHost) // Request new insets to trigger inset listener } } } diff --git a/build.gradle b/build.gradle index 3b059030ce..240873db19 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { minSdkVersion = 24 targetSdkVersion = 34 - kotlinVersion = '1.7.21' + kotlinVersion = '1.9.22' ktlintPinterestVersion = '0.47.0' @@ -21,13 +21,13 @@ buildscript { cardViewVersion = '1.0.0' constraintVersion = '1.1.3' - coroutinesVersion = '1.6.3' + coroutinesVersion = '1.8.1' biometricVersion = '1.0.1' progressButtonsVersion = '2.1.0' - daggerVersion = '2.44.2' + daggerVersion = '2.52' javaxInjectVersion = '1' architectureComponentVersion = '2.2.0' @@ -79,7 +79,7 @@ buildscript { bleVersion = '2.5.1' - roomVersion = '2.4.3' + roomVersion = '2.6.1' markwonVersion = '4.6.2' @@ -123,6 +123,7 @@ buildscript { lifecycleDep = "androidx.lifecycle:lifecycle-extensions:$architectureComponentVersion" lifecycleKapt = "androidx.lifecycle:lifecycle-compiler:$architectureComponentVersion" + lifecycleRuntime = "androidx.lifecycle:lifecycle-runtime-android:$architectureComponentVersion" coroutinesDep = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" coroutinesAndroidDep = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion" diff --git a/common/build.gradle b/common/build.gradle index d1703b00c1..385fa065e3 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin-parcelize' android { compileSdkVersion rootProject.compileSdkVersion @@ -72,6 +72,10 @@ android { jvmTarget = '1.8' freeCompilerArgs = ["-Xcontext-receivers"] } + + buildFeatures { + viewBinding true + } } dependencies { @@ -83,6 +87,7 @@ dependencies { implementation kotlinDep + implementation androidDep implementation cardViewDep implementation recyclerViewDep @@ -147,4 +152,5 @@ dependencies { implementation kotlinReflect implementation playServicesAuthDep + } \ No newline at end of file diff --git a/common/src/main/java/io/novafoundation/nova/common/base/BaseActivity.kt b/common/src/main/java/io/novafoundation/nova/common/base/BaseActivity.kt index 3d37503494..68c256f65e 100644 --- a/common/src/main/java/io/novafoundation/nova/common/base/BaseActivity.kt +++ b/common/src/main/java/io/novafoundation/nova/common/base/BaseActivity.kt @@ -5,11 +5,12 @@ import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.LifecycleOwner +import androidx.viewbinding.ViewBinding import io.novafoundation.nova.common.di.FeatureContainer import io.novafoundation.nova.common.utils.showToast import javax.inject.Inject -abstract class BaseActivity : +abstract class BaseActivity : AppCompatActivity(), BaseScreenMixin { override val providedContext: Context @@ -18,9 +19,14 @@ abstract class BaseActivity : override val lifecycleOwner: LifecycleOwner get() = this + protected lateinit var binder: B + private set + @Inject override lateinit var viewModel: T + protected abstract fun createBinding(): B + override fun attachBaseContext(base: Context) { val commonApi = (base.applicationContext as FeatureContainer).commonApi() val contextManager = commonApi.contextManager() @@ -37,7 +43,9 @@ abstract class BaseActivity : or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ) - setContentView(layoutResource()) + binder = createBinding() + + setContentView(binder.root) inject() initViews() @@ -50,7 +58,5 @@ abstract class BaseActivity : viewModel.toastLiveData.observeEvent { showToast(it) } } - abstract fun layoutResource(): Int - abstract fun changeLanguage() } diff --git a/common/src/main/java/io/novafoundation/nova/common/base/BaseBottomSheetFragment.kt b/common/src/main/java/io/novafoundation/nova/common/base/BaseBottomSheetFragment.kt index 61f2ab490a..64a4ceed45 100644 --- a/common/src/main/java/io/novafoundation/nova/common/base/BaseBottomSheetFragment.kt +++ b/common/src/main/java/io/novafoundation/nova/common/base/BaseBottomSheetFragment.kt @@ -1,20 +1,34 @@ package io.novafoundation.nova.common.base import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.viewbinding.ViewBinding import com.google.android.material.bottomsheet.BottomSheetDialogFragment import javax.inject.Inject -abstract class BaseBottomSheetFragment : BottomSheetDialogFragment(), BaseFragmentMixin { +abstract class BaseBottomSheetFragment : BottomSheetDialogFragment(), BaseFragmentMixin { - @Inject override lateinit var viewModel: T + @Inject + override lateinit var viewModel: T + + protected lateinit var binder: B + private set override val fragment: Fragment get() = this private val delegate by lazy(LazyThreadSafetyMode.NONE) { BaseFragmentDelegate(this) } + protected abstract fun createBinding(): B + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binder = createBinding() + return binder.root + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/common/src/main/java/io/novafoundation/nova/common/base/BaseFragment.kt b/common/src/main/java/io/novafoundation/nova/common/base/BaseFragment.kt index ff1f4eb6fe..6ec92ad346 100644 --- a/common/src/main/java/io/novafoundation/nova/common/base/BaseFragment.kt +++ b/common/src/main/java/io/novafoundation/nova/common/base/BaseFragment.kt @@ -1,19 +1,33 @@ package io.novafoundation.nova.common.base import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.viewbinding.ViewBinding import javax.inject.Inject -abstract class BaseFragment : Fragment(), BaseFragmentMixin { +abstract class BaseFragment : Fragment(), BaseFragmentMixin { - @Inject override lateinit var viewModel: T + @Inject + override lateinit var viewModel: T + + protected lateinit var binder: B + private set override val fragment: Fragment get() = this private val delegate by lazy(LazyThreadSafetyMode.NONE) { BaseFragmentDelegate(this) } + protected abstract fun createBinding(): B + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binder = createBinding() + return binder.root + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/common/src/main/java/io/novafoundation/nova/common/list/BaseListAdapter.kt b/common/src/main/java/io/novafoundation/nova/common/list/BaseListAdapter.kt index 1fdcd12499..4ae331a0ef 100644 --- a/common/src/main/java/io/novafoundation/nova/common/list/BaseListAdapter.kt +++ b/common/src/main/java/io/novafoundation/nova/common/list/BaseListAdapter.kt @@ -15,5 +15,8 @@ abstract class BaseListAdapter(diffCallback: DiffUtil.It abstract class BaseViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer { - abstract fun unbind() + val context + get() = containerView.context + + open fun unbind() {} } diff --git a/common/src/main/java/io/novafoundation/nova/common/list/EditablePlaceholderAdapter.kt b/common/src/main/java/io/novafoundation/nova/common/list/EditablePlaceholderAdapter.kt index c0b8766f4b..18db5725d4 100644 --- a/common/src/main/java/io/novafoundation/nova/common/list/EditablePlaceholderAdapter.kt +++ b/common/src/main/java/io/novafoundation/nova/common/list/EditablePlaceholderAdapter.kt @@ -1,15 +1,12 @@ package io.novafoundation.nova.common.list -import android.view.View import android.view.View.OnClickListener import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ItemPlaceholderBinding import io.novafoundation.nova.common.utils.ViewSpace -import io.novafoundation.nova.common.utils.inflateChild +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.updatePadding import io.novafoundation.nova.common.view.PlaceholderModel -import kotlinx.android.synthetic.main.item_placeholder.view.itemPlaceholder class EditablePlaceholderAdapter : SingleItemAdapter() { @@ -18,7 +15,7 @@ class EditablePlaceholderAdapter : SingleItemAdapter() { private var clickListener: OnClickListener? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EditableStubHolder { - return EditableStubHolder(parent.inflateChild(R.layout.item_placeholder)) + return EditableStubHolder(ItemPlaceholderBinding.inflate(parent.inflater(), parent, false)) } override fun onBindViewHolder(holder: EditableStubHolder, position: Int) { @@ -47,11 +44,11 @@ class EditablePlaceholderAdapter : SingleItemAdapter() { } } -class EditableStubHolder(view: View) : RecyclerView.ViewHolder(view) { +class EditableStubHolder(private val binder: ItemPlaceholderBinding) : BaseViewHolder(binder.root) { fun bind(model: PlaceholderModel?, padding: ViewSpace?, clickListener: OnClickListener?) { - model?.let { itemView.itemPlaceholder.setModel(model) } - itemView.itemPlaceholder.setButtonClickListener(clickListener) - padding?.let { itemView.updatePadding(it) } + model?.let { binder.itemPlaceholder.setModel(model) } + binder.itemPlaceholder.setButtonClickListener(clickListener) + padding?.let { binder.root.updatePadding(it) } } } diff --git a/common/src/main/java/io/novafoundation/nova/common/list/NestedAdapter.kt b/common/src/main/java/io/novafoundation/nova/common/list/NestedAdapter.kt index c90f270201..7b1966edf1 100644 --- a/common/src/main/java/io/novafoundation/nova/common/list/NestedAdapter.kt +++ b/common/src/main/java/io/novafoundation/nova/common/list/NestedAdapter.kt @@ -1,17 +1,15 @@ package io.novafoundation.nova.common.list import android.graphics.Rect -import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.Orientation import androidx.recyclerview.widget.RecyclerView.ViewHolder -import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ItemNestedListBinding import io.novafoundation.nova.common.utils.dp -import io.novafoundation.nova.common.utils.inflateChild -import kotlinx.android.synthetic.main.item_nested_list.view.itemNestedList +import io.novafoundation.nova.common.utils.inflater class NestedAdapter( private val nestedAdapter: ListAdapter, @@ -25,7 +23,7 @@ class NestedAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NestedListViewHolder { return NestedListViewHolder( - parent.inflateChild(R.layout.item_nested_list), + ItemNestedListBinding.inflate(parent.inflater(), parent, false), nestedAdapter, orientation, paddingInDp, @@ -61,24 +59,24 @@ class NestedAdapter( } class NestedListViewHolder( - view: View, + binder: ItemNestedListBinding, private val nestedAdapter: ListAdapter, @Orientation orientation: Int, padding: Rect?, disableItemAnimations: Boolean, -) : ViewHolder(view) { +) : BaseViewHolder(binder.root) { init { - view.itemNestedList.adapter = nestedAdapter - view.itemNestedList.layoutManager = LinearLayoutManager(view.context, orientation, false) - if (disableItemAnimations) view.itemNestedList.itemAnimator = null + binder.itemNestedList.adapter = nestedAdapter + binder.itemNestedList.layoutManager = LinearLayoutManager(binder.root.context, orientation, false) + if (disableItemAnimations) binder.itemNestedList.itemAnimator = null padding?.let { - view.itemNestedList.setPadding( - it.left.dp(view.context), - it.top.dp(view.context), - it.right.dp(view.context), - it.bottom.dp(view.context) + binder.itemNestedList.setPadding( + it.left.dp(binder.root.context), + it.top.dp(binder.root.context), + it.right.dp(binder.root.context), + it.bottom.dp(binder.root.context) ) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/list/headers/TextHeader.kt b/common/src/main/java/io/novafoundation/nova/common/list/headers/TextHeader.kt index 613f262299..263979538a 100644 --- a/common/src/main/java/io/novafoundation/nova/common/list/headers/TextHeader.kt +++ b/common/src/main/java/io/novafoundation/nova/common/list/headers/TextHeader.kt @@ -1,11 +1,8 @@ package io.novafoundation.nova.common.list.headers -import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil -import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ItemTextHeaderBinding import io.novafoundation.nova.common.list.GroupedListHolder -import io.novafoundation.nova.common.utils.inflateChild -import kotlinx.android.synthetic.main.item_text_header.view.textHeader class TextHeader(val content: String) { @@ -24,9 +21,9 @@ class TextHeader(val content: String) { } } -class TextHeaderHolder(parentView: ViewGroup) : GroupedListHolder(parentView.inflateChild(R.layout.item_text_header)) { +class TextHeaderHolder(private val binder: ItemTextHeaderBinding) : GroupedListHolder(binder.root) { fun bind(item: TextHeader) { - containerView.textHeader.text = item.content + binder.textHeader.text = item.content } } diff --git a/common/src/main/java/io/novafoundation/nova/common/mixin/actionAwaitable/ConfirmationDialog.kt b/common/src/main/java/io/novafoundation/nova/common/mixin/actionAwaitable/ConfirmationDialog.kt index ec9b593a90..0c7ee25f4c 100644 --- a/common/src/main/java/io/novafoundation/nova/common/mixin/actionAwaitable/ConfirmationDialog.kt +++ b/common/src/main/java/io/novafoundation/nova/common/mixin/actionAwaitable/ConfirmationDialog.kt @@ -36,7 +36,7 @@ fun BaseFragmentMixin<*>.setupConfirmationDialog( } } -fun BaseFragment<*>.setupConfirmationOrDenyDialog(@StyleRes style: Int, awaitableMixin: ConfirmOrDenyAwaitable) { +fun BaseFragment<*, *>.setupConfirmationOrDenyDialog(@StyleRes style: Int, awaitableMixin: ConfirmOrDenyAwaitable) { awaitableMixin.awaitableActionLiveData.observeEvent { action -> dialog(requireContext(), style) { setTitle(action.payload.title) diff --git a/common/src/main/java/io/novafoundation/nova/common/mixin/hints/HintsUi.kt b/common/src/main/java/io/novafoundation/nova/common/mixin/hints/HintsUi.kt index e1c460354d..b2878709c4 100644 --- a/common/src/main/java/io/novafoundation/nova/common/mixin/hints/HintsUi.kt +++ b/common/src/main/java/io/novafoundation/nova/common/mixin/hints/HintsUi.kt @@ -53,6 +53,6 @@ fun HintsView.setSingleHint(hint: CharSequence) { setHints(listOf(hint)) } -fun BaseFragment<*>.observeHints(mixin: HintsMixin, view: HintsView) { +fun BaseFragment<*, *>.observeHints(mixin: HintsMixin, view: HintsView) { mixin.hintsFlow.observe(view::setHints) } diff --git a/common/src/main/java/io/novafoundation/nova/common/presentation/CopierBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/presentation/CopierBottomSheet.kt index 321c4335d4..ddb9fa2f63 100644 --- a/common/src/main/java/io/novafoundation/nova/common/presentation/CopierBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/presentation/CopierBottomSheet.kt @@ -2,27 +2,27 @@ package io.novafoundation.nova.common.presentation import android.content.Context import android.os.Bundle +import android.view.LayoutInflater import android.widget.Toast import androidx.annotation.StringRes import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.BottomSheeetCopierBinding import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.resources.ClipboardManager import io.novafoundation.nova.common.view.bottomSheet.list.fixed.FixedListBottomSheet import io.novafoundation.nova.common.view.bottomSheet.list.fixed.textItem -import kotlinx.android.synthetic.main.bottom_sheeet_copier.copierContainer -import kotlinx.android.synthetic.main.bottom_sheeet_copier.copierValue class CopierBottomSheet( context: Context, private val value: String, private val buttonName: String, private val onClipboardMessage: String, -) : FixedListBottomSheet( +) : FixedListBottomSheet( context, - viewConfiguration = ViewConfiguration( - layout = R.layout.bottom_sheeet_copier, - title = { copierValue }, - container = { copierContainer } + viewConfiguration = FixedListBottomSheet.ViewConfiguration( + configurationBinder = BottomSheeetCopierBinding.inflate(LayoutInflater.from(context)), + title = { configurationBinder.copierValue }, + container = { configurationBinder.copierContainer } ) ) { diff --git a/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanQrFragment.kt b/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanQrFragment.kt index a67bde80ba..addda6e1ed 100644 --- a/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanQrFragment.kt +++ b/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanQrFragment.kt @@ -2,10 +2,11 @@ package io.novafoundation.nova.common.presentation.scan import android.view.WindowManager import androidx.annotation.CallSuper +import androidx.viewbinding.ViewBinding import io.novafoundation.nova.common.base.BaseFragment import io.novafoundation.nova.common.utils.permissions.setupPermissionAsker -abstract class ScanQrFragment : BaseFragment() { +abstract class ScanQrFragment : BaseFragment() { abstract val scanView: ScanView diff --git a/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanView.kt b/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanView.kt index 10715da1f2..a16bb377bc 100644 --- a/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/presentation/scan/ScanView.kt @@ -4,7 +4,6 @@ import android.content.Context import android.graphics.Rect import android.util.AttributeSet import android.view.Gravity -import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.TextView @@ -13,13 +12,11 @@ import com.google.zxing.ResultPoint import com.journeyapps.barcodescanner.BarcodeCallback import com.journeyapps.barcodescanner.BarcodeResult import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewScanBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_scan.view.viewScanScanner -import kotlinx.android.synthetic.main.view_scan.view.viewScanSubtitle -import kotlinx.android.synthetic.main.view_scan.view.viewScanTitle -import kotlinx.android.synthetic.main.view_scan.view.viewScanViewFinder class ScanView @JvmOverloads constructor( context: Context, @@ -27,14 +24,14 @@ class ScanView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr), WithContextExtensions by WithContextExtensions(context) { - init { - View.inflate(context, R.layout.view_scan, this) + val binder = ViewScanBinding.inflate(inflater(), this) + init { setupDecoder() - viewScanViewFinder.setCameraPreview(viewScanScanner) + binder.viewScanViewFinder.setCameraPreview(binder.viewScanScanner) - viewScanViewFinder.onFinderRectChanges { + binder.viewScanViewFinder.onFinderRectChanges { positionLabels(it) } @@ -42,18 +39,18 @@ class ScanView @JvmOverloads constructor( } val subtitle: TextView - get() = viewScanSubtitle + get() = binder.viewScanSubtitle fun resume() { - viewScanScanner.resume() + binder.viewScanScanner.resume() } fun pause() { - viewScanScanner.pause() + binder.viewScanScanner.pause() } inline fun startDecoding(crossinline onScanned: (String) -> Unit) { - viewScanScanner.decodeSingle(object : BarcodeCallback { + binder.viewScanScanner.decodeSingle(object : BarcodeCallback { override fun barcodeResult(result: BarcodeResult) { onScanned(result.toString()) } @@ -67,21 +64,21 @@ class ScanView @JvmOverloads constructor( if (!changed) return - viewScanViewFinder.framingRect?.let { + binder.viewScanViewFinder.framingRect?.let { positionLabels(it) } } fun setTitle(title: String) { - viewScanTitle.text = title + binder.viewScanTitle.text = title } fun setSubtitle(subtitle: String) { - viewScanSubtitle.text = subtitle + binder.viewScanSubtitle.text = subtitle } private fun setupDecoder() { - viewScanScanner.decoderFactory = AlternatingDecoderFactory( + binder.viewScanScanner.decoderFactory = AlternatingDecoderFactory( decodeFormats = listOf(BarcodeFormat.QR_CODE), hints = null, characterSet = null, @@ -89,8 +86,8 @@ class ScanView @JvmOverloads constructor( } private fun positionLabels(finderRect: Rect) { - viewScanTitle.doIfHasText { positionTitle(finderRect) } - viewScanSubtitle.doIfHasText { positionSubTitle(finderRect) } + binder.viewScanTitle.doIfHasText { positionTitle(finderRect) } + binder.viewScanSubtitle.doIfHasText { positionSubTitle(finderRect) } } private inline fun TextView.doIfHasText(action: () -> Unit) { @@ -101,26 +98,26 @@ class ScanView @JvmOverloads constructor( val rectTop = finderRect.top // how much finderRect offsets from center of the screen + half of textView height since it is originally centered itself - val requiredBottomMargin = height / 2 - rectTop + viewScanTitle.height / 2 + val requiredBottomMargin = height / 2 - rectTop + binder.viewScanTitle.height / 2 - viewScanTitle.layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { + binder.viewScanTitle.layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { gravity = Gravity.CENTER setMargins(16.dp, 0, 16.dp, requiredBottomMargin + 24.dp) } - viewScanTitle.makeVisible() + binder.viewScanTitle.makeVisible() } private fun positionSubTitle(finderRect: Rect) { val rectBottom = finderRect.bottom // how much finderRect offsets from center of the screen + half of textView height since it is originally centered itself - val requiredTopMargin = rectBottom - height / 2 + viewScanSubtitle.height / 2 + val requiredTopMargin = rectBottom - height / 2 + binder.viewScanSubtitle.height / 2 - viewScanSubtitle.layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { + binder.viewScanSubtitle.layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { gravity = Gravity.CENTER setMargins(16.dp, requiredTopMargin + 24.dp, 16.dp, 0) } - viewScanSubtitle.makeVisible() + binder.viewScanSubtitle.makeVisible() } private fun applyAttributes(attrs: AttributeSet) = context.useAttributes(attrs, R.styleable.ScanView) { typedArray -> diff --git a/common/src/main/java/io/novafoundation/nova/common/resources/ResourceManagerImpl.kt b/common/src/main/java/io/novafoundation/nova/common/resources/ResourceManagerImpl.kt index a09693706d..261caf96a5 100644 --- a/common/src/main/java/io/novafoundation/nova/common/resources/ResourceManagerImpl.kt +++ b/common/src/main/java/io/novafoundation/nova/common/resources/ResourceManagerImpl.kt @@ -14,10 +14,8 @@ import io.novafoundation.nova.common.utils.formatting.formatDateTime import io.novafoundation.nova.common.utils.getDrawableCompat import io.novafoundation.nova.common.utils.readText import kotlin.time.Duration -import kotlin.time.ExperimentalTime -import kotlin.time.milliseconds +import kotlin.time.Duration.Companion.milliseconds -@OptIn(ExperimentalTime::class) @ApplicationScope class ResourceManagerImpl( private val contextManager: ContextManager @@ -80,14 +78,13 @@ class ResourceManagerImpl( return DateUtils.formatDateTime(contextManager.getApplicationContext(), timestamp, DateUtils.FORMAT_SHOW_TIME) } - @OptIn(ExperimentalTime::class) override fun formatDuration(elapsedTime: Long): String { val inDays = elapsedTime.daysFromMillis().toInt() return when { inDays > 0 -> getQuantityString(R.plurals.staking_main_lockup_period_value, inDays, inDays) else -> { - val inSeconds = elapsedTime.milliseconds.inSeconds.toLong() + val inSeconds = elapsedTime.milliseconds.inWholeSeconds DateUtils.formatElapsedTime(inSeconds) } diff --git a/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/PinCodeTwoFactorVerificationCommunicator.kt b/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/PinCodeTwoFactorVerificationCommunicator.kt index 88a446ef61..492186fb42 100644 --- a/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/PinCodeTwoFactorVerificationCommunicator.kt +++ b/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/PinCodeTwoFactorVerificationCommunicator.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.navigation.InterScreenResponder import io.novafoundation.nova.common.sequrity.TwoFactorVerificationResult import io.novafoundation.nova.common.sequrity.verification.PinCodeTwoFactorVerificationRequester.Request import io.novafoundation.nova.common.sequrity.verification.PinCodeTwoFactorVerificationResponder.Response -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize interface PinCodeTwoFactorVerificationRequester : InterScreenRequester { diff --git a/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/TwoFactorVerificationService.kt b/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/TwoFactorVerificationService.kt index 748ada40f2..9d85adb4c2 100644 --- a/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/TwoFactorVerificationService.kt +++ b/common/src/main/java/io/novafoundation/nova/common/sequrity/verification/TwoFactorVerificationService.kt @@ -2,7 +2,7 @@ package io.novafoundation.nova.common.sequrity import android.os.Parcelable import io.novafoundation.nova.common.data.storage.Preferences -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/MaterialCalendarExt.kt b/common/src/main/java/io/novafoundation/nova/common/utils/MaterialCalendarExt.kt index 53f4f8eaf0..262325e9d3 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/MaterialCalendarExt.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/MaterialCalendarExt.kt @@ -1,7 +1,7 @@ package io.novafoundation.nova.common.utils import com.google.android.material.datepicker.CalendarConstraints.DateValidator -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize @Parcelize class RangeDateValidator(private val start: Long?, private val end: Long?) : DateValidator { diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/PayloadCreator.kt b/common/src/main/java/io/novafoundation/nova/common/utils/PayloadCreator.kt index 0c6f3a1440..86cfb939c3 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/PayloadCreator.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/PayloadCreator.kt @@ -20,14 +20,14 @@ class FragmentPayloadCreator : PayloadCreator { } } -fun BaseFragment<*>.payload(): T { +fun BaseFragment<*, *>.payload(): T { return requireArguments().getParcelable(KEY_PAYLOAD)!! } -fun BaseFragment<*>.payloadOrNull(): T? { +fun BaseFragment<*, *>.payloadOrNull(): T? { return arguments?.getParcelable(KEY_PAYLOAD) as? T } -fun BaseFragment<*>.payloadOrElse(fallback: () -> T): T { +fun BaseFragment<*, *>.payloadOrElse(fallback: () -> T): T { return payloadOrNull() ?: fallback() } diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/Precision.kt b/common/src/main/java/io/novafoundation/nova/common/utils/Precision.kt index 5b7a08f5d2..5330005d3b 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/Precision.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/Precision.kt @@ -1,10 +1,13 @@ package io.novafoundation.nova.common.utils +import android.os.Parcelable import java.math.BigDecimal import java.math.BigInteger +import kotlinx.parcelize.Parcelize @JvmInline -value class Precision(val value: Int) +@Parcelize +value class Precision(val value: Int) : Parcelable fun Int.asPrecision() = Precision(this) diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/TokenSymbol.kt b/common/src/main/java/io/novafoundation/nova/common/utils/TokenSymbol.kt index 624e0194bb..6dc2339194 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/TokenSymbol.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/TokenSymbol.kt @@ -1,11 +1,14 @@ package io.novafoundation.nova.common.utils +import android.os.Parcelable import io.novafoundation.nova.common.utils.formatting.format import java.math.BigDecimal import java.math.RoundingMode +import kotlinx.parcelize.Parcelize @JvmInline -value class TokenSymbol(val value: String) { +@Parcelize +value class TokenSymbol(val value: String) : Parcelable { companion object; // extensions diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/ViewExt.kt b/common/src/main/java/io/novafoundation/nova/common/utils/ViewExt.kt index 841ffc101a..5809435ee0 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/ViewExt.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/ViewExt.kt @@ -38,6 +38,10 @@ import dev.chrisbanes.insetter.applyInsetter import io.novafoundation.nova.common.utils.input.Input import io.novafoundation.nova.common.utils.input.valueOrNull +fun View.inflater(): LayoutInflater { + return LayoutInflater.from(context) +} + fun View.updatePadding( top: Int = paddingTop, bottom: Int = paddingBottom, diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/permissions/Ui.kt b/common/src/main/java/io/novafoundation/nova/common/utils/permissions/Ui.kt index 3ceff0fe98..85a22f1a37 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/permissions/Ui.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/permissions/Ui.kt @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.utils.permissions.PermissionsAsker.Permissi import io.novafoundation.nova.common.utils.permissions.PermissionsAsker.PermissionDeniedLevel.CAN_ASK_AGAIN import io.novafoundation.nova.common.view.dialog.warningDialog -fun BaseFragment<*>.setupPermissionAsker( +fun BaseFragment<*, *>.setupPermissionAsker( component: PermissionsAsker, ) { component.showPermissionsDenied.awaitableActionLiveData.observeEvent { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/AccentActionView.kt b/common/src/main/java/io/novafoundation/nova/common/view/AccentActionView.kt index 731763bd51..5968c92104 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/AccentActionView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/AccentActionView.kt @@ -3,13 +3,12 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet import android.view.Gravity -import android.view.View import android.widget.LinearLayout import androidx.annotation.DrawableRes import androidx.annotation.StringRes import io.novafoundation.nova.common.R -import kotlinx.android.synthetic.main.view_accent_action.view.accentActionIcon -import kotlinx.android.synthetic.main.view_accent_action.view.accentActionText +import io.novafoundation.nova.common.databinding.ViewAccentActionBinding +import io.novafoundation.nova.common.utils.inflater class AccentActionView @JvmOverloads constructor( context: Context, @@ -17,9 +16,9 @@ class AccentActionView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { - init { - View.inflate(context, R.layout.view_accent_action, this) + private val binder = ViewAccentActionBinding.inflate(inflater(), this) + init { orientation = HORIZONTAL gravity = Gravity.CENTER_VERTICAL @@ -27,10 +26,10 @@ class AccentActionView @JvmOverloads constructor( } fun setText(@StringRes textRes: Int) { - accentActionText.setText(textRes) + binder.accentActionText.setText(textRes) } fun setIcon(@DrawableRes iconRes: Int) { - accentActionIcon.setImageResource(iconRes) + binder.accentActionIcon.setImageResource(iconRes) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/AccountInfoView.kt b/common/src/main/java/io/novafoundation/nova/common/view/AccountInfoView.kt index ba0f92e66a..4c67a8bcf4 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/AccountInfoView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/AccountInfoView.kt @@ -7,15 +7,13 @@ import android.view.View import androidx.annotation.ColorInt import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewAccountInfoBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.getColorOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.setImageTint -import kotlinx.android.synthetic.main.view_account_info.view.accountAction -import kotlinx.android.synthetic.main.view_account_info.view.accountAddressText -import kotlinx.android.synthetic.main.view_account_info.view.accountIcon -import kotlinx.android.synthetic.main.view_account_info.view.accountTitle class AccountInfoView @JvmOverloads constructor( context: Context, @@ -23,9 +21,9 @@ class AccountInfoView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr), WithContextExtensions by WithContextExtensions(context) { - init { - View.inflate(context, R.layout.view_account_info, this) + private val binder = ViewAccountInfoBinding.inflate(inflater(), this) + init { background = getRoundedCornerDrawable(fillColorRes = R.color.block_background).withRippleMask() isFocusable = true @@ -45,22 +43,22 @@ class AccountInfoView @JvmOverloads constructor( setActionIconTint(actionIconTint) val textVisible = typedArray.getBoolean(R.styleable.AccountInfoView_textVisible, true) - accountAddressText.visibility = if (textVisible) View.VISIBLE else View.GONE + binder.accountAddressText.visibility = if (textVisible) View.VISIBLE else View.GONE typedArray.recycle() } } fun setActionIcon(icon: Drawable) { - accountAction.setImageDrawable(icon) + binder.accountAction.setImageDrawable(icon) } fun setActionIconTint(@ColorInt color: Int?) { - accountAction.setImageTint(color) + binder.accountAction.setImageTint(color) } fun setActionListener(clickListener: (View) -> Unit) { - accountAction.setOnClickListener(clickListener) + binder.accountAction.setOnClickListener(clickListener) } fun setWholeClickListener(listener: (View) -> Unit) { @@ -70,22 +68,22 @@ class AccountInfoView @JvmOverloads constructor( } fun setTitle(accountName: String) { - accountTitle.text = accountName + binder.accountTitle.text = accountName } fun setText(address: String) { - accountAddressText.text = address + binder.accountAddressText.text = address } fun setAccountIcon(icon: Drawable) { - accountIcon.setImageDrawable(icon) + binder.accountIcon.setImageDrawable(icon) } fun hideBody() { - accountAddressText.makeGone() + binder.accountAddressText.makeGone() } fun showBody() { - accountAddressText.makeVisible() + binder.accountAddressText.makeVisible() } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/AddressView.kt b/common/src/main/java/io/novafoundation/nova/common/view/AddressView.kt index 6b6abedfde..baf9c70cfa 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/AddressView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/AddressView.kt @@ -3,18 +3,17 @@ package io.novafoundation.nova.common.view import android.content.Context import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.view.View import android.widget.FrameLayout import androidx.annotation.DrawableRes import io.novafoundation.nova.common.R import io.novafoundation.nova.common.address.AddressModel +import io.novafoundation.nova.common.databinding.ViewAddressBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.setDrawableEnd import io.novafoundation.nova.common.utils.setTextColorRes -import kotlinx.android.synthetic.main.view_address.view.addressImage -import kotlinx.android.synthetic.main.view_address.view.addressValue class AddressView @JvmOverloads constructor( context: Context, @@ -24,8 +23,9 @@ class AddressView @JvmOverloads constructor( override val providedContext: Context = context + private val binder = ViewAddressBinding.inflate(inflater(), this) + init { - View.inflate(context, R.layout.view_address, this) setEndIcon(R.drawable.ic_info) attrs?.let { applyStyleAttrs(it) } } @@ -34,21 +34,21 @@ class AddressView @JvmOverloads constructor( val typedArray = context.obtainStyledAttributes(attrs, R.styleable.AddressView) val textColorRes = typedArray.getResourceId(R.styleable.AddressView_android_textColor, R.color.text_secondary) - addressValue.setTextColorRes(textColorRes) + binder.addressValue.setTextColorRes(textColorRes) typedArray.recycle() } fun setAddress(icon: Drawable, address: String) { - addressImage.setImageDrawable(icon) - addressValue.text = address + binder.addressImage.setImageDrawable(icon) + binder.addressValue.text = address } fun setEndIcon(@DrawableRes iconRes: Int?) { if (iconRes == null) { - addressValue.setDrawableEnd(null) + binder.addressValue.setDrawableEnd(null) } else { - addressValue.setDrawableEnd(iconRes, widthInDp = 16, paddingInDp = 6) + binder.addressValue.setDrawableEnd(iconRes, widthInDp = 16, paddingInDp = 6) } } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/AdvertisementCard.kt b/common/src/main/java/io/novafoundation/nova/common/view/AdvertisementCard.kt index 7167df664f..6ea4286556 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/AdvertisementCard.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/AdvertisementCard.kt @@ -8,22 +8,15 @@ import androidx.core.view.isVisible import androidx.lifecycle.LifecycleOwner import com.google.android.material.card.MaterialCardView import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewAdvertisementCardBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.dp import io.novafoundation.nova.common.utils.dpF +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.utils.updatePadding import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardBackground -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardButton -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardClose -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardImage -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardLearnMoreArrow -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardLearnMoreContent -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardLearnMoreGroup -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardSubTitle -import kotlinx.android.synthetic.main.view_advertisement_card.view.advertisementCardTitle class AdvertisementCard @JvmOverloads constructor( context: Context, @@ -31,12 +24,12 @@ class AdvertisementCard @JvmOverloads constructor( defStyleAttr: Int = 0, ) : MaterialCardView(context, attrs, defStyleAttr), WithContextExtensions by WithContextExtensions(context) { + private val binder = ViewAdvertisementCardBinding.inflate(inflater(), this) + val action: PrimaryButton - get() = advertisementCardButton + get() = binder.advertisementCardButton init { - View.inflate(context, R.layout.view_advertisement_card, this) - cardElevation = 0f radius = 12f.dpF(context) strokeWidth = 1.dp(context) @@ -53,19 +46,19 @@ class AdvertisementCard @JvmOverloads constructor( } fun setOnLearnMoreClickedListener(onClicked: (View) -> Unit) { - advertisementCardLearnMoreArrow.setOnClickListener(onClicked) - advertisementCardLearnMoreContent.setOnClickListener(onClicked) + binder.advertisementCardLearnMoreArrow.setOnClickListener(onClicked) + binder.advertisementCardLearnMoreContent.setOnClickListener(onClicked) } fun setOnCloseClickListener(listener: OnClickListener?) { - advertisementCardClose.setOnClickListener(listener) + binder.advertisementCardClose.setOnClickListener(listener) } fun setModel(model: AdvertisementCardModel) { - advertisementCardTitle.text = model.title - advertisementCardSubTitle.text = model.subtitle - advertisementCardImage.setImageResource(model.imageRes) - advertisementCardBackground.setBackgroundResource(model.bannerBackgroundRes) + binder.advertisementCardTitle.text = model.title + binder.advertisementCardSubTitle.text = model.subtitle + binder.advertisementCardImage.setImageResource(model.imageRes) + binder.advertisementCardBackground.setBackgroundResource(model.bannerBackgroundRes) } private fun applyAttrs(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.AdvertisementCard) { @@ -73,23 +66,23 @@ class AdvertisementCard @JvmOverloads constructor( action.setTextOrHide(actionLabel) val learnMore = it.getString(R.styleable.AdvertisementCard_learnMore) - advertisementCardLearnMoreGroup.setVisible(learnMore != null) - advertisementCardLearnMoreContent.text = learnMore + binder.advertisementCardLearnMoreGroup.setVisible(learnMore != null) + binder.advertisementCardLearnMoreContent.text = learnMore val title = it.getString(R.styleable.AdvertisementCard_title) - advertisementCardTitle.text = title + binder.advertisementCardTitle.text = title val subtitle = it.getString(R.styleable.AdvertisementCard_subtitle) - advertisementCardSubTitle.text = subtitle + binder.advertisementCardSubTitle.text = subtitle val image = it.getDrawable(R.styleable.AdvertisementCard_image) - advertisementCardImage.setImageDrawable(image) + binder.advertisementCardImage.setImageDrawable(image) val bannerBackground = it.getDrawable(R.styleable.AdvertisementCard_advertisementCardBackground) - advertisementCardBackground.background = bannerBackground + binder.advertisementCardBackground.background = bannerBackground val showClose = it.getBoolean(R.styleable.AdvertisementCard_showClose, false) - advertisementCardClose.isVisible = showClose + binder.advertisementCardClose.isVisible = showClose } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/AlertView.kt b/common/src/main/java/io/novafoundation/nova/common/view/AlertView.kt index 3b8c888b8f..b596dc6ee7 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/AlertView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/AlertView.kt @@ -2,26 +2,21 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewAlertBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.getEnum import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.letOrHide import io.novafoundation.nova.common.utils.setImageTintRes import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.updatePadding import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_alert.view.alertActionArrow -import kotlinx.android.synthetic.main.view_alert.view.alertActionContent -import kotlinx.android.synthetic.main.view_alert.view.alertActionGroup -import kotlinx.android.synthetic.main.view_alert.view.alertIcon -import kotlinx.android.synthetic.main.view_alert.view.alertMessage -import kotlinx.android.synthetic.main.view_alert.view.alertSubMessage typealias SimpleAlertModel = String @@ -57,9 +52,9 @@ class AlertView @JvmOverloads constructor( } } - init { - View.inflate(context, R.layout.view_alert, this) + private val binder = ViewAlertBinding.inflate(inflater(), this) + init { updatePadding(top = 10.dp, start = 16.dp, end = 16.dp, bottom = 10.dp) attrs?.let(::applyAttrs) @@ -75,26 +70,26 @@ class AlertView @JvmOverloads constructor( } fun setMessage(text: String) { - alertMessage.text = text + binder.alertMessage.text = text } fun setMessage(@StringRes textRes: Int) { - alertMessage.setText(textRes) + binder.alertMessage.setText(textRes) } fun setSubMessage(text: CharSequence?) { - alertSubMessage.setTextOrHide(text) + binder.alertSubMessage.setTextOrHide(text) } fun setActionText(actionText: String?) { - alertActionGroup.letOrHide(actionText) { text -> - alertActionContent.text = text + binder.alertActionGroup.letOrHide(actionText) { text -> + binder.alertActionContent.text = text } } fun setOnActionClickedListener(listener: () -> Unit) { - alertActionContent.setOnClickListener { listener() } - alertActionArrow.setOnClickListener { listener() } + binder.alertActionContent.setOnClickListener { listener() } + binder.alertActionArrow.setOnClickListener { listener() } } fun setModel(maybeModel: SimpleAlertModel?) = letOrHide(maybeModel) { model -> @@ -106,8 +101,8 @@ class AlertView @JvmOverloads constructor( } private fun setStyleIcon(@DrawableRes iconRes: Int, iconTintRes: Int? = null) { - alertIcon.setImageResource(iconRes) - alertIcon.setImageTintRes(iconTintRes) + binder.alertIcon.setImageResource(iconRes) + binder.alertIcon.setImageTintRes(iconTintRes) } private fun applyAttrs(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.AlertView) { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/AmountView.kt b/common/src/main/java/io/novafoundation/nova/common/view/AmountView.kt index 2cb0e6491a..58e1912b05 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/AmountView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/AmountView.kt @@ -4,22 +4,18 @@ import android.content.Context import android.graphics.drawable.Drawable import android.text.InputType import android.util.AttributeSet -import android.view.View import android.widget.EditText import androidx.constraintlayout.widget.ConstraintLayout import coil.ImageLoader import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewChooseAmountOldBinding import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.utils.images.Icon import io.novafoundation.nova.common.utils.images.setIcon +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.view.shape.getBlockDrawable import io.novafoundation.nova.common.view.shape.getCornersStateDrawable -import kotlinx.android.synthetic.main.view_choose_amount_old.view.stakingAmountInput -import kotlinx.android.synthetic.main.view_choose_amount_old.view.stakingAssetBalance -import kotlinx.android.synthetic.main.view_choose_amount_old.view.stakingAssetPriceAmount -import kotlinx.android.synthetic.main.view_choose_amount_old.view.stakingAssetImage -import kotlinx.android.synthetic.main.view_choose_amount_old.view.stakingAssetToken class AmountView @JvmOverloads constructor( context: Context, @@ -27,16 +23,16 @@ class AmountView @JvmOverloads constructor( defStyle: Int = 0, ) : ConstraintLayout(context, attrs, defStyle) { + private val binder = ViewChooseAmountOldBinding.inflate(inflater(), this) + val amountInput: EditText - get() = stakingAmountInput + get() = binder.stakingAmountInput private val imageLoader: ImageLoader by lazy(LazyThreadSafetyMode.NONE) { FeatureUtils.getCommonApi(context).imageLoader() } init { - View.inflate(context, R.layout.view_choose_amount_old, this) - setBackground() applyAttributes(attrs) @@ -85,22 +81,22 @@ class AmountView @JvmOverloads constructor( } fun setAssetImage(image: Drawable) { - stakingAssetImage.setImageDrawable(image) + binder.stakingAssetImage.setImageDrawable(image) } fun loadAssetImage(icon: Icon) { - stakingAssetImage.setIcon(icon, imageLoader) + binder.stakingAssetImage.setIcon(icon, imageLoader) } fun setAssetName(name: String) { - stakingAssetToken.text = name + binder.stakingAssetToken.text = name } fun setAssetBalance(balance: String) { - stakingAssetBalance.text = balance + binder.stakingAssetBalance.text = balance } fun setFiatAmount(priceAmount: String?) { - stakingAssetPriceAmount.setTextOrHide(priceAmount) + binder.stakingAssetPriceAmount.setTextOrHide(priceAmount) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/BannerView.kt b/common/src/main/java/io/novafoundation/nova/common/view/BannerView.kt index 578675153e..078cf71c1f 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/BannerView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/BannerView.kt @@ -9,13 +9,11 @@ import androidx.annotation.DrawableRes import androidx.core.view.isVisible import com.google.android.material.card.MaterialCardView import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewBannerBinding import io.novafoundation.nova.common.utils.dp import io.novafoundation.nova.common.utils.dpF import io.novafoundation.nova.common.utils.getEnum -import kotlinx.android.synthetic.main.view_banner.view.bannerBackground -import kotlinx.android.synthetic.main.view_banner.view.bannerClose -import kotlinx.android.synthetic.main.view_banner.view.bannerContent -import kotlinx.android.synthetic.main.view_banner.view.bannerImage +import io.novafoundation.nova.common.utils.inflater class BannerView @JvmOverloads constructor( context: Context, @@ -23,8 +21,9 @@ class BannerView @JvmOverloads constructor( defStyle: Int = 0, ) : MaterialCardView(context, attrs, defStyle) { + private val binder = ViewBannerBinding.inflate(inflater(), this) + init { - View.inflate(context, R.layout.view_banner, this) cardElevation = 0f radius = 12f.dpF(context) strokeWidth = 1.dp(context) @@ -34,7 +33,7 @@ class BannerView @JvmOverloads constructor( } fun setOnCloseClickListener(listener: OnClickListener?) { - bannerClose.setOnClickListener(listener) + binder.bannerClose.setOnClickListener(listener) } private fun applyAttributes(attrs: AttributeSet?) { @@ -42,18 +41,18 @@ class BannerView @JvmOverloads constructor( val typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerView) val image = typedArray.getDrawable(R.styleable.BannerView_android_src) - bannerImage.setImageDrawable(image) + binder.bannerImage.setImageDrawable(image) val background = typedArray.getDrawable(R.styleable.BannerView_bannerBackground) - bannerBackground.background = background + binder.bannerBackground.background = background val closeIcon = typedArray.getDrawable(R.styleable.BannerView_closeIcon) if (closeIcon != null) { - bannerClose.setImageDrawable(closeIcon) + binder.bannerClose.setImageDrawable(closeIcon) } val showClose = typedArray.getBoolean(R.styleable.BannerView_showClose, false) - bannerClose.isVisible = showClose + binder.bannerClose.isVisible = showClose val style = typedArray.getEnum(R.styleable.BannerView_android_scaleType, ImageView.ScaleType.CENTER) setImageScaleType(style) @@ -66,19 +65,19 @@ class BannerView @JvmOverloads constructor( if (child.id == R.id.bannerBackground) { super.addView(child, params) } else { - bannerContent.addView(child, params) + binder.bannerContent.addView(child, params) } } fun setBannerBackground(@DrawableRes backgroundRes: Int) { - bannerBackground.setBackgroundResource(backgroundRes) + binder.bannerBackground.setBackgroundResource(backgroundRes) } fun setImage(@DrawableRes imageRes: Int) { - bannerImage.setImageResource(imageRes) + binder.bannerImage.setImageResource(imageRes) } fun setImageScaleType(scaleType: ImageView.ScaleType) { - bannerImage.scaleType = scaleType + binder.bannerImage.scaleType = scaleType } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/ButtonLarge.kt b/common/src/main/java/io/novafoundation/nova/common/view/ButtonLarge.kt index fb342ebb48..7b5b8cd79a 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/ButtonLarge.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/ButtonLarge.kt @@ -3,19 +3,17 @@ package io.novafoundation.nova.common.view import android.content.Context import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.view.View import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ButtonLargeBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.getColorFromAttr import io.novafoundation.nova.common.utils.getEnum +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.useAttributes import io.novafoundation.nova.common.view.shape.addRipple import io.novafoundation.nova.common.view.shape.getRoundedCornerDrawableFromColors -import kotlinx.android.synthetic.main.button_large.view.buttonLargeIcon -import kotlinx.android.synthetic.main.button_large.view.buttonLargeSubtitle -import kotlinx.android.synthetic.main.button_large.view.buttonLargeTitle class ButtonLarge @kotlin.jvm.JvmOverloads constructor( context: Context, @@ -23,9 +21,9 @@ class ButtonLarge @kotlin.jvm.JvmOverloads constructor( defStyleAttr: Int = 0, ) : ConstraintLayout(context, attrs, defStyleAttr), WithContextExtensions by WithContextExtensions(context) { - init { - View.inflate(context, R.layout.button_large, this) + private val binder = ButtonLargeBinding.inflate(inflater(), this) + init { minHeight = 52.dp attrs?.let(::applyAttributes) @@ -51,15 +49,15 @@ class ButtonLarge @kotlin.jvm.JvmOverloads constructor( } private fun setTitle(title: String?) { - buttonLargeTitle.text = title + binder.buttonLargeTitle.text = title } private fun setSubtitle(subtitle: String?) { - buttonLargeSubtitle.setTextOrHide(subtitle) + binder.buttonLargeSubtitle.setTextOrHide(subtitle) } private fun setIcon(icon: Drawable?) { - buttonLargeIcon.setImageDrawable(icon) + binder.buttonLargeIcon.setImageDrawable(icon) } private fun setStyle(style: Style) = with(context) { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/ChipActionsList.kt b/common/src/main/java/io/novafoundation/nova/common/view/ChipActionsList.kt index f52d356b11..0b45bd0135 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/ChipActionsList.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/ChipActionsList.kt @@ -2,11 +2,10 @@ package io.novafoundation.nova.common.view import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil -import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ItemChipActionBinding import io.novafoundation.nova.common.list.BaseListAdapter import io.novafoundation.nova.common.list.BaseViewHolder -import io.novafoundation.nova.common.utils.inflateChild -import kotlinx.android.synthetic.main.item_chip_action.view.itemChipAction +import io.novafoundation.nova.common.utils.inflater class ChipActionsModel( val action: String @@ -22,7 +21,7 @@ class ChipActionsAdapter( } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChipActionsViewHolder { - return ChipActionsViewHolder(parent, handler) + return ChipActionsViewHolder(ItemChipActionBinding.inflate(parent.inflater(), parent, false), handler) } override fun onBindViewHolder(holder: ChipActionsViewHolder, position: Int) { @@ -30,17 +29,17 @@ class ChipActionsAdapter( } } -class ChipActionsViewHolder constructor( - parent: ViewGroup, +class ChipActionsViewHolder( + private val binder: ItemChipActionBinding, handler: ChipActionsAdapter.Handler -) : BaseViewHolder(parent.inflateChild(R.layout.item_chip_action)) { +) : BaseViewHolder(binder.root) { init { - containerView.setOnClickListener { handler.chipActionClicked(bindingAdapterPosition) } + binder.root.setOnClickListener { handler.chipActionClicked(bindingAdapterPosition) } } fun bind(item: ChipActionsModel) { - containerView.itemChipAction.text = item.action + binder.itemChipAction.text = item.action } override fun unbind() {} diff --git a/common/src/main/java/io/novafoundation/nova/common/view/ExpandableView.kt b/common/src/main/java/io/novafoundation/nova/common/view/ExpandableView.kt index 4ce6e8c4fb..8b133acb29 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/ExpandableView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/ExpandableView.kt @@ -7,7 +7,6 @@ import android.util.AttributeSet import android.view.View import android.view.ViewGroup import android.view.animation.AccelerateDecelerateInterpolator -import androidx.annotation.DrawableRes import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.animation.doOnEnd import androidx.core.animation.doOnStart @@ -16,7 +15,6 @@ import io.novafoundation.nova.common.R import io.novafoundation.nova.common.utils.getResourceIdOrNull import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.makeVisible -import kotlinx.android.synthetic.main.view_banner.view.bannerImage enum class ExpandableViewState { COLLAPSED, @@ -58,10 +56,6 @@ class ExpandableView @JvmOverloads constructor( } } - fun setImage(@DrawableRes imageRes: Int) { - bannerImage.setImageResource(imageRes) - } - fun setState(state: ExpandableViewState) { when (state) { ExpandableViewState.COLLAPSED -> collapse() diff --git a/common/src/main/java/io/novafoundation/nova/common/view/GenericTableCellView.kt b/common/src/main/java/io/novafoundation/nova/common/view/GenericTableCellView.kt index 89a4509231..be09505957 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/GenericTableCellView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/GenericTableCellView.kt @@ -8,13 +8,13 @@ import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.children import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewGenericTableCellBinding import io.novafoundation.nova.common.utils.dp import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setDrawableEnd import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_generic_table_cell.view.genericTableCellTitle -import kotlinx.android.synthetic.main.view_generic_table_cell.view.genericTableCellValueProgress open class GenericTableCellView @JvmOverloads constructor( context: Context, @@ -23,6 +23,8 @@ open class GenericTableCellView @JvmOverloads constructor( defStyleRes: Int = 0, ) : ConstraintLayout(context, attrs, defStyle, defStyleRes), TableItem { + private val binder = ViewGenericTableCellBinding.inflate(inflater(), this) + protected lateinit var valueView: V companion object { @@ -33,8 +35,6 @@ open class GenericTableCellView @JvmOverloads constructor( init { minHeight = 44.dp - View.inflate(context, R.layout.view_generic_table_cell, this) - setBackgroundResource(R.drawable.bg_primary_list_item) attrs?.let(::applyAttributes) @@ -66,20 +66,20 @@ open class GenericTableCellView @JvmOverloads constructor( } fun showProgress(showProgress: Boolean) { - genericTableCellValueProgress.setVisible(showProgress) + binder.genericTableCellValueProgress.setVisible(showProgress) valueView.setVisible(!showProgress) } fun setTitle(title: String?) { - genericTableCellTitle.text = title + binder.genericTableCellTitle.text = title } fun setTitle(@StringRes titleRes: Int) { - genericTableCellTitle.setText(titleRes) + binder.genericTableCellTitle.setText(titleRes) } fun setTitleIconEnd(@DrawableRes icon: Int?) { - genericTableCellTitle.setDrawableEnd(icon, widthInDp = 16, paddingInDp = 4) + binder.genericTableCellTitle.setDrawableEnd(icon, widthInDp = 16, paddingInDp = 4) } @JvmName("setValueContentView") diff --git a/common/src/main/java/io/novafoundation/nova/common/view/GoNextView.kt b/common/src/main/java/io/novafoundation/nova/common/view/GoNextView.kt index 1c68f8512a..51ff846cc6 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/GoNextView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/GoNextView.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.annotation.ColorInt @@ -13,15 +12,11 @@ import androidx.constraintlayout.widget.ConstraintLayout import coil.ImageLoader import coil.load import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewGoNextBinding import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.setVisible -import kotlinx.android.synthetic.main.view_go_next.view.goNextActionImage -import kotlinx.android.synthetic.main.view_go_next.view.goNextBadgeText -import kotlinx.android.synthetic.main.view_go_next.view.goNextDivider -import kotlinx.android.synthetic.main.view_go_next.view.goNextIcon -import kotlinx.android.synthetic.main.view_go_next.view.goNextProgress -import kotlinx.android.synthetic.main.view_go_next.view.goNextTitle class GoNextView @JvmOverloads constructor( context: Context, @@ -29,31 +24,31 @@ class GoNextView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr) { - init { - View.inflate(context, R.layout.view_go_next, this) + private val binder = ViewGoNextBinding.inflate(inflater(), this) + init { attrs?.let(this::applyAttributes) } val icon: ImageView - get() = goNextIcon + get() = binder.goNextIcon val title: TextView - get() = goNextTitle + get() = binder.goNextTitle fun setInProgress(inProgress: Boolean) { isEnabled = !inProgress - goNextActionImage.setVisible(!inProgress) - goNextProgress.setVisible(inProgress) + binder.goNextActionImage.setVisible(!inProgress) + binder.goNextProgress.setVisible(inProgress) } fun setDividerVisible(visible: Boolean) { - goNextDivider.setVisible(visible) + binder.goNextDivider.setVisible(visible) } fun setBadgeText(badgeText: String?) { - goNextBadgeText.setTextOrHide(badgeText) + binder.goNextBadgeText.setTextOrHide(badgeText) } fun loadIcon(iconLink: String, imageLoader: ImageLoader) { @@ -62,7 +57,7 @@ class GoNextView @JvmOverloads constructor( } fun setProgressTint(@ColorRes tintColor: Int) { - goNextProgress.indeterminateTintList = ColorStateList.valueOf(context.getColor(tintColor)) + binder.goNextProgress.indeterminateTintList = ColorStateList.valueOf(context.getColor(tintColor)) } fun setIcon(drawable: Drawable?) { @@ -75,8 +70,8 @@ class GoNextView @JvmOverloads constructor( } fun setActionTint(@ColorInt color: Int) { - goNextActionImage.imageTintList = ColorStateList.valueOf(color) - goNextBadgeText.setTextColor(color) + binder.goNextActionImage.imageTintList = ColorStateList.valueOf(color) + binder.goNextBadgeText.setTextColor(color) } private fun applyAttributes(attributeSet: AttributeSet?) { @@ -95,7 +90,7 @@ class GoNextView @JvmOverloads constructor( setIconTint(iconTint) val actionIconDrawable = typedArray.getDrawable(R.styleable.GoNextView_actionIcon) - goNextActionImage.setImageDrawable(actionIconDrawable) + binder.goNextActionImage.setImageDrawable(actionIconDrawable) val dividerVisible = typedArray.getBoolean(R.styleable.GoNextView_dividerVisible, true) setDividerVisible(dividerVisible) diff --git a/common/src/main/java/io/novafoundation/nova/common/view/InsertableInputField.kt b/common/src/main/java/io/novafoundation/nova/common/view/InsertableInputField.kt index 1c96a3766e..60f321283e 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/InsertableInputField.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/InsertableInputField.kt @@ -4,23 +4,21 @@ import android.content.Context import android.text.TextUtils import android.util.AttributeSet import android.view.Gravity -import android.view.View import android.widget.EditText import android.widget.LinearLayout import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.widget.addTextChangedListener import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewInsertableInputFieldBinding import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.resources.ClipboardManager +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.useAttributes import io.novafoundation.nova.common.view.shape.addRipple import io.novafoundation.nova.common.view.shape.getInputBackground import io.novafoundation.nova.common.view.shape.getRoundedCornerDrawable -import kotlinx.android.synthetic.main.view_insertable_input_field.view.actionInputField -import kotlinx.android.synthetic.main.view_insertable_input_field.view.actionInputFieldAction -import kotlinx.android.synthetic.main.view_insertable_input_field.view.actionInputFieldClear class InsertableInputField @JvmOverloads constructor( context: Context, @@ -28,17 +26,17 @@ class InsertableInputField @JvmOverloads constructor( defStyle: Int = 0, ) : LinearLayout(context, attrs, defStyle) { + private val binder = ViewInsertableInputFieldBinding.inflate(inflater(), this) + private var clipboardManager: ClipboardManager? = getClipboardManager() val content: EditText - get() = actionInputField + get() = binder.actionInputField init { orientation = HORIZONTAL gravity = Gravity.CENTER_VERTICAL - View.inflate(context, R.layout.view_insertable_input_field, this) - setAddStatesFromChildren(true) setBackgrounds() @@ -49,11 +47,11 @@ class InsertableInputField @JvmOverloads constructor( updateButtonsVisibility(it) } - actionInputFieldAction.setOnClickListener { + binder.actionInputFieldAction.setOnClickListener { paste() } - actionInputFieldClear.setOnClickListener { content.text = null } + binder.actionInputFieldClear.setOnClickListener { content.text = null } updateButtonsVisibility(content.text) } @@ -63,8 +61,8 @@ class InsertableInputField @JvmOverloads constructor( if (enabled) { updateButtonsVisibility(content.text) } else { - actionInputFieldAction.makeGone() - actionInputFieldClear.makeGone() + binder.actionInputFieldAction.makeGone() + binder.actionInputFieldClear.makeGone() } content.isEnabled = enabled @@ -75,14 +73,14 @@ class InsertableInputField @JvmOverloads constructor( val clipboardIsNotEmpty = !TextUtils.isEmpty(clipboardValue) val textIsEmpty = TextUtils.isEmpty(text) - actionInputFieldClear.isGone = textIsEmpty - actionInputFieldAction.isVisible = textIsEmpty && clipboardIsNotEmpty + binder.actionInputFieldClear.isGone = textIsEmpty + binder.actionInputFieldAction.isVisible = textIsEmpty && clipboardIsNotEmpty } private fun setBackgrounds() = with(context) { background = context.getInputBackground() - actionInputFieldAction.background = buttonBackground() + binder.actionInputFieldAction.background = buttonBackground() } private fun paste() { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/InstructionStepView.kt b/common/src/main/java/io/novafoundation/nova/common/view/InstructionStepView.kt index 925743b51d..d2652c68d3 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/InstructionStepView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/InstructionStepView.kt @@ -2,13 +2,12 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import android.widget.LinearLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewInstructionStepBinding import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_instruction_step.view.instructionStepIndicator -import kotlinx.android.synthetic.main.view_instruction_step.view.instructionStepText class InstructionStepView @JvmOverloads constructor( context: Context, @@ -16,28 +15,28 @@ class InstructionStepView @JvmOverloads constructor( defStyle: Int = 0, ) : LinearLayout(context, attrs, defStyle) { + private val binder = ViewInstructionStepBinding.inflate(inflater(), this) + init { orientation = HORIZONTAL - View.inflate(context, R.layout.view_instruction_step, this) - attrs?.let(::applyAttributes) } fun setStepNumber(stepNumber: Int) { - instructionStepIndicator.text = stepNumber.toString() + binder.instructionStepIndicator.text = stepNumber.toString() } fun setStepText(stepText: CharSequence) { - instructionStepText.text = stepText + binder.instructionStepText.text = stepText } private fun applyAttributes(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.InstructionStepView) { val stepNumber = it.getString(R.styleable.InstructionStepView_stepNumber) - instructionStepIndicator.text = stepNumber + binder.instructionStepIndicator.text = stepNumber // use getResourceId() instead of getString() since resources might contain spans which will be lost if getString() is used val stepText = it.getResourceIdOrNull(R.styleable.InstructionStepView_stepText) - stepText?.let { instructionStepText.setText(it) } + stepText?.let { binder.instructionStepText.setText(it) } } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/LabeledTextView.kt b/common/src/main/java/io/novafoundation/nova/common/view/LabeledTextView.kt index b441b50569..3e8a2866e2 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/LabeledTextView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/LabeledTextView.kt @@ -9,19 +9,16 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewLabeledTextBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.getDrawableCompat import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.view.shape.addRipple import io.novafoundation.nova.common.view.shape.getCornersStateDrawable -import kotlinx.android.synthetic.main.view_labeled_text.view.labeledTextAction -import kotlinx.android.synthetic.main.view_labeled_text.view.labeledTextIcon -import kotlinx.android.synthetic.main.view_labeled_text.view.labeledTextLabel -import kotlinx.android.synthetic.main.view_labeled_text.view.labeledTextPrimaryIcon -import kotlinx.android.synthetic.main.view_labeled_text.view.labeledTextText class LabeledTextView @JvmOverloads constructor( context: Context, @@ -29,9 +26,9 @@ class LabeledTextView @JvmOverloads constructor( defStyleAttr: Int = 0, ) : ConstraintLayout(context, attrs, defStyleAttr), WithContextExtensions by WithContextExtensions(context) { - init { - View.inflate(context, R.layout.view_labeled_text, this) + private val binder = ViewLabeledTextBinding.inflate(inflater(), this) + init { minHeight = 48.dp setPadding(0, 8.dp, 0, 8.dp) @@ -45,10 +42,10 @@ class LabeledTextView @JvmOverloads constructor( private var singleLine: Boolean = true val textIconView: ImageView - get() = labeledTextIcon + get() = binder.labeledTextIcon val primaryIcon: ImageView - get() = labeledTextPrimaryIcon + get() = binder.labeledTextPrimaryIcon private fun applyAttributes(attrs: AttributeSet?) { attrs?.let { @@ -64,10 +61,10 @@ class LabeledTextView @JvmOverloads constructor( setMessageColor(messageColor) val messageStyle = typedArray.getResourceIdOrNull(R.styleable.LabeledTextView_messageStyle) - messageStyle?.let(labeledTextText::setTextAppearance) + messageStyle?.let(binder.labeledTextText::setTextAppearance) val labelStyle = typedArray.getResourceIdOrNull(R.styleable.LabeledTextView_labelStyle) - labelStyle?.let(labeledTextLabel::setTextAppearance) + labelStyle?.let(binder.labeledTextLabel::setTextAppearance) val textIcon = typedArray.getDrawable(R.styleable.LabeledTextView_textIcon) textIcon?.let(::setTextIcon) @@ -79,20 +76,20 @@ class LabeledTextView @JvmOverloads constructor( setActionIcon(actionIcon) singleLine = typedArray.getBoolean(R.styleable.LabeledTextView_android_singleLine, true) - labeledTextText.isSingleLine = singleLine + binder.labeledTextText.isSingleLine = singleLine typedArray.recycle() } } private fun setMessageColor(messageColor: Int) { - labeledTextText.setTextColor(messageColor) + binder.labeledTextText.setTextColor(messageColor) } override fun setEnabled(enabled: Boolean) { super.setEnabled(enabled) - labeledTextAction.setVisible(enabled) + binder.labeledTextAction.setVisible(enabled) } fun setLabel(label: String) { @@ -100,26 +97,26 @@ class LabeledTextView @JvmOverloads constructor( } fun setLabelOrHide(label: String?) { - labeledTextLabel.setTextOrHide(label) + binder.labeledTextLabel.setTextOrHide(label) } fun setActionIcon(icon: Drawable?) { - labeledTextAction.setImageDrawable(icon) + binder.labeledTextAction.setImageDrawable(icon) - labeledTextAction.setVisible(icon != null) + binder.labeledTextAction.setVisible(icon != null) } fun setMessage(@StringRes messageRes: Int) = setMessage(context.getString(messageRes)) fun setMessage(text: String?) { - labeledTextText.text = text + binder.labeledTextText.text = text } fun setTextIcon(@DrawableRes iconRes: Int) = setTextIcon(context.getDrawableCompat(iconRes)) fun setTextIcon(icon: Drawable) { - labeledTextIcon.makeVisible() - labeledTextIcon.setImageDrawable(icon) + binder.labeledTextIcon.makeVisible() + binder.labeledTextIcon.setImageDrawable(icon) } fun setPrimaryIcon(icon: Drawable) { @@ -128,7 +125,7 @@ class LabeledTextView @JvmOverloads constructor( } fun setActionClickListener(listener: (View) -> Unit) { - labeledTextAction.setOnClickListener(listener) + binder.labeledTextAction.setOnClickListener(listener) } fun setWholeClickListener(listener: (View) -> Unit) { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/LinkView.kt b/common/src/main/java/io/novafoundation/nova/common/view/LinkView.kt index dba3143f09..a4c367b3c5 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/LinkView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/LinkView.kt @@ -3,29 +3,30 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet import android.view.Gravity -import android.view.View import android.widget.LinearLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewLinkBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_link.view.viewLinkText class LinkView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = 0, ) : LinearLayout(context, attrs, defStyle), WithContextExtensions by WithContextExtensions(context) { + + private val binder = ViewLinkBinding.inflate(inflater(), this) + init { orientation = HORIZONTAL gravity = Gravity.CENTER_VERTICAL - View.inflate(context, R.layout.view_link, this) - attrs?.let(::applyAttributes) } private fun applyAttributes(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.LinkView) { val linkText = it.getString(R.styleable.LinkView_linkText) - viewLinkText.text = linkText + binder.viewLinkText.text = linkText } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/NovaConnectView.kt b/common/src/main/java/io/novafoundation/nova/common/view/NovaConnectView.kt index 785ac25097..af0e3b801a 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/NovaConnectView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/NovaConnectView.kt @@ -2,12 +2,12 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import android.widget.LinearLayout import androidx.annotation.DrawableRes import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewNovaConnectBinding +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_nova_connect.view.viewNovaConnectTargetIcon class NovaConnectView @JvmOverloads constructor( context: Context, @@ -15,20 +15,20 @@ class NovaConnectView @JvmOverloads constructor( defStyle: Int = 0, ) : LinearLayout(context, attrs, defStyle) { + private val binder = ViewNovaConnectBinding.inflate(inflater(), this) + init { orientation = HORIZONTAL - View.inflate(context, R.layout.view_nova_connect, this) - attrs?.let(::applyAttributes) } fun setTargetImage(@DrawableRes targetImageRes: Int) { - viewNovaConnectTargetIcon.setImageResource(targetImageRes) + binder.viewNovaConnectTargetIcon.setImageResource(targetImageRes) } private fun applyAttributes(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.NovaConnectView) { val targetImage = it.getDrawable(R.styleable.NovaConnectView_targetImage) - viewNovaConnectTargetIcon.setImageDrawable(targetImage) + binder.viewNovaConnectTargetIcon.setImageDrawable(targetImage) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/PlaceholderView.kt b/common/src/main/java/io/novafoundation/nova/common/view/PlaceholderView.kt index ab1cb51e3a..cafb8b535a 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/PlaceholderView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/PlaceholderView.kt @@ -3,24 +3,22 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet import android.view.Gravity -import android.view.View import android.widget.LinearLayout import androidx.annotation.ColorInt import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.view.isVisible import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewPlaceholderBinding import io.novafoundation.nova.common.utils.dp import io.novafoundation.nova.common.utils.getEnum import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setImageTint import io.novafoundation.nova.common.utils.setTextColorRes import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.useAttributes import io.novafoundation.nova.common.view.shape.getRoundedCornerDrawable -import kotlinx.android.synthetic.main.view_placeholder.view.viewPlaceholderButton -import kotlinx.android.synthetic.main.view_placeholder.view.viewPlaceholderImage -import kotlinx.android.synthetic.main.view_placeholder.view.viewPlaceholderText class PlaceholderView @JvmOverloads constructor( context: Context, @@ -34,9 +32,9 @@ class PlaceholderView @JvmOverloads constructor( NO_BACKGROUND(false, null, R.color.text_secondary) } - init { - View.inflate(context, R.layout.view_placeholder, this) + private val binder = ViewPlaceholderBinding.inflate(inflater(), this) + init { setPadding(16.dp(context), 16.dp(context), 16.dp(context), 32.dp(context)) orientation = VERTICAL @@ -62,27 +60,27 @@ class PlaceholderView @JvmOverloads constructor( } else { null } - viewPlaceholderText.setTextColorRes(style.textColorRes) + binder.viewPlaceholderText.setTextColorRes(style.textColorRes) } fun setImage(@DrawableRes image: Int) { - viewPlaceholderImage.setImageResource(image) + binder.viewPlaceholderImage.setImageResource(image) } fun setImageTint(@ColorInt tint: Int?) { - viewPlaceholderImage.setImageTint(tint) + binder.viewPlaceholderImage.setImageTint(tint) } fun setText(text: String) { - viewPlaceholderText.text = text + binder.viewPlaceholderText.text = text } fun setText(@StringRes textRes: Int) { - viewPlaceholderText.setText(textRes) + binder.viewPlaceholderText.setText(textRes) } fun setButtonText(text: String?) { - viewPlaceholderButton.setTextOrHide(text) + binder.viewPlaceholderButton.setTextOrHide(text) } fun setButtonText(@StringRes textRes: Int) { @@ -98,7 +96,7 @@ class PlaceholderView @JvmOverloads constructor( } fun setButtonClickListener(listener: OnClickListener?) { - viewPlaceholderButton.setOnClickListener(listener) + binder.viewPlaceholderButton.setOnClickListener(listener) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/PromoBannerView.kt b/common/src/main/java/io/novafoundation/nova/common/view/PromoBannerView.kt index 0685b7871b..43b6efb9a4 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/PromoBannerView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/PromoBannerView.kt @@ -2,14 +2,11 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewPromoBannerBinding +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_promo_banner.view.promoBannerClose -import kotlinx.android.synthetic.main.view_promo_banner.view.promoBannerDescription -import kotlinx.android.synthetic.main.view_promo_banner.view.promoBannerImage -import kotlinx.android.synthetic.main.view_promo_banner.view.promoBannerTitle class PromoBannerView @JvmOverloads constructor( context: Context, @@ -17,27 +14,27 @@ class PromoBannerView @JvmOverloads constructor( defStyle: Int = 0, ) : ConstraintLayout(context, attrs, defStyle) { - init { - View.inflate(context, R.layout.view_promo_banner, this) + private val binder = ViewPromoBannerBinding.inflate(inflater(), this) + init { attrs?.let(::applyAttributes) } fun setOnCloseClickListener(listener: OnClickListener?) { - promoBannerClose.setOnClickListener(listener) + binder.promoBannerClose.setOnClickListener(listener) } private fun applyAttributes(attrs: AttributeSet) = context.useAttributes(attrs, R.styleable.PromoBannerView) { typedArray -> val image = typedArray.getDrawable(R.styleable.PromoBannerView_promoBanner_image) - promoBannerImage.setImageDrawable(image) + binder.promoBannerImage.setImageDrawable(image) val background = typedArray.getDrawable(R.styleable.PromoBannerView_promoBanner_background) setBackground(background) val title = typedArray.getString(R.styleable.PromoBannerView_promoBanner_title) - promoBannerTitle.text = title + binder.promoBannerTitle.text = title val description = typedArray.getString(R.styleable.PromoBannerView_promoBanner_description) - promoBannerDescription.text = description + binder.promoBannerDescription.text = description } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/SearchToolbar.kt b/common/src/main/java/io/novafoundation/nova/common/view/SearchToolbar.kt index fbcf6a76b5..be3ac17b7b 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/SearchToolbar.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/SearchToolbar.kt @@ -2,12 +2,11 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import android.widget.LinearLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewSearchToolbarBinding +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_search_toolbar.view.searchToolbarCancel -import kotlinx.android.synthetic.main.view_search_toolbar.view.searchToolbarSearch class SearchToolbar @JvmOverloads constructor( context: Context, @@ -15,15 +14,15 @@ class SearchToolbar @JvmOverloads constructor( defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { + private val binder = ViewSearchToolbarBinding.inflate(inflater(), this) + val searchInput - get() = searchToolbarSearch + get() = binder.searchToolbarSearch val cancel - get() = searchToolbarCancel + get() = binder.searchToolbarCancel init { - View.inflate(context, R.layout.view_search_toolbar, this) - orientation = HORIZONTAL setBackgroundResource(R.color.blur_navigation_background) diff --git a/common/src/main/java/io/novafoundation/nova/common/view/SearchView.kt b/common/src/main/java/io/novafoundation/nova/common/view/SearchView.kt index 2c3009ca38..721530cfef 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/SearchView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/SearchView.kt @@ -2,16 +2,15 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import android.widget.EditText import android.widget.LinearLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewSearchBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.onTextChanged import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_search.view.searchClear -import kotlinx.android.synthetic.main.view_search.view.searchContent class SearchView @JvmOverloads constructor( context: Context, @@ -19,23 +18,23 @@ class SearchView @JvmOverloads constructor( defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr), WithContextExtensions { + private val binder = ViewSearchBinding.inflate(inflater(), this) + override val providedContext: Context get() = context val content: EditText - get() = searchContent + get() = binder.searchContent init { - View.inflate(context, R.layout.view_search, this) - background = getRoundedCornerDrawable(fillColorRes = R.color.input_background, cornerSizeDp = 10) orientation = HORIZONTAL content.onTextChanged { - searchClear.setVisible(it.isNotEmpty()) + binder.searchClear.setVisible(it.isNotEmpty()) } - searchClear.setOnClickListener { + binder.searchClear.setOnClickListener { content.text.clear() } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/Switch.kt b/common/src/main/java/io/novafoundation/nova/common/view/Switch.kt index ce0452ac18..b35105f804 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/Switch.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/Switch.kt @@ -2,16 +2,14 @@ package io.novafoundation.nova.common.view import android.content.Context import android.util.AttributeSet -import android.view.View import android.widget.CompoundButton import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewSwitchBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_switch.view.viewSwitchField -import kotlinx.android.synthetic.main.view_switch.view.viewSwitchSubtitle -import kotlinx.android.synthetic.main.view_switch.view.viewSwitchTitle private const val DIVIDER_VISIBLE_DEFAULT = false @@ -21,21 +19,21 @@ class Switch @JvmOverloads constructor( defStyleAttr: Int = 0, ) : ConstraintLayout(context, attrs, defStyleAttr), WithContextExtensions by WithContextExtensions(context) { + private val binder = ViewSwitchBinding.inflate(inflater(), this) + val field: CompoundButton - get() = viewSwitchField + get() = binder.viewSwitchField init { - View.inflate(context, R.layout.view_switch, this) - attrs?.let(::applyAttributes) } fun setTitle(title: String) { - viewSwitchTitle.text = title + binder.viewSwitchTitle.text = title } fun setSubtitle(subtitle: String?) { - viewSwitchSubtitle.setTextOrHide(subtitle) + binder.viewSwitchSubtitle.setTextOrHide(subtitle) } fun setDividerVisible(dividerVisible: Boolean) { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/TableCellView.kt b/common/src/main/java/io/novafoundation/nova/common/view/TableCellView.kt index 49183ef610..fe3505b4d9 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/TableCellView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/TableCellView.kt @@ -17,6 +17,7 @@ import coil.ImageLoader import coil.load import coil.transform.RoundedCornersTransformation import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewTableCellBinding import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.common.domain.ExtendedLoadingState import io.novafoundation.nova.common.utils.dp @@ -27,6 +28,7 @@ import io.novafoundation.nova.common.utils.getResourceIdOrNull import io.novafoundation.nova.common.utils.images.ExtraImageRequestBuilding import io.novafoundation.nova.common.utils.images.Icon import io.novafoundation.nova.common.utils.images.setIcon +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.postToSelf @@ -36,14 +38,6 @@ import io.novafoundation.nova.common.utils.setTextColorRes import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_table_cell.view.barrier -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellContent -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellImage -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellTitle -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellValueDivider -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellValuePrimary -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellValueProgress -import kotlinx.android.synthetic.main.view_table_cell.view.tableCellValueSecondary private const val DRAW_DIVIDER_DEFAULT = true @@ -70,23 +64,25 @@ open class TableCellView @JvmOverloads constructor( } } + private val binder = ViewTableCellBinding.inflate(inflater(), this) + val title: TextView - get() = tableCellTitle + get() = binder.tableCellTitle val valuePrimary: TextView - get() = tableCellValuePrimary + get() = binder.tableCellValuePrimary val valueSecondary: TextView - get() = tableCellValueSecondary + get() = binder.tableCellValueSecondary val image: ImageView - get() = tableCellImage + get() = binder.tableCellImage private val valueProgress: ProgressBar - get() = tableCellValueProgress + get() = binder.tableCellValueProgress private val contentGroup: Group - get() = tableCellContent + get() = binder.tableCellContent private var shouldDrawDivider: Boolean = DRAW_DIVIDER_DEFAULT @@ -95,8 +91,6 @@ open class TableCellView @JvmOverloads constructor( } init { - View.inflate(context, R.layout.view_table_cell, this) - setBackgroundResource(R.drawable.bg_primary_list_item) minHeight = 44.dp(context) @@ -112,11 +106,11 @@ open class TableCellView @JvmOverloads constructor( } fun setTitle(titleRes: Int) { - tableCellTitle.setText(titleRes) + binder.tableCellTitle.setText(titleRes) } fun setTitle(title: String?) { - tableCellTitle.text = title + binder.tableCellTitle.text = title } fun setImage(src: Drawable) { @@ -177,15 +171,15 @@ open class TableCellView @JvmOverloads constructor( """ ) fun setOwnDividerVisible(visible: Boolean) { - tableCellValueDivider.setVisible(visible && shouldDrawDivider) + binder.tableCellValueDivider.setVisible(visible && shouldDrawDivider) } fun setPrimaryValueEndIcon(@DrawableRes icon: Int?, @ColorRes tint: Int? = null) { - tableCellValuePrimary.setDrawableEnd(icon, widthInDp = 16, paddingInDp = 8, tint = tint) + binder.tableCellValuePrimary.setDrawableEnd(icon, widthInDp = 16, paddingInDp = 8, tint = tint) } fun setPrimaryValueStartIcon(@DrawableRes icon: Int?, @ColorRes tint: Int? = null) { - tableCellValuePrimary.setDrawableStart(icon, widthInDp = 16, paddingInDp = 8, tint = tint) + binder.tableCellValuePrimary.setDrawableStart(icon, widthInDp = 16, paddingInDp = 8, tint = tint) } fun setPrimaryValueStyle(style: FieldStyle) { @@ -209,11 +203,11 @@ open class TableCellView @JvmOverloads constructor( } fun setTitleIconEnd(@DrawableRes icon: Int?, tintRes: Int?) { - tableCellTitle.setDrawableEnd(icon, widthInDp = 16, paddingInDp = 4, tint = tintRes) + binder.tableCellTitle.setDrawableEnd(icon, widthInDp = 16, paddingInDp = 4, tint = tintRes) } fun setTitleIconStart(@DrawableRes icon: Int?, tintRes: Int?) { - tableCellTitle.setDrawableStart(icon, widthInDp = 16, paddingInDp = 4, tint = tintRes) + binder.tableCellTitle.setDrawableStart(icon, widthInDp = 16, paddingInDp = 4, tint = tintRes) } fun showValue(primary: CharSequence, secondary: CharSequence? = null) { @@ -232,14 +226,14 @@ open class TableCellView @JvmOverloads constructor( constraintSet.clone(this) if (ellipsisable) { - constraintSet.connect(tableCellTitle.id, ConstraintSet.END, barrier.id, ConstraintSet.START, 16.dp(context)) - constraintSet.clear(tableCellValuePrimary.id, ConstraintSet.START) - constraintSet.constrainedWidth(tableCellTitle.id, true) - constraintSet.setHorizontalBias(tableCellTitle.id, 0f) + constraintSet.connect(binder.tableCellTitle.id, ConstraintSet.END, binder.barrier.id, ConstraintSet.START, 16.dp(context)) + constraintSet.clear(binder.tableCellValuePrimary.id, ConstraintSet.START) + constraintSet.constrainedWidth(binder.tableCellTitle.id, true) + constraintSet.setHorizontalBias(binder.tableCellTitle.id, 0f) } else { - constraintSet.clear(tableCellTitle.id, ConstraintSet.END) - constraintSet.connect(tableCellValuePrimary.id, ConstraintSet.START, tableCellTitle.id, ConstraintSet.END, 16.dp(context)) - constraintSet.constrainedWidth(tableCellTitle.id, false) + constraintSet.clear(binder.tableCellTitle.id, ConstraintSet.END) + constraintSet.connect(binder.tableCellValuePrimary.id, ConstraintSet.START, binder.tableCellTitle.id, ConstraintSet.END, 16.dp(context)) + constraintSet.constrainedWidth(binder.tableCellTitle.id, false) } constraintSet.applyTo(this) } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/TapToViewContainer.kt b/common/src/main/java/io/novafoundation/nova/common/view/TapToViewContainer.kt index d591195457..61b9881782 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/TapToViewContainer.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/TapToViewContainer.kt @@ -14,15 +14,14 @@ import android.widget.FrameLayout import androidx.annotation.DrawableRes import androidx.core.view.isVisible import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewTapToViewContainerBinding import io.novafoundation.nova.common.utils.dpF import io.novafoundation.nova.common.utils.getParcelableCompat import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_tap_to_view_container.view.tapToViewContainer -import kotlinx.android.synthetic.main.view_tap_to_view_container.view.tapToViewHiddenContent -import kotlinx.android.synthetic.main.view_tap_to_view_container.view.tapToViewSbutitle -import kotlinx.android.synthetic.main.view_tap_to_view_container.view.tapToViewTitle + import kotlin.math.roundToInt private const val SUPER_STATE = "super_state" @@ -34,6 +33,8 @@ open class TapToViewContainer @JvmOverloads constructor( defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { + private val binder = ViewTapToViewContainerBinding.inflate(inflater(), this) + private var onShowContentClicked: OnClickListener? = null private var isContentVisible = false @@ -47,13 +48,12 @@ open class TapToViewContainer @JvmOverloads constructor( } init { - inflate(context, R.layout.view_tap_to_view_container, this) layoutTransition = LayoutTransition() // To animate this layout size change and children visibility - tapToViewContainer.setOnClickListener { + binder.tapToViewContainer.setOnClickListener { isContentVisible = true onShowContentClicked?.onClick(this) - tapToViewContainer.visibility = GONE + binder.tapToViewContainer.visibility = GONE requestLayout() } @@ -82,8 +82,8 @@ open class TapToViewContainer @JvmOverloads constructor( * Measure the height of the tap to view container background based on the its background aspect ratio */ private fun measureTapToViewContainerBackground(width: Int): Int { - val tapToViewBackgroundHeight = tapToViewContainer.background?.intrinsicHeight ?: 0 - val tabToViewBackgroundWidth = tapToViewContainer.background?.intrinsicWidth ?: 0 + val tapToViewBackgroundHeight = binder.tapToViewContainer.background?.intrinsicHeight ?: 0 + val tabToViewBackgroundWidth = binder.tapToViewContainer.background?.intrinsicWidth ?: 0 val height = tapToViewBackgroundHeight * (width.toFloat() / tabToViewBackgroundWidth.toFloat()) return height.roundToInt() } @@ -102,7 +102,7 @@ open class TapToViewContainer @JvmOverloads constructor( if (child.id == R.id.tapToViewContainer || child.id == R.id.tapToViewHiddenContent) { super.addView(child, params) } else { - tapToViewHiddenContent.addView(child, params) + binder.tapToViewHiddenContent.addView(child, params) } } @@ -120,7 +120,7 @@ open class TapToViewContainer @JvmOverloads constructor( super.onRestoreInstanceState(state.getParcelableCompat(SUPER_STATE)) isContentVisible = state.getBoolean(REVEAL_CONTAINER_VISIBILITY) - tapToViewContainer.isVisible = !isContentVisible + binder.tapToViewContainer.isVisible = !isContentVisible } else { super.onRestoreInstanceState(state) } @@ -133,15 +133,15 @@ open class TapToViewContainer @JvmOverloads constructor( } fun setTitleOrHide(title: String?) { - tapToViewTitle.setTextOrHide(title) + binder.tapToViewTitle.setTextOrHide(title) } fun setSubtitleOrHide(subtitle: String?) { - tapToViewSbutitle.setTextOrHide(subtitle) + binder.tapToViewSbutitle.setTextOrHide(subtitle) } fun setTapToViewBackground(@DrawableRes background: Int) { - tapToViewContainer.setBackgroundResource(background) + binder.tapToViewContainer.setBackgroundResource(background) requestLayout() } @@ -152,7 +152,7 @@ open class TapToViewContainer @JvmOverloads constructor( fun showContent(show: Boolean) { isContentVisible = show - tapToViewContainer.isVisible = !show + binder.tapToViewContainer.isVisible = !show requestLayout() } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/TipsInputField.kt b/common/src/main/java/io/novafoundation/nova/common/view/TipsInputField.kt index 57946789a1..2baa9a697b 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/TipsInputField.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/TipsInputField.kt @@ -17,7 +17,9 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.view.isVisible import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewTipsInputBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.onTextChanged @@ -25,11 +27,6 @@ import io.novafoundation.nova.common.utils.setImageTintRes import io.novafoundation.nova.common.utils.useAttributes import io.novafoundation.nova.common.view.shape.getInputBackground import io.novafoundation.nova.common.view.shape.getInputBackgroundError -import kotlinx.android.synthetic.main.view_tips_input.view.tipsInputClear -import kotlinx.android.synthetic.main.view_tips_input.view.tipsInputContainer -import kotlinx.android.synthetic.main.view_tips_input.view.tipsInputError -import kotlinx.android.synthetic.main.view_tips_input.view.tipsInputField -import kotlinx.android.synthetic.main.view_tips_input.view.tipsInputFieldContainer class TipsInputField @JvmOverloads constructor( context: Context, @@ -37,6 +34,8 @@ class TipsInputField @JvmOverloads constructor( defStyle: Int = 0, ) : LinearLayout(context, attrs, defStyle), WithContextExtensions by WithContextExtensions(context), ValidatableInputField { + private val binder = ViewTipsInputBinding.inflate(inflater(), this) + private var postfix: String? = null private var postfixPadding = 4.dp private var postfixPosition: PointF? = null @@ -44,17 +43,16 @@ class TipsInputField @JvmOverloads constructor( private val textPaint: Paint val content: EditText - get() = tipsInputField + get() = binder.tipsInputField init { orientation = VERTICAL - View.inflate(context, R.layout.view_tips_input, this) - tipsInputFieldContainer.setAddStatesFromChildren(true) - tipsInputFieldContainer.background = context.getInputBackground() + binder.tipsInputFieldContainer.setAddStatesFromChildren(true) + binder.tipsInputFieldContainer.background = context.getInputBackground() content.onTextChanged { - tipsInputClear.isVisible = it.isNotEmpty() - tipsInputContainer.isVisible = it.isEmpty() + binder.tipsInputClear.isVisible = it.isNotEmpty() + binder.tipsInputContainer.isVisible = it.isEmpty() measurePostfix(it) invalidate() } @@ -63,7 +61,7 @@ class TipsInputField @JvmOverloads constructor( color = content.currentTextColor } - tipsInputClear.setOnClickListener { content.text = null } + binder.tipsInputClear.setOnClickListener { content.text = null } attrs?.let(::applyAttributes) setWillNotDraw(false) @@ -95,7 +93,7 @@ class TipsInputField @JvmOverloads constructor( } fun clearTips() { - tipsInputContainer.removeAllViews() + binder.tipsInputContainer.removeAllViews() } fun addIconTip(@DrawableRes iconRes: Int, @ColorRes tintRes: Int? = null, onClick: OnClickListener): View { @@ -105,7 +103,7 @@ class TipsInputField @JvmOverloads constructor( view.setPadding(8.dp, 0.dp, 8.dp, 0.dp) view.setImageTintRes(tintRes) view.scaleType = ImageView.ScaleType.CENTER_INSIDE - tipsInputContainer.addView(view) + binder.tipsInputContainer.addView(view) return view } @@ -117,7 +115,7 @@ class TipsInputField @JvmOverloads constructor( view.setPadding(12.dp, 0.dp, 12.dp, 0.dp) tintRes?.let { view.setTextColor(context.getColor(it)) } view.gravity = Gravity.CENTER - tipsInputContainer.addView(view) + binder.tipsInputContainer.addView(view) return view } @@ -131,21 +129,21 @@ class TipsInputField @JvmOverloads constructor( } override fun showError(error: String) { - tipsInputError.makeVisible() - tipsInputError.text = error + binder.tipsInputError.makeVisible() + binder.tipsInputError.text = error val color = context.getColor(R.color.text_negative) content.setTextColor(color) textPaint.color = color - tipsInputFieldContainer.background = context.getInputBackgroundError() + binder.tipsInputFieldContainer.background = context.getInputBackgroundError() invalidate() } override fun hideError() { - tipsInputError.makeGone() + binder.tipsInputError.makeGone() val color = context.getColor(R.color.text_primary) content.setTextColor(color) textPaint.color = color - tipsInputFieldContainer.background = context.getInputBackground() + binder.tipsInputFieldContainer.background = context.getInputBackground() invalidate() } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/TitledSearchToolbar.kt b/common/src/main/java/io/novafoundation/nova/common/view/TitledSearchToolbar.kt index 3365fad573..569d21d6ff 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/TitledSearchToolbar.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/TitledSearchToolbar.kt @@ -6,8 +6,8 @@ import android.view.View import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R -import kotlinx.android.synthetic.main.view_titled_search_toolbar.view.titledSearchToolbar -import kotlinx.android.synthetic.main.view_titled_search_toolbar.view.titledSearchToolbarField +import io.novafoundation.nova.common.databinding.ViewTitledSearchToolbarBinding +import io.novafoundation.nova.common.utils.inflater class TitledSearchToolbar @JvmOverloads constructor( context: Context, @@ -15,15 +15,15 @@ class TitledSearchToolbar @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr) { + private val binder = ViewTitledSearchToolbarBinding.inflate(inflater(), this, true) + val toolbar: Toolbar - get() = titledSearchToolbar + get() = binder.titledSearchToolbar val searchField: SearchView - get() = titledSearchToolbarField + get() = binder.titledSearchToolbarField init { - View.inflate(context, R.layout.view_titled_search_toolbar, this) - applyAttributes(attrs) } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/Toolbar.kt b/common/src/main/java/io/novafoundation/nova/common/view/Toolbar.kt index 5a3b77866a..e3e767bf72 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/Toolbar.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/Toolbar.kt @@ -15,22 +15,15 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.ContextCompat import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewToolbarBinding import io.novafoundation.nova.common.utils.dp import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.utils.makeVisible import io.novafoundation.nova.common.utils.setImageTintRes import io.novafoundation.nova.common.utils.setTextColorRes import io.novafoundation.nova.common.utils.setVisible -import kotlinx.android.synthetic.main.view_toolbar.view.backImg -import kotlinx.android.synthetic.main.view_toolbar.view.rightActionContainer -import kotlinx.android.synthetic.main.view_toolbar.view.rightImg -import kotlinx.android.synthetic.main.view_toolbar.view.rightText -import kotlinx.android.synthetic.main.view_toolbar.view.titleTv -import kotlinx.android.synthetic.main.view_toolbar.view.toolbarContainer -import kotlinx.android.synthetic.main.view_toolbar.view.toolbarCustomActions -import kotlinx.android.synthetic.main.view_toolbar.view.toolbarDivider -import kotlinx.android.synthetic.main.view_toolbar.view.toolbarProgress class Toolbar @JvmOverloads constructor( context: Context, @@ -38,15 +31,15 @@ class Toolbar @JvmOverloads constructor( defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { + private val binder = ViewToolbarBinding.inflate(inflater(), this, true) + val rightActionText: TextView - get() = rightText + get() = binder.rightText val titleView: TextView - get() = titleTv + get() = binder.titleTv init { - View.inflate(context, R.layout.view_toolbar, this) - applyAttributes(attrs) } @@ -70,73 +63,73 @@ class Toolbar @JvmOverloads constructor( setHomeButtonVisibility(homeButtonVisible) val dividerVisible = typedArray.getBoolean(R.styleable.Toolbar_dividerVisible, true) - toolbarDivider.setVisible(dividerVisible) + binder.toolbarDivider.setVisible(dividerVisible) val backgroundAttrDrawable = typedArray.getDrawable(R.styleable.Toolbar_contentBackground) ?: ColorDrawable( context.getColor(R.color.secondary_screen_background) ) - toolbarContainer.background = backgroundAttrDrawable + binder.toolbarContainer.background = backgroundAttrDrawable val textAppearance = typedArray.getResourceIdOrNull(R.styleable.Toolbar_titleTextAppearance) - textAppearance?.let(titleTv::setTextAppearance) + textAppearance?.let(binder.titleTv::setTextAppearance) typedArray.recycle() } } fun setHomeButtonIcon(icon: Drawable) { - backImg.setImageDrawable(icon) + binder.backImg.setImageDrawable(icon) } fun setTextRight(action: String) { - rightImg.makeGone() + binder.rightImg.makeGone() - rightText.makeVisible() - rightText.text = action + binder.rightText.makeVisible() + binder.rightText.text = action } fun setRightIconVisible(visible: Boolean) { - rightImg.setVisible(visible) + binder.rightImg.setVisible(visible) } fun showProgress(visible: Boolean) { - toolbarProgress.setVisible(visible) - rightActionContainer.setVisible(!visible) + binder.toolbarProgress.setVisible(visible) + binder.rightActionContainer.setVisible(!visible) } fun setTitleIcon(drawable: Drawable?) { - titleTv.compoundDrawablePadding = 8.dp(context) - titleTv.setCompoundDrawables(drawable, null, null, null) + binder.titleTv.compoundDrawablePadding = 8.dp(context) + binder.titleTv.setCompoundDrawables(drawable, null, null, null) } fun setTitle(title: CharSequence?) { - titleTv.text = title + binder.titleTv.text = title } fun setTitle(@StringRes titleRes: Int) { - titleTv.setText(titleRes) + binder.titleTv.setText(titleRes) } fun showHomeButton() { - backImg.makeVisible() + binder.backImg.makeVisible() } fun hideHomeButton() { - backImg.makeGone() + binder.backImg.makeGone() } fun setHomeButtonListener(listener: (View) -> Unit) { - backImg.setOnClickListener(listener) + binder.backImg.setOnClickListener(listener) } fun hideRightAction() { - rightImg.makeGone() - rightText.makeGone() + binder.rightImg.makeGone() + binder.rightText.makeGone() } fun setRightActionTint(@ColorRes colorRes: Int) { - rightImg.setImageTintRes(colorRes) - rightText.setTextColorRes(colorRes) + binder.rightImg.setImageTintRes(colorRes) + binder.rightText.setTextColorRes(colorRes) } fun setRightIconRes(@DrawableRes iconRes: Int) { @@ -145,19 +138,19 @@ class Toolbar @JvmOverloads constructor( } fun setRightIconDrawable(assetIconDrawable: Drawable) { - rightText.makeGone() + binder.rightText.makeGone() - rightImg.makeVisible() - rightImg.setImageDrawable(assetIconDrawable) + binder.rightImg.makeVisible() + binder.rightImg.setImageDrawable(assetIconDrawable) } fun setRightActionClickListener(listener: (View) -> Unit) { - rightImg.setOnClickListener(listener) - rightText.setOnClickListener(listener) + binder.rightImg.setOnClickListener(listener) + binder.rightText.setOnClickListener(listener) } fun setHomeButtonVisibility(visible: Boolean) { - backImg.visibility = if (visible) View.VISIBLE else View.GONE + binder.backImg.visibility = if (visible) View.VISIBLE else View.GONE } fun addCustomAction(@DrawableRes icon: Int, onClick: OnClickListener): ImageView { @@ -167,7 +160,7 @@ class Toolbar @JvmOverloads constructor( layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply { val verticalMargin = 16.dp(context) - val endMarginDp = if (this@Toolbar.toolbarCustomActions.childCount == 0) 16 else 10 + val endMarginDp = if (binder.toolbarCustomActions.childCount == 0) 16 else 10 val endMargin = endMarginDp.dp(context) val startMargin = 10.dp(context) @@ -178,14 +171,14 @@ class Toolbar @JvmOverloads constructor( setOnClickListener(onClick) } - toolbarCustomActions.makeVisible() - toolbarCustomActions.addView(actionView, 0) + binder.toolbarCustomActions.makeVisible() + binder.toolbarCustomActions.addView(actionView, 0) return actionView } fun setRightActionEnabled(enabled: Boolean) { - rightImg.isEnabled = enabled - rightText.isEnabled = enabled + binder.rightImg.isEnabled = enabled + binder.rightText.isEnabled = enabled } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/WarningCheckBox.kt b/common/src/main/java/io/novafoundation/nova/common/view/WarningCheckBox.kt index 8f1a3d0156..74f4271c43 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/WarningCheckBox.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/WarningCheckBox.kt @@ -6,14 +6,14 @@ import android.widget.CompoundButton import android.widget.LinearLayout import androidx.annotation.DrawableRes import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewWarningCheckboxBinding import io.novafoundation.nova.common.utils.CheckableListener import io.novafoundation.nova.common.utils.getColorOrNull import io.novafoundation.nova.common.utils.getResourceIdOrNull +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setImageResourceOrHide import io.novafoundation.nova.common.utils.setImageTint import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_warning_checkbox.view.warningCheckBoxCheckBox -import kotlinx.android.synthetic.main.view_warning_checkbox.view.warningCheckBoxIcon class WarningCheckBox @JvmOverloads constructor( context: Context, @@ -21,9 +21,9 @@ class WarningCheckBox @JvmOverloads constructor( defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr), CheckableListener { - init { - inflate(context, R.layout.view_warning_checkbox, this) + private val binder = ViewWarningCheckboxBinding.inflate(inflater(), this) + init { orientation = VERTICAL setBackgroundResource(R.drawable.secondary_container_ripple_background) addStatesFromChildren() @@ -32,19 +32,19 @@ class WarningCheckBox @JvmOverloads constructor( } fun setText(text: CharSequence?) { - warningCheckBoxCheckBox.text = text + binder.warningCheckBoxCheckBox.text = text } fun setIconTintColor(color: Int) { - warningCheckBoxIcon.setImageTint(color) + binder.warningCheckBoxIcon.setImageTint(color) } fun setIcon(@DrawableRes iconRes: Int?) { - warningCheckBoxIcon.setImageResourceOrHide(iconRes) + binder.warningCheckBoxIcon.setImageResourceOrHide(iconRes) } override fun setOnCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener) { - warningCheckBoxCheckBox.setOnCheckedChangeListener(listener) + binder.warningCheckBoxCheckBox.setOnCheckedChangeListener(listener) } private fun applyAttributes(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.WarningCheckBox) { @@ -58,14 +58,14 @@ class WarningCheckBox @JvmOverloads constructor( } override fun setChecked(checked: Boolean) { - warningCheckBoxCheckBox.isChecked = checked + binder.warningCheckBoxCheckBox.isChecked = checked } override fun isChecked(): Boolean { - return warningCheckBoxCheckBox.isChecked + return binder.warningCheckBoxCheckBox.isChecked } override fun toggle() { - warningCheckBoxCheckBox.toggle() + binder.warningCheckBoxCheckBox.toggle() } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/ActionNotAllowedBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/ActionNotAllowedBottomSheet.kt index 207a9f43a5..5aeb4d4b3f 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/ActionNotAllowedBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/ActionNotAllowedBottomSheet.kt @@ -2,47 +2,43 @@ package io.novafoundation.nova.common.view.bottomSheet import android.content.Context import android.os.Bundle +import android.view.LayoutInflater import android.widget.ImageView import android.widget.TextView import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.view.setPadding import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.BottomSheetActionNotAllowedBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.setImageTintRes import io.novafoundation.nova.common.view.PrimaryButton -import kotlinx.android.synthetic.main.bottom_sheet_action_not_allowed.actionNotAllowedImage -import kotlinx.android.synthetic.main.bottom_sheet_action_not_allowed.actionNotAllowedOk -import kotlinx.android.synthetic.main.bottom_sheet_action_not_allowed.actionNotAllowedSubtitle -import kotlinx.android.synthetic.main.bottom_sheet_action_not_allowed.actionNotAllowedTitle open class ActionNotAllowedBottomSheet( context: Context, private val onSuccess: () -> Unit, -) : BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context) { +) : BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context) { + + override val binder = BottomSheetActionNotAllowedBinding.inflate(LayoutInflater.from(context)) val iconView: ImageView - get() = actionNotAllowedImage + get() = binder.actionNotAllowedImage val titleView: TextView - get() = actionNotAllowedTitle + get() = binder.actionNotAllowedTitle val subtitleView: TextView - get() = actionNotAllowedSubtitle + get() = binder.actionNotAllowedSubtitle val buttonView: PrimaryButton - get() = actionNotAllowedOk - - init { - setContentView(R.layout.bottom_sheet_action_not_allowed) - } + get() = binder.actionNotAllowedOk override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setOnDismissListener { onSuccess() } - actionNotAllowedOk.setOnClickListener { + binder.actionNotAllowedOk.setOnClickListener { dismiss() } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/BaseBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/BaseBottomSheet.kt index 6c153a41e6..1104fc33af 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/BaseBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/BaseBottomSheet.kt @@ -15,8 +15,9 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import androidx.viewbinding.ViewBinding -abstract class BaseBottomSheet( +abstract class BaseBottomSheet( context: Context, style: Int = R.style.BottomSheetDialog, private val onCancel: (() -> Unit)? = null, @@ -25,6 +26,8 @@ abstract class BaseBottomSheet( DialogExtensions, CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.Main) { + protected abstract val binder: B + private val backgroundAccessObserver: BackgroundAccessObserver final override val dialogInterface: DialogInterface @@ -33,6 +36,8 @@ abstract class BaseBottomSheet( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContentView(binder.root) + window?.decorView ?.findViewById(R.id.touch_outside) ?.isFocusable = false diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/action/ActionBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/action/ActionBottomSheet.kt index 4542620b7f..7749d1ca49 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/action/ActionBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/action/ActionBottomSheet.kt @@ -1,26 +1,24 @@ package io.novafoundation.nova.common.view.bottomSheet.action import android.content.Context +import android.view.LayoutInflater import android.widget.CheckBox import android.widget.ImageView import android.widget.TextView import androidx.annotation.DrawableRes import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.BottomSheetActionBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.makeGone import io.novafoundation.nova.common.view.PrimaryButton import io.novafoundation.nova.common.view.bottomSheet.BaseBottomSheet -import kotlinx.android.synthetic.main.bottom_sheet_action.actionBottomSheetCheckBox -import kotlinx.android.synthetic.main.bottom_sheet_action.actionBottomSheetImage -import kotlinx.android.synthetic.main.bottom_sheet_action.actionBottomSheetNeutralBtn -import kotlinx.android.synthetic.main.bottom_sheet_action.actionBottomSheetPositiveBtn -import kotlinx.android.synthetic.main.bottom_sheet_action.actionBottomSheetSubtitle -import kotlinx.android.synthetic.main.bottom_sheet_action.actionBottomSheetTitle class ActionBottomSheet( context: Context, payload: Payload -) : BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context) { +) : BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context) { + + override val binder: BottomSheetActionBinding = BottomSheetActionBinding.inflate(LayoutInflater.from(context)) class Payload( @DrawableRes val imageRes: Int, @@ -47,26 +45,24 @@ class ActionBottomSheet( } private val iconView: ImageView - get() = actionBottomSheetImage + get() = binder.actionBottomSheetImage private val titleView: TextView - get() = actionBottomSheetTitle + get() = binder.actionBottomSheetTitle private val subtitleView: TextView - get() = actionBottomSheetSubtitle + get() = binder.actionBottomSheetSubtitle private val neutralButton: PrimaryButton - get() = actionBottomSheetNeutralBtn + get() = binder.actionBottomSheetNeutralBtn private val actionButton: PrimaryButton - get() = actionBottomSheetPositiveBtn + get() = binder.actionBottomSheetPositiveBtn private val checkBox: CheckBox - get() = actionBottomSheetCheckBox + get() = binder.actionBottomSheetCheckBox init { - setContentView(R.layout.bottom_sheet_action) - iconView.setImageResource(payload.imageRes) titleView.text = payload.title subtitleView.text = payload.subtitle diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheet.kt index 884a753acc..bc79dd044a 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheet.kt @@ -2,25 +2,23 @@ package io.novafoundation.nova.common.view.bottomSheet.description import android.content.Context import android.os.Bundle +import android.view.LayoutInflater import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.BottomSheetDescriptionBinding import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.view.bottomSheet.BaseBottomSheet -import kotlinx.android.synthetic.main.bottom_sheet_description.sheetDescriptionDetails -import kotlinx.android.synthetic.main.bottom_sheet_description.sheetDescriptionTitle class DescriptionBottomSheet( context: Context, val titleRes: Int, val descriptionRes: Int -) : BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context) { +) : BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context) { - init { - setContentView(R.layout.bottom_sheet_description) - } + override val binder: BottomSheetDescriptionBinding = BottomSheetDescriptionBinding.inflate(LayoutInflater.from(context)) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - sheetDescriptionTitle.setText(titleRes) - sheetDescriptionDetails.setText(descriptionRes) + binder.sheetDescriptionTitle.setText(titleRes) + binder.sheetDescriptionDetails.setText(descriptionRes) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheetLauncher.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheetLauncher.kt index 99750950c9..d6a1844265 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheetLauncher.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/description/DescriptionBottomSheetLauncher.kt @@ -27,7 +27,7 @@ class RealDescriptionBottomSheetLauncher : DescriptionBottomSheetLauncher { } } -fun BaseFragment<*>.observeDescription(launcher: DescriptionBottomSheetLauncher) { +fun BaseFragment<*, *>.observeDescription(launcher: DescriptionBottomSheetLauncher) { launcher.showDescriptionEvent.observeEvent { event -> val dialog = DescriptionBottomSheet( context = requireContext(), diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListBottomSheet.kt index 4dd6b54d50..9c86bda0a9 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListBottomSheet.kt @@ -2,6 +2,7 @@ package io.novafoundation.nova.common.view.bottomSheet.list.dynamic import android.content.Context import android.os.Bundle +import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout import androidx.annotation.CallSuper @@ -9,17 +10,12 @@ import androidx.annotation.DrawableRes import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.BottomSheetDynamicListBinding import io.novafoundation.nova.common.utils.DialogExtensions import io.novafoundation.nova.common.utils.WithContextExtensions import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.view.bottomSheet.BaseBottomSheet -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetContent -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetHeader -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetItemContainer -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetRightAction -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetSubtitle -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetTitle typealias ClickHandler = (BaseDynamicListBottomSheet, T) -> Unit @@ -35,48 +31,44 @@ class ReferentialEqualityDiffCallBack : DiffUtil.ItemCallback() { } abstract class BaseDynamicListBottomSheet(context: Context) : - BaseBottomSheet(context, R.style.BottomSheetDialog), + BaseBottomSheet(context, R.style.BottomSheetDialog), WithContextExtensions by WithContextExtensions(context), DialogExtensions { + override val binder: BottomSheetDynamicListBinding = BottomSheetDynamicListBinding.inflate(LayoutInflater.from(context)) + protected val container: LinearLayout - get() = dynamicListSheetItemContainer + get() = binder.dynamicListSheetItemContainer protected val headerView: View - get() = dynamicListSheetHeader + get() = binder.dynamicListSheetHeader protected val recyclerView: RecyclerView - get() = dynamicListSheetContent - - @CallSuper - override fun onCreate(savedInstanceState: Bundle?) { - setContentView(R.layout.bottom_sheet_dynamic_list) - super.onCreate(savedInstanceState) - } + get() = binder.dynamicListSheetContent final override fun setTitle(title: CharSequence?) { - dynamicListSheetTitle.text = title + binder.dynamicListSheetTitle.text = title } fun setSubtitle(subtitle: CharSequence?) { - dynamicListSheetSubtitle.setTextOrHide(subtitle) + binder.dynamicListSheetSubtitle.setTextOrHide(subtitle) } final override fun setTitle(titleId: Int) { - dynamicListSheetTitle.setText(titleId) + binder.dynamicListSheetTitle.setText(titleId) } fun setupRightAction( @DrawableRes drawableRes: Int, onClickListener: View.OnClickListener ) { - dynamicListSheetRightAction.setImageResource(drawableRes) - dynamicListSheetRightAction.setVisible(true) - dynamicListSheetRightAction.setOnClickListener(onClickListener) + binder.dynamicListSheetRightAction.setImageResource(drawableRes) + binder.dynamicListSheetRightAction.setVisible(true) + binder.dynamicListSheetRightAction.setOnClickListener(onClickListener) } } -abstract class DynamicListBottomSheet( +abstract class DynamicListBottomSheet( context: Context, private val payload: Payload, private val diffCallback: DiffUtil.ItemCallback, @@ -91,10 +83,10 @@ abstract class DynamicListBottomSheet( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - dynamicListSheetContent.setHasFixedSize(true) + binder.dynamicListSheetContent.setHasFixedSize(true) val adapter = DynamicListSheetAdapter(payload.selected, this, diffCallback, holderCreator()) - dynamicListSheetContent.adapter = adapter + binder.dynamicListSheetContent.adapter = adapter adapter.submitList(payload.data) diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListSheetAdapter.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListSheetAdapter.kt index 065dc20ecb..36625d0be8 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListSheetAdapter.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/dynamic/DynamicListSheetAdapter.kt @@ -9,7 +9,7 @@ import kotlinx.android.extensions.LayoutContainer typealias HolderCreator = (parentView: ViewGroup) -> DynamicListSheetAdapter.Holder -class DynamicListSheetAdapter( +class DynamicListSheetAdapter( private val selected: T?, private val handler: DynamicListBottomSheet, private val diffCallback: DiffUtil.ItemCallback, diff --git a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/fixed/FixedListBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/fixed/FixedListBottomSheet.kt index 800f15e87a..7def87dbf3 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/fixed/FixedListBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/bottomSheet/list/fixed/FixedListBottomSheet.kt @@ -1,93 +1,78 @@ package io.novafoundation.nova.common.view.bottomSheet.list.fixed import android.content.Context -import android.os.Bundle +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView -import androidx.annotation.CallSuper import androidx.annotation.DrawableRes -import androidx.annotation.LayoutRes import androidx.annotation.StringRes +import androidx.viewbinding.ViewBinding import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.BottomSheeetFixedListBinding +import io.novafoundation.nova.common.databinding.ItemSheetDescriptiveActionBinding +import io.novafoundation.nova.common.databinding.ItemSheetIconicLabelBinding +import io.novafoundation.nova.common.databinding.ItemSheetSwitcherBinding import io.novafoundation.nova.common.utils.dp -import io.novafoundation.nova.common.utils.inflateChild import io.novafoundation.nova.common.utils.setDrawableEnd import io.novafoundation.nova.common.utils.setDrawableStart import io.novafoundation.nova.common.utils.setTextOrHide import io.novafoundation.nova.common.utils.setVisible import io.novafoundation.nova.common.view.bottomSheet.BaseBottomSheet -import kotlinx.android.synthetic.main.bottom_sheeet_fixed_list.fixedListSheetItemContainer -import kotlinx.android.synthetic.main.bottom_sheeet_fixed_list.fixedListSheetTitle -import kotlinx.android.synthetic.main.item_sheet_descriptive_action.view.itemSheetDescriptiveActionArrow -import kotlinx.android.synthetic.main.item_sheet_descriptive_action.view.itemSheetDescriptiveActionIcon -import kotlinx.android.synthetic.main.item_sheet_descriptive_action.view.itemSheetDescriptiveActionSubtitle -import kotlinx.android.synthetic.main.item_sheet_descriptive_action.view.itemSheetDescriptiveActionTitle -import kotlinx.android.synthetic.main.item_sheet_iconic_label.view.itemExternalActionContent -import kotlinx.android.synthetic.main.item_sheet_switcher.view.itemSheetSwitcher - -typealias ViewGetter = FixedListBottomSheet.() -> V - -abstract class FixedListBottomSheet( + +typealias ViewGetter = FixedListBottomSheet.ViewConfiguration.() -> V + +abstract class FixedListBottomSheet( context: Context, - onCancel: (() -> Unit)? = null, - private val viewConfiguration: ViewConfiguration = ViewConfiguration.default() -) : BaseBottomSheet(context, onCancel = onCancel) { - - class ViewConfiguration( - @LayoutRes val layout: Int, - val container: ViewGetter, - val title: ViewGetter, + private val viewConfiguration: ViewConfiguration, + onCancel: (() -> Unit)? = null +) : BaseBottomSheet(context, onCancel = onCancel) { + + class ViewConfiguration( + val configurationBinder: B, + val container: ViewGetter, + val title: ViewGetter, ) { companion object { - fun default() = ViewConfiguration( - layout = R.layout.bottom_sheeet_fixed_list, - container = { fixedListSheetItemContainer }, - title = { fixedListSheetTitle }, + fun default(context: Context) = ViewConfiguration( + configurationBinder = BottomSheeetFixedListBinding.inflate(LayoutInflater.from(context)), + container = { configurationBinder.fixedListSheetItemContainer }, + title = { configurationBinder.fixedListSheetTitle }, ) } } - init { - setContentView(viewConfiguration.layout) - } - - @CallSuper - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - } + override val binder: B = viewConfiguration.configurationBinder final override fun setContentView(layoutResId: Int) { super.setContentView(layoutResId) } override fun setTitle(@StringRes titleRes: Int) { - viewConfiguration.title(this).setText(titleRes) + viewConfiguration.title(viewConfiguration).setText(titleRes) } override fun setTitle(title: CharSequence?) { - viewConfiguration.title(this).setTextOrHide(title?.toString()) + viewConfiguration.title(viewConfiguration).setTextOrHide(title?.toString()) } - fun item(@LayoutRes layoutRes: Int, builder: (View) -> Unit) { - val container = viewConfiguration.container(this) - - val view = container.inflateChild(layoutRes) + fun item(binder: IB, builder: (IB) -> Unit) { + val container = viewConfiguration.container(viewConfiguration) - builder.invoke(view) + builder.invoke(binder) - container.addView(view) + container.addView(binder.root) } fun addItem(view: View) { - val container = viewConfiguration.container(this) + val container = viewConfiguration.container(viewConfiguration) container.addView(view) } fun item(view: T, builder: (T) -> Unit) { builder.invoke(view) - viewConfiguration.container(this).addView(view) + viewConfiguration.container(viewConfiguration).addView(view) } fun getCommonPadding(): Int { @@ -95,19 +80,19 @@ abstract class FixedListBottomSheet( } } -fun FixedListBottomSheet.textItem( +fun FixedListBottomSheet<*>.textItem( @DrawableRes iconRes: Int, title: String, showArrow: Boolean = false, applyIconTint: Boolean = true, onClick: (View) -> Unit, ) { - item(R.layout.item_sheet_iconic_label) { view -> - view.itemExternalActionContent.text = title + item(ItemSheetIconicLabelBinding.inflate(LayoutInflater.from(context))) { itemBinder -> + itemBinder.itemExternalActionContent.text = title val paddingInDp = 12 - view.itemExternalActionContent.setDrawableStart( + itemBinder.itemExternalActionContent.setDrawableStart( drawableRes = iconRes, widthInDp = 24, tint = R.color.icon_primary.takeIf { applyIconTint }, @@ -115,7 +100,7 @@ fun FixedListBottomSheet.textItem( ) if (showArrow) { - view.itemExternalActionContent.setDrawableEnd( + itemBinder.itemExternalActionContent.setDrawableEnd( drawableRes = R.drawable.ic_chevron_right, widthInDp = 24, tint = R.color.icon_secondary, @@ -123,11 +108,11 @@ fun FixedListBottomSheet.textItem( ) } - view.setDismissingClickListener(onClick) + itemBinder.root.setDismissingClickListener(onClick) } } -fun FixedListBottomSheet.textWithDescriptionItem( +fun FixedListBottomSheet<*>.textWithDescriptionItem( title: String, description: String, @DrawableRes iconRes: Int, @@ -135,23 +120,23 @@ fun FixedListBottomSheet.textWithDescriptionItem( showArrowWhenEnabled: Boolean = false, onClick: (View) -> Unit, ) { - item(R.layout.item_sheet_descriptive_action) { view -> - view.itemSheetDescriptiveActionTitle.text = title - view.itemSheetDescriptiveActionSubtitle.text = description + item(ItemSheetDescriptiveActionBinding.inflate(LayoutInflater.from(context))) { itemBinder -> + itemBinder.itemSheetDescriptiveActionTitle.text = title + itemBinder.itemSheetDescriptiveActionSubtitle.text = description - view.isEnabled = enabled + itemBinder.root.isEnabled = enabled - view.itemSheetDescriptiveActionIcon.setImageResource(iconRes) + itemBinder.itemSheetDescriptiveActionIcon.setImageResource(iconRes) - view.itemSheetDescriptiveActionArrow.setVisible(enabled && showArrowWhenEnabled) + itemBinder.itemSheetDescriptiveActionArrow.setVisible(enabled && showArrowWhenEnabled) if (enabled) { - view.setDismissingClickListener(onClick) + itemBinder.root.setDismissingClickListener(onClick) } } } -fun FixedListBottomSheet.textWithDescriptionItem( +fun FixedListBottomSheet<*>.textWithDescriptionItem( @StringRes titleRes: Int, @StringRes descriptionRes: Int, @DrawableRes iconRes: Int, @@ -169,7 +154,7 @@ fun FixedListBottomSheet.textWithDescriptionItem( ) } -fun FixedListBottomSheet.textItem( +fun FixedListBottomSheet<*>.textItem( @DrawableRes iconRes: Int, @StringRes titleRes: Int, showArrow: Boolean = false, @@ -185,23 +170,23 @@ fun FixedListBottomSheet.textItem( ) } -fun FixedListBottomSheet.switcherItem( +fun FixedListBottomSheet<*>.switcherItem( @DrawableRes iconRes: Int, @StringRes titleRes: Int, initialState: Boolean, onClick: (View) -> Unit ) { - item(R.layout.item_sheet_switcher) { view -> - view.itemSheetSwitcher.setText(titleRes) - view.itemSheetSwitcher.isChecked = initialState + item(ItemSheetSwitcherBinding.inflate(LayoutInflater.from(context))) { itemBinder -> + itemBinder.itemSheetSwitcher.setText(titleRes) + itemBinder.itemSheetSwitcher.isChecked = initialState - view.itemSheetSwitcher.setDrawableStart( + itemBinder.itemSheetSwitcher.setDrawableStart( drawableRes = iconRes, widthInDp = 24, tint = R.color.icon_primary, paddingInDp = 12 ) - view.setDismissingClickListener(onClick) + itemBinder.root.setDismissingClickListener(onClick) } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserBottomSheet.kt index 32e7451532..b2f1ef7350 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserBottomSheet.kt @@ -2,18 +2,15 @@ package io.novafoundation.nova.common.view.input.chooser import android.content.Context import android.os.Bundle -import android.view.View import androidx.annotation.StringRes import androidx.recyclerview.widget.DiffUtil -import io.novafoundation.nova.common.R -import io.novafoundation.nova.common.utils.inflateChild +import io.novafoundation.nova.common.databinding.ItemListChooserBinding +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.ClickHandler import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.DynamicListBottomSheet import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.DynamicListSheetAdapter import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.HolderCreator import io.novafoundation.nova.common.view.input.chooser.ListChooserMixin.Model -import kotlinx.android.synthetic.main.item_list_chooser.view.itemListChooserCheck -import kotlinx.android.synthetic.main.item_list_chooser.view.itemListChooserLabel class ListChooserBottomSheet( context: Context, @@ -41,11 +38,11 @@ class ListChooserBottomSheet( } override fun holderCreator(): HolderCreator> = { parentView -> - ListChooserViewHolder(parentView.inflateChild(R.layout.item_list_chooser)) + ListChooserViewHolder(ItemListChooserBinding.inflate(parentView.inflater(), parentView, false)) } } -private class ListChooserViewHolder(containerView: View) : DynamicListSheetAdapter.Holder>(containerView) { +private class ListChooserViewHolder(private val binder: ItemListChooserBinding) : DynamicListSheetAdapter.Holder>(binder.root) { override fun bind( item: Model, @@ -55,8 +52,8 @@ private class ListChooserViewHolder(containerView: View) : DynamicListSheetAd super.bind(item, isSelected, handler) with(containerView) { - itemListChooserLabel.text = item.display - itemListChooserCheck.isChecked = isSelected + binder.itemListChooserLabel.text = item.display + binder.itemListChooserCheck.isChecked = isSelected } } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserView.kt b/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserView.kt index 31352f5096..9bce26a875 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/input/chooser/ListChooserView.kt @@ -2,13 +2,12 @@ package io.novafoundation.nova.common.view.input.chooser import android.content.Context import android.util.AttributeSet -import android.view.View import android.widget.LinearLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewListChooserBinding import io.novafoundation.nova.common.utils.ensureSuffix +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_list_chooser.view.viewListChooserLabel -import kotlinx.android.synthetic.main.view_list_chooser.view.viewListChooserValue class ListChooserView @JvmOverloads constructor( context: Context, @@ -16,9 +15,9 @@ class ListChooserView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { - init { - View.inflate(context, R.layout.view_list_chooser, this) + private val binder = ViewListChooserBinding.inflate(inflater(), this) + init { orientation = HORIZONTAL attrs?.let(::applyAttributes) @@ -27,11 +26,11 @@ class ListChooserView @JvmOverloads constructor( fun setLabel(label: String) { val suffixedLabel = label.ensureSuffix(":") - viewListChooserLabel.text = suffixedLabel + binder.viewListChooserLabel.text = suffixedLabel } fun setValueDisplay(value: String?) { - viewListChooserValue.text = value + binder.viewListChooserValue.text = value } private fun applyAttributes(attributeSet: AttributeSet) = context.useAttributes(attributeSet, R.styleable.ListChooserView) { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/input/seekbar/Seekbar.kt b/common/src/main/java/io/novafoundation/nova/common/view/input/seekbar/Seekbar.kt index fcec98cf33..647339b57c 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/input/seekbar/Seekbar.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/input/seekbar/Seekbar.kt @@ -12,9 +12,9 @@ import android.widget.TextView import androidx.core.view.children import com.google.android.flexbox.FlexboxLayout import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewSeekbarBinding +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setTextColorRes -import kotlinx.android.synthetic.main.view_seekbar.view.seekbarInner -import kotlinx.android.synthetic.main.view_seekbar.view.seekbarTickLabelsContainer class Seekbar @JvmOverloads constructor( context: Context, @@ -22,16 +22,16 @@ class Seekbar @JvmOverloads constructor( defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { + private val binder = ViewSeekbarBinding.inflate(inflater(), this) + init { orientation = VERTICAL - - View.inflate(context, R.layout.view_seekbar, this) } var progress: Int - get() = seekbarInner.progress + get() = binder.seekbarInner.progress set(value) { - seekbarInner.progress = value + binder.seekbarInner.progress = value } init { @@ -39,18 +39,18 @@ class Seekbar @JvmOverloads constructor( } fun setValues(values: SeekbarValues<*>) { - seekbarInner.max = values.max + binder.seekbarInner.max = values.max - seekbarTickLabelsContainer.removeAllViews() + binder.seekbarTickLabelsContainer.removeAllViews() values.values.forEach { seekbarValue -> val tickLabel = tickLabelView(seekbarValue) - seekbarTickLabelsContainer.addView(tickLabel) + binder.seekbarTickLabelsContainer.addView(tickLabel) } } fun setOnProgressChangedListener(listener: (Int) -> Unit) { - seekbarInner.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { + binder.seekbarInner.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { listener(progress) } @@ -75,12 +75,12 @@ class Seekbar @JvmOverloads constructor( } private fun addTickLabelOnLayoutListener() { - seekbarTickLabelsContainer.addOnLayoutChangeListener { viewGroup, _, _, _, _, _, _, _, _ -> + binder.seekbarTickLabelsContainer.addOnLayoutChangeListener { viewGroup, _, _, _, _, _, _, _, _ -> require(viewGroup is ViewGroup) - val seekbarSteps = seekbarInner.max - val seekbarStartPadding = seekbarInner.paddingStart - val seekbarEndPadding = seekbarInner.paddingEnd + val seekbarSteps = binder.seekbarInner.max + val seekbarStartPadding = binder.seekbarInner.paddingStart + val seekbarEndPadding = binder.seekbarInner.paddingEnd val slideZoneWidth = getParentMeasuredWidth() - (seekbarStartPadding + seekbarEndPadding) val seekbarStepWidth = slideZoneWidth / seekbarSteps diff --git a/common/src/main/java/io/novafoundation/nova/common/view/input/selector/DynamicSelectorBottomSheet.kt b/common/src/main/java/io/novafoundation/nova/common/view/input/selector/DynamicSelectorBottomSheet.kt index 7827946ba5..8125ce5449 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/input/selector/DynamicSelectorBottomSheet.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/input/selector/DynamicSelectorBottomSheet.kt @@ -2,10 +2,9 @@ package io.novafoundation.nova.common.view.input.selector import android.content.Context import android.os.Bundle -import android.view.View import androidx.recyclerview.widget.DiffUtil -import io.novafoundation.nova.common.R -import io.novafoundation.nova.common.utils.inflateChild +import io.novafoundation.nova.common.databinding.ItemListSelectorBinding +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setImageTintRes import io.novafoundation.nova.common.utils.setTextColorRes import io.novafoundation.nova.common.utils.setTextOrHide @@ -13,9 +12,6 @@ import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.ClickHandler import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.DynamicListBottomSheet import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.DynamicListSheetAdapter import io.novafoundation.nova.common.view.bottomSheet.list.dynamic.HolderCreator -import kotlinx.android.synthetic.main.bottom_sheet_dynamic_list.dynamicListSheetSubtitle -import kotlinx.android.synthetic.main.item_list_selector.view.itemSelectorIcon -import kotlinx.android.synthetic.main.item_list_selector.view.itemSelectorTitle class DynamicSelectorBottomSheet( context: Context, @@ -40,15 +36,15 @@ class DynamicSelectorBottomSheet( super.onCreate(savedInstanceState) setTitle(payload.titleRes) - dynamicListSheetSubtitle.setTextOrHide(payload.subtitle) + binder.dynamicListSheetSubtitle.setTextOrHide(payload.subtitle) } override fun holderCreator(): HolderCreator = { parentView -> - SelectorViewHolder(parentView.inflateChild(R.layout.item_list_selector)) + SelectorViewHolder(ItemListSelectorBinding.inflate(parentView.inflater(), parentView, false)) } } -private class SelectorViewHolder(containerView: View) : DynamicListSheetAdapter.Holder(containerView) { +private class SelectorViewHolder(private val binder: ItemListSelectorBinding) : DynamicListSheetAdapter.Holder(binder.root) { override fun bind( item: ListSelectorMixin.Item, @@ -58,10 +54,10 @@ private class SelectorViewHolder(containerView: View) : DynamicListSheetAdapter. super.bind(item, isSelected, handler) with(containerView) { - itemSelectorIcon.setImageResource(item.iconRes) - itemSelectorIcon.setImageTintRes(item.iconTintRes) - itemSelectorTitle.setText(item.titleRes) - itemSelectorTitle.setTextColorRes(item.titleColorRes) + binder.itemSelectorIcon.setImageResource(item.iconRes) + binder.itemSelectorIcon.setImageTintRes(item.iconTintRes) + binder.itemSelectorTitle.setText(item.titleRes) + binder.itemSelectorTitle.setTextColorRes(item.titleColorRes) } } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/adapter/text/TextAdapter.kt b/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/adapter/text/TextAdapter.kt index 9131dca031..a8a4aa1efd 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/adapter/text/TextAdapter.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/adapter/text/TextAdapter.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.common.view.recyclerview.adapter.text -import android.view.View import android.view.ViewGroup import androidx.annotation.ColorRes import androidx.annotation.StyleRes @@ -8,11 +7,11 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ItemTextBinding import io.novafoundation.nova.common.utils.ViewSpace import io.novafoundation.nova.common.utils.dp -import io.novafoundation.nova.common.utils.inflateChild +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.updatePadding -import kotlinx.android.synthetic.main.item_text.view.itemText class TextAdapter( private var text: String? = null, @@ -23,7 +22,7 @@ class TextAdapter( ) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextViewHolder { - return TextViewHolder(parent.inflateChild(R.layout.item_text)) + return TextViewHolder(ItemTextBinding.inflate(parent.inflater(), parent, false)) } override fun getItemCount(): Int { @@ -45,13 +44,13 @@ class TextAdapter( } } -class TextViewHolder(view: View) : ViewHolder(view) { +class TextViewHolder(private val binder: ItemTextBinding) : ViewHolder(binder.root) { fun bind(text: String?, styleRes: Int, textColor: Int?, paddingInDp: ViewSpace?, isShown: Boolean) { - itemView.itemText.isVisible = isShown - itemView.itemText.text = text - itemView.itemText.setTextAppearance(styleRes) - textColor?.let { itemView.itemText.setTextColor(itemView.context.getColor(it)) } + binder.itemText.isVisible = isShown + binder.itemText.text = text + binder.itemText.setTextAppearance(styleRes) + textColor?.let { binder.itemText.setTextColor(itemView.context.getColor(it)) } paddingInDp?.let { itemView.updatePadding(it.dp(itemView.context)) } } } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/item/OperationListItem.kt b/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/item/OperationListItem.kt index a5f76b4294..51333877b2 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/item/OperationListItem.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/recyclerview/item/OperationListItem.kt @@ -2,7 +2,6 @@ package io.novafoundation.nova.common.view.recyclerview.item import android.content.Context import android.util.AttributeSet -import android.view.View import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT @@ -11,15 +10,11 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.setPadding import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ItemOperationListItemBinding import io.novafoundation.nova.common.utils.WithContextExtensions +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setImageTint import io.novafoundation.nova.common.utils.setImageTintRes -import kotlinx.android.synthetic.main.item_operation_list_item.view.itemOperationHeader -import kotlinx.android.synthetic.main.item_operation_list_item.view.itemOperationIcon -import kotlinx.android.synthetic.main.item_operation_list_item.view.itemOperationSubHeader -import kotlinx.android.synthetic.main.item_operation_list_item.view.itemOperationValuePrimary -import kotlinx.android.synthetic.main.item_operation_list_item.view.itemOperationValueSecondary -import kotlinx.android.synthetic.main.item_operation_list_item.view.itemOperationValueStatus class OperationListItem @kotlin.jvm.JvmOverloads constructor( context: Context, @@ -31,27 +26,27 @@ class OperationListItem @kotlin.jvm.JvmOverloads constructor( BORDERED_CIRCLE, DEFAULT } + private val binder = ItemOperationListItemBinding.inflate(inflater(), this) + val icon: ImageView - get() = itemOperationIcon + get() = binder.itemOperationIcon val header: TextView - get() = itemOperationHeader + get() = binder.itemOperationHeader val subHeader: TextView - get() = itemOperationSubHeader + get() = binder.itemOperationSubHeader val valuePrimary: TextView - get() = itemOperationValuePrimary + get() = binder.itemOperationValuePrimary val valueSecondary: TextView - get() = itemOperationValueSecondary + get() = binder.itemOperationValueSecondary val status: ImageView - get() = itemOperationValueStatus + get() = binder.itemOperationValueStatus init { - View.inflate(context, R.layout.item_operation_list_item, this) - layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT) setBackgroundResource(R.drawable.bg_primary_list_item) diff --git a/common/src/main/java/io/novafoundation/nova/common/view/section/SectionView.kt b/common/src/main/java/io/novafoundation/nova/common/view/section/SectionView.kt index e77c66f353..c75a071420 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/section/SectionView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/section/SectionView.kt @@ -2,7 +2,6 @@ package io.novafoundation.nova.common.view.section import android.content.Context import android.util.AttributeSet -import android.view.View import androidx.constraintlayout.widget.ConstraintLayout import io.novafoundation.nova.common.R import io.novafoundation.nova.common.utils.WithContextExtensions @@ -10,7 +9,6 @@ import io.novafoundation.nova.common.view.shape.addRipple import io.novafoundation.nova.common.view.shape.getRoundedCornerDrawable abstract class SectionView( - layoutId: Int, context: Context, attrs: AttributeSet?, defStyleAttr: Int, @@ -19,8 +17,6 @@ abstract class SectionView( override val providedContext: Context = context init { - View.inflate(context, layoutId, this) - background = with(context) { addRipple(getRoundedCornerDrawable(R.color.block_background)) } diff --git a/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsItemView.kt b/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsItemView.kt index 9a5f6cf699..177abf8a30 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsItemView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsItemView.kt @@ -3,15 +3,13 @@ package io.novafoundation.nova.common.view.settings import android.content.Context import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.view.View import android.widget.LinearLayout import androidx.core.view.isVisible import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewSettingsItemBinding import io.novafoundation.nova.common.utils.getDrawableCompat +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_settings_item.view.settingsItemIcon -import kotlinx.android.synthetic.main.view_settings_item.view.settingsItemTitle -import kotlinx.android.synthetic.main.view_settings_item.view.settingsItemValue class SettingsItemView @JvmOverloads constructor( context: Context, @@ -19,9 +17,9 @@ class SettingsItemView @JvmOverloads constructor( defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { - init { - View.inflate(context, R.layout.view_settings_item, this) + private val binder = ViewSettingsItemBinding.inflate(inflater(), this) + init { orientation = HORIZONTAL background = context.getDrawableCompat(R.drawable.bg_primary_list_item) @@ -29,16 +27,16 @@ class SettingsItemView @JvmOverloads constructor( } fun setTitle(title: String?) { - settingsItemTitle.text = title + binder.settingsItemTitle.text = title } fun setValue(value: String?) { - settingsItemValue.text = value + binder.settingsItemValue.text = value } fun setIcon(icon: Drawable?) { - settingsItemIcon.isVisible = icon != null - settingsItemIcon.setImageDrawable(icon) + binder.settingsItemIcon.isVisible = icon != null + binder.settingsItemIcon.setImageDrawable(icon) } private fun applyAttributes(attrs: AttributeSet) = context.useAttributes(attrs, R.styleable.SettingsItemView) { diff --git a/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsSwitcherView.kt b/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsSwitcherView.kt index 37b7ebf160..505f29fa1b 100644 --- a/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsSwitcherView.kt +++ b/common/src/main/java/io/novafoundation/nova/common/view/settings/SettingsSwitcherView.kt @@ -3,14 +3,14 @@ package io.novafoundation.nova.common.view.settings import android.content.Context import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.view.View import android.widget.FrameLayout import androidx.annotation.ColorRes import io.novafoundation.nova.common.R +import io.novafoundation.nova.common.databinding.ViewSettingsSwitcherBinding import io.novafoundation.nova.common.utils.dp +import io.novafoundation.nova.common.utils.inflater import io.novafoundation.nova.common.utils.setCompoundDrawableTintRes import io.novafoundation.nova.common.utils.useAttributes -import kotlinx.android.synthetic.main.view_settings_switcher.view.settingsSwitcher class SettingsSwitcherView @JvmOverloads constructor( context: Context, @@ -18,34 +18,34 @@ class SettingsSwitcherView @JvmOverloads constructor( defStyleAttr: Int = 0, ) : FrameLayout(context, attrs, defStyleAttr) { - init { - View.inflate(context, R.layout.view_settings_switcher, this) + private val binder = ViewSettingsSwitcherBinding.inflate(inflater(), this) + init { attrs?.let(::applyAttributes) } fun setTitle(title: String?) { - settingsSwitcher.text = title + binder.settingsSwitcher.text = title } fun setIconTintColor(@ColorRes tintRes: Int?) { - settingsSwitcher.setCompoundDrawableTintRes(tintRes) + binder.settingsSwitcher.setCompoundDrawableTintRes(tintRes) } fun setIcon(icon: Drawable?) { // Set icon size 24 dp val iconSize = 24.dp icon?.setBounds(0, 0, iconSize, iconSize) - settingsSwitcher.setCompoundDrawables(icon, null, null, null) + binder.settingsSwitcher.setCompoundDrawables(icon, null, null, null) } fun setChecked(checked: Boolean) { - settingsSwitcher.isChecked = checked + binder.settingsSwitcher.isChecked = checked } override fun setEnabled(enabled: Boolean) { super.setEnabled(enabled) - settingsSwitcher.isEnabled = enabled + binder.settingsSwitcher.isEnabled = enabled } private fun applyAttributes(attrs: AttributeSet) = context.useAttributes(attrs, R.styleable.SettingsSwitcherView) { @@ -56,6 +56,6 @@ class SettingsSwitcherView @JvmOverloads constructor( setIcon(icon) val textColorStateList = it.getColorStateList(R.styleable.SettingsSwitcherView_switcherTextColor) - textColorStateList?.let { settingsSwitcher.setTextColor(it) } + textColorStateList?.let { binder.settingsSwitcher.setTextColor(it) } } } diff --git a/common/src/main/res/layout/view_toolbar.xml b/common/src/main/res/layout/view_toolbar.xml index ccbd1ec725..bfeea37830 100644 --- a/common/src/main/res/layout/view_toolbar.xml +++ b/common/src/main/res/layout/view_toolbar.xml @@ -4,10 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/toolbarContainer" android:layout_width="match_parent" - android:layout_height="?attr/actionBarSize" - android:gravity="center_vertical" - android:orientation="horizontal" - tools:layout_height="48dp"> + android:layout_height="56dp" + android:minHeight="56dp"> @style/bottomSheetStyleWrapper @color/android_system_accent + 100% + 100%