1/*
2 * Copyright (C) 2011 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
17package com.example.android.hcgallery;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.view.View;
22import android.view.ViewGroup;
23
24/**
25 * A simple layout that fits and centers each child view, maintaining aspect ratio.
26 */
27public class FitCenterFrameLayout extends ViewGroup {
28    public FitCenterFrameLayout(Context context) {
29        super(context);
30    }
31
32    public FitCenterFrameLayout(Context context, AttributeSet attrs) {
33        super(context, attrs);
34    }
35
36    @Override
37    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
38        // We purposely disregard child measurements.
39        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
40        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
41        setMeasuredDimension(width, height);
42
43        int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
44        int childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED);
45
46        int childCount = getChildCount();
47        for (int i = 0; i < childCount; i++) {
48            getChildAt(i).measure(childWidthSpec, childHeightSpec);
49        }
50    }
51
52    @Override
53    protected void onLayout(boolean changed, int l, int t, int r, int b) {
54        final int childCount = getChildCount();
55
56        final int parentLeft = getPaddingLeft();
57        final int parentTop = getPaddingTop();
58        final int parentRight = r - l - getPaddingRight();
59        final int parentBottom = b - t - getPaddingBottom();
60
61        final int parentWidth = parentRight - parentLeft;
62        final int parentHeight = parentBottom - parentTop;
63
64        int unpaddedWidth, unpaddedHeight, parentUnpaddedWidth, parentUnpaddedHeight;
65        int childPaddingLeft, childPaddingTop, childPaddingRight, childPaddingBottom;
66
67        for (int i = 0; i < childCount; i++) {
68            final View child = getChildAt(i);
69            if (child.getVisibility() == GONE) {
70                continue;
71            }
72
73            // Fit and center the child within the parent. Make sure not to consider padding
74            // as part of the child's aspect ratio.
75
76            childPaddingLeft = child.getPaddingLeft();
77            childPaddingTop = child.getPaddingTop();
78            childPaddingRight = child.getPaddingRight();
79            childPaddingBottom = child.getPaddingBottom();
80
81            unpaddedWidth = child.getMeasuredWidth() - childPaddingLeft - childPaddingRight;
82            unpaddedHeight = child.getMeasuredHeight() - childPaddingTop - childPaddingBottom;
83
84            parentUnpaddedWidth = parentWidth - childPaddingLeft - childPaddingRight;
85            parentUnpaddedHeight = parentHeight - childPaddingTop - childPaddingBottom;
86
87            if (parentUnpaddedWidth * unpaddedHeight > parentUnpaddedHeight * unpaddedWidth) {
88                // The child view should be left/right letterboxed.
89                final int scaledChildWidth = unpaddedWidth * parentUnpaddedHeight
90                        / unpaddedHeight + childPaddingLeft + childPaddingRight;
91                child.layout(
92                        parentLeft + (parentWidth - scaledChildWidth) / 2,
93                        parentTop,
94                        parentRight - (parentWidth - scaledChildWidth) / 2,
95                        parentBottom);
96            } else {
97                // The child view should be top/bottom letterboxed.
98                final int scaledChildHeight = unpaddedHeight * parentUnpaddedWidth
99                        / unpaddedWidth + childPaddingTop + childPaddingBottom;
100                child.layout(
101                        parentLeft,
102                        parentTop + (parentHeight - scaledChildHeight) / 2,
103                        parentRight,
104                        parentTop + (parentHeight + scaledChildHeight) / 2);
105            }
106        }
107    }
108}
109