1 /* 2 * Copyright (C) 2015 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.tv.ui; 18 19 import android.animation.TimeInterpolator; 20 import android.app.Dialog; 21 import android.content.Context; 22 import android.os.Handler; 23 import android.util.AttributeSet; 24 import android.util.Log; 25 import android.view.View; 26 import android.view.ViewTreeObserver; 27 import android.view.animation.AnimationUtils; 28 import android.widget.FrameLayout; 29 import com.android.tv.MainActivity; 30 import com.android.tv.R; 31 import com.android.tv.dialog.FullscreenDialogFragment; 32 33 public class FullscreenDialogView extends FrameLayout 34 implements FullscreenDialogFragment.DialogView { 35 private static final String TAG = "FullscreenDialogView"; 36 private static final boolean DEBUG = false; 37 38 private static final int FADE_IN_DURATION_MS = 400; 39 private static final int FADE_OUT_DURATION_MS = 250; 40 private static final int TRANSITION_INTERVAL_MS = 300; 41 42 private MainActivity mActivity; 43 private Dialog mDialog; 44 private boolean mSkipEnterAlphaAnimation; 45 private boolean mSkipExitAlphaAnimation; 46 47 private final TimeInterpolator mLinearOutSlowIn; 48 private final TimeInterpolator mFastOutLinearIn; 49 FullscreenDialogView(Context context)50 public FullscreenDialogView(Context context) { 51 this(context, null, 0); 52 } 53 FullscreenDialogView(Context context, AttributeSet attrs)54 public FullscreenDialogView(Context context, AttributeSet attrs) { 55 this(context, attrs, 0); 56 } 57 FullscreenDialogView(Context context, AttributeSet attrs, int defStyle)58 public FullscreenDialogView(Context context, AttributeSet attrs, int defStyle) { 59 super(context, attrs, defStyle); 60 mLinearOutSlowIn = 61 AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); 62 mFastOutLinearIn = 63 AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_linear_in); 64 getViewTreeObserver() 65 .addOnGlobalLayoutListener( 66 new ViewTreeObserver.OnGlobalLayoutListener() { 67 @Override 68 public void onGlobalLayout() { 69 getViewTreeObserver().removeOnGlobalLayoutListener(this); 70 startEnterAnimation(); 71 } 72 }); 73 } 74 getActivity()75 protected MainActivity getActivity() { 76 return mActivity; 77 } 78 79 /** Gets the host {@link Dialog}. */ getDialog()80 protected Dialog getDialog() { 81 return mDialog; 82 } 83 84 /** Dismisses the host {@link Dialog}. */ dismiss()85 protected void dismiss() { 86 startExitAnimation(() -> mDialog.dismiss()); 87 } 88 89 @Override initialize(MainActivity activity, Dialog dialog)90 public void initialize(MainActivity activity, Dialog dialog) { 91 mActivity = activity; 92 mDialog = dialog; 93 } 94 95 @Override onBackPressed()96 public void onBackPressed() {} 97 98 @Override onDestroy()99 public void onDestroy() {} 100 101 /** Transitions to another view inside the host {@link Dialog}. */ transitionTo(final FullscreenDialogView v)102 public void transitionTo(final FullscreenDialogView v) { 103 mSkipExitAlphaAnimation = true; 104 v.mSkipEnterAlphaAnimation = true; 105 v.initialize(mActivity, mDialog); 106 startExitAnimation( 107 () -> 108 new Handler() 109 .postDelayed( 110 new Runnable() { 111 @Override 112 public void run() { 113 v.initialize(getActivity(), getDialog()); 114 getDialog().setContentView(v); 115 } 116 }, 117 TRANSITION_INTERVAL_MS)); 118 } 119 120 /** Called when an enter animation starts. Sub-view specific animation can be implemented. */ onStartEnterAnimation(TimeInterpolator interpolator, long duration)121 protected void onStartEnterAnimation(TimeInterpolator interpolator, long duration) {} 122 123 /** Called when an exit animation starts. Sub-view specific animation can be implemented. */ onStartExitAnimation( TimeInterpolator interpolator, long duration, Runnable onAnimationEnded)124 protected void onStartExitAnimation( 125 TimeInterpolator interpolator, long duration, Runnable onAnimationEnded) {} 126 startEnterAnimation()127 private void startEnterAnimation() { 128 if (DEBUG) Log.d(TAG, "start an enter animation"); 129 View backgroundView = findViewById(R.id.background); 130 if (!mSkipEnterAlphaAnimation) { 131 backgroundView.setAlpha(0); 132 backgroundView 133 .animate() 134 .alpha(1.0f) 135 .setInterpolator(mLinearOutSlowIn) 136 .setDuration(FADE_IN_DURATION_MS) 137 .withLayer() 138 .start(); 139 } 140 onStartEnterAnimation(mLinearOutSlowIn, FADE_IN_DURATION_MS); 141 } 142 startExitAnimation(final Runnable onAnimationEnded)143 private void startExitAnimation(final Runnable onAnimationEnded) { 144 if (DEBUG) Log.d(TAG, "start an exit animation"); 145 View backgroundView = findViewById(R.id.background); 146 if (!mSkipExitAlphaAnimation) { 147 backgroundView 148 .animate() 149 .alpha(0.0f) 150 .setInterpolator(mFastOutLinearIn) 151 .setDuration(FADE_OUT_DURATION_MS) 152 .withLayer() 153 .start(); 154 } 155 onStartExitAnimation(mFastOutLinearIn, FADE_OUT_DURATION_MS, onAnimationEnded); 156 } 157 } 158