13f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu/*
23f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * Copyright (C) 2012 The Android Open Source Project
33f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu *
43f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License");
53f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * you may not use this file except in compliance with the License.
63f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * You may obtain a copy of the License at
73f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu *
83f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu *      http://www.apache.org/licenses/LICENSE-2.0
93f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu *
103f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * Unless required by applicable law or agreed to in writing, software
113f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS,
123f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * See the License for the specific language governing permissions and
143f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * limitations under the License.
153f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu */
163f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
173f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhupackage com.android.gallery3d.app;
183f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
193f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.content.Context;
20634248d313c88f14ff851e7b6769b432ce45e15eztenghuiimport android.content.res.Resources;
213f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.graphics.Rect;
223f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.view.Gravity;
233f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.view.KeyEvent;
243f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.view.MotionEvent;
253f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.view.View;
263f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.view.View.OnClickListener;
273f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.FrameLayout;
283f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.ImageView;
293f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.ImageView.ScaleType;
303f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.LinearLayout;
313f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.ProgressBar;
323f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.RelativeLayout;
333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport android.widget.TextView;
343f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
353f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhuimport com.android.gallery3d.R;
363f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
373f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu/**
383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * The common playback controller for the Movie Player or Video Trimming.
393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu */
403f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhupublic abstract class CommonControllerOverlay extends FrameLayout implements
413f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        ControllerOverlay,
423f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        OnClickListener,
433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        TimeBar.Listener {
443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
453f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected enum State {
463f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        PLAYING,
473f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        PAUSED,
483f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        ENDED,
493f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        ERROR,
503f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        LOADING
513f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
523f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
533f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6;
543f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
553f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected Listener mListener;
563f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
573f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final View mBackground;
583f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected TimeBar mTimeBar;
593f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
603f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected View mMainView;
613f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final LinearLayout mLoadingView;
623f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final TextView mErrorView;
633f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final ImageView mPlayPauseReplayView;
643f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
653f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected State mState;
663f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
673f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected boolean mCanReplay = true;
683f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
69e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui    public void setSeekable(boolean canSeek) {
70e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui        mTimeBar.setSeekable(canSeek);
71e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui    }
72e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui
733f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public CommonControllerOverlay(Context context) {
743f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        super(context);
753f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
763f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mState = State.LOADING;
773f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // TODO: Move the following layout code into xml file.
783f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        LayoutParams wrapContent =
793f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
803f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        LayoutParams matchParent =
813f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
823f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
833f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mBackground = new View(context);
843f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mBackground.setBackgroundColor(context.getResources().getColor(R.color.darker_transparent));
853f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        addView(mBackground, matchParent);
863f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
873f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // Depending on the usage, the timeBar can show a single scrubber, or
883f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // multiple ones for trimming.
893f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        createTimeBar(context);
903f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        addView(mTimeBar, wrapContent);
91634248d313c88f14ff851e7b6769b432ce45e15eztenghui        mTimeBar.setContentDescription(
92634248d313c88f14ff851e7b6769b432ce45e15eztenghui                context.getResources().getString(R.string.accessibility_time_bar));
933f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView = new LinearLayout(context);
943f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView.setOrientation(LinearLayout.VERTICAL);
953f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView.setGravity(Gravity.CENTER_HORIZONTAL);
963f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        ProgressBar spinner = new ProgressBar(context);
973f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        spinner.setIndeterminate(true);
983f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView.addView(spinner, wrapContent);
993f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        TextView loadingText = createOverlayTextView(context);
1003f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        loadingText.setText(R.string.loading_video);
1013f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView.addView(loadingText, wrapContent);
1023f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        addView(mLoadingView, wrapContent);
1033f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1043f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView = new ImageView(context);
1053f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play);
106634248d313c88f14ff851e7b6769b432ce45e15eztenghui        mPlayPauseReplayView.setContentDescription(
107634248d313c88f14ff851e7b6769b432ce45e15eztenghui                context.getResources().getString(R.string.accessibility_play_video));
1083f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol);
1093f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setScaleType(ScaleType.CENTER);
1103f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setFocusable(true);
1113f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setClickable(true);
1123f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setOnClickListener(this);
1133f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        addView(mPlayPauseReplayView, wrapContent);
1143f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1153f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mErrorView = createOverlayTextView(context);
1163f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        addView(mErrorView, matchParent);
1173f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1183f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        RelativeLayout.LayoutParams params =
1193f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                new RelativeLayout.LayoutParams(
1203f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                        LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
1213f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        setLayoutParams(params);
1223f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        hide();
1233f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1243f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1253f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    abstract protected void createTimeBar(Context context);
1263f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1273f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private TextView createOverlayTextView(Context context) {
1283f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        TextView view = new TextView(context);
1293f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        view.setGravity(Gravity.CENTER);
1303f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        view.setTextColor(0xFFFFFFFF);
1313f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        view.setPadding(0, 15, 0, 15);
1323f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return view;
1333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1343f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1353f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1363f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void setListener(Listener listener) {
1373f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        this.mListener = listener;
1383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1403f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1413f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void setCanReplay(boolean canReplay) {
1423f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        this.mCanReplay = canReplay;
1433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1453f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1463f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public View getView() {
1473f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return this;
1483f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1493f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1503f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1513f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void showPlaying() {
1523f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mState = State.PLAYING;
1533f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        showMainView(mPlayPauseReplayView);
1543f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1553f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1563f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1573f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void showPaused() {
1583f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mState = State.PAUSED;
1593f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        showMainView(mPlayPauseReplayView);
1603f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1613f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1623f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1633f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void showEnded() {
1643f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mState = State.ENDED;
16562e98689761a7900dd7e556d04bde8955b94ebdbBobby Georgescu        if (mCanReplay) showMainView(mPlayPauseReplayView);
1663f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1673f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1683f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1693f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void showLoading() {
1703f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mState = State.LOADING;
1713f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        showMainView(mLoadingView);
1723f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1733f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1743f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1753f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void showErrorMessage(String message) {
1763f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mState = State.ERROR;
1773f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING);
1783f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mErrorView.setPadding(
1793f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                padding, mErrorView.getPaddingTop(), padding, mErrorView.getPaddingBottom());
1803f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mErrorView.setText(message);
1813f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        showMainView(mErrorView);
1823f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1833f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1843f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1853f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void setTimes(int currentTime, int totalTime,
1863f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            int trimStartTime, int trimEndTime) {
1873f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime);
1883f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1893f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1903f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void hide() {
1913f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setVisibility(View.INVISIBLE);
1923f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView.setVisibility(View.INVISIBLE);
1933f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mBackground.setVisibility(View.INVISIBLE);
1943f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeBar.setVisibility(View.INVISIBLE);
1953f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        setVisibility(View.INVISIBLE);
1963f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        setFocusable(true);
1973f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        requestFocus();
1983f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
1993f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2003f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private void showMainView(View view) {
2013f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mMainView = view;
2023f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mErrorView.setVisibility(mMainView == mErrorView ? View.VISIBLE : View.INVISIBLE);
2033f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mLoadingView.setVisibility(mMainView == mLoadingView ? View.VISIBLE : View.INVISIBLE);
2043f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setVisibility(
2053f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                mMainView == mPlayPauseReplayView ? View.VISIBLE : View.INVISIBLE);
2063f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        show();
2073f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2083f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2093f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2103f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void show() {
2113f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        updateViews();
2123f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        setVisibility(View.VISIBLE);
2133f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        setFocusable(false);
2143f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2153f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2163f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2173f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void onClick(View view) {
2183f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mListener != null) {
2193f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            if (view == mPlayPauseReplayView) {
2203f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                if (mState == State.ENDED) {
2213f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    if (mCanReplay) {
2223f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                        mListener.onReplay();
2233f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    }
2243f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                } else if (mState == State.PAUSED || mState == State.PLAYING) {
2253f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mListener.onPlayPause();
2263f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                }
2273f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            }
2283f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
2293f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2303f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2313f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2323f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public boolean onKeyDown(int keyCode, KeyEvent event) {
2333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return super.onKeyDown(keyCode, event);
2343f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2353f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2363f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2373f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public boolean onTouchEvent(MotionEvent event) {
2383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (super.onTouchEvent(event)) {
2393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            return true;
2403f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
2413f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return false;
2423f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // The paddings of 4 sides which covered by system components. E.g.
2453f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // +-----------------+\
2463f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // | Action Bar | insets.top
2473f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // +-----------------+/
2483f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // | |
2493f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // | Content Area | insets.right = insets.left = 0
2503f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // | |
2513f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // +-----------------+\
2523f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // | Navigation Bar | insets.bottom
2533f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // +-----------------+/
2543f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // Please see View.fitSystemWindows() for more details.
2553f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private final Rect mWindowInsets = new Rect();
2563f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2573f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2583f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected boolean fitSystemWindows(Rect insets) {
2593f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // We don't set the paddings of this View, otherwise,
2603f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // the content will get cropped outside window
2613f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mWindowInsets.set(insets);
2623f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return true;
2633f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2643f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2653f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2663f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
2673f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        Rect insets = mWindowInsets;
2683f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int pl = insets.left; // the left paddings
2693f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int pr = insets.right;
2703f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int pt = insets.top;
2713f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int pb = insets.bottom;
2723f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2733f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int h = bottom - top;
2743f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int w = right - left;
2753f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        boolean error = mErrorView.getVisibility() == View.VISIBLE;
2763f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2773f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int y = h - pb;
2783f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // Put both TimeBar and Background just above the bottom system
2793f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // component.
2803f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // But extend the background to the width of the screen, since we don't
2813f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // care if it will be covered by a system component and it looks better.
2823f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y);
2833f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(), w - pr, y);
2843f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2853f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // Put the play/pause/next/ previous button in the center of the screen
2863f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h);
2873f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2883f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mMainView != null) {
2893f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            layoutCenteredView(mMainView, 0, 0, w, h);
2903f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
2913f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2923f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2933f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private void layoutCenteredView(View view, int l, int t, int r, int b) {
2943f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int cw = view.getMeasuredWidth();
2953f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int ch = view.getMeasuredHeight();
2963f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int cl = (r - l - cw) / 2;
2973f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int ct = (b - t - ch) / 2;
2983f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        view.layout(cl, ct, cl + cw, ct + ch);
2993f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
3003f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
3013f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
3023f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3033f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
3043f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        measureChildren(widthMeasureSpec, heightMeasureSpec);
3053f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
3063f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
3073f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected void updateViews() {
3083f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mBackground.setVisibility(View.VISIBLE);
3093f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeBar.setVisibility(View.VISIBLE);
310634248d313c88f14ff851e7b6769b432ce45e15eztenghui        Resources resources = getContext().getResources();
311634248d313c88f14ff851e7b6769b432ce45e15eztenghui        int imageResource = R.drawable.ic_vidcontrol_reload;
312634248d313c88f14ff851e7b6769b432ce45e15eztenghui        String contentDescription = resources.getString(R.string.accessibility_reload_video);
313634248d313c88f14ff851e7b6769b432ce45e15eztenghui        if (mState == State.PAUSED) {
314634248d313c88f14ff851e7b6769b432ce45e15eztenghui            imageResource = R.drawable.ic_vidcontrol_play;
315634248d313c88f14ff851e7b6769b432ce45e15eztenghui            contentDescription = resources.getString(R.string.accessibility_play_video);
316634248d313c88f14ff851e7b6769b432ce45e15eztenghui        } else if (mState == State.PLAYING) {
317634248d313c88f14ff851e7b6769b432ce45e15eztenghui            imageResource = R.drawable.ic_vidcontrol_pause;
318634248d313c88f14ff851e7b6769b432ce45e15eztenghui            contentDescription = resources.getString(R.string.accessibility_pause_video);
319634248d313c88f14ff851e7b6769b432ce45e15eztenghui        }
320634248d313c88f14ff851e7b6769b432ce45e15eztenghui
321634248d313c88f14ff851e7b6769b432ce45e15eztenghui        mPlayPauseReplayView.setImageResource(imageResource);
322634248d313c88f14ff851e7b6769b432ce45e15eztenghui        mPlayPauseReplayView.setContentDescription(contentDescription);
3233f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayPauseReplayView.setVisibility(
3243f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                (mState != State.LOADING && mState != State.ERROR &&
3253f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                !(mState == State.ENDED && !mCanReplay))
3263f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                ? View.VISIBLE : View.GONE);
3273f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        requestLayout();
3283f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
3293f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
3303f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // TimeBar listener
3313f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
3323f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
3333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void onScrubbingStart() {
3343f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mListener.onSeekStart();
3353f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
3363f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
3373f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
3383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void onScrubbingMove(int time) {
3393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mListener.onSeekMove(time);
3403f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
3413f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
3423f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
3433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) {
3443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mListener.onSeekEnd(time, trimStartTime, trimEndTime);
3453f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
3463f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu}
347