TopRightWeightedLayout.java revision 1d346bc4df3d0258ee9db30c7232440ed38ee70c
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.ui;
18
19import android.content.Context;
20import android.content.res.Configuration;
21import android.util.AttributeSet;
22import android.view.Gravity;
23import android.view.View;
24import android.view.ViewGroup;
25import android.widget.LinearLayout;
26
27import java.util.ArrayList;
28import java.util.List;
29
30/**
31 * TopRightWeightedLayout is a LinearLayout that reorders its
32 * children such that the right most child is the top most child
33 * on an orientation change.
34 */
35public class TopRightWeightedLayout extends LinearLayout {
36    public TopRightWeightedLayout(Context context, AttributeSet attrs) {
37        super(context, attrs);
38    }
39
40    @Override
41    public void onFinishInflate() {
42        Configuration configuration = getContext().getResources().getConfiguration();
43        checkOrientation(configuration.orientation);
44    }
45
46    @Override
47    public void onConfigurationChanged(Configuration configuration) {
48        super.onConfigurationChanged(configuration);
49        checkOrientation(configuration.orientation);
50    }
51
52    /**
53     * Set the orientation of this layout if it has changed,
54     * and center the elements based on the new orientation.
55     */
56    private void checkOrientation(int orientation) {
57        final boolean isHorizontal = LinearLayout.HORIZONTAL == getOrientation();
58        final boolean isPortrait = Configuration.ORIENTATION_PORTRAIT == orientation;
59        if (isPortrait && !isHorizontal) {
60            // Portrait orientation is out of sync, setting to horizontal
61            // and reversing children
62            fixGravity(LinearLayout.HORIZONTAL);
63            setOrientation(LinearLayout.HORIZONTAL);
64            reverseChildren();
65            requestLayout();
66        } else if (!isPortrait && isHorizontal) {
67            // Landscape orientation is out of sync, setting to vertical
68            // and reversing children
69            fixGravity(LinearLayout.VERTICAL);
70            setOrientation(LinearLayout.VERTICAL);
71            reverseChildren();
72            requestLayout();
73        }
74    }
75
76    /**
77     * Reverse the ordering of the children in this layout.
78     * Note: bringChildToFront produced a non-deterministic ordering.
79     */
80    private void reverseChildren() {
81        List<View> children = new ArrayList<View>();
82        for (int i = getChildCount() - 1; i >= 0; i--) {
83            children.add(getChildAt(i));
84        }
85        for (View v : children) {
86            bringChildToFront(v);
87        }
88    }
89
90    /**
91     * Swap gravity:
92     * left for bottom
93     * right for top
94     * center horizontal for center vertical
95     * etc
96     */
97    private void fixGravity(int direction) {
98        for (int i = 0; i < getChildCount(); i++) {
99            View v = getChildAt(i);
100            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) v.getLayoutParams();
101            int gravity = layoutParams.gravity;
102
103            if (direction == LinearLayout.VERTICAL) {
104                if ((gravity & Gravity.LEFT) != 0) {   // if gravity left is set . . .
105                    gravity &= ~Gravity.LEFT;          // unset left
106                    gravity |= Gravity.BOTTOM;         // and set bottom
107                }
108            } else {
109                if ((gravity & Gravity.BOTTOM) != 0) { // etc
110                    gravity &= ~Gravity.BOTTOM;
111                    gravity |= Gravity.LEFT;
112                }
113            }
114
115            if (direction == LinearLayout.VERTICAL) {
116                if ((gravity & Gravity.RIGHT) != 0) {
117                    gravity &= ~Gravity.RIGHT;
118                    gravity |= Gravity.TOP;
119                }
120            } else {
121                if ((gravity & Gravity.TOP) != 0) {
122                    gravity &= ~Gravity.TOP;
123                    gravity |= Gravity.RIGHT;
124                }
125            }
126
127            // don't mess with children that are centered in both directions
128            if ((gravity & Gravity.CENTER) != Gravity.CENTER) {
129                if (direction == LinearLayout.VERTICAL) {
130                    if ((gravity & Gravity.CENTER_VERTICAL) != 0) {
131                        gravity &= ~ Gravity.CENTER_VERTICAL;
132                        gravity |= Gravity.CENTER_HORIZONTAL;
133                    }
134                } else {
135                    if ((gravity & Gravity.CENTER_HORIZONTAL) != 0) {
136                        gravity &= ~ Gravity.CENTER_HORIZONTAL;
137                        gravity |= Gravity.CENTER_VERTICAL;
138                    }
139                }
140            }
141
142            layoutParams.gravity = gravity;
143        }
144    }
145}