Home | History | Annotate | Download | only in graph
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *      http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  *
     15  *
     16  */
     17 
     18 package com.android.settings.graph;
     19 
     20 import android.annotation.Nullable;
     21 import android.content.Context;
     22 import android.support.annotation.VisibleForTesting;
     23 import android.util.AttributeSet;
     24 import android.view.Gravity;
     25 import android.view.View;
     26 import android.widget.LinearLayout;
     27 
     28 import com.android.settingslib.R;
     29 
     30 /**
     31  * An extension of LinearLayout that automatically switches to vertical
     32  * orientation when it can't fit its child views horizontally.
     33  *
     34  * Main logic in this class comes from {@link android.support.v7.widget.ButtonBarLayout}.
     35  * Compared with {@link android.support.v7.widget.ButtonBarLayout}, this layout won't reverse
     36  * children's order and won't update the minimum height
     37  */
     38 public class BottomLabelLayout extends LinearLayout {
     39     private static final String TAG = "BottomLabelLayout";
     40 
     41     public BottomLabelLayout(Context context,
     42             @Nullable 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         final boolean isStacked = isStacked();
     50         boolean needsRemeasure = false;
     51 
     52         // If we're not stacked, make sure the measure spec is AT_MOST rather
     53         // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we
     54         // know to stack the buttons.
     55         final int initialWidthMeasureSpec;
     56         if (!isStacked && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
     57             initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
     58 
     59             // We'll need to remeasure again to fill excess space.
     60             needsRemeasure = true;
     61         } else {
     62             initialWidthMeasureSpec = widthMeasureSpec;
     63         }
     64 
     65         super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
     66         if (!isStacked) {
     67             final int measuredWidth = getMeasuredWidthAndState();
     68             final int measuredWidthState = measuredWidth & View.MEASURED_STATE_MASK;
     69 
     70             if (measuredWidthState == View.MEASURED_STATE_TOO_SMALL) {
     71                 setStacked(true);
     72                 // Measure again in the new orientation.
     73                 needsRemeasure = true;
     74             }
     75         }
     76 
     77         if (needsRemeasure) {
     78             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     79         }
     80 
     81     }
     82 
     83     @VisibleForTesting
     84     void setStacked(boolean stacked) {
     85         setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
     86         setGravity(stacked ? Gravity.START : Gravity.BOTTOM);
     87 
     88         final View spacer = findViewById(R.id.spacer);
     89         if (spacer != null) {
     90             spacer.setVisibility(stacked ? View.GONE : View.VISIBLE);
     91         }
     92     }
     93 
     94     private boolean isStacked() {
     95         return getOrientation() == LinearLayout.VERTICAL;
     96     }
     97 }
     98