Catalog Jetpack Compose refactor (#57)
* Updated gradle dependencies to support jetpack compose * Added Catalog screen and ViewPager component * Added catalog pages composable functions * Added coil dependency * Move some dependendies from androidx to compose dependencies * Use composeUiVersion in build.gradle instead of harcoded value * Added missing Copyright * Move padding to BottomPageNumber composable function * Created GuitarImage composable function * Added pager state saver to preserve the state when configuration changes occurs * Fixed lint issue * Updated Dagger Hilt version from 2.39.1 to 2.42 and removed lintOptions * Added PageLayout composable to hold page ui * Updated ui to support small width devices * Removed background color for seventh page * Added selectPageNumber function in order to jump to a specific page number * Replaced hardcoded values for destinationPage * Updated Copyright for ViewPager class * Added page number as last character for ContentTextItem * Removed all files related to Catalog UI View System * Avoid adding one more page for view pager when the current page is max page and configuration change occurs
This commit is contained in:
Родитель
73d62cf1cf
Коммит
b27b34168d
|
@ -75,6 +75,11 @@ android {
|
|||
buildFeatures {
|
||||
dataBinding true
|
||||
viewBinding true
|
||||
compose true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion rootProject.ext.composeUiVersion
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
|
@ -109,6 +114,17 @@ dependencies {
|
|||
implementation navigationDependencies.fragmentKtx
|
||||
implementation navigationDependencies.uiKtx
|
||||
|
||||
implementation composeDependencies.composeUi
|
||||
debugImplementation composeDependencies.composeTooling
|
||||
implementation composeDependencies.composeFoundation
|
||||
implementation composeDependencies.composeMaterial
|
||||
implementation composeDependencies.composeMaterialIcons
|
||||
implementation composeDependencies.composeMaterialIconsExtended
|
||||
implementation composeDependencies.composeViewModel
|
||||
implementation composeDependencies.composeLiveData
|
||||
implementation composeDependencies.constraintlayoutCompose
|
||||
implementation composeDependencies.coil
|
||||
|
||||
implementation googleDependencies.ossLicenses
|
||||
implementation googleDependencies.material
|
||||
implementation googleDependencies.gson
|
||||
|
@ -127,6 +143,7 @@ dependencies {
|
|||
implementation microsoftDependencies.layouts
|
||||
implementation microsoftDependencies.wmUtils
|
||||
implementation microsoftDependencies.snackbar
|
||||
implementation microsoftDependencies.windowState
|
||||
|
||||
implementation uiDependencies.lottie
|
||||
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.rule.ActivityTestRule
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import com.microsoft.device.dualscreen.testing.resetOrientation
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.MainActivity
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.store.checkToolbar
|
||||
import dagger.hilt.android.testing.HiltAndroidRule
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import org.junit.After
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
|
||||
@HiltAndroidTest
|
||||
class CatalogNavigationDualScreenTest {
|
||||
|
||||
private val activityRule = ActivityTestRule(MainActivity::class.java)
|
||||
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
||||
@get:Rule
|
||||
var ruleChain: RuleChain =
|
||||
RuleChain.outerRule(HiltAndroidRule(this)).around(activityRule)
|
||||
|
||||
@After
|
||||
fun resetOrientation() {
|
||||
device.resetOrientation()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkAllCatalogItems() {
|
||||
navigateToCatalogSection()
|
||||
|
||||
checkToolbar(R.string.toolbar_catalog_title)
|
||||
|
||||
checkCatalogPageIsDisplayed(1)
|
||||
|
||||
swipeCatalogViewPagerToTheLeft()
|
||||
checkCatalogPageIsDisplayed(2)
|
||||
|
||||
swipeCatalogViewPagerToTheLeft()
|
||||
checkCatalogPageIsDisplayed(3)
|
||||
|
||||
swipeCatalogViewPagerToTheLeft()
|
||||
checkCatalogPageIsDisplayed(4)
|
||||
|
||||
swipeCatalogViewPagerToTheLeft()
|
||||
checkCatalogPageIsDisplayed(5)
|
||||
|
||||
swipeCatalogViewPagerToTheLeft()
|
||||
checkCatalogPageIsDisplayed(6)
|
||||
|
||||
swipeCatalogViewPagerToTheLeft()
|
||||
checkCatalogPageIsDisplayed(7)
|
||||
|
||||
checkToolbar(R.string.toolbar_catalog_title)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkAllCatalogItemsAfterRotation() {
|
||||
navigateToCatalogSection()
|
||||
device.setOrientationRight()
|
||||
|
||||
checkAllCatalogItems()
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog
|
||||
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.swipeLeft
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.util.forceClick
|
||||
import org.hamcrest.core.AllOf.allOf
|
||||
|
||||
fun navigateToCatalogSection() {
|
||||
onView(withId(R.id.navigation_catalog_graph)).perform(forceClick())
|
||||
}
|
||||
|
||||
fun checkCatalogPageIsDisplayed(pageNo: Int) {
|
||||
onView(
|
||||
allOf(
|
||||
withId(R.id.pages),
|
||||
withText("Page $pageNo of 7")
|
||||
)
|
||||
).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
fun swipeCatalogViewPagerToTheLeft() {
|
||||
onView(withId(R.id.pager)).perform(swipeLeft())
|
||||
}
|
|
@ -264,10 +264,10 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
if (layoutInfoViewModel.isDualMode.value == true) {
|
||||
menuInflater.inflate(R.menu.main_menu, menu)
|
||||
menu?.findItem(R.id.menu_main_dev_mode)?.actionView?.apply {
|
||||
menu.findItem(R.id.menu_main_dev_mode)?.actionView?.apply {
|
||||
setOnClickListener {
|
||||
onDevModeClicked(it)
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentPagerAdapter
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page1
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page2
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page3
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page4
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page5
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page6
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage.Page7
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage1Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage2Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage3Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage4Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage5Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage6Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item.CatalogPage7Fragment
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.DataListProvider
|
||||
|
||||
internal class CatalogListAdapter(
|
||||
fragmentManager: FragmentManager,
|
||||
private val dataProvider: DataListProvider<CatalogItem>
|
||||
) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||
var showTwoPages = false
|
||||
|
||||
override fun getCount(): Int = dataProvider.getDataList()?.size ?: 0
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
dataProvider.getDataList()?.get(position)?.let { item ->
|
||||
return when (item.viewType) {
|
||||
Page1 -> CatalogPage1Fragment()
|
||||
Page2 -> CatalogPage2Fragment()
|
||||
Page3 -> CatalogPage3Fragment()
|
||||
Page4 -> CatalogPage4Fragment()
|
||||
Page5 -> CatalogPage5Fragment()
|
||||
Page6 -> CatalogPage6Fragment()
|
||||
Page7 -> CatalogPage7Fragment()
|
||||
}
|
||||
}
|
||||
throw RuntimeException("Catalog Type Error")
|
||||
}
|
||||
|
||||
fun refreshData() {
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getPageWidth(position: Int): Float {
|
||||
// 0.5f : Each page occupies full space
|
||||
// 1.0f : Each page occupies half space
|
||||
return if (showTwoPages) 0.5f else 1.0f
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog
|
||||
|
@ -13,36 +12,39 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import androidx.window.layout.WindowInfoTracker
|
||||
import androidx.window.layout.WindowLayoutInfo
|
||||
import com.microsoft.device.dualscreen.utils.wm.getFoldingFeature
|
||||
import com.microsoft.device.dualscreen.utils.wm.isFoldingFeatureVertical
|
||||
import com.microsoft.device.dualscreen.utils.wm.isInDualMode
|
||||
import com.microsoft.device.dualscreen.windowstate.FoldState
|
||||
import com.microsoft.device.dualscreen.windowstate.rememberWindowState
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogBinding
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.theme.CatalogTheme
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view.Catalog
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.appCompatActivity
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.changeToolbarTitle
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.isFoldOrSmallHinge
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.isFragmentWidthSmall
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.setupToolbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class CatalogListFragment : Fragment(), ViewPager.OnPageChangeListener {
|
||||
class CatalogListFragment : Fragment() {
|
||||
|
||||
private val viewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
private var binding: FragmentCatalogBinding? = null
|
||||
private var catalogAdapter: CatalogListAdapter? = null
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
|
@ -68,36 +70,36 @@ class CatalogListFragment : Fragment(), ViewPager.OnPageChangeListener {
|
|||
): View? {
|
||||
binding = FragmentCatalogBinding.inflate(inflater, container, false)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
binding?.composeView?.apply {
|
||||
// Dispose of the Composition when the view's LifecycleOwner
|
||||
// is destroyed
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
CatalogTheme {
|
||||
val windowState = appCompatActivity?.rememberWindowState()
|
||||
if (windowState != null) {
|
||||
val isFeatureFoldHorizontal =
|
||||
windowState.hasFold && windowState.foldIsHorizontal
|
||||
val isFoldStateHalfOpened = windowState.foldState == FoldState.HALF_OPENED
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupAdapter()
|
||||
setupObservers()
|
||||
}
|
||||
|
||||
private fun setupAdapter() {
|
||||
catalogAdapter = CatalogListAdapter(childFragmentManager, viewModel)
|
||||
}
|
||||
|
||||
private fun setupViewPager() {
|
||||
binding?.pager?.apply {
|
||||
adapter = catalogAdapter
|
||||
currentItem = viewModel.catalogItemPosition.value ?: 0
|
||||
addOnPageChangeListener(this@CatalogListFragment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupObservers() {
|
||||
viewModel.catalogItemList.observe(viewLifecycleOwner) { catalogAdapter?.refreshData() }
|
||||
viewModel.catalogItemPosition.observe(viewLifecycleOwner) { newPageNumber ->
|
||||
binding?.pager?.apply {
|
||||
if (currentItem != newPageNumber) {
|
||||
setCurrentItem(newPageNumber, true)
|
||||
Catalog(
|
||||
pane1WidthDp = windowState.pane1SizeDp.width,
|
||||
pane2WidthDp = windowState.pane2SizeDp.width,
|
||||
foldSizeDp = windowState.foldSizeDp,
|
||||
isFeatureHorizontal = isFeatureFoldHorizontal,
|
||||
isSinglePortrait = windowState.isSinglePortrait(),
|
||||
showTwoPages = viewModel.showTwoPages.observeAsState().value ?: false,
|
||||
showSmallWindowWidthLayout =
|
||||
viewModel.showSmallWindowWidthLayout.observeAsState().value ?: false,
|
||||
isFoldStateHalfOpened = isFoldStateHalfOpened,
|
||||
catalogList =
|
||||
viewModel.catalogItemList.observeAsState().value ?: listOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -113,30 +115,23 @@ class CatalogListFragment : Fragment(), ViewPager.OnPageChangeListener {
|
|||
private fun onWindowLayoutInfoChanged(windowLayoutInfo: WindowLayoutInfo) {
|
||||
val isLargeScreenOrHasHinge = activity?.hasExpandedWindowLayoutSize() == true ||
|
||||
windowLayoutInfo.getFoldingFeature()?.isFoldOrSmallHinge() == false
|
||||
|
||||
catalogAdapter?.showTwoPages = windowLayoutInfo.isInDualMode() &&
|
||||
val shouldShowTwoPages = windowLayoutInfo.isInDualMode() &&
|
||||
windowLayoutInfo.isFoldingFeatureVertical() &&
|
||||
isLargeScreenOrHasHinge
|
||||
viewModel.showTwoPages.value = catalogAdapter?.showTwoPages ?: false
|
||||
val shouldShowSmallWindowWidthLayout =
|
||||
appCompatActivity?.isFragmentWidthSmall(
|
||||
windowLayoutInfo.getFoldingFeature(),
|
||||
shouldShowTwoPages
|
||||
)?.takeIf {
|
||||
it && !shouldShowTwoPages
|
||||
} ?: false
|
||||
|
||||
setupViewPager()
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
viewModel.catalogItemPosition.value = position
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
// do nothing
|
||||
viewModel.updateShowTwoPages(shouldShowTwoPages)
|
||||
viewModel.updateShowSmallWindowWidthLayout(shouldShowSmallWindowWidthLayout)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
binding = null
|
||||
catalogAdapter = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
@ -23,7 +24,14 @@ class CatalogListViewModel @Inject constructor(
|
|||
) : ViewModel(), DataListProvider<CatalogItem> {
|
||||
var catalogItemList = MutableLiveData<List<CatalogItem>?>(null)
|
||||
var catalogItemPosition = MutableLiveData(0)
|
||||
var showTwoPages = MutableLiveData(false)
|
||||
|
||||
private val _showTwoPages = MutableLiveData(false)
|
||||
val showTwoPages: LiveData<Boolean>
|
||||
get() = _showTwoPages
|
||||
|
||||
private val _showSmallWindowWidthLayout = MutableLiveData(false)
|
||||
val showSmallWindowWidthLayout: LiveData<Boolean>
|
||||
get() = _showSmallWindowWidthLayout
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
|
@ -31,5 +39,13 @@ class CatalogListViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun updateShowTwoPages(showTwoPages: Boolean) {
|
||||
_showTwoPages.value = showTwoPages
|
||||
}
|
||||
|
||||
fun updateShowSmallWindowWidthLayout(showSmallWindowWidthLayout: Boolean) {
|
||||
_showSmallWindowWidthLayout.value = showSmallWindowWidthLayout
|
||||
}
|
||||
|
||||
override fun getDataList(): List<CatalogItem>? = catalogItemList.value
|
||||
}
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage1Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage1Fragment : Fragment() {
|
||||
|
||||
private val viewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
private var binding: FragmentCatalogItemPage1Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage1Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page1.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page1.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupClickListeners()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun setupClickListeners() {
|
||||
binding?.textSecond?.setOnClickListener {
|
||||
viewModel.catalogItemPosition.value = CatalogPage.Page2.ordinal
|
||||
}
|
||||
binding?.textThird?.setOnClickListener {
|
||||
viewModel.catalogItemPosition.value = CatalogPage.Page3.ordinal
|
||||
}
|
||||
binding?.textFourth?.setOnClickListener {
|
||||
viewModel.catalogItemPosition.value = CatalogPage.Page4.ordinal
|
||||
}
|
||||
binding?.textFifth?.setOnClickListener {
|
||||
viewModel.catalogItemPosition.value = CatalogPage.Page6.ordinal
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text18sp = resources.getDimension(R.dimen.text_size_18)
|
||||
val text20sp = resources.getDimension(R.dimen.text_size_20)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text20sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text18sp)
|
||||
binding?.textThird?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text18sp)
|
||||
binding?.textFourth?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text18sp)
|
||||
binding?.textFifth?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text18sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem1Layout ?: return
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
set.connect(
|
||||
R.id.catalog_item_scroll_view, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage2Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.isFragmentWidthSmall
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage2Fragment : Fragment() {
|
||||
|
||||
private var binding: FragmentCatalogItemPage2Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage2Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page2.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page2.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
activity?.isFragmentWidthSmall(currentFoldingFeature, showsTwoPages)?.takeIf {
|
||||
it && !showsTwoPages
|
||||
}?.let {
|
||||
alignLayoutToSmallWindowWidth()
|
||||
}
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text20sp = resources.getDimension(R.dimen.text_size_20)
|
||||
val text16sp = resources.getDimension(R.dimen.text_size_16)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text20sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
binding?.textThird?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToSmallWindowWidth() {
|
||||
val constraintLayout = binding?.catalogItem2Layout ?: return
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.BOTTOM,
|
||||
R.id.text_second, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
binding?.catalogFlow?.setMaxElementsWrap(1)
|
||||
|
||||
val catalogFlowArray = IntArray(2).apply {
|
||||
this[0] = R.id.text_second
|
||||
this[1] = R.id.image_first
|
||||
}
|
||||
|
||||
binding?.catalogFlow?.referencedIds = catalogFlowArray
|
||||
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem2Layout ?: return
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
|
||||
set.connect(
|
||||
R.id.catalog_flow, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_third, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage3Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.isFragmentWidthSmall
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage3Fragment : Fragment() {
|
||||
|
||||
private var binding: FragmentCatalogItemPage3Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage3Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page3.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page3.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
activity?.isFragmentWidthSmall(currentFoldingFeature, showsTwoPages)?.takeIf {
|
||||
it && !showsTwoPages
|
||||
}?.let {
|
||||
alignLayoutToSmallWindowWidth()
|
||||
}
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text20sp = resources.getDimension(R.dimen.text_size_20)
|
||||
val text16sp = resources.getDimension(R.dimen.text_size_16)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text20sp)
|
||||
binding?.textThird?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToSmallWindowWidth() {
|
||||
val constraintLayout = binding?.catalogItem3Layout ?: return
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
val margin = resources.getDimension(R.dimen.normal_margin).toInt()
|
||||
val marginHorizontal = resources.getDimension(R.dimen.catalog_horizontal_margin).toInt()
|
||||
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.END,
|
||||
R.id.catalog_item3_layout, ConstraintSet.END, marginHorizontal
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.BOTTOM,
|
||||
R.id.text_first, ConstraintSet.TOP, margin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.TOP,
|
||||
R.id.image_first, ConstraintSet.BOTTOM, margin
|
||||
)
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.START,
|
||||
R.id.catalog_item3_layout, ConstraintSet.START, marginHorizontal
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.TOP,
|
||||
R.id.text_first, ConstraintSet.BOTTOM, margin
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.BOTTOM,
|
||||
R.id.text_second, ConstraintSet.TOP, margin
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.START,
|
||||
R.id.catalog_item3_layout, ConstraintSet.START, marginHorizontal
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.image_second, ConstraintSet.BOTTOM, margin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_third, ConstraintSet.END,
|
||||
R.id.catalog_item3_layout, ConstraintSet.END, marginHorizontal
|
||||
)
|
||||
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem3Layout ?: return
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
|
||||
if (activity?.isFragmentWidthSmall(foldingFeature, false) == false) {
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
} else {
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
}
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage4Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage4Fragment : Fragment() {
|
||||
|
||||
private var binding: FragmentCatalogItemPage4Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage4Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page4.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page4.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text20sp = resources.getDimension(R.dimen.text_size_20)
|
||||
val text16sp = resources.getDimension(R.dimen.text_size_16)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text20sp)
|
||||
binding?.textThird?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem4Layout ?: return
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage5Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage5Fragment : Fragment() {
|
||||
|
||||
private var binding: FragmentCatalogItemPage5Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage5Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page5.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page5.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text16sp = resources.getDimension(R.dimen.text_size_16)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem5Layout ?: return
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.END,
|
||||
R.id.catalog_item5_layout, ConstraintSet.END, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage6Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage6Fragment : Fragment() {
|
||||
|
||||
private var binding: FragmentCatalogItemPage6Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage6Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page6.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page6.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text20sp = resources.getDimension(R.dimen.text_size_20)
|
||||
val text16sp = resources.getDimension(R.dimen.text_size_16)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text20sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem6Layout ?: return
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.item
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.databinding.FragmentCatalogItemPage7Binding
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.CatalogListViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.LayoutInfoViewModel
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getBoundsInWindow
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.hasExpandedWindowLayoutSize
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.isFragmentWidthSmall
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
class CatalogPage7Fragment : Fragment() {
|
||||
|
||||
private var binding: FragmentCatalogItemPage7Binding? = null
|
||||
|
||||
private val layoutInfoViewModel: LayoutInfoViewModel by activityViewModels()
|
||||
private val catalogViewModel: CatalogListViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentCatalogItemPage7Binding.inflate(inflater, container, false)
|
||||
binding?.catalogItem = catalogViewModel.catalogItemList.value?.get(CatalogPage.Page7.ordinal)
|
||||
binding?.pageNumber = resources.getString(
|
||||
R.string.catalog_page_no,
|
||||
CatalogPage.Page7.ordinal + 1,
|
||||
catalogViewModel.getDataList().sizeOrZero()
|
||||
)
|
||||
binding?.lifecycleOwner = this
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val showsTwoPages = catalogViewModel.showTwoPages.value == true
|
||||
val isDualMode = layoutInfoViewModel.isDualMode.value == true
|
||||
val currentFoldingFeature = layoutInfoViewModel.foldingFeature.value
|
||||
val isExpandedWindowSize = activity?.hasExpandedWindowLayoutSize() == true
|
||||
|
||||
activity?.isFragmentWidthSmall(currentFoldingFeature, showsTwoPages)?.takeIf {
|
||||
it && !showsTwoPages
|
||||
}?.let {
|
||||
alignLayoutToSmallWindowWidth()
|
||||
}
|
||||
|
||||
currentFoldingFeature?.takeIf {
|
||||
isDualMode && !showsTwoPages && it.orientation == FoldingFeature.Orientation.HORIZONTAL
|
||||
}?.let {
|
||||
alignLayoutToHorizontalFoldingFeature(it)
|
||||
|
||||
if (isExpandedWindowSize) {
|
||||
updateText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
val text16sp = resources.getDimension(R.dimen.text_size_16)
|
||||
binding?.textFirst?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
binding?.textSecond?.setTextSize(TypedValue.COMPLEX_UNIT_PX, text16sp)
|
||||
}
|
||||
|
||||
private fun alignLayoutToSmallWindowWidth() {
|
||||
val constraintLayout = binding?.catalogItem7Layout ?: return
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
val margin = resources.getDimension(R.dimen.normal_margin).toInt()
|
||||
val marginHorizontal = resources.getDimension(R.dimen.catalog_horizontal_margin).toInt()
|
||||
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.END,
|
||||
R.id.catalog_item7_layout, ConstraintSet.END, marginHorizontal
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.BOTTOM,
|
||||
R.id.text_first, ConstraintSet.TOP, margin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.TOP,
|
||||
R.id.image_first, ConstraintSet.BOTTOM, margin
|
||||
)
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.START,
|
||||
R.id.catalog_item7_layout, ConstraintSet.START, marginHorizontal
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.TOP,
|
||||
R.id.text_first, ConstraintSet.BOTTOM, margin
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.BOTTOM,
|
||||
R.id.text_second, ConstraintSet.TOP, margin
|
||||
)
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.START,
|
||||
R.id.catalog_item7_layout, ConstraintSet.START, marginHorizontal
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.image_second, ConstraintSet.BOTTOM, margin
|
||||
)
|
||||
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.END,
|
||||
R.id.catalog_item7_layout, ConstraintSet.END, marginHorizontal
|
||||
)
|
||||
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
|
||||
private fun alignLayoutToHorizontalFoldingFeature(foldingFeature: FoldingFeature) {
|
||||
val constraintLayout = binding?.catalogItem7Layout ?: return
|
||||
|
||||
foldingFeature.getBoundsInWindow(binding?.root)?.let { rect ->
|
||||
val horizontalFoldingFeatureHeight = rect.height().coerceAtLeast(1)
|
||||
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
set.constrainHeight(R.id.horizontal_fold, horizontalFoldingFeatureHeight)
|
||||
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START, 0
|
||||
)
|
||||
set.connect(
|
||||
R.id.horizontal_fold, ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
|
||||
)
|
||||
|
||||
val foldingMargin = resources.getDimension(R.dimen.small_margin).toInt()
|
||||
|
||||
set.setMargin(R.id.horizontal_fold, ConstraintSet.TOP, rect.top)
|
||||
|
||||
if (activity?.isFragmentWidthSmall(foldingFeature, false) == false) {
|
||||
set.connect(
|
||||
R.id.image_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
set.connect(
|
||||
R.id.text_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
}
|
||||
set.connect(
|
||||
R.id.image_second, ConstraintSet.TOP,
|
||||
R.id.horizontal_fold, ConstraintSet.BOTTOM, foldingMargin
|
||||
)
|
||||
set.connect(
|
||||
R.id.text_first, ConstraintSet.BOTTOM,
|
||||
R.id.horizontal_fold, ConstraintSet.TOP, foldingMargin
|
||||
)
|
||||
|
||||
set.setVisibility(R.id.horizontal_fold, View.INVISIBLE)
|
||||
set.applyTo(constraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val Purple200 = Color(0xFFBB86FC)
|
||||
val Purple500 = Color(0xFF6200EE)
|
||||
val Purple700 = Color(0xFF3700B3)
|
||||
val Teal200 = Color(0xFF03DAC5)
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.theme
|
||||
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Shapes
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val Shapes = Shapes(
|
||||
small = RoundedCornerShape(4.dp),
|
||||
medium = RoundedCornerShape(4.dp),
|
||||
large = RoundedCornerShape(0.dp)
|
||||
)
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.theme
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
private val DarkColorPalette = darkColors(
|
||||
primary = Purple200,
|
||||
primaryVariant = Purple700,
|
||||
secondary = Teal200
|
||||
)
|
||||
|
||||
private val LightColorPalette = lightColors(
|
||||
primary = Purple500,
|
||||
primaryVariant = Purple700,
|
||||
secondary = Teal200
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun CatalogTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
|
||||
val colors = if (darkTheme) {
|
||||
DarkColorPalette
|
||||
} else {
|
||||
LightColorPalette
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colors = colors,
|
||||
typography = Typography,
|
||||
shapes = Shapes,
|
||||
content = content
|
||||
)
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.theme
|
||||
|
||||
import androidx.compose.material.Typography
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
|
||||
val Typography = Typography(
|
||||
h5 = TextStyle(
|
||||
fontFamily = FontFamily.Serif,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
h6 = TextStyle(
|
||||
fontFamily = FontFamily(Font(R.font.roboto)),
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 18.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
body1 = TextStyle(
|
||||
fontFamily = FontFamily(Font(R.font.dmsans_regular)),
|
||||
fontWeight = FontWeight.Normal,
|
||||
lineHeight = 24.sp,
|
||||
fontSize = 16.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
body2 = TextStyle(
|
||||
fontFamily = FontFamily.Serif,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontStyle = FontStyle.Italic,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp
|
||||
),
|
||||
caption = TextStyle(
|
||||
fontFamily = FontFamily.Serif,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 14.sp,
|
||||
color = Color.Gray
|
||||
)
|
||||
)
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.min
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PagerState
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.ViewPager
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.rememberViewPagerState
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.abs
|
||||
|
||||
@Composable
|
||||
fun Catalog(
|
||||
pane1WidthDp: Dp,
|
||||
pane2WidthDp: Dp,
|
||||
foldSizeDp: Dp,
|
||||
isFeatureHorizontal: Boolean,
|
||||
isSinglePortrait: Boolean,
|
||||
showTwoPages: Boolean,
|
||||
showSmallWindowWidthLayout: Boolean,
|
||||
isFoldStateHalfOpened: Boolean,
|
||||
catalogList: List<CatalogItem>
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
// Calculate page text width based on the smallest pane width
|
||||
val pageTextWidth = min(pane1WidthDp, pane2WidthDp)
|
||||
|
||||
// Calculate the necessary page padding, based on pane width differences and fold width
|
||||
val pagePadding = abs(pane1WidthDp.value - pane2WidthDp.value).dp + foldSizeDp
|
||||
|
||||
val pagerState = rememberViewPagerState()
|
||||
|
||||
val pages = setupPages(
|
||||
pageTextWidth,
|
||||
pagePadding,
|
||||
catalogList,
|
||||
isFeatureHorizontal,
|
||||
isSinglePortrait,
|
||||
showTwoPages,
|
||||
showSmallWindowWidthLayout,
|
||||
isFoldStateHalfOpened
|
||||
) { destinationPage ->
|
||||
coroutineScope.launch {
|
||||
pagerState.selectPageNumber(destinationPage)
|
||||
}
|
||||
}
|
||||
PageViews(pagerState, pages, showTwoPages)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PageViews(
|
||||
pagerState: PagerState = rememberViewPagerState(),
|
||||
pages: List<@Composable () -> Unit>,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
val maxPage = (pages.size - 1).coerceAtLeast(0)
|
||||
|
||||
pagerState.isDualMode = showTwoPages
|
||||
pagerState.maxPage = maxPage
|
||||
|
||||
ViewPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
pages[page]()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupPages(
|
||||
pageTextWidth: Dp,
|
||||
pagePadding: Dp = 0.dp,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean,
|
||||
isSinglePortrait: Boolean,
|
||||
showTwoPages: Boolean,
|
||||
showSmallWindowWidthLayout: Boolean,
|
||||
isFoldStateHalfOpened: Boolean,
|
||||
onItemClick: (Int) -> Unit
|
||||
): List<@Composable () -> Unit> {
|
||||
val modifier = if (pageTextWidth.value != 0f && showTwoPages) Modifier
|
||||
.padding(end = pagePadding)
|
||||
.width(pageTextWidth)
|
||||
.fillMaxHeight()
|
||||
.clipToBounds() else Modifier.fillMaxSize()
|
||||
return listOf<@Composable () -> Unit>(
|
||||
{
|
||||
CatalogFirstPage(modifier = modifier, catalogList = catalogList, onItemClick)
|
||||
},
|
||||
{
|
||||
CatalogSecondPage(
|
||||
modifier = modifier,
|
||||
catalogList = catalogList,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
showTwoPages = showTwoPages,
|
||||
isSmallWindowWidth = showSmallWindowWidthLayout
|
||||
)
|
||||
},
|
||||
{
|
||||
CatalogThirdPage(
|
||||
modifier = modifier,
|
||||
catalogList = catalogList,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
isSinglePortrait = isSinglePortrait,
|
||||
showTwoPages = showTwoPages,
|
||||
isSmallWindowWidth = showSmallWindowWidthLayout,
|
||||
isFoldStateHalfOpened = isFoldStateHalfOpened
|
||||
)
|
||||
},
|
||||
{
|
||||
CatalogFourthPage(
|
||||
modifier = modifier,
|
||||
catalogList = catalogList,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
showTwoPages = showTwoPages
|
||||
)
|
||||
},
|
||||
{
|
||||
CatalogFifthPage(
|
||||
modifier = modifier,
|
||||
catalogList = catalogList,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
isSmallWindowWidth = showSmallWindowWidthLayout,
|
||||
showTwoPages = showTwoPages
|
||||
)
|
||||
},
|
||||
{
|
||||
CatalogSixthPage(
|
||||
modifier = modifier,
|
||||
catalogList = catalogList,
|
||||
isFeatureHorizontal = isFeatureHorizontal
|
||||
)
|
||||
},
|
||||
{
|
||||
CatalogSeventhPage(
|
||||
modifier = modifier,
|
||||
catalogList = catalogList,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
isSmallWindowWidth = showSmallWindowWidthLayout,
|
||||
showTwoPages = showTwoPages
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.RoundedImage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.TextDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.fontDimensionResource
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getImageUri
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val FIFTH_PAGE_FIRST_TEXT_ID = "fifthPageFirstText"
|
||||
const val FIFTH_PAGE_FIRST_IMAGE_ID = "fifthPageFirstImage"
|
||||
const val FIFTH_PAGE_SECOND_IMAGE_ID = "fifthPageSecondImage"
|
||||
const val FIFTH_PAGE_SECOND_TEXT_ID = "fifthPageSecondText"
|
||||
|
||||
@Composable
|
||||
fun CatalogFifthPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean = false,
|
||||
isSmallWindowWidth: Boolean = false,
|
||||
showTwoPages: Boolean = false
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page5.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
val fourthPageConstraintSet = getConstraintSetForFifthPage(isFeatureHorizontal)
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
FifthPageContent(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
start = dimensionResource(
|
||||
id = if (isSmallWindowWidth && !showTwoPages)
|
||||
R.dimen.catalog_margin_small
|
||||
else
|
||||
R.dimen.catalog_horizontal_margin
|
||||
),
|
||||
end = dimensionResource(
|
||||
id = if (isSmallWindowWidth && !showTwoPages)
|
||||
R.dimen.catalog_margin_small
|
||||
else
|
||||
R.dimen.catalog_horizontal_margin
|
||||
),
|
||||
top = if (isFeatureHorizontal)
|
||||
dimensionResource(id = R.dimen.catalog_margin_normal)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding),
|
||||
)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
constraintSet = fourthPageConstraintSet,
|
||||
catalogItem = catalogItem,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
isSmallWindowWidth = isSmallWindowWidth,
|
||||
showTwoPages = showTwoPages
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstraintSetForFifthPage(
|
||||
isFeatureHorizontal: Boolean
|
||||
) =
|
||||
ConstraintSet {
|
||||
val firstTextRef = createRefFor(FIFTH_PAGE_FIRST_TEXT_ID)
|
||||
val firstImageRef = createRefFor(FIFTH_PAGE_FIRST_IMAGE_ID)
|
||||
val secondImageRef = createRefFor(FIFTH_PAGE_SECOND_IMAGE_ID)
|
||||
val secondTextRef = createRefFor(FIFTH_PAGE_SECOND_TEXT_ID)
|
||||
val verticalGuideline = createGuidelineFromStart(0.5f)
|
||||
val horizontalGuideline = createGuidelineFromTop(0.5f)
|
||||
|
||||
val topMargin = 20.dp
|
||||
val verticalMargin = 16.dp
|
||||
|
||||
constrain(firstTextRef) {
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(parent.top, topMargin)
|
||||
}
|
||||
|
||||
constrain(firstImageRef) {
|
||||
start.linkTo(parent.start)
|
||||
end.linkTo(verticalGuideline)
|
||||
if (isFeatureHorizontal) {
|
||||
bottom.linkTo(horizontalGuideline)
|
||||
top.linkTo(firstTextRef.bottom)
|
||||
} else {
|
||||
top.linkTo(firstTextRef.bottom, topMargin)
|
||||
}
|
||||
height = Dimension.preferredWrapContent
|
||||
width = Dimension.preferredWrapContent
|
||||
}
|
||||
|
||||
constrain(secondImageRef) {
|
||||
if (isFeatureHorizontal) {
|
||||
top.linkTo(firstTextRef.bottom)
|
||||
bottom.linkTo(horizontalGuideline, verticalMargin)
|
||||
} else {
|
||||
top.linkTo(firstImageRef.top)
|
||||
}
|
||||
start.linkTo(verticalGuideline, 8.dp)
|
||||
end.linkTo(parent.end)
|
||||
height = Dimension.fillToConstraints
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
if (isFeatureHorizontal) {
|
||||
top.linkTo(horizontalGuideline, margin = verticalMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
} else {
|
||||
linkTo(start = firstTextRef.start, end = secondImageRef.start)
|
||||
top.linkTo(firstImageRef.bottom, margin = verticalMargin)
|
||||
}
|
||||
width = Dimension.fillToConstraints
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FifthPageContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
isSmallWindowWidth: Boolean,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(FIFTH_PAGE_FIRST_TEXT_ID),
|
||||
text = catalogItem.primaryDescription,
|
||||
contentDescription = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(FIFTH_PAGE_FIRST_IMAGE_ID)
|
||||
.requiredWidth(
|
||||
if (!showTwoPages && isSmallWindowWidth)
|
||||
dimensionResource(id = R.dimen.catalog_small_screen_min_image_width)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_width)
|
||||
)
|
||||
.requiredHeight(
|
||||
if (!showTwoPages && isSmallWindowWidth)
|
||||
dimensionResource(id = R.dimen.catalog_base_min_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(FIFTH_PAGE_SECOND_IMAGE_ID)
|
||||
.padding(
|
||||
bottom = if (!showTwoPages && isSmallWindowWidth)
|
||||
dimensionResource(id = R.dimen.small_margin)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
)
|
||||
.requiredWidth(
|
||||
if (!showTwoPages && isSmallWindowWidth)
|
||||
dimensionResource(id = R.dimen.catalog_small_screen_min_image_width)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_width)
|
||||
)
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_medium_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_double_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.secondaryDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
end = if (!showTwoPages && isSmallWindowWidth)
|
||||
dimensionResource(id = R.dimen.small_margin)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_horizontal_margin)
|
||||
)
|
||||
.layoutId(FIFTH_PAGE_SECOND_TEXT_ID),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.ContentTextItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.contentDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val FIRST_PAGE_FIRST_TEXT_ID = "firstText"
|
||||
const val FIRST_PAGE_SECOND_TEXT_ID = "secondText"
|
||||
const val FIRST_PAGE_THIRD_TEXT_ID = "thirdText"
|
||||
const val FIRST_PAGE_FOURTH_TEXT_ID = "fourthText"
|
||||
const val FIRST_PAGE_FIFTH_TEXT_ID = "fifthText"
|
||||
|
||||
@Composable
|
||||
fun CatalogFirstPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
onItemClick: (Int) -> Unit
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page1.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
TableOfContents(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
catalogItem = catalogItem,
|
||||
onItemClick = onItemClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getConstraintSetForTableOfContents() = ConstraintSet {
|
||||
val firstTextRef = createRefFor(FIRST_PAGE_FIRST_TEXT_ID)
|
||||
val secondTextRef = createRefFor(FIRST_PAGE_SECOND_TEXT_ID)
|
||||
val thirdTextRef = createRefFor(FIRST_PAGE_THIRD_TEXT_ID)
|
||||
val fourthTextRef = createRefFor(FIRST_PAGE_FOURTH_TEXT_ID)
|
||||
val fifthTextRef = createRefFor(FIRST_PAGE_FIFTH_TEXT_ID)
|
||||
|
||||
constrain(firstTextRef) {
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(parent.top)
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
end.linkTo(parent.end)
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(firstTextRef.bottom)
|
||||
}
|
||||
|
||||
constrain(thirdTextRef) {
|
||||
end.linkTo(parent.end)
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(secondTextRef.bottom)
|
||||
}
|
||||
|
||||
constrain(fourthTextRef) {
|
||||
end.linkTo(parent.end)
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(thirdTextRef.bottom)
|
||||
}
|
||||
|
||||
constrain(fifthTextRef) {
|
||||
end.linkTo(parent.end)
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(fourthTextRef.bottom)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TableOfContents(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogItem: CatalogItem,
|
||||
onItemClick: (Int) -> Unit
|
||||
) {
|
||||
val constraintSet = getConstraintSetForTableOfContents()
|
||||
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier.fillMaxSize()
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
top = dimensionResource(id = R.dimen.catalog_margin_very_large),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin)
|
||||
)
|
||||
.layoutId(FIRST_PAGE_FIRST_TEXT_ID),
|
||||
text = catalogItem.primaryDescription,
|
||||
style = MaterialTheme.typography.h6.copy(color = MaterialTheme.colors.onSurface)
|
||||
)
|
||||
|
||||
ContentTextItem(
|
||||
modifier = Modifier
|
||||
.contentDescription(
|
||||
getPageContentDescription(
|
||||
catalogItem.secondaryDescription ?: "",
|
||||
stringResource(id = R.string.catalog_toc_item_content_description)
|
||||
)
|
||||
)
|
||||
.layoutId(FIRST_PAGE_SECOND_TEXT_ID),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
destinationPage = CatalogPage.Page2.ordinal + 1,
|
||||
onItemClick = onItemClick
|
||||
)
|
||||
|
||||
ContentTextItem(
|
||||
modifier = Modifier
|
||||
.contentDescription(
|
||||
getPageContentDescription(
|
||||
catalogItem.thirdDescription ?: "",
|
||||
stringResource(id = R.string.catalog_toc_item_content_description)
|
||||
)
|
||||
)
|
||||
.layoutId(FIRST_PAGE_THIRD_TEXT_ID),
|
||||
text = catalogItem.thirdDescription ?: "",
|
||||
destinationPage = CatalogPage.Page3.ordinal + 1,
|
||||
onItemClick = onItemClick
|
||||
)
|
||||
|
||||
ContentTextItem(
|
||||
modifier = Modifier
|
||||
.contentDescription(
|
||||
getPageContentDescription(
|
||||
catalogItem.fourthDescription ?: "",
|
||||
stringResource(id = R.string.catalog_toc_item_content_description)
|
||||
)
|
||||
)
|
||||
.layoutId(FIRST_PAGE_FOURTH_TEXT_ID),
|
||||
text = catalogItem.fourthDescription ?: "",
|
||||
destinationPage = CatalogPage.Page4.ordinal + 1,
|
||||
onItemClick = onItemClick
|
||||
)
|
||||
|
||||
ContentTextItem(
|
||||
modifier = Modifier
|
||||
.contentDescription(
|
||||
getPageContentDescription(
|
||||
catalogItem.fifthDescription ?: "",
|
||||
stringResource(id = R.string.catalog_toc_item_content_description)
|
||||
)
|
||||
)
|
||||
.layoutId(FIRST_PAGE_FIFTH_TEXT_ID),
|
||||
text = catalogItem.fifthDescription ?: "",
|
||||
destinationPage = CatalogPage.Page6.ordinal + 1,
|
||||
onItemClick = onItemClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getPageContentDescription(value: String, replacement: String): String {
|
||||
val titleIndex = value.indexOf('.')
|
||||
val pageNumberIndex = value.lastIndexOf('.') + 1
|
||||
|
||||
return value.replaceRange(titleIndex, pageNumberIndex, replacement)
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.constraintlayout.compose.ChainStyle
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.RoundedImage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.TextDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.fontDimensionResource
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getImageUri
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val FOURTH_PAGE_FIRST_IMAGE_ID = "fourthPageFirstImage"
|
||||
const val FOURTH_PAGE_SECOND_IMAGE_ID = "fourthPageSecondImage"
|
||||
const val FOURTH_PAGE_FIRST_TEXT_ID = "fourthPageFirstText"
|
||||
const val FOURTH_PAGE_SECOND_TEXT_ID = "fourthPageSecondText"
|
||||
const val FOURTH_PAGE_THIRD_TEXT_ID = "fourthPageThirdText"
|
||||
|
||||
@Composable
|
||||
fun CatalogFourthPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean = false,
|
||||
showTwoPages: Boolean = false
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page4.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
|
||||
val fourthPageConstraintSet = getConstraintSetForFourthPage(isFeatureHorizontal)
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
FourthPageContent(
|
||||
modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
start = if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_page_padding)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding),
|
||||
top = if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_margin_normal)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
),
|
||||
fourthPageConstraintSet,
|
||||
catalogItem,
|
||||
isFeatureHorizontal,
|
||||
showTwoPages
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstraintSetForFourthPage(isFeatureHorizontal: Boolean) = ConstraintSet {
|
||||
val firstImageRef = createRefFor(FOURTH_PAGE_FIRST_IMAGE_ID)
|
||||
val secondImageRef = createRefFor(FOURTH_PAGE_SECOND_IMAGE_ID)
|
||||
val firstTextRef = createRefFor(FOURTH_PAGE_FIRST_TEXT_ID)
|
||||
val secondTextRef = createRefFor(FOURTH_PAGE_SECOND_TEXT_ID)
|
||||
val thirdTextRef = createRefFor(FOURTH_PAGE_THIRD_TEXT_ID)
|
||||
val horizontalGuideline = createGuidelineFromTop(0.5f)
|
||||
|
||||
constrain(firstTextRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(firstImageRef.bottom)
|
||||
if (isFeatureHorizontal) {
|
||||
bottom.linkTo(horizontalGuideline)
|
||||
}
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
top.linkTo(if (isFeatureHorizontal) horizontalGuideline else firstTextRef.bottom)
|
||||
start.linkTo(firstTextRef.start)
|
||||
}
|
||||
|
||||
constrain(thirdTextRef) {
|
||||
linkTo(start = firstTextRef.start, end = firstTextRef.end)
|
||||
top.linkTo(secondTextRef.bottom)
|
||||
}
|
||||
|
||||
constrain(firstImageRef) {
|
||||
top.linkTo(parent.top)
|
||||
start.linkTo(secondTextRef.start)
|
||||
}
|
||||
|
||||
constrain(secondImageRef) {
|
||||
start.linkTo(firstImageRef.start)
|
||||
top.linkTo(firstImageRef.top)
|
||||
end.linkTo(secondTextRef.end)
|
||||
}
|
||||
|
||||
createHorizontalChain(
|
||||
firstImageRef,
|
||||
secondImageRef,
|
||||
chainStyle = ChainStyle.Spread
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FourthPageContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_top_margin))
|
||||
.layoutId(FOURTH_PAGE_FIRST_IMAGE_ID)
|
||||
.requiredWidth(
|
||||
if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_max_image_height_dual_landscape)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
)
|
||||
.requiredHeight(
|
||||
if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = dimensionResource(id = R.dimen.catalog_top_margin),
|
||||
end = if (showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_margin_large)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
)
|
||||
.layoutId(FOURTH_PAGE_SECOND_IMAGE_ID)
|
||||
.requiredWidth(
|
||||
if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_max_image_height_dual_landscape)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
)
|
||||
.requiredHeight(
|
||||
if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.secondPictureDescription
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
horizontal = if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
else
|
||||
dimensionResource(id = R.dimen.medium_margin)
|
||||
)
|
||||
.layoutId(FOURTH_PAGE_FIRST_TEXT_ID),
|
||||
text = catalogItem.primaryDescription,
|
||||
contentDescription = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = dimensionResource(id = R.dimen.catalog_top_margin),
|
||||
start = if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
else
|
||||
dimensionResource(id = R.dimen.medium_margin)
|
||||
)
|
||||
.layoutId(FOURTH_PAGE_SECOND_TEXT_ID),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_20)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = dimensionResource(id = R.dimen.catalog_top_margin),
|
||||
start = if (isFeatureHorizontal && showTwoPages)
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
else
|
||||
dimensionResource(id = R.dimen.medium_margin)
|
||||
)
|
||||
.layoutId(FOURTH_PAGE_THIRD_TEXT_ID),
|
||||
text = catalogItem.thirdDescription ?: "",
|
||||
contentDescription = catalogItem.thirdDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ChainStyle
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.RoundedImage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.TextDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.fontDimensionResource
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getImageUri
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val SECOND_PAGE_TITLE_TEXT_ID = "secondPageTitle"
|
||||
const val SECOND_PAGE_FIRST_ROW_ID = "secondPageFirstRow"
|
||||
const val SECOND_PAGE_SECOND_TEXT_ID = "secondPageSecondText"
|
||||
const val SECOND_PAGE_THIRD_TEXT_ID = "secondPageThirdText"
|
||||
const val SECOND_PAGE_FIRST_IMAGE_ID = "secondPageFirstImage"
|
||||
const val SECOND_PAGE_FIRST_ROW_IMAGE_ID = "secondPageFirstRowImage"
|
||||
const val SECOND_PAGE_SECOND_ROW_IMAGE_ID = "secondPageSecondRowImage"
|
||||
|
||||
const val HORIZONTAL_GUIDELINE_FRACTION = 0.5f
|
||||
|
||||
@Composable
|
||||
fun CatalogSecondPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean = false,
|
||||
showTwoPages: Boolean = false,
|
||||
isSmallWindowWidth: Boolean = false
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page2.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
|
||||
val secondPageConstraintSet = if (isSmallWindowWidth)
|
||||
getConstraintSetForSmallWindowWidth()
|
||||
else
|
||||
getConstraintSetForSecondPage(isFeatureHorizontal)
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
SecondPageContent(
|
||||
modifier = modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
top = if (isFeatureHorizontal)
|
||||
dimensionResource(id = R.dimen.catalog_margin_normal)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
),
|
||||
constraintSet = secondPageConstraintSet,
|
||||
catalogItem = catalogItem,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
isSmallWindowWidth = isSmallWindowWidth,
|
||||
showTwoPages = showTwoPages
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getConstraintSetForSecondPage(isFeatureHorizontal: Boolean) = ConstraintSet {
|
||||
val titleRef = createRefFor(SECOND_PAGE_TITLE_TEXT_ID)
|
||||
val firstRowRef = createRefFor(SECOND_PAGE_FIRST_ROW_ID)
|
||||
val thirdTextRef = createRefFor(SECOND_PAGE_THIRD_TEXT_ID)
|
||||
val firstRowImageRef = createRefFor(SECOND_PAGE_FIRST_ROW_IMAGE_ID)
|
||||
val secondRowImageRef = createRefFor(SECOND_PAGE_SECOND_ROW_IMAGE_ID)
|
||||
val horizontalGuideline = createGuidelineFromTop(HORIZONTAL_GUIDELINE_FRACTION)
|
||||
|
||||
val horizontalMargin = 36.dp
|
||||
val topMargin = 20.dp
|
||||
val smallMargin = 8.dp
|
||||
|
||||
constrain(titleRef) {
|
||||
top.linkTo(parent.top, topMargin)
|
||||
start.linkTo(parent.start, horizontalMargin)
|
||||
}
|
||||
|
||||
constrain(firstRowRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(titleRef.bottom, smallMargin)
|
||||
if (isFeatureHorizontal) {
|
||||
bottom.linkTo(horizontalGuideline)
|
||||
}
|
||||
}
|
||||
|
||||
constrain(thirdTextRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
if (isFeatureHorizontal) {
|
||||
top.linkTo(horizontalGuideline)
|
||||
} else {
|
||||
top.linkTo(firstRowRef.bottom)
|
||||
}
|
||||
}
|
||||
|
||||
constrain(firstRowImageRef) {
|
||||
top.linkTo(thirdTextRef.bottom, topMargin)
|
||||
start.linkTo(firstRowRef.start)
|
||||
}
|
||||
|
||||
constrain(secondRowImageRef) {
|
||||
start.linkTo(firstRowImageRef.start)
|
||||
top.linkTo(firstRowImageRef.top)
|
||||
end.linkTo(firstRowRef.end)
|
||||
}
|
||||
|
||||
createHorizontalChain(
|
||||
firstRowImageRef,
|
||||
secondRowImageRef,
|
||||
chainStyle = ChainStyle.SpreadInside
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getConstraintSetForSmallWindowWidth() = ConstraintSet {
|
||||
val titleRef = createRefFor(SECOND_PAGE_TITLE_TEXT_ID)
|
||||
val firstImageRef = createRefFor(SECOND_PAGE_FIRST_IMAGE_ID)
|
||||
val secondTextRef = createRefFor(SECOND_PAGE_SECOND_TEXT_ID)
|
||||
val thirdTextRef = createRefFor(SECOND_PAGE_THIRD_TEXT_ID)
|
||||
val firstRowImageRef = createRefFor(SECOND_PAGE_FIRST_ROW_IMAGE_ID)
|
||||
val secondRowImageRef = createRefFor(SECOND_PAGE_SECOND_ROW_IMAGE_ID)
|
||||
|
||||
val horizontalMargin = 36.dp
|
||||
val topMargin = 20.dp
|
||||
val smallMargin = 8.dp
|
||||
|
||||
constrain(titleRef) {
|
||||
top.linkTo(parent.top, topMargin)
|
||||
start.linkTo(parent.start, horizontalMargin)
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
linkTo(
|
||||
start = parent.start,
|
||||
end = parent.end,
|
||||
startMargin = horizontalMargin,
|
||||
endMargin = horizontalMargin
|
||||
)
|
||||
top.linkTo(titleRef.bottom, smallMargin)
|
||||
}
|
||||
|
||||
constrain(firstImageRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(secondTextRef.bottom, smallMargin)
|
||||
height = Dimension.fillToConstraints
|
||||
}
|
||||
|
||||
constrain(thirdTextRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(firstImageRef.bottom)
|
||||
}
|
||||
|
||||
constrain(firstRowImageRef) {
|
||||
top.linkTo(thirdTextRef.bottom, smallMargin)
|
||||
start.linkTo(secondTextRef.start, horizontalMargin)
|
||||
}
|
||||
|
||||
constrain(secondRowImageRef) {
|
||||
start.linkTo(firstRowImageRef.start)
|
||||
top.linkTo(firstRowImageRef.top)
|
||||
end.linkTo(secondTextRef.end, horizontalMargin)
|
||||
}
|
||||
|
||||
createHorizontalChain(
|
||||
firstRowImageRef,
|
||||
secondRowImageRef,
|
||||
chainStyle = ChainStyle.Spread
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SecondPageContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
isSmallWindowWidth: Boolean,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(SECOND_PAGE_TITLE_TEXT_ID),
|
||||
text = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_20)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_16),
|
||||
contentDescription = catalogItem.primaryDescription
|
||||
)
|
||||
|
||||
if (isSmallWindowWidth && !showTwoPages) {
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.layoutId(SECOND_PAGE_SECOND_TEXT_ID)
|
||||
.padding(horizontal = dimensionResource(id = R.dimen.catalog_horizontal_margin)),
|
||||
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.secondaryDescription ?: ""
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(SECOND_PAGE_FIRST_IMAGE_ID)
|
||||
.requiredWidth(dimensionResource(id = R.dimen.catalog_small_screen_min_image_width))
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height)),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription,
|
||||
contentScale = ContentScale.FillHeight
|
||||
)
|
||||
} else {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.layoutId(SECOND_PAGE_FIRST_ROW_ID)
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_margin_small)),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.padding(start = dimensionResource(id = R.dimen.catalog_image_margin_start))
|
||||
.requiredWidth(dimensionResource(id = R.dimen.catalog_min_image_width))
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height)),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.padding(
|
||||
top = dimensionResource(id = R.dimen.small_margin),
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin)
|
||||
),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.secondaryDescription ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.layoutId(SECOND_PAGE_THIRD_TEXT_ID)
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
top = dimensionResource(id = R.dimen.catalog_margin_large)
|
||||
),
|
||||
text = catalogItem.thirdDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.thirdDescription ?: ""
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(SECOND_PAGE_FIRST_ROW_IMAGE_ID)
|
||||
.padding(
|
||||
start = if (isSmallWindowWidth && !showTwoPages)
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_image_margin_start)
|
||||
)
|
||||
.requiredWidth(
|
||||
if (isSmallWindowWidth && !showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_small_screen_min_image_width)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_width)
|
||||
)
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height)),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(SECOND_PAGE_SECOND_ROW_IMAGE_ID)
|
||||
.padding(
|
||||
end = if (isSmallWindowWidth && !showTwoPages)
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_image_margin_end)
|
||||
)
|
||||
.requiredWidth(
|
||||
if (isSmallWindowWidth && !showTwoPages)
|
||||
dimensionResource(id = R.dimen.catalog_small_screen_min_image_width)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_width)
|
||||
)
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height)),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.thirdPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.RoundedImage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.TextDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.fontDimensionResource
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getImageUri
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val SEVENTH_PAGE_FIRST_ROW_ID = "seventhPageFirstRow"
|
||||
const val SEVENTH_PAGE_SECOND_ROW_ID = "seventhPageSecondRow"
|
||||
const val SEVENTH_PAGE_FIRST_IMAGE_ID = "seventhPageFirstImage"
|
||||
const val SEVENTH_PAGE_SECOND_IMAGE_ID = "seventhPageSecondImage"
|
||||
const val SEVENTH_PAGE_FIRST_TEXT_ID = "seventhPageFirstText"
|
||||
const val SEVENTH_PAGE_SECOND_TEXT_ID = "seventhPageSecondText"
|
||||
|
||||
@Composable
|
||||
fun CatalogSeventhPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean = false,
|
||||
isSmallWindowWidth: Boolean = false,
|
||||
showTwoPages: Boolean = false
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page7.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
if (isSmallWindowWidth && !showTwoPages) {
|
||||
SeventhPageContentSmallWidth(
|
||||
modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
top = if (isFeatureHorizontal)
|
||||
dimensionResource(id = R.dimen.catalog_margin_normal)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
),
|
||||
getConstraintSetForSmallWindowWidth(),
|
||||
catalogItem,
|
||||
isFeatureHorizontal,
|
||||
showTwoPages
|
||||
)
|
||||
} else {
|
||||
SeventhPageContent(
|
||||
modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
top = if (isFeatureHorizontal)
|
||||
dimensionResource(id = R.dimen.catalog_margin_normal)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding)
|
||||
),
|
||||
getConstraintSetForSeventhPage(isFeatureHorizontal),
|
||||
catalogItem,
|
||||
isFeatureHorizontal,
|
||||
showTwoPages
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstraintSetForSeventhPage(isFeatureHorizontal: Boolean) = ConstraintSet {
|
||||
val firstRowRef = createRefFor(SEVENTH_PAGE_FIRST_ROW_ID)
|
||||
val secondRowRef = createRefFor(SEVENTH_PAGE_SECOND_ROW_ID)
|
||||
val horizontalGuideline = createGuidelineFromTop(0.5f)
|
||||
|
||||
val topMargin = 20.dp
|
||||
|
||||
constrain(firstRowRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(parent.top)
|
||||
if (isFeatureHorizontal) {
|
||||
bottom.linkTo(horizontalGuideline)
|
||||
}
|
||||
}
|
||||
|
||||
constrain(secondRowRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(if (isFeatureHorizontal) horizontalGuideline else firstRowRef.bottom, topMargin)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SeventhPageContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.wrapContentHeight()
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_top_margin))
|
||||
.layoutId(SEVENTH_PAGE_FIRST_ROW_ID),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_top_margin))
|
||||
.weight(1f)
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_min_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.padding(top = dimensionResource(id = R.dimen.normal_margin))
|
||||
.weight(1f),
|
||||
text = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.primaryDescription
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.layoutId(SEVENTH_PAGE_SECOND_ROW_ID),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_min_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.secondaryDescription
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getConstraintSetForSmallWindowWidth() = ConstraintSet {
|
||||
val firstImageRef = createRefFor(SEVENTH_PAGE_FIRST_IMAGE_ID)
|
||||
val firstTextRef = createRefFor(SEVENTH_PAGE_FIRST_TEXT_ID)
|
||||
val secondImageRef = createRefFor(SEVENTH_PAGE_SECOND_IMAGE_ID)
|
||||
val secondTextRef = createRefFor(SEVENTH_PAGE_SECOND_TEXT_ID)
|
||||
|
||||
val topMargin = 20.dp
|
||||
|
||||
constrain(firstImageRef) {
|
||||
top.linkTo(parent.top, topMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
}
|
||||
|
||||
constrain(firstTextRef) {
|
||||
top.linkTo(firstImageRef.bottom, topMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
}
|
||||
|
||||
constrain(secondImageRef) {
|
||||
top.linkTo(firstTextRef.bottom, topMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
top.linkTo(secondImageRef.bottom, topMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SeventhPageContentSmallWidth(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(SEVENTH_PAGE_FIRST_IMAGE_ID)
|
||||
.requiredWidth(dimensionResource(id = R.dimen.catalog_small_screen_min_image_width))
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height))
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_min_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(SEVENTH_PAGE_FIRST_TEXT_ID),
|
||||
text = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.primaryDescription
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(SEVENTH_PAGE_SECOND_IMAGE_ID)
|
||||
.requiredWidth(dimensionResource(id = R.dimen.catalog_small_screen_min_image_width))
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height))
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_min_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.secondaryDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(SEVENTH_PAGE_SECOND_TEXT_ID),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.RoundedImage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.TextDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.fontDimensionResource
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getImageUri
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val SIXTH_PAGE_FIRST_TEXT_ID = "sixthPageFirstText"
|
||||
const val SIXTH_PAGE_FIRST_IMAGE_ID = "sixthPageFirstImage"
|
||||
const val SIXTH_PAGE_SECOND_TEXT_ID = "sixthPageSecondText"
|
||||
|
||||
@Composable
|
||||
fun CatalogSixthPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean = false,
|
||||
showTwoPages: Boolean = false
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page6.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
|
||||
val sixthPageConstraintSet = getConstraintSetForSixthPage(isFeatureHorizontal)
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
SixthPageContent(
|
||||
modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
bottom = dimensionResource(id = R.dimen.catalog_margin_normal),
|
||||
top = if (isFeatureHorizontal)
|
||||
dimensionResource(id = R.dimen.catalog_margin_normal)
|
||||
else
|
||||
dimensionResource(id = R.dimen.zero_padding),
|
||||
),
|
||||
sixthPageConstraintSet,
|
||||
catalogItem,
|
||||
isFeatureHorizontal,
|
||||
showTwoPages
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstraintSetForSixthPage(isFeatureHorizontal: Boolean) = ConstraintSet {
|
||||
val firstTextRef = createRefFor(SIXTH_PAGE_FIRST_TEXT_ID)
|
||||
val firstImageRef = createRefFor(SIXTH_PAGE_FIRST_IMAGE_ID)
|
||||
val secondTextRef = createRefFor(SIXTH_PAGE_SECOND_TEXT_ID)
|
||||
|
||||
val horizontalGuideline = createGuidelineFromTop(0.5f)
|
||||
val topMargin = 20.dp
|
||||
|
||||
constrain(firstTextRef) {
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(parent.top, topMargin)
|
||||
}
|
||||
|
||||
constrain(firstImageRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
if (isFeatureHorizontal) {
|
||||
linkTo(top = firstTextRef.bottom, bottom = horizontalGuideline, topMargin = topMargin)
|
||||
} else {
|
||||
top.linkTo(firstTextRef.bottom, margin = topMargin)
|
||||
}
|
||||
width = Dimension.wrapContent
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
if (isFeatureHorizontal) {
|
||||
top.linkTo(horizontalGuideline, margin = topMargin)
|
||||
} else {
|
||||
top.linkTo(firstImageRef.bottom, margin = topMargin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SixthPageContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
showTwoPages: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(SIXTH_PAGE_FIRST_TEXT_ID),
|
||||
text = catalogItem.primaryDescription,
|
||||
contentDescription = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_20)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(SIXTH_PAGE_FIRST_IMAGE_ID)
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_min_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(SIXTH_PAGE_SECOND_TEXT_ID),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem
|
||||
import com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogPage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.PageLayout
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.RoundedImage
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.TextDescription
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils.fontDimensionResource
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.getImageUri
|
||||
import com.microsoft.device.samples.dualscreenexperience.presentation.util.sizeOrZero
|
||||
|
||||
const val THIRD_PAGE_FIRST_ROW_ID = "thirdPageFirstRow"
|
||||
const val THIRD_PAGE_SECOND_ROW_ID = "thirdPageSecondRow"
|
||||
const val THIRD_PAGE_FIRST_IMAGE_ID = "thirdPageFirstImage"
|
||||
const val THIRD_PAGE_FIRST_TEXT_ID = "thirdPageFirstText"
|
||||
const val THIRD_PAGE_SECOND_TEXT_ID = "thirdPageSecondText"
|
||||
const val THIRD_PAGE_THIRD_TEXT_ID = "thirdPageThirdText"
|
||||
const val THIRD_PAGE_SECOND_IMAGE_ID = "thirdPageSecondImage"
|
||||
|
||||
const val ROW_WEIGHT = 1f
|
||||
|
||||
@Composable
|
||||
fun CatalogThirdPage(
|
||||
modifier: Modifier = Modifier,
|
||||
catalogList: List<CatalogItem>,
|
||||
isFeatureHorizontal: Boolean = false,
|
||||
isSinglePortrait: Boolean,
|
||||
showTwoPages: Boolean = false,
|
||||
isSmallWindowWidth: Boolean = false,
|
||||
isFoldStateHalfOpened: Boolean = false
|
||||
) {
|
||||
val pageNumberOrdinal = CatalogPage.Page3.ordinal
|
||||
val catalogItem = catalogList[pageNumberOrdinal]
|
||||
|
||||
PageLayout(
|
||||
modifier,
|
||||
pageNumberOrdinal + 1,
|
||||
catalogList.sizeOrZero()
|
||||
) {
|
||||
val contentModifier =
|
||||
modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_margin_normal))
|
||||
if (isSmallWindowWidth) {
|
||||
ThirdPageSmallWindowWidthContent(
|
||||
modifier = contentModifier,
|
||||
constraintSet = getConstraintSetForSmallWindowWidth(),
|
||||
catalogItem = catalogItem
|
||||
)
|
||||
} else {
|
||||
ThirdPageContent(
|
||||
modifier = contentModifier,
|
||||
constraintSet = getConstraintSetForThirdPage(isFeatureHorizontal),
|
||||
catalogItem = catalogItem,
|
||||
isFeatureHorizontal = isFeatureHorizontal,
|
||||
isSinglePortrait = isSinglePortrait,
|
||||
showTwoPages = showTwoPages,
|
||||
isFoldStateHalfOpened = isFoldStateHalfOpened
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstraintSetForThirdPage(isFeatureHorizontal: Boolean) = ConstraintSet {
|
||||
val firstRowRef = createRefFor(THIRD_PAGE_FIRST_ROW_ID)
|
||||
val secondRowRef = createRefFor(THIRD_PAGE_SECOND_ROW_ID)
|
||||
val horizontalGuideline = createGuidelineFromTop(0.5f)
|
||||
|
||||
val topMargin = 20.dp
|
||||
val smallMargin = 8.dp
|
||||
|
||||
constrain(firstRowRef) {
|
||||
linkTo(
|
||||
start = parent.start,
|
||||
startMargin = smallMargin,
|
||||
end = parent.end,
|
||||
endMargin = smallMargin
|
||||
)
|
||||
top.linkTo(parent.top)
|
||||
if (isFeatureHorizontal) {
|
||||
bottom.linkTo(horizontalGuideline)
|
||||
}
|
||||
}
|
||||
|
||||
constrain(secondRowRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
top.linkTo(if (isFeatureHorizontal) horizontalGuideline else firstRowRef.bottom, topMargin)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getConstraintSetForSmallWindowWidth() = ConstraintSet {
|
||||
val firstImageRef = createRefFor(THIRD_PAGE_FIRST_IMAGE_ID)
|
||||
val firstTextRef = createRefFor(THIRD_PAGE_FIRST_TEXT_ID)
|
||||
val secondImageRef = createRefFor(THIRD_PAGE_SECOND_IMAGE_ID)
|
||||
val secondTextRef = createRefFor(THIRD_PAGE_SECOND_TEXT_ID)
|
||||
val thirdTextRef = createRefFor(THIRD_PAGE_THIRD_TEXT_ID)
|
||||
|
||||
val horizontalMargin = 36.dp
|
||||
val topMargin = 20.dp
|
||||
val smallMargin = 8.dp
|
||||
|
||||
constrain(firstImageRef) {
|
||||
top.linkTo(parent.top, topMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
}
|
||||
|
||||
constrain(firstTextRef) {
|
||||
top.linkTo(firstImageRef.bottom, topMargin)
|
||||
linkTo(
|
||||
start = parent.start,
|
||||
end = parent.end,
|
||||
startMargin = horizontalMargin,
|
||||
endMargin = horizontalMargin
|
||||
)
|
||||
}
|
||||
|
||||
constrain(secondImageRef) {
|
||||
top.linkTo(firstTextRef.bottom, smallMargin)
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
}
|
||||
|
||||
constrain(secondTextRef) {
|
||||
top.linkTo(secondImageRef.bottom, topMargin)
|
||||
start.linkTo(parent.start, horizontalMargin)
|
||||
}
|
||||
|
||||
constrain(thirdTextRef) {
|
||||
top.linkTo(secondTextRef.bottom)
|
||||
linkTo(
|
||||
start = parent.start,
|
||||
end = parent.end,
|
||||
startMargin = horizontalMargin,
|
||||
endMargin = horizontalMargin
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ThirdPageContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem,
|
||||
isFeatureHorizontal: Boolean,
|
||||
isSinglePortrait: Boolean,
|
||||
showTwoPages: Boolean,
|
||||
isFoldStateHalfOpened: Boolean
|
||||
) {
|
||||
ConstraintLayout(
|
||||
constraintSet = constraintSet,
|
||||
modifier = modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = dimensionResource(id = R.dimen.catalog_top_margin),
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.normal_margin)
|
||||
)
|
||||
.layoutId(THIRD_PAGE_FIRST_ROW_ID),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.weight(ROW_WEIGHT)
|
||||
.requiredWidth(
|
||||
if ((isFeatureHorizontal && !showTwoPages) ||
|
||||
isSinglePortrait || (isFoldStateHalfOpened && !showTwoPages)
|
||||
)
|
||||
dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_width)
|
||||
)
|
||||
.requiredHeight(
|
||||
if ((isFeatureHorizontal && !showTwoPages) ||
|
||||
isSinglePortrait || (isFoldStateHalfOpened && !showTwoPages)
|
||||
)
|
||||
dimensionResource(id = R.dimen.catalog_medium_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.normal_margin)
|
||||
)
|
||||
.weight(ROW_WEIGHT),
|
||||
text = catalogItem.primaryDescription,
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.primaryDescription
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(end = dimensionResource(id = R.dimen.normal_margin))
|
||||
.layoutId(THIRD_PAGE_SECOND_ROW_ID),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = dimensionResource(id = R.dimen.catalog_horizontal_margin))
|
||||
.weight(ROW_WEIGHT)
|
||||
) {
|
||||
TextDescription(
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_20)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
)
|
||||
TextDescription(
|
||||
modifier = Modifier.padding(
|
||||
top = dimensionResource(id = R.dimen.catalog_top_margin)
|
||||
),
|
||||
text = catalogItem.thirdDescription ?: "",
|
||||
contentDescription = catalogItem.thirdDescription ?: "",
|
||||
fontSize = if (isFeatureHorizontal && showTwoPages)
|
||||
fontDimensionResource(id = R.dimen.text_size_16)
|
||||
else
|
||||
fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
}
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_top_margin))
|
||||
.weight(ROW_WEIGHT)
|
||||
.requiredWidth(
|
||||
if ((isFeatureHorizontal && !showTwoPages) ||
|
||||
isSinglePortrait || (isFoldStateHalfOpened && !showTwoPages)
|
||||
)
|
||||
dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_width)
|
||||
)
|
||||
.requiredHeight(
|
||||
if ((isFeatureHorizontal && !showTwoPages) ||
|
||||
isSinglePortrait || (isFoldStateHalfOpened && !showTwoPages)
|
||||
)
|
||||
dimensionResource(id = R.dimen.catalog_medium_image_height)
|
||||
else
|
||||
dimensionResource(id = R.dimen.catalog_min_image_height)
|
||||
)
|
||||
.heightIn(
|
||||
min = dimensionResource(id = R.dimen.catalog_min_image_height),
|
||||
max = dimensionResource(id = R.dimen.catalog_max_image_height)
|
||||
),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.secondaryDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ThirdPageSmallWindowWidthContent(
|
||||
modifier: Modifier,
|
||||
constraintSet: ConstraintSet,
|
||||
catalogItem: CatalogItem
|
||||
) {
|
||||
ConstraintLayout(constraintSet, modifier = modifier) {
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(THIRD_PAGE_FIRST_IMAGE_ID)
|
||||
.requiredWidth(dimensionResource(id = R.dimen.catalog_small_screen_min_image_width))
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height)),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.firstPicture)),
|
||||
contentDescription = catalogItem.firstPictureDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.layoutId(THIRD_PAGE_FIRST_TEXT_ID)
|
||||
.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.normal_margin)
|
||||
),
|
||||
text = catalogItem.primaryDescription,
|
||||
fontSize =
|
||||
fontDimensionResource(id = R.dimen.text_size_12),
|
||||
contentDescription = catalogItem.primaryDescription
|
||||
)
|
||||
|
||||
RoundedImage(
|
||||
modifier = Modifier
|
||||
.layoutId(THIRD_PAGE_SECOND_IMAGE_ID)
|
||||
.padding(top = dimensionResource(id = R.dimen.catalog_top_margin))
|
||||
.requiredWidth(dimensionResource(id = R.dimen.catalog_small_screen_min_image_width))
|
||||
.requiredHeight(dimensionResource(id = R.dimen.catalog_min_image_height)),
|
||||
painter = rememberAsyncImagePainter(model = getImageUri(catalogItem.secondPicture)),
|
||||
contentDescription = catalogItem.secondaryDescription,
|
||||
contentScale = ContentScale.FillBounds
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier.layoutId(THIRD_PAGE_SECOND_TEXT_ID),
|
||||
text = catalogItem.secondaryDescription ?: "",
|
||||
contentDescription = catalogItem.secondaryDescription ?: "",
|
||||
fontSize = fontDimensionResource(id = R.dimen.text_size_16)
|
||||
)
|
||||
|
||||
TextDescription(
|
||||
modifier = Modifier
|
||||
.layoutId(THIRD_PAGE_THIRD_TEXT_ID)
|
||||
.padding(
|
||||
top = dimensionResource(id = R.dimen.catalog_top_margin),
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.normal_margin)
|
||||
),
|
||||
text = catalogItem.thirdDescription ?: "",
|
||||
contentDescription = catalogItem.thirdDescription ?: "",
|
||||
fontSize = fontDimensionResource(id = R.dimen.text_size_12)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
|
||||
fun Modifier.contentDescription(contentDescription: String) =
|
||||
this.semantics {
|
||||
this.contentDescription = contentDescription
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils
|
||||
|
||||
import androidx.annotation.DimenRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun fontDimensionResource(@DimenRes id: Int) =
|
||||
dimensionResource(id = id).value.sp
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintSet
|
||||
import com.microsoft.device.samples.dualscreenexperience.R
|
||||
|
||||
const val CONTENT_ID = "tableOfContents"
|
||||
const val BOTTOM_PAGE_NUMBER_ID = "bottomPageNumber"
|
||||
|
||||
@Composable
|
||||
fun PageLayout(
|
||||
modifier: Modifier = Modifier,
|
||||
pageNumber: Int,
|
||||
maxPageNumber: Int,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val constraintSet = getMainConstraintSet()
|
||||
|
||||
ConstraintLayout(constraintSet = constraintSet, modifier = modifier) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.layoutId(CONTENT_ID)
|
||||
.fillMaxHeight()
|
||||
.padding(bottom = dimensionResource(id = R.dimen.catalog_margin_normal))
|
||||
) {
|
||||
content()
|
||||
}
|
||||
|
||||
BottomPageNumber(
|
||||
modifier = Modifier.layoutId(BOTTOM_PAGE_NUMBER_ID),
|
||||
text = stringResource(
|
||||
id = R.string.catalog_page_no, pageNumber, maxPageNumber
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getMainConstraintSet() = ConstraintSet {
|
||||
val contentRef = createRefFor(CONTENT_ID)
|
||||
val bottomPageNumberRef = createRefFor(BOTTOM_PAGE_NUMBER_ID)
|
||||
|
||||
constrain(contentRef) {
|
||||
linkTo(start = parent.start, end = parent.end)
|
||||
linkTo(top = parent.top, bottom = bottomPageNumberRef.top)
|
||||
}
|
||||
|
||||
constrain(bottomPageNumberRef) {
|
||||
start.linkTo(parent.start)
|
||||
bottom.linkTo(parent.bottom)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BottomPageNumber(modifier: Modifier = Modifier, text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
style = TextStyle(
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
fontFamily = FontFamily(Font(R.font.dmsans_regular)),
|
||||
lineHeight = fontDimensionResource(id = R.dimen.text_size_4),
|
||||
fontSize = fontDimensionResource(id = R.dimen.text_size_12),
|
||||
textAlign = TextAlign.Start
|
||||
),
|
||||
modifier = modifier.padding(
|
||||
start = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
end = dimensionResource(id = R.dimen.catalog_horizontal_margin),
|
||||
bottom = dimensionResource(id = R.dimen.catalog_margin_small)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TextDescription(
|
||||
modifier: Modifier = Modifier,
|
||||
text: String,
|
||||
contentDescription: String,
|
||||
textStyle: TextStyle = MaterialTheme.typography.body1,
|
||||
color: Color = MaterialTheme.colors.onSurface,
|
||||
textAlign: TextAlign = TextAlign.Start,
|
||||
fontSize: TextUnit = fontDimensionResource(id = R.dimen.text_size_12),
|
||||
lineHeight: TextUnit = fontDimensionResource(id = R.dimen.text_size_20)
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier.contentDescription(contentDescription),
|
||||
text = text,
|
||||
lineHeight = lineHeight,
|
||||
textAlign = textAlign,
|
||||
style = textStyle,
|
||||
color = color,
|
||||
fontSize = fontSize
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RoundedImage(
|
||||
modifier: Modifier = Modifier,
|
||||
painter: Painter,
|
||||
contentDescription: String?,
|
||||
contentScale: ContentScale = ContentScale.None
|
||||
) {
|
||||
Image(
|
||||
modifier = modifier
|
||||
.clip(MaterialTheme.shapes.small)
|
||||
.clipToBounds(),
|
||||
painter = painter,
|
||||
contentDescription = contentDescription,
|
||||
contentScale = contentScale
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ContentTextItem(
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = MaterialTheme.colors.onSurface,
|
||||
textAlign: TextAlign = TextAlign.Start,
|
||||
text: String,
|
||||
destinationPage: Int,
|
||||
onItemClick: (Int) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
vertical = dimensionResource(id = R.dimen.catalog_margin_normal),
|
||||
horizontal = dimensionResource(id = R.dimen.catalog_horizontal_margin)
|
||||
)
|
||||
.wrapContentWidth()
|
||||
.clickable { onItemClick(destinationPage - 1) },
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = text,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = color,
|
||||
textAlign = textAlign
|
||||
)
|
||||
Text(
|
||||
text = destinationPage.toString(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = color
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.catalog.utils
|
||||
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.compose.animation.core.Animatable
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.draggable
|
||||
import androidx.compose.foundation.gestures.rememberDraggableState
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.mapSaver
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.structuralEqualityPolicy
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.layout.Measurable
|
||||
import androidx.compose.ui.layout.ParentDataModifier
|
||||
import androidx.compose.ui.unit.Density
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* This is a modified version of the "Pager" from the Compose JetCaster official sample under Apache License v2
|
||||
* Source code:
|
||||
* https://github.com/android/compose-samples/blob/main/Jetcaster/app/src/main/java/com/example/jetcaster/util/Pager.kt
|
||||
* License:
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
class PagerState(
|
||||
currentPage: Int = 0,
|
||||
minPage: Int = 0,
|
||||
maxPage: Int = 0
|
||||
) {
|
||||
private var _minPage by mutableStateOf(minPage)
|
||||
var minPage: Int
|
||||
get() = _minPage
|
||||
set(value) {
|
||||
_minPage = value.coerceAtMost(_maxPage)
|
||||
_currentPage = _currentPage.coerceIn(_minPage, _maxPage)
|
||||
}
|
||||
|
||||
private var _maxPage by mutableStateOf(maxPage, structuralEqualityPolicy())
|
||||
var maxPage: Int
|
||||
get() = _maxPage
|
||||
set(value) {
|
||||
_maxPage = value.coerceAtLeast(_minPage)
|
||||
_currentPage = if (isDualMode && _currentPage == _maxPage) {
|
||||
_currentPage.coerceIn(_minPage - 1, _maxPage - 1)
|
||||
} else {
|
||||
_currentPage.coerceIn(_minPage, _maxPage)
|
||||
}
|
||||
}
|
||||
|
||||
private var _currentPage by mutableStateOf(currentPage.coerceIn(minPage, maxPage))
|
||||
var currentPage: Int
|
||||
get() = _currentPage
|
||||
set(value) {
|
||||
_currentPage = value.coerceIn(minPage, maxPage)
|
||||
}
|
||||
|
||||
enum class SelectionState { Selected, Undecided }
|
||||
|
||||
var selectionState by mutableStateOf(SelectionState.Selected)
|
||||
|
||||
var isDualMode: Boolean = false // support dual-screen mode
|
||||
|
||||
suspend fun selectPage() {
|
||||
currentPage -= updatePage(currentPageOffset)
|
||||
snapToOffset(0f)
|
||||
selectionState = SelectionState.Selected
|
||||
}
|
||||
|
||||
suspend fun selectPageNumber(pageNumber: Int) {
|
||||
currentPage = pageNumber
|
||||
snapToOffset(0f)
|
||||
}
|
||||
|
||||
private var _currentPageOffset = Animatable(0f).apply {
|
||||
updateBounds(-1f, 1f)
|
||||
}
|
||||
val currentPageOffset: Float
|
||||
get() = _currentPageOffset.value
|
||||
|
||||
suspend fun snapToOffset(offset: Float) {
|
||||
val max = if (currentPage == minPage) 0f else 1f
|
||||
val lastPage = if (isDualMode) maxPage - 1 else maxPage
|
||||
val min = if (currentPage == lastPage) 0f else -1f
|
||||
|
||||
_currentPageOffset.snapTo(offset.coerceIn(min, max))
|
||||
}
|
||||
|
||||
private val minDragOffset = 0.1f // customize the minimum offset to enhance the dragging gesture
|
||||
|
||||
private fun roundOffset(original: Float): Float {
|
||||
return if (original > minDragOffset) 1f else if (original < -minDragOffset) -1f else 0f // ease the scrolling transition
|
||||
}
|
||||
|
||||
private fun updatePage(offset: Float): Int {
|
||||
return if (offset > minDragOffset) 1 else if (offset < -minDragOffset) -1 else 0
|
||||
}
|
||||
|
||||
suspend fun fling(velocity: Float) {
|
||||
if (velocity < 0 && currentPage == maxPage) return
|
||||
if (velocity > 0 && currentPage == minPage) return
|
||||
|
||||
val offset = roundOffset(currentPageOffset)
|
||||
_currentPageOffset.animateTo(offset)
|
||||
|
||||
selectPage()
|
||||
}
|
||||
|
||||
override fun toString(): String = "PagerState{minPage=$minPage, maxPage=$maxPage, " +
|
||||
"currentPage=$currentPage, currentPageOffset=$currentPageOffset}"
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Default [Saver] implementation for [PagerState]
|
||||
*/
|
||||
val Saver = run {
|
||||
val currentPageKey = "currentPage"
|
||||
val minPageKey = "minPage"
|
||||
val maxPageKey = "maxPage"
|
||||
mapSaver(
|
||||
save = {
|
||||
mapOf(
|
||||
currentPageKey to it.currentPage,
|
||||
minPageKey to it.minPage,
|
||||
maxPageKey to it.maxPage
|
||||
)
|
||||
},
|
||||
restore = {
|
||||
PagerState(
|
||||
it[currentPageKey] as Int,
|
||||
it[minPageKey] as Int,
|
||||
it[maxPageKey] as Int
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberViewPagerState(
|
||||
@IntRange(from = 0) currentPage: Int = 0,
|
||||
@IntRange(from = 0) minPage: Int = 0,
|
||||
@IntRange(from = 0) maxPage: Int = 0
|
||||
): PagerState = rememberSaveable(saver = PagerState.Saver) {
|
||||
PagerState(
|
||||
currentPage = currentPage,
|
||||
minPage = minPage,
|
||||
maxPage = maxPage
|
||||
)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private data class PageData(val page: Int) : ParentDataModifier {
|
||||
override fun Density.modifyParentData(parentData: Any?): Any = this@PageData
|
||||
}
|
||||
|
||||
private val Measurable.page: Int
|
||||
get() = (parentData as? PageData)?.page ?: error("no PageData for measurable $this")
|
||||
|
||||
@Composable
|
||||
fun ViewPager(
|
||||
state: PagerState,
|
||||
modifier: Modifier = Modifier,
|
||||
offscreenLimit: Int = 2, // the amount of non visible screens to be precomputed to either side of the current page
|
||||
pageContent: @Composable PagerScope.() -> Unit
|
||||
) {
|
||||
var pageSize by rememberSaveable() { mutableStateOf(0) }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
Layout(
|
||||
content = {
|
||||
val minPage = (state.currentPage - offscreenLimit).coerceAtLeast(state.minPage)
|
||||
val maxPage = (state.currentPage + offscreenLimit).coerceAtMost(state.maxPage)
|
||||
|
||||
for (page in minPage..maxPage) {
|
||||
val pageData = PageData(page)
|
||||
val scope = PagerScope(page)
|
||||
key(pageData) {
|
||||
Box(contentAlignment = Alignment.Center, modifier = pageData) {
|
||||
scope.pageContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = modifier.draggable(
|
||||
orientation = Orientation.Horizontal,
|
||||
onDragStarted = {
|
||||
state.selectionState = PagerState.SelectionState.Undecided
|
||||
},
|
||||
onDragStopped = { velocity ->
|
||||
coroutineScope.launch {
|
||||
// Velocity is in pixels per second, but we deal in percentage offsets, so we
|
||||
// need to scale the velocity to match
|
||||
state.fling(velocity / pageSize)
|
||||
}
|
||||
},
|
||||
state = rememberDraggableState { dy ->
|
||||
coroutineScope.launch {
|
||||
with(state) {
|
||||
val pos = pageSize * currentPageOffset
|
||||
val max = if (currentPage == minPage) 0 else pageSize * offscreenLimit
|
||||
val min = if (currentPage == maxPage) 0 else -pageSize * offscreenLimit
|
||||
val newPos = (pos + dy).coerceIn(min.toFloat(), max.toFloat())
|
||||
snapToOffset(newPos / pageSize)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
) { measurables, constraints ->
|
||||
layout(constraints.maxWidth, constraints.maxHeight) {
|
||||
val currentPage = state.currentPage
|
||||
val offset = state.currentPageOffset
|
||||
val childConstraints = constraints.copy(minWidth = 0, minHeight = 0)
|
||||
|
||||
measurables
|
||||
.map {
|
||||
it.measure(childConstraints) to it.page
|
||||
}
|
||||
.forEach { (placeable, page) ->
|
||||
// TODO: current this centers each page. We should investigate reading
|
||||
// gravity modifiers on the child, or maybe as a param to Pager.
|
||||
val yCenterOffset = (constraints.maxHeight - placeable.height) / 2
|
||||
|
||||
if (currentPage == page) {
|
||||
pageSize = placeable.width
|
||||
}
|
||||
|
||||
val xItemOffset = ((page + offset - currentPage) * placeable.width).roundToInt()
|
||||
|
||||
placeable.place(
|
||||
x = xItemOffset,
|
||||
y = yCenterOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope for [ViewPager] content.
|
||||
*/
|
||||
class PagerScope(
|
||||
val page: Int
|
||||
)
|
|
@ -147,10 +147,10 @@ class DevModeActivity : AppCompatActivity() {
|
|||
private fun getFinalRadius() =
|
||||
(max(binding.devRootLayout.width, binding.devRootLayout.height) * RADIUS_MULTIPLIER).toFloat()
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
if (layoutInfoViewModel.isDualMode.value == true) {
|
||||
menuInflater.inflate(R.menu.dev_mode_menu, menu)
|
||||
menu?.findItem(R.id.menu_main_user_mode)?.actionView?.setOnClickListener {
|
||||
menu.findItem(R.id.menu_main_user_mode)?.actionView?.setOnClickListener {
|
||||
unRevealActivity(it)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.microsoft.device.samples.dualscreenexperience.presentation.util
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
fun getImageUri(imagePath: String?): Uri? = Uri.parse("file:///android_asset/$imagePath")
|
|
@ -9,16 +9,9 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".presentation.catalog.CatalogListFragment">
|
||||
|
||||
<FrameLayout
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/compose_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/colorBackground">
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</layout>
|
|
@ -1,161 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item1_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:background="?android:attr/colorBackground">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.TableOfContents"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
android:textSize="@dimen/text_size_18"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.TableOfContents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:ellipsize="middle"
|
||||
android:paddingTop="@dimen/normal_padding"
|
||||
android:paddingBottom="@dimen/normal_padding"
|
||||
android:singleLine="true"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
app:clickActionLabel="@{@string/catalog_action_label}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_first"
|
||||
app:pageContentDescription="@{catalogItem.secondaryDescription}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_third"
|
||||
style="@style/Catalog.TableOfContents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:ellipsize="middle"
|
||||
android:paddingTop="@dimen/normal_padding"
|
||||
android:paddingBottom="@dimen/normal_padding"
|
||||
android:singleLine="true"
|
||||
android:text="@{catalogItem.thirdDescription}"
|
||||
app:clickActionLabel="@{@string/catalog_action_label}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_second"
|
||||
app:pageContentDescription="@{catalogItem.thirdDescription}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_fourth"
|
||||
style="@style/Catalog.TableOfContents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:ellipsize="middle"
|
||||
android:paddingTop="@dimen/normal_padding"
|
||||
android:paddingBottom="@dimen/normal_padding"
|
||||
android:singleLine="true"
|
||||
android:text="@{catalogItem.fourthDescription}"
|
||||
app:clickActionLabel="@{@string/catalog_action_label}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_third"
|
||||
app:pageContentDescription="@{catalogItem.fourthDescription}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_fifth"
|
||||
style="@style/Catalog.TableOfContents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:ellipsize="middle"
|
||||
android:paddingTop="@dimen/normal_padding"
|
||||
android:paddingBottom="@dimen/normal_padding"
|
||||
android:singleLine="true"
|
||||
android:text="@{catalogItem.fifthDescription}"
|
||||
app:clickActionLabel="@{@string/catalog_action_label}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_fourth"
|
||||
app:pageContentDescription="@{catalogItem.fifthDescription}" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,183 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item2_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
android:textSize="@dimen/text_size_16"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.helper.widget.Flow
|
||||
android:id="@+id/catalog_flow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/catalog_horizontal_margin"
|
||||
android:paddingEnd="@dimen/catalog_horizontal_margin"
|
||||
app:constraint_referenced_ids="image_first, text_second"
|
||||
app:flow_horizontalGap="@dimen/small_margin"
|
||||
app:flow_horizontalStyle="packed"
|
||||
app:flow_verticalGap="@dimen/small_margin"
|
||||
app:flow_verticalStyle="packed"
|
||||
app:flow_wrapMode="chain"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_third"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_first"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_first"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:contentDescription="@{catalogItem.firstPictureDescription}"
|
||||
app:assetImage="@{catalogItem.firstPicture}"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:minHeight="@dimen/catalog_max_image_height"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/small_margin"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="image_first, text_second" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_third"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_margin_large"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.thirdDescription}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier1" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_second"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_margin_small"
|
||||
android:layout_marginEnd="@dimen/catalog_margin_small"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.secondPictureDescription}"
|
||||
app:assetImage="@{catalogItem.secondPicture}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_third"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_third"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_third"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_margin_small"
|
||||
android:layout_marginTop="@dimen/catalog_margin_small"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.thirdPictureDescription}"
|
||||
app:assetImage="@{catalogItem.thirdPicture}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toEndOf="@+id/image_second"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_third"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,164 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item3_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_first"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.firstPictureDescription}"
|
||||
app:assetImage="@{catalogItem.firstPicture}"
|
||||
app:layout_constraintBottom_toTopOf="@id/barrier1"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline_vertical"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
app:layout_constraintBottom_toTopOf="@id/barrier1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="image_first,text_first" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_margin_small"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
android:textSize="@dimen/text_size_16"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_third"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_third"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_margin_small"
|
||||
android:text="@{catalogItem.thirdDescription}"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_second" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_second"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_margin_small"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:contentDescription="@{catalogItem.secondPictureDescription}"
|
||||
app:assetImage="@{catalogItem.secondPicture}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toTopOf="@id/text_second"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,156 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item4_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_first"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/micro_margin"
|
||||
android:layout_marginBottom="@dimen/small_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.firstPictureDescription}"
|
||||
app:assetImage="@{catalogItem.firstPicture}"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_first"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_second"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_base_min_image_height"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/catalog_tools_image_background" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_second"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/micro_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.secondPictureDescription}"
|
||||
app:assetImage="@{catalogItem.secondPicture}"
|
||||
app:layout_constraintBottom_toBottomOf="@id/image_first"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_base_min_image_height"
|
||||
app:layout_constraintStart_toEndOf="@+id/image_first"
|
||||
app:layout_constraintTop_toTopOf="@id/image_first"
|
||||
tools:background="@color/catalog_tools_image_background" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="image_first,image_second" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_second"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_first" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
android:textSize="@dimen/text_size_16"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_first" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_third"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.thirdDescription}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_second" />
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,143 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item5_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
app:layout_constraintBottom_toTopOf="@id/image_first"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_first"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_margin_large"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.firstPictureDescription}"
|
||||
app:assetImage="@{catalogItem.firstPicture}"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_second"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_second"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_first"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_second"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_margin_large"
|
||||
android:layout_marginTop="@dimen/catalog_margin_large"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:contentDescription="@{catalogItem.secondPictureDescription}"
|
||||
app:assetImage="@{catalogItem.secondPicture}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_double_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toEndOf="@id/image_first"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_first"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_double_max_image_height" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="image_first,image_second" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_margin_large"
|
||||
android:layout_marginEnd="@dimen/catalog_margin_small"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_second"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_first" />
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,121 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item6_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
android:textSize="@dimen/text_size_16"
|
||||
app:layout_constraintBottom_toTopOf="@id/image_first"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_first"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.firstPictureDescription}"
|
||||
app:assetImage="@{catalogItem.firstPicture}"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_second"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_first"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_margin_very_large"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_first" />
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,151 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
~
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pageNumber"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="catalogItem"
|
||||
type="com.microsoft.device.samples.dualscreenexperience.domain.catalog.model.CatalogItem" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/catalog_item_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:fadeScrollbars="true"
|
||||
android:scrollbarThumbVertical="@color/primary_gold"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/pages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/catalog_item7_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_first"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.firstPictureDescription}"
|
||||
app:assetImage="@{catalogItem.firstPicture}"
|
||||
app:layout_constraintBottom_toTopOf="@id/barrier1"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline_vertical"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_first"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_top_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:text="@{catalogItem.primaryDescription}"
|
||||
app:layout_constraintBottom_toTopOf="@id/barrier1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="image_first,text_first" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_second"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_margin_normal"
|
||||
android:text="@{catalogItem.secondaryDescription}"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier1" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_second"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/catalog_margin_small"
|
||||
android:layout_marginTop="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@{catalogItem.secondPictureDescription}"
|
||||
app:assetImage="@{catalogItem.secondPicture}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="@dimen/catalog_max_image_height"
|
||||
app:layout_constraintHeight_min="@dimen/catalog_min_image_height"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier1"
|
||||
tools:background="@color/catalog_tools_image_background"
|
||||
tools:minHeight="@dimen/catalog_max_image_height" />
|
||||
|
||||
<View
|
||||
android:id="@+id/horizontal_fold"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/Catalog.Description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/catalog_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/catalog_margin_small"
|
||||
android:text="@{pageNumber}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -57,6 +57,7 @@
|
|||
<dimen name="text_size_16">16sp</dimen>
|
||||
<dimen name="text_size_14">14sp</dimen>
|
||||
<dimen name="text_size_12">12sp</dimen>
|
||||
<dimen name="text_size_4">4sp</dimen>
|
||||
|
||||
<dimen name="team_link_button_width">84dp</dimen>
|
||||
<dimen name="team_link_button_height">78dp</dimen>
|
||||
|
@ -106,7 +107,15 @@
|
|||
<dimen name="catalog_top_margin">20dp</dimen>
|
||||
<dimen name="catalog_double_max_image_height">500dp</dimen>
|
||||
<dimen name="catalog_max_image_height">250dp</dimen>
|
||||
<dimen name="catalog_max_image_height_dual_landscape">300dp</dimen>
|
||||
<dimen name="catalog_page_padding">26dp</dimen>
|
||||
<dimen name="catalog_min_image_height">150dp</dimen>
|
||||
<dimen name="catalog_min_image_width">200dp</dimen>
|
||||
<dimen name="catalog_medium_image_height">200dp</dimen>
|
||||
<dimen name="catalog_max_image_width">250dp</dimen>
|
||||
<dimen name="catalog_small_screen_min_image_width">150dp</dimen>
|
||||
<dimen name="catalog_image_margin_start">52dp</dimen>
|
||||
<dimen name="catalog_image_margin_end">52dp</dimen>
|
||||
<dimen name="catalog_base_min_image_height">100dp</dimen>
|
||||
|
||||
<dimen name="touch_target_size">48dp</dimen>
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
*/
|
||||
|
||||
ext {
|
||||
gradlePluginVersion = "7.0.3"
|
||||
kotlinVersion = '1.6.0'
|
||||
gradlePluginVersion = '7.2.0'
|
||||
kotlinVersion = '1.6.10'
|
||||
compileSdkVersion = 31
|
||||
buildToolsVersion = '30.0.3'
|
||||
targetSdkVersion = compileSdkVersion
|
||||
|
@ -35,7 +35,7 @@ ext {
|
|||
]
|
||||
|
||||
//AndroidX versions
|
||||
appCompatVersion = '1.3.1'
|
||||
appCompatVersion = '1.4.1'
|
||||
constraintLayoutVersion = '2.1.1'
|
||||
ktxCoreVersion = '1.6.0'
|
||||
ktxFragmentVersion = '1.3.6'
|
||||
|
@ -44,23 +44,45 @@ ext {
|
|||
windowManagerVersion = '1.0.0'
|
||||
lifecycleRuntimeKtxVersion = "2.4.0-rc01"
|
||||
|
||||
|
||||
androidxDependencies = [
|
||||
appCompat : "androidx.appcompat:appcompat:$appCompatVersion",
|
||||
constraintLayout : "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion",
|
||||
ktxCore : "androidx.core:core-ktx:$ktxCoreVersion",
|
||||
ktxFragment : "androidx.fragment:fragment-ktx:$ktxFragmentVersion",
|
||||
room : "androidx.room:room-runtime:$roomVersion",
|
||||
roomCompiler : "androidx.room:room-compiler:$roomVersion",
|
||||
roomKtx : "androidx.room:room-ktx:$roomVersion",
|
||||
webkit : "androidx.webkit:webkit:$webkitVersion",
|
||||
windowManager : "androidx.window:window-java:$windowManagerVersion",
|
||||
lifecycleRuntimeKtx: "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleRuntimeKtxVersion"
|
||||
appCompat : "androidx.appcompat:appcompat:$appCompatVersion",
|
||||
constraintLayout : "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion",
|
||||
ktxCore : "androidx.core:core-ktx:$ktxCoreVersion",
|
||||
ktxFragment : "androidx.fragment:fragment-ktx:$ktxFragmentVersion",
|
||||
room : "androidx.room:room-runtime:$roomVersion",
|
||||
roomCompiler : "androidx.room:room-compiler:$roomVersion",
|
||||
roomKtx : "androidx.room:room-ktx:$roomVersion",
|
||||
webkit : "androidx.webkit:webkit:$webkitVersion",
|
||||
windowManager : "androidx.window:window-java:$windowManagerVersion",
|
||||
lifecycleRuntimeKtx : "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleRuntimeKtxVersion",
|
||||
]
|
||||
|
||||
//Jetpack compose dependencies versions
|
||||
composeUiVersion = "1.1.1"
|
||||
composeViewModelVersion = '2.4.1'
|
||||
activityComposeVersion = "1.4.0"
|
||||
constraintLayoutComposeVersion = "1.0.0"
|
||||
coilVersion = "2.1.0"
|
||||
|
||||
composeDependencies = [
|
||||
composeUi : "androidx.compose.ui:ui:$composeUiVersion",
|
||||
composeTooling : "androidx.compose.ui:ui-tooling:$composeUiVersion",
|
||||
composeFoundation : "androidx.compose.foundation:foundation:$composeUiVersion",
|
||||
composeMaterial : "androidx.compose.material:material:$composeUiVersion",
|
||||
composeMaterialIcons : "androidx.compose.material:material-icons-core:$composeUiVersion",
|
||||
composeMaterialIconsExtended : "androidx.compose.material:material-icons-extended:$composeUiVersion",
|
||||
composeViewModel : "androidx.lifecycle:lifecycle-viewmodel-compose:$composeViewModelVersion",
|
||||
composeLiveData : "androidx.compose.runtime:runtime-livedata:$composeUiVersion",
|
||||
activityCompose : "androidx.activity:activity-compose:$activityComposeVersion",
|
||||
constraintlayoutCompose : "androidx.constraintlayout:constraintlayout-compose:$constraintLayoutComposeVersion",
|
||||
coil : "io.coil-kt:coil-compose:$coilVersion"
|
||||
]
|
||||
|
||||
//Google dependencies
|
||||
materialVersion = '1.4.0'
|
||||
gsonVersion = '2.9.0'
|
||||
hiltVersion = '2.39.1'
|
||||
hiltVersion = '2.42'
|
||||
mapsVersion = '17.0.1'
|
||||
mapsKtxVersion = '3.2.0'
|
||||
ossLicensesVersion = '17.0.0'
|
||||
|
@ -85,6 +107,7 @@ ext {
|
|||
snackbarVersion = "1.0.0-alpha1"
|
||||
|
||||
bingMapsVersion = "1.2.0"
|
||||
windowStateVersion = "1.0.0-alpha04"
|
||||
|
||||
microsoftDependencies = [
|
||||
bingMaps : "com.microsoft.maps:maps-sdk:$bingMapsVersion",
|
||||
|
@ -94,6 +117,7 @@ ext {
|
|||
layouts : "com.microsoft.device.dualscreen:layouts:$layoutsVersion",
|
||||
wmUtils : "com.microsoft.device.dualscreen:wm-utils:$wmUtilsVersion",
|
||||
snackbar : "com.microsoft.device.dualscreen:snackbar:$snackbarVersion",
|
||||
windowState : "com.microsoft.device.dualscreen:windowstate:$windowStateVersion",
|
||||
]
|
||||
|
||||
//UI dependencies
|
||||
|
@ -103,7 +127,7 @@ ext {
|
|||
uiDependencies = [
|
||||
lottie : "com.airbnb.android:lottie:$lottieVersion",
|
||||
glide : "com.github.bumptech.glide:glide:$glideVersion",
|
||||
glideAnnotationProcesor: "com.github.bumptech.glide:compiler:$glideVersion"
|
||||
glideAnnotationProcesor: "com.github.bumptech.glide:compiler:$glideVersion",
|
||||
]
|
||||
|
||||
//Test dependencies version
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Thu Jan 28 15:34:03 EET 2021
|
||||
#Thu May 12 21:29:55 EEST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
Загрузка…
Ссылка в новой задаче