1f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski/*
2f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Copyright (C) 2015 The Android Open Source Project
3f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
4f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Licensed under the Apache License, Version 2.0 (the "License");
5f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * you may not use this file except in compliance with the License.
6f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * You may obtain a copy of the License at
7f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
8f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *      http://www.apache.org/licenses/LICENSE-2.0
9f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
10f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Unless required by applicable law or agreed to in writing, software
11f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * distributed under the License is distributed on an "AS IS" BASIS,
12f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * See the License for the specific language governing permissions and
14f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * limitations under the License.
15f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski */
16f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
17f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskipackage android.support.percent;
18f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
19f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.content.Context;
20f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.content.res.TypedArray;
2172de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikovimport android.support.annotation.NonNull;
22f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.support.v4.view.MarginLayoutParamsCompat;
23f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.support.v4.view.ViewCompat;
24f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.util.AttributeSet;
25f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.util.Log;
26f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.view.View;
27f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.view.ViewGroup;
28f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
29f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski/**
30f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Helper for layouts that want to support percentage based dimensions.
31f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
32f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <p>This class collects utility methods that are involved in extracting percentage based dimension
33f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * attributes and applying them to ViewGroup's children. If you would like to implement a layout
34f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * that supports percentage based dimensions, you need to take several steps:
35f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
36f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <ol>
37f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <li> You need a {@link ViewGroup.LayoutParams} subclass in your ViewGroup that implements
38f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * {@link android.support.percent.PercentLayoutHelper.PercentLayoutParams}.
39f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <li> In your {@code LayoutParams(Context c, AttributeSet attrs)} constructor create an instance
40f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * of {@link PercentLayoutHelper.PercentLayoutInfo} by calling
41f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * {@link PercentLayoutHelper#getPercentLayoutInfo(Context, AttributeSet)}. Return this
42f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * object from {@code public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo()}
43f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * method that you implemented for {@link android.support.percent.PercentLayoutHelper.PercentLayoutParams} interface.
44f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <li> Override
45f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * {@link ViewGroup.LayoutParams#setBaseAttributes(TypedArray, int, int)}
46f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * with a single line implementation {@code PercentLayoutHelper.fetchWidthAndHeight(this, a,
47f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * widthAttr, heightAttr);}
48f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <li> In your ViewGroup override {@link ViewGroup#generateLayoutParams(AttributeSet)} to return
49f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * your LayoutParams.
50f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <li> In your {@link ViewGroup#onMeasure(int, int)} override, you need to implement following
51f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * pattern:
52f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <pre class="prettyprint">
53f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
54f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec);
55f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
56f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     if (mHelper.handleMeasuredStateTooSmall()) {
57f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
58f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     }
59f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * }
60f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * </pre>
61f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <li>In your {@link ViewGroup#onLayout(boolean, int, int, int, int)} override, you need to
62f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * implement following pattern:
63f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <pre class="prettyprint">
64f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
65f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     super.onLayout(changed, left, top, right, bottom);
66f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     mHelper.restoreOriginalParams();
67f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * }
68f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * </pre>
69f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * </ol>
70199e575893be653ba3088c19e95adda62b8344fbAga Madurska * @deprecated consider using ConstraintLayout and associated layouts instead. The following shows
71199e575893be653ba3088c19e95adda62b8344fbAga Madurska * how to replicate the functionality of percentage layouts with a ConstraintLayout. The Guidelines
72199e575893be653ba3088c19e95adda62b8344fbAga Madurska * are used to define each percentage break point, and then a Button view is stretched to fill
73199e575893be653ba3088c19e95adda62b8344fbAga Madurska * the gap:
74199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
75199e575893be653ba3088c19e95adda62b8344fbAga Madurska * <pre class="prettyprint">
76199e575893be653ba3088c19e95adda62b8344fbAga Madurska * &lt;android.support.constraint.ConstraintLayout
77199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         xmlns:android="http://schemas.android.com/apk/res/android"
78199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         xmlns:app="http://schemas.android.com/apk/res-auto"
79199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_width="match_parent"
80199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_height="match_parent"&gt
81199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
82199e575893be653ba3088c19e95adda62b8344fbAga Madurska *     &lt;android.support.constraint.Guideline
83199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_width="wrap_content"
84199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_height="wrap_content"
85199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:id="@+id/left_guideline"
86199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintGuide_percent=".15"
87199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:orientation="vertical"/&gt
88199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
89199e575893be653ba3088c19e95adda62b8344fbAga Madurska *     &lt;android.support.constraint.Guideline
90199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_width="wrap_content"
91199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_height="wrap_content"
92199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:id="@+id/right_guideline"
93199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintGuide_percent=".85"
94199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:orientation="vertical"/&gt
95199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
96199e575893be653ba3088c19e95adda62b8344fbAga Madurska *     &lt;android.support.constraint.Guideline
97199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_width="wrap_content"
98199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_height="wrap_content"
99199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:id="@+id/top_guideline"
100199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintGuide_percent=".15"
101199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:orientation="horizontal"/&gt
102199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
103199e575893be653ba3088c19e95adda62b8344fbAga Madurska *     &lt;android.support.constraint.Guideline
104199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_width="wrap_content"
105199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_height="wrap_content"
106199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:id="@+id/bottom_guideline"
107199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintGuide_percent=".85"
108199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:orientation="horizontal"/&gt
109199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
110199e575893be653ba3088c19e95adda62b8344fbAga Madurska *     &lt;Button
111199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:text="Button"
112199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_width="0dp"
113199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:layout_height="0dp"
114199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         android:id="@+id/button"
115199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintLeft_toLeftOf="@+id/left_guideline"
116199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintRight_toRightOf="@+id/right_guideline"
117199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintTop_toTopOf="@+id/top_guideline"
118199e575893be653ba3088c19e95adda62b8344fbAga Madurska *         app:layout_constraintBottom_toBottomOf="@+id/bottom_guideline" /&gt
119199e575893be653ba3088c19e95adda62b8344fbAga Madurska *
120199e575893be653ba3088c19e95adda62b8344fbAga Madurska * &lt;/android.support.constraint.ConstraintLayout&gt
121f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski */
122199e575893be653ba3088c19e95adda62b8344fbAga Madurska@Deprecated
123f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskipublic class PercentLayoutHelper {
124f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    private static final String TAG = "PercentLayout";
125f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
126aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski    private static final boolean DEBUG = false;
127aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski    private static final boolean VERBOSE = false;
128aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski
129f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    private final ViewGroup mHost;
130f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
13172de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov    public PercentLayoutHelper(@NonNull ViewGroup host) {
13272de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov        if (host == null) {
13372de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov            throw new IllegalArgumentException("host must be non-null");
13472de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov        }
135f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        mHost = host;
136f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
137f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
138f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
139f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Helper method to be called from {@link ViewGroup.LayoutParams#setBaseAttributes} override
140f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * that reads layout_width and layout_height attribute values without throwing an exception if
141f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * they aren't present.
142f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
143f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public static void fetchWidthAndHeight(ViewGroup.LayoutParams params, TypedArray array,
144f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            int widthAttr, int heightAttr) {
145f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        params.width = array.getLayoutDimension(widthAttr, 0);
146f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        params.height = array.getLayoutDimension(heightAttr, 0);
147f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
148f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
149f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
150f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Iterates over children and changes their width and height to one calculated from percentage
151f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * values.
152f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * @param widthMeasureSpec Width MeasureSpec of the parent ViewGroup.
153f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * @param heightMeasureSpec Height MeasureSpec of the parent ViewGroup.
154f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
155f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public void adjustChildren(int widthMeasureSpec, int heightMeasureSpec) {
156aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski        if (DEBUG) {
157f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            Log.d(TAG, "adjustChildren: " + mHost + " widthMeasureSpec: "
158f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    + View.MeasureSpec.toString(widthMeasureSpec) + " heightMeasureSpec: "
159f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    + View.MeasureSpec.toString(heightMeasureSpec));
160f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
161b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
16272de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov        // Calculate available space, accounting for host's paddings
16372de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov        int widthHint = View.MeasureSpec.getSize(widthMeasureSpec) - mHost.getPaddingLeft()
16472de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov                - mHost.getPaddingRight();
16572de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov        int heightHint = View.MeasureSpec.getSize(heightMeasureSpec) - mHost.getPaddingTop()
16672de056d527299b1c8db8825e9ca435f13f585d9Kirill Grouchnikov                - mHost.getPaddingBottom();
167f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        for (int i = 0, N = mHost.getChildCount(); i < N; i++) {
168f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            View view = mHost.getChildAt(i);
169f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            ViewGroup.LayoutParams params = view.getLayoutParams();
170aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (DEBUG) {
171f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.d(TAG, "should adjust " + view + " " + params);
172f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
173f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (params instanceof PercentLayoutParams) {
174f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                PercentLayoutInfo info =
175f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        ((PercentLayoutParams) params).getPercentLayoutInfo();
176aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski                if (DEBUG) {
177f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    Log.d(TAG, "using " + info);
178f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                }
179f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                if (info != null) {
180f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    if (params instanceof ViewGroup.MarginLayoutParams) {
181f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                        info.fillMarginLayoutParams(view, (ViewGroup.MarginLayoutParams) params,
182300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                                widthHint, heightHint);
183f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    } else {
184300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                        info.fillLayoutParams(params, widthHint, heightHint);
185f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    }
186f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                }
187f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
188f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
189f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
190f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
191f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
192f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Constructs a PercentLayoutInfo from attributes associated with a View. Call this method from
193f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * {@code LayoutParams(Context c, AttributeSet attrs)} constructor.
194f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
195f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public static PercentLayoutInfo getPercentLayoutInfo(Context context,
196f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            AttributeSet attrs) {
197f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        PercentLayoutInfo info = null;
198f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PercentLayout_Layout);
199f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        float value = array.getFraction(R.styleable.PercentLayout_Layout_layout_widthPercent, 1, 1,
200f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
201f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
202aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
203f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent width: " + value);
204f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
205f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
206f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.widthPercent = value;
207f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
208f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_heightPercent, 1, 1, -1f);
209f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
210aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
211f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent height: " + value);
212f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
213f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
214f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.heightPercent = value;
215f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
216f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginPercent, 1, 1, -1f);
217f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
218aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
219f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent margin: " + value);
220f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
221f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
222f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.leftMarginPercent = value;
223f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.topMarginPercent = value;
224f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.rightMarginPercent = value;
225f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.bottomMarginPercent = value;
226f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
227f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginLeftPercent, 1, 1,
228f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
229f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
230aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
231f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent left margin: " + value);
232f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
233f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
234f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.leftMarginPercent = value;
235f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
236f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginTopPercent, 1, 1,
237f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
238f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
239aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
240f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent top margin: " + value);
241f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
242f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
243f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.topMarginPercent = value;
244f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
245f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginRightPercent, 1, 1,
246f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
247f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
248aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
249f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent right margin: " + value);
250f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
251f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
252f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.rightMarginPercent = value;
253f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
254f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginBottomPercent, 1, 1,
255f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
256f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
257aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
258f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent bottom margin: " + value);
259f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
260f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
261f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.bottomMarginPercent = value;
262f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
263f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginStartPercent, 1, 1,
264f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
265f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
266aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
267f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent start margin: " + value);
268f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
269f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
270f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.startMarginPercent = value;
271f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
272f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginEndPercent, 1, 1,
273f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                -1f);
274f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (value != -1f) {
275aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
276f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.v(TAG, "percent end margin: " + value);
277f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
278f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info = info != null ? info : new PercentLayoutInfo();
279f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            info.endMarginPercent = value;
280f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
281b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
282300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski        value = array.getFraction(R.styleable.PercentLayout_Layout_layout_aspectRatio, 1, 1, -1f);
283300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski        if (value != -1f) {
284aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (VERBOSE) {
285300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                Log.v(TAG, "aspect ratio: " + value);
286300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            }
287b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee            info = info != null ? info : new PercentLayoutInfo();
288300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            info.aspectRatio = value;
289b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee        }
290b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
291f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        array.recycle();
292aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski        if (DEBUG) {
293f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            Log.d(TAG, "constructed: " + info);
294f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
295f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        return info;
296f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
297f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
298f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
299f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Iterates over children and restores their original dimensions that were changed for
300f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * percentage values. Calling this method only makes sense if you previously called
301f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * {@link PercentLayoutHelper#adjustChildren(int, int)}.
302f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
303f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public void restoreOriginalParams() {
304f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        for (int i = 0, N = mHost.getChildCount(); i < N; i++) {
305f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            View view = mHost.getChildAt(i);
306f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            ViewGroup.LayoutParams params = view.getLayoutParams();
307aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (DEBUG) {
308f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.d(TAG, "should restore " + view + " " + params);
309f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
310f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (params instanceof PercentLayoutParams) {
311f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                PercentLayoutInfo info =
312f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        ((PercentLayoutParams) params).getPercentLayoutInfo();
313aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski                if (DEBUG) {
314f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    Log.d(TAG, "using " + info);
315f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                }
316f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                if (info != null) {
317f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    if (params instanceof ViewGroup.MarginLayoutParams) {
318f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        info.restoreMarginLayoutParams((ViewGroup.MarginLayoutParams) params);
319f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    } else {
320f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        info.restoreLayoutParams(params);
321f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    }
322f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                }
323f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
324f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
325f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
326f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
327f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
328f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Iterates over children and checks if any of them would like to get more space than it
329f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * received through the percentage dimension.
330f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     *
331f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * If you are building a layout that supports percentage dimensions you are encouraged to take
332f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * advantage of this method. The developer should be able to specify that a child should be
333f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * remeasured by adding normal dimension attribute with {@code wrap_content} value. For example
334f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * he might specify child's attributes as {@code app:layout_widthPercent="60%p"} and
335f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * {@code android:layout_width="wrap_content"}. In this case if the child receives too little
336f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * space, it will be remeasured with width set to {@code WRAP_CONTENT}.
337f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     *
338f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * @return True if the measure phase needs to be rerun because one of the children would like
339f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * to receive more space.
340f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
341f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public boolean handleMeasuredStateTooSmall() {
342f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        boolean needsSecondMeasure = false;
343f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        for (int i = 0, N = mHost.getChildCount(); i < N; i++) {
344f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            View view = mHost.getChildAt(i);
345f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            ViewGroup.LayoutParams params = view.getLayoutParams();
346aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (DEBUG) {
347f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.d(TAG, "should handle measured state too small " + view + " " + params);
348f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
349f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (params instanceof PercentLayoutParams) {
350f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                PercentLayoutInfo info =
351f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        ((PercentLayoutParams) params).getPercentLayoutInfo();
352f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                if (info != null) {
353f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    if (shouldHandleMeasuredWidthTooSmall(view, info)) {
354f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        needsSecondMeasure = true;
355f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
356f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    }
357f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    if (shouldHandleMeasuredHeightTooSmall(view, info)) {
358f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        needsSecondMeasure = true;
359f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
360f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    }
361f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                }
362f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
363f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
364aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski        if (DEBUG) {
365f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            Log.d(TAG, "should trigger second measure pass: " + needsSecondMeasure);
366f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
367f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        return needsSecondMeasure;
368f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
369f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
370f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    private static boolean shouldHandleMeasuredWidthTooSmall(View view, PercentLayoutInfo info) {
371fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas        int state = view.getMeasuredWidthAndState() & View.MEASURED_STATE_MASK;
372fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas        return state == View.MEASURED_STATE_TOO_SMALL && info.widthPercent >= 0
373fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas                && info.mPreservedParams.width == ViewGroup.LayoutParams.WRAP_CONTENT;
374f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
375f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
376f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    private static boolean shouldHandleMeasuredHeightTooSmall(View view, PercentLayoutInfo info) {
377fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas        int state = view.getMeasuredHeightAndState() & View.MEASURED_STATE_MASK;
378fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas        return state == View.MEASURED_STATE_TOO_SMALL && info.heightPercent >= 0
379fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas                && info.mPreservedParams.height == ViewGroup.LayoutParams.WRAP_CONTENT;
380f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
381f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
382ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov    /* package */ static class PercentMarginLayoutParams extends ViewGroup.MarginLayoutParams {
383ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        // These two flags keep track of whether we're computing the LayoutParams width and height
384ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        // in the fill pass based on the aspect ratio. This allows the fill pass to be re-entrant
385ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        // as the framework code can call onMeasure() multiple times before the onLayout() is
386ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        // called. Those multiple invocations of onMeasure() are not guaranteed to be called with
387ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        // the same set of width / height.
388ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        private boolean mIsHeightComputedFromAspectRatio;
389ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        private boolean mIsWidthComputedFromAspectRatio;
390ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov
391ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        public PercentMarginLayoutParams(int width, int height) {
392ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            super(width, height);
393ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        }
394ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov    }
395ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov
396f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
397f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Container for information about percentage dimensions and margins. It acts as an extension
398f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * for {@code LayoutParams}.
399199e575893be653ba3088c19e95adda62b8344fbAga Madurska     *
400199e575893be653ba3088c19e95adda62b8344fbAga Madurska     * @deprecated use ConstraintLayout and Guidelines for layout support.
401f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
402199e575893be653ba3088c19e95adda62b8344fbAga Madurska    @Deprecated
403f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public static class PercentLayoutInfo {
4041b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based width. */
405f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float widthPercent;
406f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4071b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based height. */
408f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float heightPercent;
409f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4101b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based left margin. */
411f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float leftMarginPercent;
412f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4131b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based top margin. */
414f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float topMarginPercent;
415f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4161b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based right margin. */
417f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float rightMarginPercent;
418f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4191b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based bottom margin. */
420f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float bottomMarginPercent;
421f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4221b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based start margin. */
423f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float startMarginPercent;
424f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4251b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based end margin. */
426f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public float endMarginPercent;
427f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
4281b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov        /** The decimal value of the percentage-based aspect ratio. */
429300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski        public float aspectRatio;
430b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
431ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov        /* package */ final PercentMarginLayoutParams mPreservedParams;
432f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
433f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public PercentLayoutInfo() {
434f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            widthPercent = -1f;
435f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            heightPercent = -1f;
436f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            leftMarginPercent = -1f;
437f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            topMarginPercent = -1f;
438f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            rightMarginPercent = -1f;
439f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            bottomMarginPercent = -1f;
440f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            startMarginPercent = -1f;
441f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            endMarginPercent = -1f;
442ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            mPreservedParams = new PercentMarginLayoutParams(0, 0);
443f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
444f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
445f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        /**
4461b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * Fills the {@link ViewGroup.LayoutParams#width} and {@link ViewGroup.LayoutParams#height}
4471b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * fields of the passed {@link ViewGroup.LayoutParams} object based on currently set
4481b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * percentage values.
449f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski         */
450f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public void fillLayoutParams(ViewGroup.LayoutParams params, int widthHint,
451300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                int heightHint) {
452f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            // Preserve the original layout params, so we can restore them after the measure step.
453f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPreservedParams.width = params.width;
454f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPreservedParams.height = params.height;
455f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
456300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            // We assume that width/height set to 0 means that value was unset. This might not
457300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            // necessarily be true, as the user might explicitly set it to 0. However, we use this
458300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            // information only for the aspect ratio. If the user set the aspect ratio attribute,
459300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            // it means they accept or soon discover that it will be disregarded.
460ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            final boolean widthNotSet =
461ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                    (mPreservedParams.mIsWidthComputedFromAspectRatio
462ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                            || mPreservedParams.width == 0) && (widthPercent < 0);
463ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            final boolean heightNotSet =
464ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                    (mPreservedParams.mIsHeightComputedFromAspectRatio
465ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                            || mPreservedParams.height == 0) && (heightPercent < 0);
466300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski
467f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (widthPercent >= 0) {
46800665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                params.width = Math.round(widthHint * widthPercent);
469f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
470b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
471f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (heightPercent >= 0) {
47200665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                params.height = Math.round(heightHint * heightPercent);
473f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
474b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
475300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            if (aspectRatio >= 0) {
476300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                if (widthNotSet) {
47700665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                    params.width = Math.round(params.height * aspectRatio);
478ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                    // Keep track that we've filled the width based on the height and aspect ratio.
479ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                    mPreservedParams.mIsWidthComputedFromAspectRatio = true;
480300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                }
481300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                if (heightNotSet) {
48200665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                    params.height = Math.round(params.width / aspectRatio);
483ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                    // Keep track that we've filled the height based on the width and aspect ratio.
484ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                    mPreservedParams.mIsHeightComputedFromAspectRatio = true;
485300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski                }
486b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee            }
487b1aad00281aaeb43988dc76141a18ff528d88d49Bryce Lee
488aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (DEBUG) {
489f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.d(TAG, "after fillLayoutParams: (" + params.width + ", " + params.height + ")");
490f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
491f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
492f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
493f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        /**
494d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette         * @deprecated Use
495f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov         * {@link #fillMarginLayoutParams(View, ViewGroup.MarginLayoutParams, int, int)}
496f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov         * for proper RTL support.
497f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov         */
498f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov        @Deprecated
499f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov        public void fillMarginLayoutParams(ViewGroup.MarginLayoutParams params,
500f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                int widthHint, int heightHint) {
501f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov            fillMarginLayoutParams(null, params, widthHint, heightHint);
502f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov        }
503f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov
504f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov        /**
5051b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * Fills the margin fields of the passed {@link ViewGroup.MarginLayoutParams} object based
5061b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * on currently set percentage values and the current layout direction of the passed
5071b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * {@link View}.
508f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski         */
509f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov        public void fillMarginLayoutParams(View view, ViewGroup.MarginLayoutParams params,
510f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                int widthHint, int heightHint) {
511300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski            fillLayoutParams(params, widthHint, heightHint);
512f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
513f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov            // Preserve the original margins, so we can restore them after the measure step.
514f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPreservedParams.leftMargin = params.leftMargin;
515f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPreservedParams.topMargin = params.topMargin;
516f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPreservedParams.rightMargin = params.rightMargin;
517f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPreservedParams.bottomMargin = params.bottomMargin;
518f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            MarginLayoutParamsCompat.setMarginStart(mPreservedParams,
519f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    MarginLayoutParamsCompat.getMarginStart(params));
520f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            MarginLayoutParamsCompat.setMarginEnd(mPreservedParams,
521f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    MarginLayoutParamsCompat.getMarginEnd(params));
522f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
523f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (leftMarginPercent >= 0) {
52400665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                params.leftMargin = Math.round(widthHint * leftMarginPercent);
525f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
526f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (topMarginPercent >= 0) {
52700665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                params.topMargin = Math.round(heightHint * topMarginPercent);
528f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
529f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (rightMarginPercent >= 0) {
53000665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                params.rightMargin = Math.round(widthHint * rightMarginPercent);
531f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
532f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (bottomMarginPercent >= 0) {
53300665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                params.bottomMargin = Math.round(heightHint * bottomMarginPercent);
534f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
535f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov            boolean shouldResolveLayoutDirection = false;
536f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (startMarginPercent >= 0) {
537f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                MarginLayoutParamsCompat.setMarginStart(params,
53800665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                        Math.round(widthHint * startMarginPercent));
539f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                shouldResolveLayoutDirection = true;
540f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
541f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            if (endMarginPercent >= 0) {
542f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                MarginLayoutParamsCompat.setMarginEnd(params,
54300665762f050ac347c8ce226268b90e99225a415Filip Gruszczynski                        Math.round(widthHint * endMarginPercent));
544f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                shouldResolveLayoutDirection = true;
545f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov            }
546f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov            if (shouldResolveLayoutDirection && (view != null)) {
547f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                // Force the resolve pass so that start / end margins are propagated to the
548f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                // matching left / right fields
549f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                MarginLayoutParamsCompat.resolveLayoutDirection(params,
550f7ad43b79cc11e66f519ef11a108f31e3fe95e10Kirill Grouchnikov                        ViewCompat.getLayoutDirection(view));
551f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
552aaef140ef2ddf27acae1a5dac5b96f877991d798Filip Gruszczynski            if (DEBUG) {
553f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                Log.d(TAG, "after fillMarginLayoutParams: (" + params.width + ", " + params.height
554f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                        + ")");
555f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            }
556f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
557f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
558f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        @Override
559f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public String toString() {
560f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            return String.format("PercentLayoutInformation width: %f height %f, margins (%f, %f, "
561f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                            + " %f, %f, %f, %f)", widthPercent, heightPercent, leftMarginPercent,
562f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    topMarginPercent, rightMarginPercent, bottomMarginPercent, startMarginPercent,
563f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    endMarginPercent);
564f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
565f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
566f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
567f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        /**
5681b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * Restores the original dimensions and margins after they were changed for percentage based
5691b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * values. You should call this method only if you previously called
5701b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * {@link PercentLayoutHelper.PercentLayoutInfo#fillMarginLayoutParams(View, ViewGroup.MarginLayoutParams, int, int)}.
571f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski         */
572f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public void restoreMarginLayoutParams(ViewGroup.MarginLayoutParams params) {
573f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            restoreLayoutParams(params);
574f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            params.leftMargin = mPreservedParams.leftMargin;
575f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            params.topMargin = mPreservedParams.topMargin;
576f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            params.rightMargin = mPreservedParams.rightMargin;
577f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            params.bottomMargin = mPreservedParams.bottomMargin;
578f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            MarginLayoutParamsCompat.setMarginStart(params,
579f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    MarginLayoutParamsCompat.getMarginStart(mPreservedParams));
580f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            MarginLayoutParamsCompat.setMarginEnd(params,
581f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski                    MarginLayoutParamsCompat.getMarginEnd(mPreservedParams));
582f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
583f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
584f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        /**
5851b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * Restores original dimensions after they were changed for percentage based values.
5861b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * You should call this method only if you previously called
5871b963b22f1201289a7ed31ee07aabdfe316c442cKirill Grouchnikov         * {@link PercentLayoutHelper.PercentLayoutInfo#fillLayoutParams(ViewGroup.LayoutParams, int, int)}.
588f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski         */
589f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public void restoreLayoutParams(ViewGroup.LayoutParams params) {
590ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            if (!mPreservedParams.mIsWidthComputedFromAspectRatio) {
591ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                // Only restore the width if we didn't compute it based on the height and
592ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                // aspect ratio in the fill pass.
593ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                params.width = mPreservedParams.width;
594ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            }
595ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            if (!mPreservedParams.mIsHeightComputedFromAspectRatio) {
596ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                // Only restore the height if we didn't compute it based on the width and
597ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                // aspect ratio in the fill pass.
598ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov                params.height = mPreservedParams.height;
599ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            }
600ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov
601ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            // Reset the tracking flags.
602ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            mPreservedParams.mIsWidthComputedFromAspectRatio = false;
603ff6cfa41a3c76a979795b32985f8e1f7157cb33cKirill Grouchnikov            mPreservedParams.mIsHeightComputedFromAspectRatio = false;
604f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
605f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
606f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
607f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    /**
608f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * If a layout wants to support percentage based dimensions and use this helper class, its
609f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * {@code LayoutParams} subclass must implement this interface.
610f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     *
611f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * Your {@code LayoutParams} subclass should contain an instance of {@code PercentLayoutInfo}
612f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     * and the implementation of this interface should be a simple accessor.
613199e575893be653ba3088c19e95adda62b8344fbAga Madurska     *
614199e575893be653ba3088c19e95adda62b8344fbAga Madurska     * @deprecated this class is deprecated along with its parent class.
615f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski     */
616199e575893be653ba3088c19e95adda62b8344fbAga Madurska    @Deprecated
617f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public interface PercentLayoutParams {
618f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        PercentLayoutInfo getPercentLayoutInfo();
619f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
620f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski}
621