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 package com.android.car.view;
     17 
     18 import android.content.Context;
     19 import android.content.res.TypedArray;
     20 import android.util.AttributeSet;
     21 import android.view.View;
     22 import android.widget.FrameLayout;
     23 
     24 import com.android.car.stream.ui.R;
     25 
     26 import java.util.ArrayList;
     27 import java.util.List;
     28 
     29 /**
     30  * Acts as a container to make the width of all its children not larger than the setup max width.
     31  *
     32  * To use MaxWidthLayout, put it as the outermost layout of all children you want to limit its max
     33  * width and set the maxWidth appropriately.
     34  */
     35 public class MaxWidthLayout extends FrameLayout {
     36 
     37     // If mMaxChildrenWidth == 0, it means that it doesn't set the max width, just use the current
     38     // width directly.
     39     private int mMaxChildrenWidth;
     40 
     41     public MaxWidthLayout(Context context) {
     42         super(context);
     43         initialize(context.obtainStyledAttributes(R.styleable.MaxWidthLayout));
     44     }
     45 
     46     public MaxWidthLayout(Context context, AttributeSet attrs) {
     47         super(context, attrs);
     48         initialize(context.obtainStyledAttributes(attrs, R.styleable.MaxWidthLayout));
     49     }
     50 
     51     public MaxWidthLayout(Context context, AttributeSet attrs, int defStyleAttr) {
     52         super(context, attrs, defStyleAttr);
     53         initialize(context
     54                 .obtainStyledAttributes(attrs, R.styleable.MaxWidthLayout, defStyleAttr, 0));
     55     }
     56 
     57     /**
     58      * Initialize MaxWidthLayout specific attributes and recycle the TypeArray.
     59      */
     60     private void initialize(TypedArray ta) {
     61         mMaxChildrenWidth = (int) (ta.getDimension(R.styleable.MaxWidthLayout_carMaxWidth, 0));
     62         ta.recycle();
     63     }
     64 
     65     /**
     66      * Re-measure the child width if it is greater than max width.
     67      */
     68     @Override
     69     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     70         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     71         if (mMaxChildrenWidth == 0) {
     72             return;
     73         }
     74 
     75         final List<View> matchParentChildren = new ArrayList<View>();
     76         for (int i = getChildCount() - 1; i >= 0; --i) {
     77             final View child = getChildAt(i);
     78             if (child.getVisibility() != GONE) {
     79                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
     80                 if (lp.width == LayoutParams.MATCH_PARENT) {
     81                     matchParentChildren.add(child);
     82                 }
     83             }
     84         }
     85         for (int i = matchParentChildren.size() - 1; i >= 0; --i) {
     86             final View child = matchParentChildren.get(i);
     87             final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
     88             if (child.getMeasuredWidth() > mMaxChildrenWidth) {
     89                 int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
     90                         mMaxChildrenWidth - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
     91                 int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
     92                         child.getMeasuredHeight(), MeasureSpec.EXACTLY);
     93                 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     94             }
     95         }
     96     }
     97 }
     98