• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ButtonBarLayout(Context context)38     public ButtonBarLayout(Context context) {
39         super(context);
40     }
41 
ButtonBarLayout(Context context, AttributeSet attrs)42     public ButtonBarLayout(Context context, AttributeSet attrs) {
43         super(context, attrs);
44     }
45 
46     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)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 
setStacked(boolean stacked)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