diff options
| author | 2018-05-24 05:03:14 +0000 | |
|---|---|---|
| committer | 2018-05-24 05:03:14 +0000 | |
| commit | 5d8559fea3f3e2fb14496b72f3dbaadf7a53a15f (patch) | |
| tree | 4173715fbee5fed31c82af1d92ab79d4aa735a86 | |
| parent | 6450335b56b5fa6728a26cb0f6bda3ecb38720ef (diff) | |
| parent | f77fb9176e59419519ed09e6cbd9d053d5506f30 (diff) | |
Merge "Fork navbar layout for quickstep" into pi-dev
12 files changed, 210 insertions, 57 deletions
diff --git a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml index 6a7f18b80b9f..d5f8a2ad113d 100644 --- a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml +++ b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml @@ -15,11 +15,11 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24.0dp" - android:height="24.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:width="20dp" + android:height="20dp" + android:viewportWidth="24" + android:viewportHeight="24"> <path - android:pathData="M21,4H3C1.9,4 1,4.9 1,6v13c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2V6C23,4.9 22.1,4 21,4zM21,19H3V6h18V19zM9,8h2v2H9V8zM5,8h2v2H5V8zM8,16h8v1H8V16zM13,8h2v2h-2V8zM9,12h2v2H9V12zM5,12h2v2H5V12zM13,12h2v2h-2V12zM17,8h2v2h-2V8zM17,12h2v2h-2V12z" + android:pathData="M19,7h2v2h-2V7zM15,7h2v2h-2V7zM3,7h2v2H3V7zM7,7h2v2H7V7zM11,7h2v2h-2V7zM19,11h2v2h-2V11zM15,11h2v2h-2V11zM3,11h2v2H3V11zM7,11h2v2H7V11zM11,11h2v2h-2V11zM7,15h10v2H7V15z" android:fillColor="?attr/singleToneColor"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml index 6fbc404d9905..8d569b2ca6e4 100644 --- a/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml @@ -15,8 +15,8 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" + android:width="21dp" + android:height="21dp" android:viewportWidth="24" android:viewportHeight="24"> <path diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml index b02a252bf01d..93b2f9c85bd1 100644 --- a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml @@ -19,10 +19,7 @@ android:height="28dp" android:viewportWidth="28" android:viewportHeight="28"> - - <path - android:fillColor="?attr/singleToneColor" - android:pathData="M17.25,10.15V14v3.85L14,15.95L10.69,14L14,12.05L17.25,10.15 M18.16,7.71c-0.14,0-0.28,0.04-0.42,0.12 l-4.63,2.72l-4.73,2.78c-0.52,0.3-0.52,1.05,0,1.36l4.73,2.78l4.63,2.72c0.13,0.08,0.28,0.12,0.42,0.12c0.44,0,0.84-0.36,0.84-0.86 V14V8.58C19,8.08,18.6,7.71,18.16,7.71L18.16,7.71z" /> <path - android:pathData="M 0 0 H 28 V 28 H 0 V 0 Z" /> + android:pathData="M16.78,10.03l-3.97,3.97l3.97,3.97l-1.06,1.06l-5.03,-5.03l5.03,-5.03z" + android:fillColor="?attr/singleToneColor" /> </vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml index 5cc17911f11f..d53c95b1cb80 100644 --- a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml @@ -15,8 +15,8 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="28dp" - android:height="28dp" + android:width="21dp" + android:height="21dp" android:viewportWidth="28" android:viewportHeight="28"> diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml index 6c1ae9994035..907be01be508 100644 --- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml @@ -17,14 +17,14 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="root" - android:width="24dp" - android:height="24dp" + android:width="21dp" + android:height="21dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <group android:name="icon" android:pivotX="12" android:pivotY="12"> <!-- Tint color to be set directly --> <path android:fillColor="#FFFFFFFF" - android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7z"/> + android:pathData="M12,4c-0.06,0 -0.12,0.01 -0.18,0.01l1.09,-1.09L11.5,1.5L8,5l3.5,3.5l1.41,-1.41l-1.08,-1.08C11.89,6.01 11.95,6 12,6c3.31,0 6,2.69 6,6c0,1.7 -0.71,3.23 -1.85,4.32l1.41,1.41C19.06,16.28 20,14.25 20,12C20,7.59 16.41,4 12,4zM16,19l-3.5,3.5l-1.41,-1.41l1.1,-1.1C12.13,19.98 12.06,20 12,20c-4.41,0 -8,-3.59 -8,-8c0,-2.25 0.94,-4.28 2.43,-5.73l1.41,1.41C6.71,8.77 6,10.3 6,12c0,3.31 2.69,6 6,6c0.05,0 0.11,-0.01 0.16,-0.01l-1.07,-1.07l1.41,-1.41L16,19z"/> </group> </vector> </aapt:attr> diff --git a/packages/SystemUI/res/layout/contextual.xml b/packages/SystemUI/res/layout/contextual.xml new file mode 100644 index 000000000000..94591e932b5b --- /dev/null +++ b/packages/SystemUI/res/layout/contextual.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res-auto" + android:id="@+id/menu_container" + android:layout_width="@dimen/navigation_key_width" + android:layout_height="match_parent" + android:importantForAccessibility="no" + android:clipChildren="false" + android:clipToPadding="false" + > + <com.android.systemui.statusbar.policy.KeyButtonView + android:id="@+id/menu" + android:layout_height="match_parent" + android:layout_width="match_parent" + android:layout_weight="0" + android:scaleType="center" + systemui:keyCode="82" + systemui:playSound="false" + android:visibility="invisible" + android:contentDescription="@string/accessibility_menu" + android:paddingStart="@dimen/navigation_key_padding" + android:paddingEnd="@dimen/navigation_key_padding" + /> + <com.android.systemui.statusbar.policy.KeyButtonView + android:id="@+id/ime_switcher" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="0" + android:scaleType="center" + android:visibility="invisible" + android:contentDescription="@string/accessibility_ime_switch_button" + android:paddingStart="@dimen/navigation_key_padding" + android:paddingEnd="@dimen/navigation_key_padding" + /> + <com.android.systemui.statusbar.policy.KeyButtonView + android:id="@+id/rotate_suggestion" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="0" + android:scaleType="center" + android:visibility="invisible" + android:contentDescription="@string/accessibility_rotate_button" + android:paddingStart="@dimen/navigation_key_padding" + android:paddingEnd="@dimen/navigation_key_padding" + /> + <com.android.systemui.statusbar.policy.KeyButtonView + android:id="@+id/accessibility_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="0" + android:scaleType="center" + android:visibility="invisible" + android:contentDescription="@string/accessibility_accessibility_button" + android:paddingStart="@dimen/navigation_key_padding" + android:paddingEnd="@dimen/navigation_key_padding" + /> +</FrameLayout> diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml index d72021e27e0b..baaf699c278a 100644 --- a/packages/SystemUI/res/layout/navigation_layout.xml +++ b/packages/SystemUI/res/layout/navigation_layout.xml @@ -18,16 +18,14 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginStart="@dimen/rounded_corner_content_padding" - android:layout_marginEnd="@dimen/rounded_corner_content_padding" - android:paddingStart="@dimen/nav_content_padding" - android:paddingEnd="@dimen/nav_content_padding"> + android:layout_height="match_parent"> <com.android.systemui.statusbar.phone.NearestTouchFrame android:id="@+id/nav_buttons" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingStart="@dimen/rounded_corner_content_padding" + android:paddingEnd="@dimen/rounded_corner_content_padding" android:clipChildren="false" android:clipToPadding="false"> @@ -36,6 +34,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" + android:paddingStart="@dimen/nav_content_padding" + android:paddingEnd="@dimen/nav_content_padding" android:clipToPadding="false" android:clipChildren="false" /> @@ -46,6 +46,8 @@ android:layout_gravity="center" android:gravity="center" android:orientation="horizontal" + android:paddingStart="@dimen/nav_content_padding" + android:paddingEnd="@dimen/nav_content_padding" android:clipToPadding="false" android:clipChildren="false" /> diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml index 0e17e5b57cae..6d5b77885a09 100644 --- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml +++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml @@ -18,23 +18,26 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="@dimen/rounded_corner_content_padding" - android:layout_marginBottom="@dimen/rounded_corner_content_padding" - android:paddingTop="8dp" - android:paddingBottom="8dp"> + android:layout_height="match_parent"> <com.android.systemui.statusbar.phone.NearestTouchFrame android:id="@+id/nav_buttons" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:paddingTop="@dimen/rounded_corner_content_padding" + android:paddingBottom="@dimen/rounded_corner_content_padding" + android:clipChildren="false" + android:clipToPadding="false"> <com.android.systemui.statusbar.phone.ReverseLinearLayout android:id="@+id/ends_group" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:clipChildren="false" /> + android:paddingTop="@dimen/nav_content_padding" + android:paddingBottom="@dimen/nav_content_padding" + android:clipChildren="false" + android:clipToPadding="false" /> <com.android.systemui.statusbar.phone.ReverseLinearLayout android:id="@+id/center_group" @@ -42,7 +45,10 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - android:clipChildren="false" /> + android:paddingTop="@dimen/nav_content_padding" + android:paddingBottom="@dimen/nav_content_padding" + android:clipChildren="false" + android:clipToPadding="false" /> </com.android.systemui.statusbar.phone.NearestTouchFrame> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 251589ba17f6..a68ba9b2b411 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -364,6 +364,7 @@ <!-- Nav bar button default ordering/layout --> <string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string> + <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string> <bool name="quick_settings_show_full_alarm">false</bool> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java index 4885c2f796d9..e6f2c33c33d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java @@ -34,11 +34,12 @@ import android.widget.LinearLayout; import android.widget.Space; import com.android.systemui.Dependency; +import com.android.systemui.OverviewProxyService; import com.android.systemui.R; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider; -import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseFrameLayout; +import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout; import com.android.systemui.statusbar.policy.KeyButtonView; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; @@ -67,6 +68,7 @@ public class NavigationBarInflaterView extends FrameLayout public static final String KEY = "key"; public static final String LEFT = "left"; public static final String RIGHT = "right"; + public static final String CONTEXTUAL = "contextual"; public static final String GRAVITY_SEPARATOR = ";"; public static final String BUTTON_SEPARATOR = ","; @@ -97,6 +99,9 @@ public class NavigationBarInflaterView extends FrameLayout private View mLastLandscape; private boolean mAlternativeOrder; + private boolean mUsingCustomLayout; + + private OverviewProxyService mOverviewProxyService; public NavigationBarInflaterView(Context context, AttributeSet attrs) { super(context, attrs); @@ -105,6 +110,7 @@ public class NavigationBarInflaterView extends FrameLayout context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); Mode displayMode = mDisplay.getMode(); isRot0Landscape = displayMode.getPhysicalWidth() > displayMode.getPhysicalHeight(); + mOverviewProxyService = Dependency.get(OverviewProxyService.class); } private void createInflaters() { @@ -136,7 +142,10 @@ public class NavigationBarInflaterView extends FrameLayout } protected String getDefaultLayout() { - return mContext.getString(R.string.config_navBarLayout); + final int defaultResource = mOverviewProxyService.shouldShowSwipeUpUI() + ? R.string.config_navBarLayoutQuickstep + : R.string.config_navBarLayout; + return mContext.getString(defaultResource); } @Override @@ -159,6 +168,7 @@ public class NavigationBarInflaterView extends FrameLayout public void onTuningChanged(String key, String newValue) { if (NAV_BAR_VIEWS.equals(key)) { if (!Objects.equals(mCurrentLayout, newValue)) { + mUsingCustomLayout = newValue != null; clearViews(); inflateLayout(newValue); } @@ -168,6 +178,18 @@ public class NavigationBarInflaterView extends FrameLayout } } + public void onLikelyDefaultLayoutChange() { + // Don't override custom layouts + if (mUsingCustomLayout) return; + + // Reevaluate new layout + final String newValue = getDefaultLayout(); + if (!Objects.equals(mCurrentLayout, newValue)) { + clearViews(); + inflateLayout(newValue); + } + } + public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) { mButtonDispatchers = buttonDispatchers; for (int i = 0; i < buttonDispatchers.size(); i++) { @@ -178,10 +200,12 @@ public class NavigationBarInflaterView extends FrameLayout public void updateButtonDispatchersCurrentView() { if (mButtonDispatchers != null) { final int rotation = mDisplay.getRotation(); - final View view = rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 - ? mRot0 : mRot90; + final boolean portrait = rotation == Surface.ROTATION_0 + || rotation == Surface.ROTATION_180; + final View view = portrait ? mRot0 : mRot90; for (int i = 0; i < mButtonDispatchers.size(); i++) { - mButtonDispatchers.valueAt(i).setCurrentView(view); + final ButtonDispatcher dispatcher = mButtonDispatchers.valueAt(i); + dispatcher.setCurrentView(view); } } } @@ -288,8 +312,8 @@ public class NavigationBarInflaterView extends FrameLayout addToDispatchers(v); View lastView = landscape ? mLastLandscape : mLastPortrait; View accessibilityView = v; - if (v instanceof ReverseFrameLayout) { - accessibilityView = ((ReverseFrameLayout) v).getChildAt(0); + if (v instanceof ReverseRelativeLayout) { + accessibilityView = ((ReverseRelativeLayout) v).getChildAt(0); } if (lastView != null) { accessibilityView.setAccessibilityTraversalAfter(lastView.getId()); @@ -307,21 +331,33 @@ public class NavigationBarInflaterView extends FrameLayout if (sizeStr == null) return v; if (sizeStr.contains(WEIGHT_SUFFIX)) { + // To support gravity, wrap in RelativeLayout and apply gravity to it. + // Children wanting to use gravity must be smaller then the frame. float weight = Float.parseFloat(sizeStr.substring(0, sizeStr.indexOf(WEIGHT_SUFFIX))); - FrameLayout frame = new ReverseFrameLayout(mContext); + ReverseRelativeLayout frame = new ReverseRelativeLayout(mContext); LayoutParams childParams = new LayoutParams(v.getLayoutParams()); - if (sizeStr.endsWith(WEIGHT_CENTERED_SUFFIX)) { - childParams.gravity = Gravity.CENTER; - } else { - childParams.gravity = landscape ? (start ? Gravity.BOTTOM : Gravity.TOP) - : (start ? Gravity.START : Gravity.END); - } + + // Compute gravity to apply + int gravity = (landscape) ? (start ? Gravity.TOP : Gravity.BOTTOM) + : (start ? Gravity.START : Gravity.END); + if (sizeStr.endsWith(WEIGHT_CENTERED_SUFFIX)) gravity = Gravity.CENTER; + + // Set default gravity, flipped if needed in reversed layouts (270 RTL and 90 LTR) + frame.setDefaultGravity(gravity); + frame.setGravity(gravity); // Apply gravity to root + frame.addView(v, childParams); + + // Use weighting to set the width of the frame frame.setLayoutParams(new LinearLayout.LayoutParams(0, MATCH_PARENT, weight)); + + // Ensure ripples can be drawn outside bounds frame.setClipChildren(false); frame.setClipToPadding(false); + return frame; } + float size = Float.parseFloat(sizeStr); ViewGroup.LayoutParams params = v.getLayoutParams(); params.width = (int) (params.width * size); @@ -355,6 +391,8 @@ public class NavigationBarInflaterView extends FrameLayout v = inflater.inflate(R.layout.nav_key_space, parent, false); } else if (CLIPBOARD.equals(button)) { v = inflater.inflate(R.layout.clipboard, parent, false); + } else if (CONTEXTUAL.equals(button)) { + v = inflater.inflate(R.layout.contextual, parent, false); } else if (button.startsWith(KEY)) { String uri = extractImage(button); int code = extractKeycode(button); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 49f9ee2b1c83..704e9634bb2a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -746,6 +746,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav public void updateStates() { final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI(); + + if (mNavigationInflaterView != null) { + // Reinflate the navbar if needed, no-op unless the swipe up state changes + mNavigationInflaterView.onLikelyDefaultLayoutChange(); + } + updateSlippery(); reloadNavIcons(); updateNavButtonIcons(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java index bcbc3457a2e2..d3ec187ef20f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java @@ -17,10 +17,11 @@ package com.android.systemui.statusbar.phone; import android.annotation.Nullable; import android.content.Context; import android.util.AttributeSet; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import java.util.ArrayList; @@ -48,7 +49,7 @@ public class ReverseLinearLayout extends LinearLayout { @Override public void addView(View child) { - reverseParams(child.getLayoutParams(), child); + reverseParams(child.getLayoutParams(), child, mIsLayoutReverse); if (mIsLayoutReverse) { super.addView(child, 0); } else { @@ -58,7 +59,7 @@ public class ReverseLinearLayout extends LinearLayout { @Override public void addView(View child, ViewGroup.LayoutParams params) { - reverseParams(params, child); + reverseParams(params, child, mIsLayoutReverse); if (mIsLayoutReverse) { super.addView(child, 0, params); } else { @@ -94,15 +95,17 @@ public class ReverseLinearLayout extends LinearLayout { } removeAllViews(); for (int i = childCount - 1; i >= 0; i--) { - super.addView(childList.get(i)); + final View child = childList.get(i); + super.addView(child); } mIsLayoutReverse = isLayoutReverse; } } - private static void reverseParams(ViewGroup.LayoutParams params, View child) { + private static void reverseParams(ViewGroup.LayoutParams params, View child, + boolean isLayoutReverse) { if (child instanceof Reversable) { - ((Reversable) child).reverse(); + ((Reversable) child).reverse(isLayoutReverse); } if (child.getPaddingLeft() == child.getPaddingRight() && child.getPaddingTop() == child.getPaddingBottom()) { @@ -118,20 +121,48 @@ public class ReverseLinearLayout extends LinearLayout { } public interface Reversable { - void reverse(); + void reverse(boolean isLayoutReverse); } - public static class ReverseFrameLayout extends FrameLayout implements Reversable { + public static class ReverseRelativeLayout extends RelativeLayout implements Reversable { - public ReverseFrameLayout(Context context) { + public ReverseRelativeLayout(Context context) { super(context); } @Override - public void reverse() { - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - reverseParams(child.getLayoutParams(), child); + public void reverse(boolean isLayoutReverse) { + updateGravity(isLayoutReverse); + reverseGroup(this, isLayoutReverse); + } + + private int mDefaultGravity = Gravity.NO_GRAVITY; + public void setDefaultGravity(int gravity) { + mDefaultGravity = gravity; + } + + public void updateGravity(boolean isLayoutReverse) { + // Flip gravity if top of bottom is used + if (mDefaultGravity != Gravity.TOP && mDefaultGravity != Gravity.BOTTOM) return; + + // Use the default (intended for 270 LTR and 90 RTL) unless layout is otherwise + int gravityToApply = mDefaultGravity; + if (isLayoutReverse) { + gravityToApply = mDefaultGravity == Gravity.TOP ? Gravity.BOTTOM : Gravity.TOP; + } + + if (getGravity() != gravityToApply) setGravity(gravityToApply); + } + } + + private static void reverseGroup(ViewGroup group, boolean isLayoutReverse) { + for (int i = 0; i < group.getChildCount(); i++) { + final View child = group.getChildAt(i); + reverseParams(child.getLayoutParams(), child, isLayoutReverse); + + // Recursively reverse all children + if (child instanceof ViewGroup) { + reverseGroup((ViewGroup) child, isLayoutReverse); } } } |