1 /*
<lambda>null2  * Copyright (C) 2023 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  */
17 
18 package com.android.wallpaper.picker
19 
20 import android.content.Context
21 import android.util.AttributeSet
22 import android.widget.LinearLayout
23 import androidx.core.view.children
24 import androidx.core.view.marginBottom
25 import androidx.core.view.marginEnd
26 import androidx.core.view.marginStart
27 import androidx.core.view.marginTop
28 import com.android.wallpaper.util.ScreenSizeCalculator
29 
30 /**
31  * [LinearLayout] that sizes its children using a fixed aspect ratio that is the same as that of the
32  * display, and can lay out multiple children horizontally with margin
33  */
34 class DisplayAspectRatioLinearLayout(
35     context: Context,
36     attrs: AttributeSet?,
37 ) : LinearLayout(context, attrs) {
38 
39     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
40         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
41 
42         val screenAspectRatio = ScreenSizeCalculator.getInstance().getScreenAspectRatio(context)
43         val parentWidth = this.measuredWidth
44         val parentHeight = this.measuredHeight
45         val (childWidth, childHeight) =
46             if (orientation == HORIZONTAL) {
47                 var childMargins = 0
48                 children.forEach { childMargins += it.marginStart + it.marginEnd }
49                 val availableWidth = parentWidth - paddingStart - paddingEnd - childMargins
50                 val availableHeight = parentHeight - paddingTop - paddingBottom
51                 var width = availableWidth / childCount
52                 var height = (width * screenAspectRatio).toInt()
53                 if (height > availableHeight) {
54                     height = availableHeight
55                     width = (height / screenAspectRatio).toInt()
56                 }
57                 width to height
58             } else {
59                 var childMargins = 0
60                 children.forEach { childMargins += it.marginTop + it.marginBottom }
61                 val availableWidth = parentWidth - paddingStart - paddingEnd
62                 val availableHeight = parentHeight - paddingTop - paddingBottom - childMargins
63                 var height = availableHeight / childCount
64                 var width = (height / screenAspectRatio).toInt()
65                 if (width > availableWidth) {
66                     width = availableWidth
67                     height = (width * screenAspectRatio).toInt()
68                 }
69                 width to height
70             }
71 
72         children.forEachIndexed { index, child ->
73             child.measure(
74                 MeasureSpec.makeMeasureSpec(
75                     childWidth,
76                     MeasureSpec.EXACTLY,
77                 ),
78                 MeasureSpec.makeMeasureSpec(
79                     childHeight,
80                     MeasureSpec.EXACTLY,
81                 ),
82             )
83         }
84     }
85 }
86