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.graphics.Rect;
     21 import android.util.AttributeSet;
     22 import android.view.View;
     23 import android.widget.FrameLayout;
     24 
     25 import com.android.camera2.R;
     26 
     27 public class CameraControls extends RotatableLayout {
     28 
     29     private static final String TAG = "CAM_Controls";
     30 
     31     private View mBackgroundView;
     32     private View mShutter;
     33     private View mSwitcher;
     34     private View mMenu;
     35     private View mIndicators;
     36     private View mPreview;
     37 
     38     public CameraControls(Context context, AttributeSet attrs) {
     39         super(context, attrs);
     40         setMeasureAllChildren(true);
     41     }
     42 
     43     public CameraControls(Context context) {
     44         super(context);
     45         setMeasureAllChildren(true);
     46     }
     47 
     48     @Override
     49     public void onFinishInflate() {
     50         super.onFinishInflate();
     51         mBackgroundView = findViewById(R.id.blocker);
     52         mSwitcher = findViewById(R.id.camera_switcher);
     53         mShutter = findViewById(R.id.shutter_button);
     54         mMenu = findViewById(R.id.menu);
     55         mIndicators = findViewById(R.id.on_screen_indicators);
     56         mPreview = findViewById(R.id.preview_thumb);
     57     }
     58 
     59     @Override
     60     public void onLayout(boolean changed, int l, int t, int r, int b) {
     61         int orientation = getResources().getConfiguration().orientation;
     62         int size = getResources().getDimensionPixelSize(R.dimen.camera_controls_size);
     63         int rotation = getUnifiedRotation();
     64         adjustBackground();
     65         // As l,t,r,b are positions relative to parents, we need to convert them
     66         // to child's coordinates
     67         r = r - l;
     68         b = b - t;
     69         l = 0;
     70         t = 0;
     71         for (int i = 0; i < getChildCount(); i++) {
     72             View v = getChildAt(i);
     73             v.layout(l, t, r, b);
     74         }
     75         Rect shutter = new Rect();
     76         topRight(mPreview, l, t, r, b);
     77         if (size > 0) {
     78             // restrict controls to size
     79             switch (rotation) {
     80             case 0:
     81             case 180:
     82                 l = (l + r - size) / 2;
     83                 r = l + size;
     84                 break;
     85             case 90:
     86             case 270:
     87                 t = (t + b - size) / 2;
     88                 b = t + size;
     89                 break;
     90             }
     91         }
     92         center(mShutter, l, t, r, b, orientation, rotation, shutter);
     93         center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect());
     94         toLeft(mSwitcher, shutter, rotation);
     95         toRight(mMenu, shutter, rotation);
     96         toRight(mIndicators, shutter, rotation);
     97         View retake = findViewById(R.id.btn_retake);
     98         if (retake != null) {
     99             center(retake, shutter, rotation);
    100             View cancel = findViewById(R.id.btn_cancel);
    101             toLeft(cancel, shutter, rotation);
    102             View done = findViewById(R.id.btn_done);
    103             toRight(done, shutter, rotation);
    104         }
    105     }
    106 
    107     private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) {
    108         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
    109         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
    110         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
    111         switch (rotation) {
    112         case 0:
    113             // phone portrait; controls bottom
    114             result.left = (r + l) / 2 - tw / 2 + lp.leftMargin;
    115             result.right = (r + l) / 2 + tw / 2 - lp.rightMargin;
    116             result.bottom = b - lp.bottomMargin;
    117             result.top = b - th + lp.topMargin;
    118             break;
    119         case 90:
    120             // phone landscape: controls right
    121             result.right = r - lp.rightMargin;
    122             result.left = r - tw + lp.leftMargin;
    123             result.top = (b + t) / 2 - th / 2 + lp.topMargin;
    124             result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin;
    125             break;
    126         case 180:
    127             // phone upside down: controls top
    128             result.left = (r + l) / 2 - tw / 2 + lp.leftMargin;
    129             result.right = (r + l) / 2 + tw / 2 - lp.rightMargin;
    130             result.top = t + lp.topMargin;
    131             result.bottom = t + th - lp.bottomMargin;
    132             break;
    133         case 270:
    134             // reverse landscape: controls left
    135             result.left = l + lp.leftMargin;
    136             result.right = l + tw - lp.rightMargin;
    137             result.top = (b + t) / 2 - th / 2 + lp.topMargin;
    138             result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin;
    139             break;
    140         }
    141         v.layout(result.left, result.top, result.right, result.bottom);
    142     }
    143 
    144     private void center(View v, Rect other, int rotation) {
    145         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
    146         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
    147         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
    148         int cx = (other.left + other.right) / 2;
    149         int cy = (other.top + other.bottom) / 2;
    150         v.layout(cx - tw / 2 + lp.leftMargin,
    151                 cy - th / 2 + lp.topMargin,
    152                 cx + tw / 2 - lp.rightMargin,
    153                 cy + th / 2 - lp.bottomMargin);
    154     }
    155 
    156     private void toLeft(View v, Rect other, int rotation) {
    157         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
    158         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
    159         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
    160         int cx = (other.left + other.right) / 2;
    161         int cy = (other.top + other.bottom) / 2;
    162         int l = 0, r = 0, t = 0, b = 0;
    163         switch (rotation) {
    164         case 0:
    165             // portrait, to left of anchor at bottom
    166             l = other.left - tw + lp.leftMargin;
    167             r = other.left - lp.rightMargin;
    168             t = cy - th / 2 + lp.topMargin;
    169             b = cy + th / 2 - lp.bottomMargin;
    170             break;
    171         case 90:
    172             // phone landscape: below anchor on right
    173             l = cx - tw / 2 + lp.leftMargin;
    174             r = cx + tw / 2 - lp.rightMargin;
    175             t = other.bottom + lp.topMargin;
    176             b = other.bottom + th - lp.bottomMargin;
    177             break;
    178         case 180:
    179             // phone upside down: right of anchor at top
    180             l = other.right + lp.leftMargin;
    181             r = other.right + tw - lp.rightMargin;
    182             t = cy - th / 2 + lp.topMargin;
    183             b = cy + th / 2 - lp.bottomMargin;
    184             break;
    185         case 270:
    186             // reverse landscape: above anchor on left
    187             l = cx - tw / 2 + lp.leftMargin;
    188             r = cx + tw / 2 - lp.rightMargin;
    189             t = other.top - th + lp.topMargin;
    190             b = other.top - lp.bottomMargin;
    191             break;
    192         }
    193         v.layout(l, t, r, b);
    194     }
    195 
    196     private void toRight(View v, Rect other, int rotation) {
    197         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
    198         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
    199         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
    200         int cx = (other.left + other.right) / 2;
    201         int cy = (other.top + other.bottom) / 2;
    202         int l = 0, r = 0, t = 0, b = 0;
    203         switch (rotation) {
    204         case 0:
    205             l = other.right + lp.leftMargin;
    206             r = other.right + tw - lp.rightMargin;
    207             t = cy - th / 2 + lp.topMargin;
    208             b = cy + th / 2 - lp.bottomMargin;
    209             break;
    210         case 90:
    211             l = cx - tw / 2 + lp.leftMargin;
    212             r = cx + tw / 2 - lp.rightMargin;
    213             t = other.top - th + lp.topMargin;
    214             b = other.top - lp.bottomMargin;
    215             break;
    216         case 180:
    217             l = other.left - tw + lp.leftMargin;
    218             r = other.left - lp.rightMargin;
    219             t = cy - th / 2 + lp.topMargin;
    220             b = cy + th / 2 - lp.bottomMargin;
    221             break;
    222         case 270:
    223             l = cx - tw / 2 + lp.leftMargin;
    224             r = cx + tw / 2 - lp.rightMargin;
    225             t = other.bottom + lp.topMargin;
    226             b = other.bottom + th - lp.bottomMargin;
    227             break;
    228         }
    229         v.layout(l, t, r, b);
    230     }
    231 
    232     private void topRight(View v, int l, int t, int r, int b) {
    233         // layout using the specific margins; the rotation code messes up the others
    234         int mt = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_top);
    235         int mr = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_right);
    236         v.layout(r - v.getMeasuredWidth() - mr, t + mt, r - mr, t + mt + v.getMeasuredHeight());
    237     }
    238 
    239     private void adjustBackground() {
    240         int rotation = getUnifiedRotation();
    241         // remove current drawable and reset rotation
    242         mBackgroundView.setBackgroundDrawable(null);
    243         mBackgroundView.setRotationX(0);
    244         mBackgroundView.setRotationY(0);
    245         // if the switcher background is top aligned we need to flip the background
    246         // drawable vertically; if left aligned, flip horizontally
    247         switch (rotation) {
    248             case 180:
    249                 mBackgroundView.setRotationX(180);
    250                 break;
    251             case 270:
    252                 mBackgroundView.setRotationY(180);
    253                 break;
    254             default:
    255                 break;
    256         }
    257         mBackgroundView.setBackgroundResource(R.drawable.switcher_bg);
    258     }
    259 
    260 }
    261