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.content.res.Configuration;
20 import android.util.AttributeSet;
21 import android.view.View;
22 import android.view.ViewGroup;
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 
ReverseLinearLayout(Context context, @Nullable AttributeSet attrs)39     public ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) {
40         super(context, attrs);
41     }
42 
43     @Override
onFinishInflate()44     protected void onFinishInflate() {
45         super.onFinishInflate();
46         updateOrder();
47     }
48 
49     @Override
addView(View child)50     public void addView(View child) {
51         reversParams(child.getLayoutParams());
52         if (mIsLayoutReverse) {
53             super.addView(child, 0);
54         } else {
55             super.addView(child);
56         }
57     }
58 
59     @Override
addView(View child, ViewGroup.LayoutParams params)60     public void addView(View child, ViewGroup.LayoutParams params) {
61         reversParams(params);
62         if (mIsLayoutReverse) {
63             super.addView(child, 0, params);
64         } else {
65             super.addView(child, params);
66         }
67     }
68 
69     @Override
onRtlPropertiesChanged(int layoutDirection)70     public void onRtlPropertiesChanged(int layoutDirection) {
71         super.onRtlPropertiesChanged(layoutDirection);
72         updateOrder();
73     }
74 
setAlternativeOrder(boolean alternative)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      */
updateOrder()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 
reversParams(ViewGroup.LayoutParams params)103     private void reversParams(ViewGroup.LayoutParams params) {
104         if (params == null) {
105             return;
106         }
107         int width = params.width;
108         params.width = params.height;
109         params.height = width;
110     }
111 
112 }
113