188ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu/*
288ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * Copyright (C) 2014 The Android Open Source Project
388ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu *
488ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * Licensed under the Apache License, Version 2.0 (the "License");
588ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * you may not use this file except in compliance with the License.
688ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * You may obtain a copy of the License at
788ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu *
888ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu *      http://www.apache.org/licenses/LICENSE-2.0
988ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu *
1088ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * Unless required by applicable law or agreed to in writing, software
1188ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * distributed under the License is distributed on an "AS IS" BASIS,
1288ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1388ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * See the License for the specific language governing permissions and
1488ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu * limitations under the License.
1588ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu */
1688ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
1788ea520053c1911e013ba675136be7dfa28c6c3bDoris Liupackage com.android.camera.ui;
1888ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
1988ea520053c1911e013ba675136be7dfa28c6c3bDoris Liuimport android.content.Context;
2054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport android.content.res.Configuration;
2154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport android.view.animation.Interpolator;
2254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport android.graphics.PointF;
2328a2950939614a0c1c83787960ce1a218fb69a5eDoris Liuimport android.graphics.RectF;
2488ea520053c1911e013ba675136be7dfa28c6c3bDoris Liuimport android.util.AttributeSet;
2588ea520053c1911e013ba675136be7dfa28c6c3bDoris Liuimport android.view.View;
2688ea520053c1911e013ba675136be7dfa28c6c3bDoris Liuimport android.widget.FrameLayout;
2788ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
2828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liuimport com.android.camera.CaptureLayoutHelper;
2928a2950939614a0c1c83787960ce1a218fb69a5eDoris Liuimport com.android.camera.debug.Log;
3054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport com.android.camera.ui.motion.InterpolatorHelper;
3154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport com.android.camera.widget.ModeOptions;
3254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport com.android.camera.widget.ModeOptionsOverlay;
33427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Huimport com.android.camera.widget.RoundedThumbnailView;
3488ea520053c1911e013ba675136be7dfa28c6c3bDoris Liuimport com.android.camera2.R;
3588ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
3688ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu/**
37427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu * The goal of this class is to ensure mode options and capture indicator is
38427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu * always laid out to the left of or above bottom bar in landscape or portrait
39427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu * respectively. All the other children in this view group can be expected to
40427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu * be laid out the same way as they are in a normal FrameLayout.
4188ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu */
42427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hupublic class StickyBottomCaptureLayout extends FrameLayout {
4388ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
44427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    private final static Log.Tag TAG = new Log.Tag("StickyBotCapLayout");
45427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    private RoundedThumbnailView mRoundedThumbnailView;
4654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    private ModeOptionsOverlay mModeOptionsOverlay;
4788ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    private View mBottomBar;
4828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    private CaptureLayoutHelper mCaptureLayoutHelper = null;
4988ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
5054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    private ModeOptions.Listener mModeOptionsListener = new ModeOptions.Listener() {
5154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        @Override
5254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        public void onBeginToShowModeOptions() {
5354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            final PointF thumbnailViewPosition = getRoundedThumbnailPosition(
5454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    mCaptureLayoutHelper.getUncoveredPreviewRect(),
5554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    false,
5654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    mModeOptionsOverlay.getModeOptionsToggleWidth());
5754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            final int orientation = getResources().getConfiguration().orientation;
5854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
5954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                animateCaptureIndicatorToY(thumbnailViewPosition.y);
6054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            } else {
6154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                animateCaptureIndicatorToX(thumbnailViewPosition.x);
6254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            }
6354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        }
6454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
6554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        @Override
6654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        public void onBeginToHideModeOptions() {
6754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            final PointF thumbnailViewPosition = getRoundedThumbnailPosition(
6854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    mCaptureLayoutHelper.getUncoveredPreviewRect(),
6954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    true,
7054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    mModeOptionsOverlay.getModeOptionsToggleWidth());
7154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            final int orientation = getResources().getConfiguration().orientation;
7254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
7354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                animateCaptureIndicatorToY(thumbnailViewPosition.y);
7454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            } else {
7554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                animateCaptureIndicatorToX(thumbnailViewPosition.x);
7654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            }
7754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        }
7854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    };
7954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
80427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    public StickyBottomCaptureLayout(Context context, AttributeSet attrs) {
8188ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu        super(context, attrs);
8288ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    }
8388ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
8488ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    @Override
8588ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    public void onFinishInflate() {
86427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        mRoundedThumbnailView = (RoundedThumbnailView) findViewById(R.id.rounded_thumbnail_view);
8754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        mModeOptionsOverlay = (ModeOptionsOverlay) findViewById(R.id.mode_options_overlay);
8854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        mModeOptionsOverlay.setModeOptionsListener(mModeOptionsListener);
8988ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu        mBottomBar = findViewById(R.id.bottom_bar);
9088ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    }
9188ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu
9228a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    /**
9328a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu     * Sets a capture layout helper to query layout rect from.
9428a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu     */
9528a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    public void setCaptureLayoutHelper(CaptureLayoutHelper helper) {
9628a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        mCaptureLayoutHelper = helper;
9728a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu    }
9828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu
9988ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    @Override
10088ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
10128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        if (mCaptureLayoutHelper == null) {
10228a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            Log.e(TAG, "Capture layout helper needs to be set first.");
10328a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu            return;
10488ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu        }
10554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        // Layout mode options overlay.
10628a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        RectF uncoveredPreviewRect = mCaptureLayoutHelper.getUncoveredPreviewRect();
10728a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        mModeOptionsOverlay.layout((int) uncoveredPreviewRect.left, (int) uncoveredPreviewRect.top,
10828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu                (int) uncoveredPreviewRect.right, (int) uncoveredPreviewRect.bottom);
10954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
11054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        // Layout capture indicator.
11154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        PointF roundedThumbnailViewPosition = getRoundedThumbnailPosition(
11254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                uncoveredPreviewRect,
11354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                mModeOptionsOverlay.isModeOptionsHidden(),
11454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                mModeOptionsOverlay.getModeOptionsToggleWidth());
11554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        mRoundedThumbnailView.layout(
11654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                (int) roundedThumbnailViewPosition.x,
11754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                (int) roundedThumbnailViewPosition.y,
11854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                (int) roundedThumbnailViewPosition.x + mRoundedThumbnailView.getMeasuredWidth(),
11954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                (int) roundedThumbnailViewPosition.y + mRoundedThumbnailView.getMeasuredHeight());
12054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
12154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        // Layout bottom bar.
12254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        RectF bottomBarRect = mCaptureLayoutHelper.getBottomBarRect();
12328a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu        mBottomBar.layout((int) bottomBarRect.left, (int) bottomBarRect.top,
12428a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu                (int) bottomBarRect.right, (int) bottomBarRect.bottom);
12588ea520053c1911e013ba675136be7dfa28c6c3bDoris Liu    }
12654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
12754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    /**
12854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     * Calculates the desired layout of capture indicator.
12954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     *
13054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     * @param uncoveredPreviewRect The uncovered preview bound which contains mode option
13154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     *                             overlay and capture indicator.
13254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     * @param isModeOptionsHidden Whether the mode options button are hidden.
13354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     * @param modeOptionsToggleWidth The width of mode options toggle (three dots button).
13454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     * @return the desired view bound for capture indicator.
13554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu     */
13654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    private PointF getRoundedThumbnailPosition(
13754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            RectF uncoveredPreviewRect, boolean isModeOptionsHidden, float modeOptionsToggleWidth) {
13854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float threeDotsButtonDiameter =
13954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                getResources().getDimension(R.dimen.option_button_circle_size);
14054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float threeDotsButtonPadding =
14154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                getResources().getDimension(R.dimen.mode_options_toggle_padding);
14254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float modeOptionsHeight = getResources().getDimension(R.dimen.mode_options_height);
14354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
14454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float roundedThumbnailViewSize = mRoundedThumbnailView.getMeasuredWidth();
14554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float roundedThumbnailFinalSize = mRoundedThumbnailView.getThumbnailFinalDiameter();
14654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float roundedThumbnailViewPadding = mRoundedThumbnailView.getThumbnailPadding();
14754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
14854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        // The view bound is based on the maximal ripple ring diameter. This is the diff of maximal
14954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        // ripple ring radius and the final thumbnail radius.
15054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float radiusDiffBetweenViewAndThumbnail =
15154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                (roundedThumbnailViewSize - roundedThumbnailFinalSize) / 2.0f;
15254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final float distanceFromModeOptions = roundedThumbnailViewPadding +
15354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                roundedThumbnailFinalSize + radiusDiffBetweenViewAndThumbnail;
15454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
15554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final int orientation = getResources().getConfiguration().orientation;
15654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
15754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        float x = 0;
15854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        float y = 0;
15954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
16054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            // The view finder of 16:9 aspect ratio might have a black padding.
16154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            x = uncoveredPreviewRect.right - distanceFromModeOptions;
16254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
16354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            y = uncoveredPreviewRect.bottom;
16454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            if (isModeOptionsHidden) {
16554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                y -= threeDotsButtonPadding + threeDotsButtonDiameter;
16654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            } else {
16754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                y -= modeOptionsHeight;
16854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            }
16954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            y -= distanceFromModeOptions;
17054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        }
17154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
17254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            if (isModeOptionsHidden) {
17354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                x = uncoveredPreviewRect.right - threeDotsButtonPadding - modeOptionsToggleWidth;
17454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            } else {
17554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                x = uncoveredPreviewRect.right - modeOptionsHeight;
17654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            }
17754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            x -= distanceFromModeOptions;
17854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu            y = uncoveredPreviewRect.top + roundedThumbnailViewPadding -
17954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    radiusDiffBetweenViewAndThumbnail;
18054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        }
18154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        return new PointF(x, y);
18254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    }
18354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
18454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    private void animateCaptureIndicatorToX(float x) {
18554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final Interpolator interpolator =
18654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                InterpolatorHelper.getLinearOutSlowInInterpolator(getContext());
18754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        mRoundedThumbnailView.animate()
18854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .setDuration(ModeOptions.PADDING_ANIMATION_TIME)
18954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .setInterpolator(interpolator)
19054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .x(x)
19154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .withEndAction(new Runnable() {
19254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    @Override
19354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    public void run() {
19454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                        mRoundedThumbnailView.setTranslationX(0.0f);
19554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                        requestLayout();
19654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    }
19754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                });
19854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    }
19954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu
20054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    private void animateCaptureIndicatorToY(float y) {
20154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        final Interpolator interpolator =
20254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                InterpolatorHelper.getLinearOutSlowInInterpolator(getContext());
20354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu        mRoundedThumbnailView.animate()
20454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .setDuration(ModeOptions.PADDING_ANIMATION_TIME)
20554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .setInterpolator(interpolator)
20654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .y(y)
20754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                .withEndAction(new Runnable() {
20854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    @Override
20954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    public void run() {
21054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                        mRoundedThumbnailView.setTranslationY(0.0f);
21154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                        requestLayout();
21254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                    }
21354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu                });
21454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu    }
21554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu}
216