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 50 public FullscreenDialogView(Context context) { 51 this(context, null, 0); 52 } 53 54 public FullscreenDialogView(Context context, AttributeSet attrs) { 55 this(context, attrs, 0); 56 } 57 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 75 protected MainActivity getActivity() { 76 return mActivity; 77 } 78 79 /** Gets the host {@link Dialog}. */ 80 protected Dialog getDialog() { 81 return mDialog; 82 } 83 84 /** Dismisses the host {@link Dialog}. */ 85 protected void dismiss() { 86 startExitAnimation( 87 new Runnable() { 88 @Override 89 public void run() { 90 mDialog.dismiss(); 91 } 92 }); 93 } 94 95 @Override 96 public void initialize(MainActivity activity, Dialog dialog) { 97 mActivity = activity; 98 mDialog = dialog; 99 } 100 101 @Override 102 public void onBackPressed() {} 103 104 @Override 105 public void onDestroy() {} 106 107 /** Transitions to another view inside the host {@link Dialog}. */ 108 public void transitionTo(final FullscreenDialogView v) { 109 mSkipExitAlphaAnimation = true; 110 v.mSkipEnterAlphaAnimation = true; 111 v.initialize(mActivity, mDialog); 112 startExitAnimation( 113 new Runnable() { 114 @Override 115 public void run() { 116 new Handler() 117 .postDelayed( 118 new Runnable() { 119 @Override 120 public void run() { 121 v.initialize(getActivity(), getDialog()); 122 getDialog().setContentView(v); 123 } 124 }, 125 TRANSITION_INTERVAL_MS); 126 } 127 }); 128 } 129 130 /** Called when an enter animation starts. Sub-view specific animation can be implemented. */ 131 protected void onStartEnterAnimation(TimeInterpolator interpolator, long duration) {} 132 133 /** Called when an exit animation starts. Sub-view specific animation can be implemented. */ 134 protected void onStartExitAnimation( 135 TimeInterpolator interpolator, long duration, Runnable onAnimationEnded) {} 136 137 private void startEnterAnimation() { 138 if (DEBUG) Log.d(TAG, "start an enter animation"); 139 View backgroundView = findViewById(R.id.background); 140 if (!mSkipEnterAlphaAnimation) { 141 backgroundView.setAlpha(0); 142 backgroundView 143 .animate() 144 .alpha(1.0f) 145 .setInterpolator(mLinearOutSlowIn) 146 .setDuration(FADE_IN_DURATION_MS) 147 .withLayer() 148 .start(); 149 } 150 onStartEnterAnimation(mLinearOutSlowIn, FADE_IN_DURATION_MS); 151 } 152 153 private void startExitAnimation(final Runnable onAnimationEnded) { 154 if (DEBUG) Log.d(TAG, "start an exit animation"); 155 View backgroundView = findViewById(R.id.background); 156 if (!mSkipExitAlphaAnimation) { 157 backgroundView 158 .animate() 159 .alpha(0.0f) 160 .setInterpolator(mFastOutLinearIn) 161 .setDuration(FADE_OUT_DURATION_MS) 162 .withLayer() 163 .start(); 164 } 165 onStartExitAnimation(mFastOutLinearIn, FADE_OUT_DURATION_MS, onAnimationEnded); 166 } 167 } 168