Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2017 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 package com.android.setupwizardlib.view;
     18 
     19 import android.content.Context;
     20 import android.util.AttributeSet;
     21 import android.view.View;
     22 import android.widget.LinearLayout;
     23 
     24 import com.android.setupwizardlib.R;
     25 
     26 /**
     27  * An extension of LinearLayout that automatically switches to vertical orientation when it can't
     28  * fit its child views horizontally.
     29  *
     30  * Modified from {@code com.android.internal.widget.ButtonBarLayout}
     31  */
     32 public class ButtonBarLayout extends LinearLayout {
     33 
     34     private boolean mStacked = false;
     35     private int mOriginalPaddingLeft;
     36     private int mOriginalPaddingRight;
     37 
     38     public ButtonBarLayout(Context context) {
     39         super(context);
     40     }
     41 
     42     public ButtonBarLayout(Context context, AttributeSet attrs) {
     43         super(context, attrs);
     44     }
     45 
     46     @Override
     47     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     48         final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
     49 
     50         setStacked(false);
     51 
     52         boolean needsRemeasure = false;
     53 
     54         int initialWidthMeasureSpec = widthMeasureSpec;
     55         if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
     56             // Measure with WRAP_CONTENT, so that we can compare the measured size with the
     57             // available size to see if we need to stack.
     58             initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
     59 
     60             // We'll need to remeasure again to fill excess space.
     61             needsRemeasure = true;
     62         }
     63 
     64         super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
     65 
     66         if (getMeasuredWidth() > widthSize) {
     67             setStacked(true);
     68 
     69             // Measure again in the new orientation.
     70             needsRemeasure = true;
     71         }
     72 
     73         if (needsRemeasure) {
     74             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     75         }
     76     }
     77 
     78     private void setStacked(boolean stacked) {
     79         if (mStacked == stacked) {
     80             return;
     81         }
     82         mStacked = stacked;
     83         int childCount = getChildCount();
     84         for (int i = 0; i < childCount; i++) {
     85             View child = getChildAt(i);
     86             LayoutParams childParams = (LayoutParams) child.getLayoutParams();
     87             if (stacked) {
     88                 child.setTag(R.id.suw_original_weight, childParams.weight);
     89                 childParams.weight = 0;
     90             } else {
     91                 Float weight = (Float) child.getTag(R.id.suw_original_weight);
     92                 if (weight != null) {
     93                     childParams.weight = weight;
     94                 }
     95             }
     96             child.setLayoutParams(childParams);
     97         }
     98 
     99         setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
    100 
    101         // Reverse the child order, so that the primary button is towards the top when vertical
    102         for (int i = childCount - 1; i >= 0; i--) {
    103             bringChildToFront(getChildAt(i));
    104         }
    105 
    106         if (stacked) {
    107             // HACK: In the default button bar style, the left and right paddings are not
    108             // balanced to compensate for different alignment for borderless (left) button and
    109             // the raised (right) button. When it's stacked, we want the buttons to be centered,
    110             // so we balance out the paddings here.
    111             mOriginalPaddingLeft = getPaddingLeft();
    112             mOriginalPaddingRight = getPaddingRight();
    113             int paddingHorizontal = Math.max(mOriginalPaddingLeft, mOriginalPaddingRight);
    114             setPadding(
    115                     paddingHorizontal, getPaddingTop(), paddingHorizontal, getPaddingBottom());
    116         } else {
    117             setPadding(
    118                     mOriginalPaddingLeft,
    119                     getPaddingTop(),
    120                     mOriginalPaddingRight,
    121                     getPaddingBottom());
    122         }
    123     }
    124 }
    125