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 17 package com.android.camera.ui; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.util.AttributeSet; 22 import android.view.Gravity; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.LinearLayout; 26 27 import java.util.ArrayList; 28 import 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 */ 35 public 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 fixGravityAndPadding(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 fixGravityAndPadding(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 * also swap left|right padding for bottom|top 98 */ 99 private void fixGravityAndPadding(int direction) { 100 for (int i = 0; i < getChildCount(); i++) { 101 // gravity swap 102 View v = getChildAt(i); 103 LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) v.getLayoutParams(); 104 int gravity = layoutParams.gravity; 105 106 if (direction == LinearLayout.VERTICAL) { 107 if ((gravity & Gravity.LEFT) != 0) { // if gravity left is set . . . 108 gravity &= ~Gravity.LEFT; // unset left 109 gravity |= Gravity.BOTTOM; // and set bottom 110 } 111 } else { 112 if ((gravity & Gravity.BOTTOM) != 0) { // etc 113 gravity &= ~Gravity.BOTTOM; 114 gravity |= Gravity.LEFT; 115 } 116 } 117 118 if (direction == LinearLayout.VERTICAL) { 119 if ((gravity & Gravity.RIGHT) != 0) { 120 gravity &= ~Gravity.RIGHT; 121 gravity |= Gravity.TOP; 122 } 123 } else { 124 if ((gravity & Gravity.TOP) != 0) { 125 gravity &= ~Gravity.TOP; 126 gravity |= Gravity.RIGHT; 127 } 128 } 129 130 // don't mess with children that are centered in both directions 131 if ((gravity & Gravity.CENTER) != Gravity.CENTER) { 132 if (direction == LinearLayout.VERTICAL) { 133 if ((gravity & Gravity.CENTER_VERTICAL) != 0) { 134 gravity &= ~ Gravity.CENTER_VERTICAL; 135 gravity |= Gravity.CENTER_HORIZONTAL; 136 } 137 } else { 138 if ((gravity & Gravity.CENTER_HORIZONTAL) != 0) { 139 gravity &= ~ Gravity.CENTER_HORIZONTAL; 140 gravity |= Gravity.CENTER_VERTICAL; 141 } 142 } 143 } 144 145 layoutParams.gravity = gravity; 146 147 // padding swap 148 int paddingLeft = v.getPaddingLeft(); 149 int paddingTop = v.getPaddingTop(); 150 int paddingRight = v.getPaddingRight(); 151 int paddingBottom = v.getPaddingBottom(); 152 v.setPadding(paddingBottom, paddingRight, paddingTop, paddingLeft); 153 } 154 } 155 }