1 /* 2 * 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 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 android.widget.FrameLayout 22 import com.android.wallpaper.picker.preview.ui.util.CropSizeUtil.findMaxRectWithRatioIn 23 24 /** 25 * A [FrameLayout] that scales to largest possible on current display with the size preserving 26 * target display aspect ratio. 27 * 28 * Acts as [FrameLayout] if the current and target display size were not set by the time of 29 * [onMeasure]. 30 */ 31 class FullPreviewFrameLayout(context: Context, attrs: AttributeSet? = null) : 32 FrameLayout(context, attrs) { 33 34 // Current display size represents the size of the currently used display. There is only one 35 // size for handheld and tablet devices, but there are 2 sizes for foldable devices. 36 private var currentDisplaySize: Point? = null 37 38 // Target display size represents the size of the display that a wallpaper aims to be set to. 39 private var targetDisplaySize: Point? = null 40 onMeasurenull41 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 42 super.onMeasure(widthMeasureSpec, heightMeasureSpec) 43 44 val currentSize = currentDisplaySize 45 val targetSize = targetDisplaySize 46 47 if (currentSize == null || targetSize == null) { 48 setMeasuredDimension(widthMeasureSpec, heightMeasureSpec) 49 return 50 } 51 52 val maxRect = targetSize.findMaxRectWithRatioIn(currentSize) 53 val width = maxRect.x.toInt() 54 val height = maxRect.y.toInt() 55 measureChildren( 56 MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 57 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) 58 ) 59 } 60 61 /** 62 * Sets the target display size and the current display size. 63 * 64 * The view size is maxed out within current display size while preserving the aspect ratio of 65 * the target display size. On a single display device the current display size is always the 66 * target display size. 67 * 68 * @param currentSize current display size used as the max bound of this view. 69 * @param targetSize target display size to get and preserve it's aspect ratio. 70 */ setCurrentAndTargetDisplaySizenull71 fun setCurrentAndTargetDisplaySize(currentSize: Point, targetSize: Point) { 72 currentDisplaySize = currentSize 73 targetDisplaySize = targetSize 74 } 75 } 76