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