[go: nahoru, domu]

11f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu/*
21f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * Copyright (C) 2014 The Android Open Source Project
31f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu *
41f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
51f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * in compliance with the License. You may obtain a copy of the License at
61f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu *
71f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * http://www.apache.org/licenses/LICENSE-2.0
81f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu *
91f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
101f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
111f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * or implied. See the License for the specific language governing permissions and limitations under
121f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * the License.
131f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu */
141f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gupackage android.support.v17.leanback.widget;
151f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
161f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.content.Context;
171f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.graphics.drawable.Drawable;
181f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.util.AttributeSet;
191f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.view.Gravity;
201f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.view.View;
21a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnataimport android.view.ViewGroup;
221f000f84b9f8db8778b941a6a1bf60f3d349545dDake Guimport android.widget.FrameLayout;
231f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
241f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu/**
251f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * Subclass of FrameLayout that support scale layout area size for children.
261f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu * @hide
271f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu */
281f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gupublic class ScaleFrameLayout extends FrameLayout {
291f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
301f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
311f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
321f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private float mLayoutScaleX = 1f;
331f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private float mLayoutScaleY = 1f;
341f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
35a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    private float mChildScale = 1f;
36a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
371f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public ScaleFrameLayout(Context context) {
381f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        this(context ,null);
391f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
401f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
411f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public ScaleFrameLayout(Context context, AttributeSet attrs) {
421f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        this(context, attrs, 0);
431f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
441f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
451f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public ScaleFrameLayout(Context context, AttributeSet attrs,
461f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            int defStyle) {
471f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        super(context, attrs, defStyle);
481f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
491f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
501f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public void setLayoutScaleX(float scaleX) {
511f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (scaleX != mLayoutScaleX) {
521f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            mLayoutScaleX = scaleX;
531f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            requestLayout();
541f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
551f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
561f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
571f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public void setLayoutScaleY(float scaleY) {
581f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (scaleY != mLayoutScaleY) {
591f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            mLayoutScaleY = scaleY;
601f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            requestLayout();
611f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
621f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
631f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
64a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    public void setChildScale(float scale) {
65a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        if (mChildScale != scale) {
66a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mChildScale = scale;
67a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            for (int i = 0; i < getChildCount(); i++) {
68a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                getChildAt(i).setScaleX(scale);
69a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                getChildAt(i).setScaleY(scale);
70a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            }
71a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        }
72a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    }
73a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
74a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    @Override
75a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    public void addView(View child, int index, ViewGroup.LayoutParams params) {
76a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        super.addView(child, index, params);
77a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        child.setScaleX(mChildScale);
78a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        child.setScaleY(mChildScale);
79a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    }
80a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
811f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    @Override
82be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu    protected boolean addViewInLayout (View child, int index, ViewGroup.LayoutParams params,
83be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu            boolean preventRequestLayout) {
84be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu        boolean ret = super.addViewInLayout(child, index, params, preventRequestLayout);
85be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu        if (ret) {
86be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu            child.setScaleX(mChildScale);
87be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu            child.setScaleY(mChildScale);
88be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu        }
89be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu        return ret;
90be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu    }
91be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu
92be5bcc2e3b3bbe468c1425b2919e1fa072af1854Dake Gu    @Override
931f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
941f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        final int count = getChildCount();
951f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
961f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        final int parentLeft, parentRight;
978e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        final int layoutDirection = getLayoutDirection();
988e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        final float pivotX = (layoutDirection == View.LAYOUT_DIRECTION_RTL) ?
998e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                getWidth() - getPivotX() :
1008e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing                getPivotX();
1011f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (mLayoutScaleX != 1f) {
1021f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentLeft = getPaddingLeft() + (int)(pivotX - pivotX / mLayoutScaleX + 0.5f);
1031f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentRight = (int)(pivotX + (right - left - pivotX) / mLayoutScaleX + 0.5f)
1041f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    - getPaddingRight();
1051f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        } else {
1061f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentLeft = getPaddingLeft();
1071f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentRight = right - left - getPaddingRight();
1081f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
1091f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1101f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        final int parentTop, parentBottom;
1113595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        final float pivotY = getPivotY();
1121f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (mLayoutScaleY != 1f) {
1131f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentTop = getPaddingTop() + (int)(pivotY - pivotY / mLayoutScaleY + 0.5f);
1141f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentBottom = (int)(pivotY + (bottom - top - pivotY) / mLayoutScaleY + 0.5f)
1151f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    - getPaddingBottom();
1161f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        } else {
1171f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentTop = getPaddingTop();
1181f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            parentBottom = bottom - top - getPaddingBottom();
1191f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
1201f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1211f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        for (int i = 0; i < count; i++) {
1221f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            final View child = getChildAt(i);
1231f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            if (child.getVisibility() != GONE) {
1241f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1251f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1261f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                final int width = child.getMeasuredWidth();
1271f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                final int height = child.getMeasuredHeight();
1281f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1291f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                int childLeft;
1301f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                int childTop;
1311f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1321f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                int gravity = lp.gravity;
1331f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                if (gravity == -1) {
1341f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    gravity = DEFAULT_CHILD_GRAVITY;
1351f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                }
1361f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1371f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
1381f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
1391f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1401f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
1411f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    case Gravity.CENTER_HORIZONTAL:
1421f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
1431f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                                lp.leftMargin - lp.rightMargin;
1441f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        break;
1451f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    case Gravity.RIGHT:
1461f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childLeft = parentRight - width - lp.rightMargin;
1471f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        break;
1481f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    case Gravity.LEFT:
1491f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    default:
1501f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childLeft = parentLeft + lp.leftMargin;
1511f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                }
1521f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1531f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                switch (verticalGravity) {
1541f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    case Gravity.TOP:
1551f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childTop = parentTop + lp.topMargin;
1561f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        break;
1571f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    case Gravity.CENTER_VERTICAL:
1581f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childTop = parentTop + (parentBottom - parentTop - height) / 2 +
1591f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                                lp.topMargin - lp.bottomMargin;
1601f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        break;
1611f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    case Gravity.BOTTOM:
1621f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childTop = parentBottom - height - lp.bottomMargin;
1631f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        break;
1641f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    default:
1651f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                        childTop = parentTop + lp.topMargin;
1661f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                }
1671f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1681f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                child.layout(childLeft, childTop, childLeft + width, childTop + height);
1693595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu                // synchronize child pivot to be same as ScaleFrameLayout's pivot
1703595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu                child.setPivotX(pivotX - childLeft);
1713595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu                child.setPivotY(pivotY - childTop);
1721f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            }
1731f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
1741f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
1751f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1761f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    private static int getScaledMeasureSpec(int measureSpec, float scale) {
1771f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        return scale == 1f ? measureSpec : MeasureSpec.makeMeasureSpec(
1781f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                (int) (MeasureSpec.getSize(measureSpec) / scale + 0.5f),
1791f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                MeasureSpec.getMode(measureSpec));
1801f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
1811f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1821f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    @Override
1831f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1841f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        if (mLayoutScaleX != 1f || mLayoutScaleY != 1f) {
1851f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            final int scaledWidthMeasureSpec =
1861f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    getScaledMeasureSpec(widthMeasureSpec, mLayoutScaleX);
1871f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            final int scaledHeightMeasureSpec =
1881f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    getScaledMeasureSpec(heightMeasureSpec, mLayoutScaleY);
1891f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            super.onMeasure(scaledWidthMeasureSpec, scaledHeightMeasureSpec);
1901f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            setMeasuredDimension((int)(getMeasuredWidth() * mLayoutScaleX + 0.5f),
1911f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu                    (int)(getMeasuredHeight() * mLayoutScaleY + 0.5f));
1921f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        } else {
1931f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
1941f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        }
1951f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
1961f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu
1971f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    /**
1981f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu     * setForeground() is not supported,  throws UnsupportedOperationException() when called.
1991f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu     */
2001f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    @Override
2011f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    public void setForeground(Drawable d) {
2021f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu        throw new UnsupportedOperationException();
2031f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu    }
204a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
2051f000f84b9f8db8778b941a6a1bf60f3d349545dDake Gu}
206