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
17package com.android.tv.ui;
18
19import android.animation.TimeInterpolator;
20import android.app.Dialog;
21import android.content.Context;
22import android.os.Handler;
23import android.util.AttributeSet;
24import android.util.Log;
25import android.view.View;
26import android.view.ViewTreeObserver;
27import android.view.animation.AnimationUtils;
28import android.widget.FrameLayout;
29import com.android.tv.MainActivity;
30import com.android.tv.R;
31import com.android.tv.dialog.FullscreenDialogFragment;
32
33public 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