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 * <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"> 81199e575893be653ba3088c19e95adda62b8344fbAga Madurska * 82199e575893be653ba3088c19e95adda62b8344fbAga Madurska * <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"/> 88199e575893be653ba3088c19e95adda62b8344fbAga Madurska * 89199e575893be653ba3088c19e95adda62b8344fbAga Madurska * <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"/> 95199e575893be653ba3088c19e95adda62b8344fbAga Madurska * 96199e575893be653ba3088c19e95adda62b8344fbAga Madurska * <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"/> 102199e575893be653ba3088c19e95adda62b8344fbAga Madurska * 103199e575893be653ba3088c19e95adda62b8344fbAga Madurska * <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"/> 109199e575893be653ba3088c19e95adda62b8344fbAga Madurska * 110199e575893be653ba3088c19e95adda62b8344fbAga Madurska * <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" /> 119199e575893be653ba3088c19e95adda62b8344fbAga Madurska * 120199e575893be653ba3088c19e95adda62b8344fbAga Madurska * </android.support.constraint.ConstraintLayout> 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