15e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy/* 25e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * Copyright (C) 2010 The Android Open Source Project 35e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * 45e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 55e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * you may not use this file except in compliance with the License. 65e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * You may obtain a copy of the License at 75e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * 85e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 95e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * 105e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * Unless required by applicable law or agreed to in writing, software 115e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 125e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * See the License for the specific language governing permissions and 145e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * limitations under the License. 155e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy */ 165e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 175e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guypackage com.android.internal.widget; 185e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 195e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport android.content.Context; 205e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport android.content.res.TypedArray; 215e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport android.util.AttributeSet; 225e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport android.util.DisplayMetrics; 235e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport android.widget.LinearLayout; 245e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 255e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport static android.view.View.MeasureSpec.*; 265e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guyimport static com.android.internal.R.*; 275e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 285e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy/** 295e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * A special layout when measured in AT_MOST will take up a given percentage of 305e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy * the available space. 315e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy */ 325e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guypublic class WeightedLinearLayout extends LinearLayout { 334fb17b0490915d1c26663140c377037ea6af132eAdam Powell private float mMajorWeightMin; 344fb17b0490915d1c26663140c377037ea6af132eAdam Powell private float mMinorWeightMin; 354fb17b0490915d1c26663140c377037ea6af132eAdam Powell private float mMajorWeightMax; 364fb17b0490915d1c26663140c377037ea6af132eAdam Powell private float mMinorWeightMax; 375e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 385e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy public WeightedLinearLayout(Context context) { 395e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy super(context); 405e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy } 415e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 425e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy public WeightedLinearLayout(Context context, AttributeSet attrs) { 435e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy super(context, attrs); 445e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 455e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy TypedArray a = 465e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy context.obtainStyledAttributes(attrs, styleable.WeightedLinearLayout); 475e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 484fb17b0490915d1c26663140c377037ea6af132eAdam Powell mMajorWeightMin = a.getFloat(styleable.WeightedLinearLayout_majorWeightMin, 0.0f); 494fb17b0490915d1c26663140c377037ea6af132eAdam Powell mMinorWeightMin = a.getFloat(styleable.WeightedLinearLayout_minorWeightMin, 0.0f); 504fb17b0490915d1c26663140c377037ea6af132eAdam Powell mMajorWeightMax = a.getFloat(styleable.WeightedLinearLayout_majorWeightMax, 0.0f); 514fb17b0490915d1c26663140c377037ea6af132eAdam Powell mMinorWeightMax = a.getFloat(styleable.WeightedLinearLayout_minorWeightMax, 0.0f); 525e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 535e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy a.recycle(); 545e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy } 555e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 565e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy @Override 575e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 585e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); 59d60d3742abe4e6c51681276713bbd68a3e21f04eRomain Guy final int screenWidth = metrics.widthPixels; 60d60d3742abe4e6c51681276713bbd68a3e21f04eRomain Guy final boolean isPortrait = screenWidth < metrics.heightPixels; 615e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 625e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy final int widthMode = getMode(widthMeasureSpec); 635e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 645e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy super.onMeasure(widthMeasureSpec, heightMeasureSpec); 655e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 665e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy int width = getMeasuredWidth(); 675e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy boolean measure = false; 685e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 695e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY); 705e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 714fb17b0490915d1c26663140c377037ea6af132eAdam Powell final float widthWeightMin = isPortrait ? mMinorWeightMin : mMajorWeightMin; 724fb17b0490915d1c26663140c377037ea6af132eAdam Powell final float widthWeightMax = isPortrait ? mMinorWeightMax : mMajorWeightMax; 734fb17b0490915d1c26663140c377037ea6af132eAdam Powell if (widthMode == AT_MOST) { 744fb17b0490915d1c26663140c377037ea6af132eAdam Powell final int weightedMin = (int) (screenWidth * widthWeightMin); 754fb17b0490915d1c26663140c377037ea6af132eAdam Powell final int weightedMax = (int) (screenWidth * widthWeightMin); 764fb17b0490915d1c26663140c377037ea6af132eAdam Powell if (widthWeightMin > 0.0f && width < weightedMin) { 774fb17b0490915d1c26663140c377037ea6af132eAdam Powell widthMeasureSpec = MeasureSpec.makeMeasureSpec(weightedMin, EXACTLY); 784fb17b0490915d1c26663140c377037ea6af132eAdam Powell measure = true; 794fb17b0490915d1c26663140c377037ea6af132eAdam Powell } else if (widthWeightMax > 0.0f && width > weightedMax) { 804fb17b0490915d1c26663140c377037ea6af132eAdam Powell widthMeasureSpec = MeasureSpec.makeMeasureSpec(weightedMax, EXACTLY); 815e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy measure = true; 825e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy } 835e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy } 845e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 855e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy // TODO: Support height? 865e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy 875e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy if (measure) { 884fb17b0490915d1c26663140c377037ea6af132eAdam Powell super.onMeasure(widthMeasureSpec, heightMeasureSpec); 895e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy } 905e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy } 915e5e6ccc37151c3e5d5272e8c1997955b6bed069Romain Guy} 92