15e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam/*
25e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * Copyright (C) 2017 The Android Open Source Project
35e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam *
45e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * Licensed under the Apache License, Version 2.0 (the "License");
55e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * you may not use this file except in compliance with the License.
65e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * You may obtain a copy of the License at
75e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam *
85e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam *      http://www.apache.org/licenses/LICENSE-2.0
95e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam *
105e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * Unless required by applicable law or agreed to in writing, software
115e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * distributed under the License is distributed on an "AS IS" BASIS,
125e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * See the License for the specific language governing permissions and
145e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * limitations under the License.
155e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam */
165e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
175e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lampackage com.android.setupwizardlib.view;
185e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
195e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lamimport android.content.Context;
205e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lamimport android.util.AttributeSet;
215e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lamimport android.view.View;
225e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lamimport android.widget.LinearLayout;
235e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
245e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lamimport com.android.setupwizardlib.R;
255e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
265e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam/**
275e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * An extension of LinearLayout that automatically switches to vertical orientation when it can't
285e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * fit its child views horizontally.
295e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam *
305e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam * Modified from {@code com.android.internal.widget.ButtonBarLayout}
315e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam */
325e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lampublic class ButtonBarLayout extends LinearLayout {
335e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
345e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    private boolean mStacked = false;
355e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    private int mOriginalPaddingLeft;
365e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    private int mOriginalPaddingRight;
375e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
385e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    public ButtonBarLayout(Context context) {
395e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        super(context);
405e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    }
415e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
425e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    public ButtonBarLayout(Context context, AttributeSet attrs) {
435e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        super(context, attrs);
445e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    }
455e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
465e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    @Override
475e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
485e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
495e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
505e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        setStacked(false);
515e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
525e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        boolean needsRemeasure = false;
535e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
545e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        int initialWidthMeasureSpec = widthMeasureSpec;
555e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
565e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // Measure with WRAP_CONTENT, so that we can compare the measured size with the
575e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // available size to see if we need to stack.
585e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
595e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
605e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // We'll need to remeasure again to fill excess space.
615e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            needsRemeasure = true;
625e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
635e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
645e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
655e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
665e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        if (getMeasuredWidth() > widthSize) {
675e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            setStacked(true);
685e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
695e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // Measure again in the new orientation.
705e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            needsRemeasure = true;
715e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
725e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
735e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        if (needsRemeasure) {
745e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
755e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
765e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    }
775e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
785e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    private void setStacked(boolean stacked) {
795e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        if (mStacked == stacked) {
805e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            return;
815e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
825e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        mStacked = stacked;
835e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        int childCount = getChildCount();
845e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        for (int i = 0; i < childCount; i++) {
855e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            View child = getChildAt(i);
865e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            LayoutParams childParams = (LayoutParams) child.getLayoutParams();
875e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            if (stacked) {
885e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                child.setTag(R.id.suw_original_weight, childParams.weight);
895e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                childParams.weight = 0;
905e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            } else {
915e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                Float weight = (Float) child.getTag(R.id.suw_original_weight);
925e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                if (weight != null) {
935e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                    childParams.weight = weight;
945e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                }
955e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            }
965e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            child.setLayoutParams(childParams);
975e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
985e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
995e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
1005e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
1015e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        // Reverse the child order, so that the primary button is towards the top when vertical
1025e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        for (int i = childCount - 1; i >= 0; i--) {
1035e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            bringChildToFront(getChildAt(i));
1045e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
1055e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam
1065e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        if (stacked) {
1075e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // HACK: In the default button bar style, the left and right paddings are not
1085e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // balanced to compensate for different alignment for borderless (left) button and
1095e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // the raised (right) button. When it's stacked, we want the buttons to be centered,
1105e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            // so we balance out the paddings here.
1115e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            mOriginalPaddingLeft = getPaddingLeft();
1125e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            mOriginalPaddingRight = getPaddingRight();
1135e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            int paddingHorizontal = Math.max(mOriginalPaddingLeft, mOriginalPaddingRight);
1145e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            setPadding(
1155e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                    paddingHorizontal, getPaddingTop(), paddingHorizontal, getPaddingBottom());
1165e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        } else {
1175e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam            setPadding(
1185e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                    mOriginalPaddingLeft,
1195e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                    getPaddingTop(),
1205e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                    mOriginalPaddingRight,
1215e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam                    getPaddingBottom());
1225e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam        }
1235e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam    }
1245e98278ebfad7aa858fbfcc4dd53db7442f9bc15Maurice Lam}
125