12c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam/*
22c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * Copyright (C) 2016 The Android Open Source Project
32c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam *
42c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * Licensed under the Apache License, Version 2.0 (the "License");
52c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * you may not use this file except in compliance with the License.
62c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * You may obtain a copy of the License at
72c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam *
82c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam *      http://www.apache.org/licenses/LICENSE-2.0
92c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam *
102c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * Unless required by applicable law or agreed to in writing, software
112c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * distributed under the License is distributed on an "AS IS" BASIS,
122c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * See the License for the specific language governing permissions and
142c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * limitations under the License.
152c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam */
162c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
172c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lampackage com.android.setupwizardlib.view;
182c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
192c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport android.annotation.TargetApi;
202c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport android.content.Context;
212c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport android.content.res.TypedArray;
222c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport android.os.Build.VERSION_CODES;
232c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport android.util.AttributeSet;
242c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport android.widget.FrameLayout;
252c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
262c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lamimport com.android.setupwizardlib.R;
272c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
282c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam/**
292c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * A FrameLayout subclass that has an "intrinsic size", which is the size it wants to be if that is
302c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * within the constraints given by the parent. The intrinsic size can be set with the
312c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * {@code android:width} and {@code android:height} attributes in XML.
322c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam *
332c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * Note that for the intrinsic size to be meaningful, {@code android:layout_width} and/or
342c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam * {@code android:layout_height} will need to be {@code wrap_content}.
352c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam */
362c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lampublic class IntrinsicSizeFrameLayout extends FrameLayout {
372c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
382c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    private int mIntrinsicHeight = 0;
392c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    private int mIntrinsicWidth = 0;
402c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
412c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    public IntrinsicSizeFrameLayout(Context context) {
422c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        super(context);
432c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        init(context, null, 0);
442c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    }
452c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
462c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    public IntrinsicSizeFrameLayout(Context context, AttributeSet attrs) {
472c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        super(context, attrs);
482c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        init(context, attrs, 0);
492c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    }
502c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
512c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    @TargetApi(VERSION_CODES.HONEYCOMB)
522c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    public IntrinsicSizeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
532c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        super(context, attrs, defStyleAttr);
542c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        init(context, attrs, defStyleAttr);
552c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    }
562c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
572c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
582c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        final TypedArray a = context.obtainStyledAttributes(attrs,
592da78450d5e9723ca93fa39bfdc3f8dd27b41e89Maurice Lam                R.styleable.SuwIntrinsicSizeFrameLayout, defStyleAttr, 0);
602c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        mIntrinsicHeight =
612da78450d5e9723ca93fa39bfdc3f8dd27b41e89Maurice Lam                a.getDimensionPixelSize(R.styleable.SuwIntrinsicSizeFrameLayout_android_height, 0);
622c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        mIntrinsicWidth =
632da78450d5e9723ca93fa39bfdc3f8dd27b41e89Maurice Lam                a.getDimensionPixelSize(R.styleable.SuwIntrinsicSizeFrameLayout_android_width, 0);
642c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        a.recycle();
652c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    }
662c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
672c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    @Override
682c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
692c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        super.onMeasure(getIntrinsicMeasureSpec(widthMeasureSpec, mIntrinsicWidth),
702c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam                getIntrinsicMeasureSpec(heightMeasureSpec, mIntrinsicHeight));
712c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    }
722c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam
732c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    private int getIntrinsicMeasureSpec(int measureSpec, int intrinsicSize) {
742c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        if (intrinsicSize <= 0) {
752c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            // Intrinsic size is not set, just return the original spec
762c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            return measureSpec;
772c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        }
782c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        final int mode = MeasureSpec.getMode(measureSpec);
792c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        final int size = MeasureSpec.getSize(measureSpec);
802c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        if (mode == MeasureSpec.UNSPECIFIED) {
812c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            // Parent did not give any constraint, so we'll be the intrinsic size
822c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            return MeasureSpec.makeMeasureSpec(mIntrinsicHeight, MeasureSpec.EXACTLY);
832c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        } else if (mode == MeasureSpec.AT_MOST) {
842c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            // If intrinsic size is within parents constraint, take the intrinsic size.
852c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            // Otherwise take the parents size because that's closest to the intrinsic size.
862c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam            return MeasureSpec.makeMeasureSpec(Math.min(size, mIntrinsicHeight),
872c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam                    MeasureSpec.EXACTLY);
882c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        }
892c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        // Parent specified EXACTLY, or in all other cases, just return the original spec
902c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam        return measureSpec;
912c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam    }
922c42b3f95a9319fc36f1dea5e775e2fab13a0a25Maurice Lam}
93