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