1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.phone; 16 17 import android.annotation.Nullable; 18 import android.content.Context; 19 import android.util.AttributeSet; 20 import android.view.View; 21 import android.view.ViewGroup; 22 import android.widget.FrameLayout; 23 import android.widget.LinearLayout; 24 25 import java.util.ArrayList; 26 27 /** 28 * Automatically reverses the order of children as they are added. 29 * Also reverse the width and height values of layout params 30 */ 31 public class ReverseLinearLayout extends LinearLayout { 32 33 /** If true, the layout is reversed vs. a regular linear layout */ 34 private boolean mIsLayoutReverse; 35 36 /** If true, the layout is opposite to it's natural reversity from the layout direction */ 37 private boolean mIsAlternativeOrder; 38 39 public ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) { 40 super(context, attrs); 41 } 42 43 @Override 44 protected void onFinishInflate() { 45 super.onFinishInflate(); 46 updateOrder(); 47 } 48 49 @Override 50 public void addView(View child) { 51 reverseParams(child.getLayoutParams(), child); 52 if (mIsLayoutReverse) { 53 super.addView(child, 0); 54 } else { 55 super.addView(child); 56 } 57 } 58 59 @Override 60 public void addView(View child, ViewGroup.LayoutParams params) { 61 reverseParams(params, child); 62 if (mIsLayoutReverse) { 63 super.addView(child, 0, params); 64 } else { 65 super.addView(child, params); 66 } 67 } 68 69 @Override 70 public void onRtlPropertiesChanged(int layoutDirection) { 71 super.onRtlPropertiesChanged(layoutDirection); 72 updateOrder(); 73 } 74 75 public void setAlternativeOrder(boolean alternative) { 76 mIsAlternativeOrder = alternative; 77 updateOrder(); 78 } 79 80 /** 81 * In landscape, the LinearLayout is not auto mirrored since it is vertical. Therefore we 82 * have to do it manually 83 */ 84 private void updateOrder() { 85 boolean isLayoutRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; 86 boolean isLayoutReverse = isLayoutRtl ^ mIsAlternativeOrder; 87 88 if (mIsLayoutReverse != isLayoutReverse) { 89 // reversity changed, swap the order of all views. 90 int childCount = getChildCount(); 91 ArrayList<View> childList = new ArrayList<>(childCount); 92 for (int i = 0; i < childCount; i++) { 93 childList.add(getChildAt(i)); 94 } 95 removeAllViews(); 96 for (int i = childCount - 1; i >= 0; i--) { 97 super.addView(childList.get(i)); 98 } 99 mIsLayoutReverse = isLayoutReverse; 100 } 101 } 102 103 private static void reverseParams(ViewGroup.LayoutParams params, View child) { 104 if (child instanceof Reversable) { 105 ((Reversable) child).reverse(); 106 } 107 if (child.getPaddingLeft() == child.getPaddingRight() 108 && child.getPaddingTop() == child.getPaddingBottom()) { 109 child.setPadding(child.getPaddingTop(), child.getPaddingLeft(), 110 child.getPaddingTop(), child.getPaddingLeft()); 111 } 112 if (params == null) { 113 return; 114 } 115 int width = params.width; 116 params.width = params.height; 117 params.height = width; 118 } 119 120 public interface Reversable { 121 void reverse(); 122 } 123 124 public static class ReverseFrameLayout extends FrameLayout implements Reversable { 125 126 public ReverseFrameLayout(Context context) { 127 super(context); 128 } 129 130 @Override 131 public void reverse() { 132 for (int i = 0; i < getChildCount(); i++) { 133 View child = getChildAt(i); 134 reverseParams(child.getLayoutParams(), child); 135 } 136 } 137 } 138 139 } 140