Home | History | Annotate | Download | only in ui
      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 }