1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.wallpaper.picker.preview.ui.view
17 
18 import android.content.Context
19 import android.graphics.Point
20 import android.util.AttributeSet
21 import androidx.viewpager.widget.ViewPager
22 import com.android.wallpaper.R
23 import com.android.wallpaper.model.wallpaper.DeviceDisplayType
24 
25 /**
26  * This view pager sizes itself to be the exact height required by its content views:
27  * [DualDisplayAspectRatioLayout]. This is required because the actual heights of
28  * [DualDisplayAspectRatioLayout] are determined after the their parent ViewPager is rendered. This
29  * prevents the ViewPager from sizing itself to wrap its contents.
30  */
31 class DualPreviewViewPager
32 @JvmOverloads
33 constructor(context: Context, attrs: AttributeSet? = null /* attrs */) : ViewPager(context, attrs) {
34     private var previewDisplaySizes: Map<DeviceDisplayType, Point>? = null
35 
onMeasurenull36     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
37         if (previewDisplaySizes == null) {
38             super.onMeasure(widthMeasureSpec, heightMeasureSpec)
39             return
40         }
41 
42         val parentWidth =
43             this.measuredWidth -
44                 context.resources.let {
45                     it.getDimension(R.dimen.small_dual_preview_edge_space) * 2 -
46                         it.getDimension(R.dimen.small_preview_inter_preview_margin) * 3
47                 }
48 
49         val smallDisplayAspectRatio =
50             getPreviewDisplaySize(DeviceDisplayType.FOLDED).let { it.x.toFloat() / it.y }
51 
52         val largeDisplayAspectRatio =
53             getPreviewDisplaySize(DeviceDisplayType.UNFOLDED).let { it.x.toFloat() / it.y }
54 
55         val viewPagerHeight = parentWidth / (largeDisplayAspectRatio + smallDisplayAspectRatio)
56 
57         super.onMeasure(
58             widthMeasureSpec,
59             MeasureSpec.makeMeasureSpec(
60                 viewPagerHeight.toInt(),
61                 MeasureSpec.EXACTLY,
62             )
63         )
64     }
65 
setDisplaySizesnull66     fun setDisplaySizes(displaySizes: Map<DeviceDisplayType, Point>) {
67         previewDisplaySizes = displaySizes
68     }
69 
70     /**
71      * Gets the display size for a [DualDisplayAspectRatioLayout.Companion.PreviewView].
72      *
73      * Outside this class we should get display size via
74      * [DualDisplayAspectRatioLayout.getPreviewDisplaySize].
75      */
getPreviewDisplaySizenull76     private fun getPreviewDisplaySize(display: DeviceDisplayType): Point {
77         return checkNotNull(previewDisplaySizes?.get(display))
78     }
79 }
80