10744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/*
20744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Copyright (C) 2013 The Android Open Source Project
30744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *
40744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
50744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * you may not use this file except in compliance with the License.
60744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * You may obtain a copy of the License at
70744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *
80744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
90744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *
100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Unless required by applicable law or agreed to in writing, software
110744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
120744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * See the License for the specific language governing permissions and
140744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * limitations under the License.
150744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen */
160744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
170744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenpackage com.android.camera.ui;
180744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
190744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.Context;
20d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.content.res.TypedArray;
212268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Spragueimport android.graphics.Rect;
22a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0Doris Liuimport android.graphics.RectF;
23d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.drawable.ColorDrawable;
244dae414b0e4ad4d6528ee04f0761fbe9eacca5ceSpike Spragueimport android.graphics.drawable.Drawable;
25d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.drawable.LayerDrawable;
264dae414b0e4ad4d6528ee04f0761fbe9eacca5ceSpike Spragueimport android.graphics.drawable.TransitionDrawable;
270744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.util.AttributeSet;
284efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.view.MotionEvent;
292268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Spragueimport android.view.TouchDelegate;
300744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.View;
310744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.widget.FrameLayout;
3266a3e6ceb306833355acb740711ccb5c53576e0aSpike Spragueimport android.widget.ImageButton;
330744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
3428a2950939614a0c1c83787960ce1a218fb69a5eDoris Liuimport com.android.camera.CaptureLayoutHelper;
3539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera.ShutterButton;
365596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log;
3779150ed3f8963016e1dc4576e6acab507bef4228Spike Spragueimport com.android.camera.util.ApiHelper;
38d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport com.android.camera.util.CameraUtil;
3939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera2.R;
4039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
410744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/**
42d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * BottomBar swaps its width and height on rotation. In addition, it also
43d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * changes gravity and layout orientation based on the new orientation.
44d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * Specifically, in landscape it aligns to the right side of its parent and lays
45d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * out its children vertically, whereas in portrait, it stays at the bottom of
46d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * the parent and has a horizontal layout orientation.
47d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague */
4828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liupublic class BottomBar extends FrameLayout {
4994c9b43061bee072a2322a2001d27e51dae023dbSpike Sprague
505596b4c902dcb685928b43678f428746ca5ffd08Angus Kong    private static final Log.Tag TAG = new Log.Tag("BottomBar");
5139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
52217512ce074220090a8ede01adf0406a70f4958fSpike Sprague    private static final int CIRCLE_ANIM_DURATION_MS = 300;
53d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private static final int DRAWABLE_MAX_LEVEL = 10000;
54d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague    private static final int MODE_CAPTURE = 0;
55165bb8d85e6eab4e261c6b21a754ee227f732795Erin Dahlgren    private static final int MODE_INTENT = 1;
56165bb8d85e6eab4e261c6b21a754ee227f732795Erin Dahlgren    private static final int MODE_INTENT_REVIEW = 2;
572db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael    private static final int MODE_CANCEL = 3;
582db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael
59d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague    private int mMode;
60d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague
6158b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong    private final int mBackgroundAlphaOverlay;
6258b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong    private final int mBackgroundAlphaDefault;
6370da918464276b110c43868caa272c97baadb89eDoris Liu    private boolean mOverLayBottomBar;
640744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
654efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private FrameLayout mCaptureLayout;
662db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael    private FrameLayout mCancelLayout;
6715690d02da08bda74ed63f260b70076801bf91bfSpike Sprague    private TopRightWeightedLayout mIntentReviewLayout;
684efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
6939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private ShutterButton mShutterButton;
702db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael    private ImageButton mCancelButton;
7139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
7239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private int mBackgroundColor;
73b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    private int mBackgroundPressedColor;
74b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    private int mBackgroundAlpha = 0xff;
75b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
76e3f095bd84ba5a07d5fba1020a28d40d067d187cSpike Sprague    private boolean mDrawCircle;
774dae414b0e4ad4d6528ee04f0761fbe9eacca5ceSpike Sprague    private final float mCircleRadius;
7828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    private CaptureLayoutHelper mCaptureLayoutHelper = null;
7994c9b43061bee072a2322a2001d27e51dae023dbSpike Sprague
80fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague    private final Drawable.ConstantState[] mShutterButtonBackgroundConstantStates;
81d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    // a reference to the shutter background's first contained drawable
82d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    // if it's an animated circle drawable (for video mode)
83d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private AnimatedCircleDrawable mAnimatedCircleDrawable;
84d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    // a reference to the shutter background's first contained drawable
85d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    // if it's a color drawable (for all other modes)
86d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private ColorDrawable mColorDrawable;
87d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
889bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague    private RectF mRect = new RectF();
899bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague
900744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    public BottomBar(Context context, AttributeSet attrs) {
910744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        super(context, attrs);
924dae414b0e4ad4d6528ee04f0761fbe9eacca5ceSpike Sprague        mCircleRadius = getResources()
93d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                .getDimensionPixelSize(R.dimen.video_capture_circle_diameter) / 2;
94d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mBackgroundAlphaOverlay = getResources()
95d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                .getInteger(R.integer.bottom_bar_background_alpha_overlay);
96d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mBackgroundAlphaDefault = getResources()
97d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                .getInteger(R.integer.bottom_bar_background_alpha);
98d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
99d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        // preload all the drawable BGs
100d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        TypedArray ar = context.getResources()
101d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                .obtainTypedArray(R.array.shutter_button_backgrounds);
102d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        int len = ar.length();
103fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        mShutterButtonBackgroundConstantStates = new Drawable.ConstantState[len];
104d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        for (int i = 0; i < len; i++) {
105d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            int drawableId = ar.getResourceId(i, -1);
106fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague            mShutterButtonBackgroundConstantStates[i] =
107fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague                    context.getResources().getDrawable(drawableId).getConstantState();
108d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
109d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        ar.recycle();
1100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    }
1110744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
112d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void setPaintColor(int alpha, int color) {
113d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        if (mAnimatedCircleDrawable != null) {
114d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mAnimatedCircleDrawable.setColor(color);
115d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mAnimatedCircleDrawable.setAlpha(alpha);
116d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        } else if (mColorDrawable != null) {
117d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mColorDrawable.setColor(color);
118d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mColorDrawable.setAlpha(alpha);
119d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
120d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
121d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        if (mIntentReviewLayout != null) {
122d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            ColorDrawable intentBackground = (ColorDrawable) mIntentReviewLayout
123d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                    .getBackground();
124d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            intentBackground.setColor(color);
125d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            intentBackground.setAlpha(alpha);
126d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
127b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    }
128b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
129d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void refreshPaintColor() {
130d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setPaintColor(mBackgroundAlpha, mBackgroundColor);
131d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    }
132d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
133d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void setCancelBackgroundColor(int alpha, int color) {
134d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        LayerDrawable layerDrawable = (LayerDrawable) mCancelButton.getBackground();
135bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague        Drawable d = layerDrawable.getDrawable(0);
136bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague        if (d instanceof AnimatedCircleDrawable) {
137bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            AnimatedCircleDrawable animatedCircleDrawable = (AnimatedCircleDrawable) d;
138bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            animatedCircleDrawable.setColor(color);
139bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            animatedCircleDrawable.setAlpha(alpha);
140bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague        } else if (d instanceof ColorDrawable) {
141bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            ColorDrawable colorDrawable = (ColorDrawable) d;
142bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            if (!ApiHelper.isLOrHigher()) {
143bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague                colorDrawable.setColor(color);
144bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            }
145bfec41e5a5b57715e91ca273d3d1bde65bbcc154Spike Sprague            colorDrawable.setAlpha(alpha);
146d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
147cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague    }
148cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague
14987f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague    private void setCaptureButtonUp() {
150d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setPaintColor(mBackgroundAlpha, mBackgroundColor);
15187f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague    }
15287f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague
15387f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague    private void setCaptureButtonDown() {
15479150ed3f8963016e1dc4576e6acab507bef4228Spike Sprague        if (!ApiHelper.isLOrHigher()) {
155d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            setPaintColor(mBackgroundAlpha, mBackgroundPressedColor);
156d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
157d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    }
158d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
159d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void setCancelButtonUp() {
160d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setCancelBackgroundColor(mBackgroundAlpha, mBackgroundColor);
161d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    }
162d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
163d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void setCancelButtonDown() {
164d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setCancelBackgroundColor(mBackgroundAlpha, mBackgroundPressedColor);
16587f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague    }
16687f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague
1674efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    @Override
1684efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void onFinishInflate() {
1699bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague        mCaptureLayout =
1709bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                (FrameLayout) findViewById(R.id.bottombar_capture);
1719bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague        mCancelLayout =
1729bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                (FrameLayout) findViewById(R.id.bottombar_cancel);
173d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mCancelLayout.setVisibility(View.GONE);
1742db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael
1759bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague        mIntentReviewLayout =
1769bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                (TopRightWeightedLayout) findViewById(R.id.bottombar_intent_review);
177b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
1789bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague        mShutterButton =
1799bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                (ShutterButton) findViewById(R.id.shutter_button);
180b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        mShutterButton.setOnTouchListener(new OnTouchListener() {
181b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague            @Override
182b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague            public boolean onTouch(View v, MotionEvent event) {
183b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                if (MotionEvent.ACTION_DOWN == event.getActionMasked()) {
18487f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague                    setCaptureButtonDown();
18558b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong                } else if (MotionEvent.ACTION_UP == event.getActionMasked() ||
18658b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong                        MotionEvent.ACTION_CANCEL == event.getActionMasked()) {
18787f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague                    setCaptureButtonUp();
18887f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague                } else if (MotionEvent.ACTION_MOVE == event.getActionMasked()) {
1899bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                    mRect.set(0, 0, getWidth(), getHeight());
19087f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague                    if (!mRect.contains(event.getX(), event.getY())) {
19187f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague                        setCaptureButtonUp();
19287f7af57932a826d54a74eb2b22b5bfa7a94f583Spike Sprague                    }
193b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                }
194b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                return false;
195b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague            }
196b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        });
1972db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael
1989bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague        mCancelButton =
1999bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                (ImageButton) findViewById(R.id.shutter_cancel_button);
2002db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael        mCancelButton.setOnTouchListener(new OnTouchListener() {
2012db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael            @Override
2022db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael            public boolean onTouch(View v, MotionEvent event) {
2032db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                if (MotionEvent.ACTION_DOWN == event.getActionMasked()) {
204d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                    setCancelButtonDown();
2052db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                } else if (MotionEvent.ACTION_UP == event.getActionMasked() ||
2062db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                        MotionEvent.ACTION_CANCEL == event.getActionMasked()) {
207d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                    setCancelButtonUp();
2082db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                } else if (MotionEvent.ACTION_MOVE == event.getActionMasked()) {
2099bfd6bddaa09ccdadabf3b0e7e2b81bc1bcf175dSpike Sprague                    mRect.set(0, 0, getWidth(), getHeight());
2102db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                    if (!mRect.contains(event.getX(), event.getY())) {
211d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                        setCancelButtonUp();
2122db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                    }
2132db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                }
2142db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael                return false;
2152db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael            }
2162db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael        });
2172db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael
2182268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague        extendTouchAreaToMatchParent(R.id.done_button);
2192268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague    }
2202268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague
2212268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague    private void extendTouchAreaToMatchParent(int id) {
2222268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague        final View button = findViewById(id);
2232268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague        final View parent = (View) button.getParent();
2242268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague
2252268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague        parent.post(new Runnable() {
2262268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague            @Override
2272268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague            public void run() {
2282268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                Rect parentRect = new Rect();
2292268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                parent.getHitRect(parentRect);
2302268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                Rect buttonRect = new Rect();
2312268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                button.getHitRect(buttonRect);
2322268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague
2332268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                int widthDiff = parentRect.width() - buttonRect.width();
2342268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                int heightDiff = parentRect.height() - buttonRect.height();
2352268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague
2362268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                buttonRect.left -= widthDiff/2;
2372268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                buttonRect.right += widthDiff/2;
2382268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                buttonRect.top -= heightDiff/2;
2392268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                buttonRect.bottom += heightDiff/2;
2402268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague
2412268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague                parent.setTouchDelegate(new TouchDelegate(buttonRect, button));
2422268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague            }
2432268fbb50d07e327c9ac00642db0a83a49c8f3e3Spike Sprague        });
2444efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2454efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2464efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
247d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Perform a transition from the bottom bar options layout to the bottom bar
248d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * capture layout.
2494efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
250a1fab413bcbe5f62ae1d829bac0539519fef96a6Erin Dahlgren    public void transitionToCapture() {
2514efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mCaptureLayout.setVisibility(View.VISIBLE);
252d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mCancelLayout.setVisibility(View.GONE);
253d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mIntentReviewLayout.setVisibility(View.GONE);
254d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague
255d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague        mMode = MODE_CAPTURE;
2564efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2582db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael    /**
259d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Perform a transition from the bottom bar options layout to the bottom bar
260d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * capture layout.
2612db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael     */
2622db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael    public void transitionToCancel() {
263d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mCaptureLayout.setVisibility(View.GONE);
264d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mIntentReviewLayout.setVisibility(View.GONE);
2652db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael        mCancelLayout.setVisibility(View.VISIBLE);
266d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
2672db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael        mMode = MODE_CANCEL;
2682db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael    }
2692db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael
2704efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
271d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Perform a transition to the global intent layout. The current layout
272d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * state of the bottom bar is irrelevant.
2730f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague     */
27415690d02da08bda74ed63f260b70076801bf91bfSpike Sprague    public void transitionToIntentCaptureLayout() {
275d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mIntentReviewLayout.setVisibility(View.GONE);
2764efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mCaptureLayout.setVisibility(View.VISIBLE);
277d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mCancelLayout.setVisibility(View.GONE);
2782db51d761f8fb070f660b90913e131ab361cbbadSeth Raphael
279d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague        mMode = MODE_INTENT;
2804efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2814efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2824efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
283d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Perform a transition to the global intent review layout. The current
284d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * layout state of the bottom bar is irrelevant.
2854efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
2864efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void transitionToIntentReviewLayout() {
287d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mCaptureLayout.setVisibility(View.GONE);
28815690d02da08bda74ed63f260b70076801bf91bfSpike Sprague        mIntentReviewLayout.setVisibility(View.VISIBLE);
289d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mCancelLayout.setVisibility(View.GONE);
290d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague
291d4c5070dfcd7007654ad71ab292d1909c0091cebSpike Sprague        mMode = MODE_INTENT_REVIEW;
2920f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague    }
2930f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague
2949f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague    /**
2959f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague     * @return whether UI is in intent review mode
2969f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague     */
2979f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague    public boolean isInIntentReview() {
2989f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague        return mMode == MODE_INTENT_REVIEW;
2999f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague    }
3009f3d01d9c5d2200882de76e309db55d74d950110Spike Sprague
30166a3e6ceb306833355acb740711ccb5c53576e0aSpike Sprague    private void setButtonImageLevels(int level) {
30266a3e6ceb306833355acb740711ccb5c53576e0aSpike Sprague        ((ImageButton) findViewById(R.id.cancel_button)).setImageLevel(level);
30366a3e6ceb306833355acb740711ccb5c53576e0aSpike Sprague        ((ImageButton) findViewById(R.id.done_button)).setImageLevel(level);
30466a3e6ceb306833355acb740711ccb5c53576e0aSpike Sprague        ((ImageButton) findViewById(R.id.retake_button)).setImageLevel(level);
30566a3e6ceb306833355acb740711ccb5c53576e0aSpike Sprague    }
30666a3e6ceb306833355acb740711ccb5c53576e0aSpike Sprague
307d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger    /**
308d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * Configure the bottom bar to either overlay a live preview, or render off
309d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * the preview. If overlaying the preview, ensure contained drawables have
310d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * reduced opacity and that the bottom bar itself has no background to allow
311d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * the preview to render through. If not overlaying the preview, set
312d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * contained drawables to opaque and ensure that the bottom bar itself has
313d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * a view background, so that varying alpha (i.e. mode list transitions) are
314d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * based upon that background instead of an underlying preview.
315d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     *
316d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     * @param overlay if true, treat bottom bar as overlaying the preview
317d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger     */
31858b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong    private void setOverlayBottomBar(boolean overlay) {
31958b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        mOverLayBottomBar = overlay;
32058b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        if (overlay) {
32158b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong            setBackgroundAlpha(mBackgroundAlphaOverlay);
32258b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong            setButtonImageLevels(1);
323d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            // clear background on the containing bottom bar, rather than the
324d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            // contained drawables
325d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            super.setBackground(null);
32658b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        } else {
32758b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong            setBackgroundAlpha(mBackgroundAlphaDefault);
32858b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong            setButtonImageLevels(0);
329d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            // setBackgroundColor is overridden and delegates to contained
330d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            // drawables, call super to set the containing background color in
331d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            // this mode.
332d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger            super.setBackgroundColor(mBackgroundColor);
33358b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        }
33458b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong    }
33558b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong
33628a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    /**
33728a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu     * Sets a capture layout helper to query layout rect from.
33828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu     */
33928a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    public void setCaptureLayoutHelper(CaptureLayoutHelper helper) {
34028a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        mCaptureLayoutHelper = helper;
34128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    }
34228a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu
34370da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
34470da918464276b110c43868caa272c97baadb89eDoris Liu    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
34558b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        final int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
34658b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        final int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
34758b9b03f2bedc522bde5b4199121ea2e559c79a9Angus Kong        if (measureWidth == 0 || measureHeight == 0) {
34870da918464276b110c43868caa272c97baadb89eDoris Liu            return;
34970da918464276b110c43868caa272c97baadb89eDoris Liu        }
35070da918464276b110c43868caa272c97baadb89eDoris Liu
35128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        if (mCaptureLayoutHelper == null) {
35228a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
35328a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            Log.e(TAG, "Capture layout helper needs to be set first.");
3540744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        } else {
35528a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            RectF bottomBarRect = mCaptureLayoutHelper.getBottomBarRect();
35628a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            super.onMeasure(MeasureSpec.makeMeasureSpec(
357d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                    (int) bottomBarRect.width(), MeasureSpec.EXACTLY),
35828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu                    MeasureSpec.makeMeasureSpec((int) bottomBarRect.height(), MeasureSpec.EXACTLY)
359d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague                    );
36028a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            boolean shouldOverlayBottomBar = mCaptureLayoutHelper.shouldOverlayBottomBar();
36128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            setOverlayBottomBar(shouldOverlayBottomBar);
3620744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        }
36370da918464276b110c43868caa272c97baadb89eDoris Liu    }
36470da918464276b110c43868caa272c97baadb89eDoris Liu
365e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    // prevent touches on bottom bar (not its children)
366e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    // from triggering a touch event on preview area
367e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    @Override
368e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    public boolean onTouchEvent(MotionEvent event) {
369e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague        return true;
370e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    }
37139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
37239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    @Override
37339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void setBackgroundColor(int color) {
37439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mBackgroundColor = color;
375b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        setPaintColor(mBackgroundAlpha, mBackgroundColor);
376d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setCancelBackgroundColor(mBackgroundAlpha, mBackgroundColor);
377d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    }
378d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
379d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void setBackgroundPressedColor(int color) {
38079150ed3f8963016e1dc4576e6acab507bef4228Spike Sprague        if (ApiHelper.isLOrHigher()) {
381d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            // not supported (setting a color on a RippleDrawable is hard =[ )
382d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        } else {
383d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mBackgroundPressedColor = color;
384d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
385d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    }
386d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
387fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague    private LayerDrawable applyCircleDrawableToShutterBackground(LayerDrawable shutterBackground) {
388fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        // the background for video has a circle_item drawable placeholder
389fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        // that gets replaced by an AnimatedCircleDrawable for the cool
390fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        // shrink-down-to-a-circle effect
391fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        // all other modes need not do this replace
392fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        Drawable d = shutterBackground.findDrawableByLayerId(R.id.circle_item);
393fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        if (d != null) {
394fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague            Drawable animatedCircleDrawable =
395fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague                    new AnimatedCircleDrawable((int) mCircleRadius);
396fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague            shutterBackground
397fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague                    .setDrawableByLayerId(R.id.circle_item, animatedCircleDrawable);
398c5ecbd6e0a6c2a2d93fc58f0ba3d273249b06da2Spike Sprague            animatedCircleDrawable.setLevel(DRAWABLE_MAX_LEVEL);
399fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        }
400fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague
401fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        return shutterBackground;
402fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague    }
403fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague
404fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague    private LayerDrawable newDrawableFromConstantState(Drawable.ConstantState constantState) {
405fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        return (LayerDrawable) constantState.newDrawable(getContext().getResources());
406fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague    }
407fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague
408d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    private void setupShutterBackgroundForModeIndex(int index) {
409fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        LayerDrawable shutterBackground = applyCircleDrawableToShutterBackground(
410fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague                newDrawableFromConstantState(mShutterButtonBackgroundConstantStates[index]));
411d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mShutterButton.setBackground(shutterBackground);
412fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague        mCancelButton.setBackground(applyCircleDrawableToShutterBackground(
413fcc9143368d134ce26dec7d904f21e06676b2a02Spike Sprague                newDrawableFromConstantState(mShutterButtonBackgroundConstantStates[index])));
414d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
415d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        Drawable d = shutterBackground.getDrawable(0);
416d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mAnimatedCircleDrawable = null;
417d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        mColorDrawable = null;
418d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        if (d instanceof AnimatedCircleDrawable) {
419d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mAnimatedCircleDrawable = (AnimatedCircleDrawable) d;
420d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        } else if (d instanceof ColorDrawable) {
421d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mColorDrawable = (ColorDrawable) d;
422d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        }
423d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague
424d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        int colorId = CameraUtil.getCameraThemeColorId(index, getContext());
425d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        int pressedColor = getContext().getResources().getColor(colorId);
426d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setBackgroundPressedColor(pressedColor);
427d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        refreshPaintColor();
428b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    }
429b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
430d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague    public void setColorsForModeIndex(int index) {
431d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setupShutterBackgroundForModeIndex(index);
43239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
43339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
43439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void setBackgroundAlpha(int alpha) {
435b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        mBackgroundAlpha = alpha;
436b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        setPaintColor(mBackgroundAlpha, mBackgroundColor);
437d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        setCancelBackgroundColor(mBackgroundAlpha, mBackgroundColor);
43839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
43939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
440667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren    /**
441667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren     * Sets the shutter button enabled if true, disabled if false.
442667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren     * <p>
443d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Disabled means that the shutter button is not clickable and is greyed
444d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * out.
445667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren     */
44657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling    public void setShutterButtonEnabled(final boolean enabled) {
44757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling        mShutterButton.post(new Runnable() {
44857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling            @Override
44957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling            public void run() {
45057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling                mShutterButton.setEnabled(enabled);
45157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling                setShutterButtonImportantToA11y(enabled);
45257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling            }
45357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling        });
454b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague    }
455b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague
456b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague    /**
457d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Sets whether shutter button should be included in a11y announcement and
458d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * navigation
459b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague     */
460b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague    public void setShutterButtonImportantToA11y(boolean important) {
461b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague        if (important) {
46238989540cb1488cb7b8062ff74b9dedcd76c047fSpike Sprague            mShutterButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
46338989540cb1488cb7b8062ff74b9dedcd76c047fSpike Sprague        } else {
46438989540cb1488cb7b8062ff74b9dedcd76c047fSpike Sprague            mShutterButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
46538989540cb1488cb7b8062ff74b9dedcd76c047fSpike Sprague        }
466a93909ffe93c9f5e27e493f32a78aab6fbf3e06eSpike Sprague    }
467a93909ffe93c9f5e27e493f32a78aab6fbf3e06eSpike Sprague
468667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren    /**
469667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren     * Returns whether the capture button is enabled.
470667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren     */
471667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren    public boolean isShutterButtonEnabled() {
472667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren        return mShutterButton.isEnabled();
473667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren    }
474667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren
47539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private TransitionDrawable crossfadeDrawable(Drawable from, Drawable to) {
476d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        Drawable[] arrayDrawable = new Drawable[2];
47739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        arrayDrawable[0] = from;
47839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        arrayDrawable[1] = to;
47939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        TransitionDrawable transitionDrawable = new TransitionDrawable(arrayDrawable);
48039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        transitionDrawable.setCrossFadeEnabled(true);
48139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        return transitionDrawable;
48239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
48339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
48439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    /**
485d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * Sets the shutter button's icon resource. By default, all drawables
486d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * instances loaded from the same resource share a common state; if you
487d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * modify the state of one instance, all the other instances will receive
488d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * the same modification. In order to modify properties of this icon
489d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * drawable without affecting other drawables, here we use a mutable
490d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague     * drawable which is guaranteed to not share states with other drawables.
49139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     */
49239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void setShutterButtonIcon(int resId) {
49358ac7e042e0718e860f9aea6dca3697e1c3d9bb8Doris Liu        Drawable iconDrawable = getResources().getDrawable(resId);
49458ac7e042e0718e860f9aea6dca3697e1c3d9bb8Doris Liu        if (iconDrawable != null) {
49558ac7e042e0718e860f9aea6dca3697e1c3d9bb8Doris Liu            iconDrawable = iconDrawable.mutate();
49658ac7e042e0718e860f9aea6dca3697e1c3d9bb8Doris Liu        }
49758ac7e042e0718e860f9aea6dca3697e1c3d9bb8Doris Liu        mShutterButton.setImageDrawable(iconDrawable);
49839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
49939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
50039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    /**
50139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     * Animates bar to a single stop button
50239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     */
50345a821d43ae8d7287b649f670a66ab3d99eeccafSpike Sprague    public void animateToVideoStop(int resId) {
504d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        if (mOverLayBottomBar && mAnimatedCircleDrawable != null) {
505d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mAnimatedCircleDrawable.animateToSmallRadius();
50645a821d43ae8d7287b649f670a66ab3d99eeccafSpike Sprague            mDrawCircle = true;
50745a821d43ae8d7287b649f670a66ab3d99eeccafSpike Sprague        }
50839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
50939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        TransitionDrawable transitionDrawable = crossfadeDrawable(
51039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mShutterButton.getDrawable(),
51139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                getResources().getDrawable(resId));
51239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mShutterButton.setImageDrawable(transitionDrawable);
51339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS);
51439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
51539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
51639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    /**
51739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     * Animates bar to full width / length with video capture icon
51839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     */
51939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void animateToFullSize(int resId) {
520d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague        if (mDrawCircle && mAnimatedCircleDrawable != null) {
521d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mAnimatedCircleDrawable.animateToFullSize();
522d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague            mDrawCircle = false;
52345a821d43ae8d7287b649f670a66ab3d99eeccafSpike Sprague        }
52439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
52539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        TransitionDrawable transitionDrawable = crossfadeDrawable(
52639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mShutterButton.getDrawable(),
52739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                getResources().getDrawable(resId));
52839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mShutterButton.setImageDrawable(transitionDrawable);
52939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS);
53039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
5310744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen}
532