1ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/*
2ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Copyright (C) 2010 The Android Open Source Project
3ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *
4ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Licensed under the Apache License, Version 2.0 (the "License");
5ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * you may not use this file except in compliance with the License.
6ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * You may obtain a copy of the License at
7ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *
8ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *      http://www.apache.org/licenses/LICENSE-2.0
9ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *
10ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Unless required by applicable law or agreed to in writing, software
11ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * distributed under the License is distributed on an "AS IS" BASIS,
12ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * See the License for the specific language governing permissions and
14ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * limitations under the License.
15ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */
16ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
1781393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschipackage com.android.videoeditor.widgets;
18ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
19ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport java.util.ArrayList;
20ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport java.util.List;
21ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
2281393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.R;
2397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
2497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport android.app.Activity;
25ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.Context;
2697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport android.content.res.Resources;
2797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport android.graphics.Canvas;
2897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport android.graphics.drawable.Drawable;
29ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.os.Handler;
30ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschiimport android.os.SystemClock;
31ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet;
3297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport android.view.Display;
33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.MotionEvent;
34ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.ScaleGestureDetector;
35ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.widget.HorizontalScrollView;
36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
37ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/**
38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * The timeline scroll view
39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */
40ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class TimelineHorizontalScrollView extends HorizontalScrollView {
4120e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi    public final static int PLAYHEAD_NORMAL = 1;
4220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi    public final static int PLAYHEAD_MOVE_OK = 2;
4320e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi    public final static int PLAYHEAD_MOVE_NOT_OK = 3;
4420e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi
45ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // Instance variables
46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final List<ScrollViewListener> mScrollListenerList;
47ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final Handler mHandler;
48c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng    private final int mPlayheadMarginTop;
49c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng    private final int mPlayheadMarginTopOk;
50c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng    private final int mPlayheadMarginTopNotOk;
51c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng    private final int mPlayheadMarginBottom;
5220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi    private final Drawable mNormalPlayheadDrawable;
5320e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi    private final Drawable mMoveOkPlayheadDrawable;
5420e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi    private final Drawable mMoveNotOkPlayheadDrawable;
5597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    private final int mHalfParentWidth;
56ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private ScaleGestureDetector mScaleDetector;
57ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mLastScrollX;
58ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mIsScrolling;
59ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mAppScroll;
60ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mEnableUserScrolling;
61ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
62ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // The runnable which executes when the scrolling ends
63ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private Runnable mScrollEndedRunnable = new Runnable() {
64c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng        @Override
65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        public void run() {
66ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mIsScrolling = false;
67ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            for (ScrollViewListener listener : mScrollListenerList) {
69ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                listener.onScrollEnd(TimelineHorizontalScrollView.this, getScrollX(),
70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        getScrollY(), mAppScroll);
71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
72ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
73ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mAppScroll = false;
74ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
75ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    };
76ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
77ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public TimelineHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
78ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super(context, attrs, defStyle);
79ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
80ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mEnableUserScrolling = true;
81ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListenerList = new ArrayList<ScrollViewListener>();
82ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mHandler = new Handler();
8397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
8497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Compute half the width of the screen (and therefore the parent view)
8597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
8697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mHalfParentWidth = display.getWidth() / 2;
8797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
8897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // This value is shared by all children. It represents the width of
8997c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // the left empty view.
9097c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        setTag(R.id.left_view_width, mHalfParentWidth);
9197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        setTag(R.id.playhead_offset, -1);
9220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi        setTag(R.id.playhead_type, PLAYHEAD_NORMAL);
9397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
9497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final Resources resources = context.getResources();
9597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
9697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Get the playhead margins
9797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadMarginTop = (int)resources.getDimension(R.dimen.playhead_margin_top);
9897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadMarginBottom = (int)resources.getDimension(R.dimen.playhead_margin_bottom);
99c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng        mPlayheadMarginTopOk = (int)resources.getDimension(R.dimen.playhead_margin_top_ok);
100c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng        mPlayheadMarginTopNotOk = (int)resources.getDimension(R.dimen.playhead_margin_top_not_ok);
10197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
10297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Prepare the playhead drawable
1030a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng        mNormalPlayheadDrawable = resources.getDrawable(R.drawable.ic_playhead);
10420e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi        mMoveOkPlayheadDrawable = resources.getDrawable(R.drawable.playhead_move_ok);
10520e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi        mMoveNotOkPlayheadDrawable = resources.getDrawable(R.drawable.playhead_move_not_ok);
106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public TimelineHorizontalScrollView(Context context, AttributeSet attrs) {
109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, attrs, 0);
110ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
111ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
112ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public TimelineHorizontalScrollView(Context context) {
113ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, null, 0);
114ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
115ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
116ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
117ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Invoked to enable/disable user scrolling (as opposed to programmatic scrolling)
118ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param enable true to enable user scrolling
119ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
120ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void enableUserScrolling(boolean enable) {
121ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mEnableUserScrolling = enable;
122ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
123ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
124ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
125ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean onInterceptTouchEvent(MotionEvent ev) {
126ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScaleDetector.onTouchEvent(ev);
127ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return mScaleDetector.isInProgress() || super.onInterceptTouchEvent(ev);
128ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
129ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
130ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean onTouchEvent(MotionEvent ev) {
132ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mEnableUserScrolling) {
133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mScaleDetector.onTouchEvent(ev);
134ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
135ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (!mScaleDetector.isInProgress()) {
136ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                return super.onTouchEvent(ev);
137ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
138ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                return true;
139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
141ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschi            if (mScaleDetector.isInProgress()) {
142ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschi                final MotionEvent cancelEvent = MotionEvent.obtain(SystemClock.uptimeMillis(),
143ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschi                        SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0);
144ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschi                mScaleDetector.onTouchEvent(cancelEvent);
145ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschi                cancelEvent.recycle();
146ae8adb16b19a4968e7af1088c6fb60c2aded405eGil Dobjanschi            }
147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return true;
148ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
149ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
150ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
151ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
152ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The scale listener
153ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
154ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setScaleListener(ScaleGestureDetector.SimpleOnScaleGestureListener listener) {
155ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScaleDetector = new ScaleGestureDetector(getContext(), listener);
156ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
157ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
158ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
159ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The listener
160ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
161ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void addScrollListener(ScrollViewListener listener) {
162ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListenerList.add(listener);
163ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
165ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
166ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The listener
167ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
168ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void removeScrollListener(ScrollViewListener listener) {
169ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListenerList.remove(listener);
170ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
171ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
172ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
173ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return true if scrolling is in progress
174ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
175ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean isScrolling() {
176ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return mIsScrolling;
177ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
178ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
179ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
180ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * The app wants to scroll (as opposed to the user)
181ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
182ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param scrollX Horizontal scroll position
183ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param smooth true to scroll smoothly
184ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
185ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void appScrollTo(int scrollX, boolean smooth) {
186ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (getScrollX() == scrollX) {
187ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return;
188ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
189ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
190ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mAppScroll = true;
191ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
192ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (smooth) {
193ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            smoothScrollTo(scrollX, 0);
194ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
195ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            scrollTo(scrollX, 0);
196ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
197ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
198ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
199ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
200ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * The app wants to scroll (as opposed to the user)
201ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
202ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param scrollX Horizontal scroll offset
203ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param smooth true to scroll smoothly
204ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
205ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void appScrollBy(int scrollX, boolean smooth) {
206ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mAppScroll = true;
207ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
208ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (smooth) {
209ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            smoothScrollBy(scrollX, 0);
210ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
211ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            scrollBy(scrollX, 0);
212ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
213ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
214ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
215c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng    @Override
216ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void computeScroll() {
217ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super.computeScroll();
218ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
219ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int scrollX = getScrollX();
220ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mLastScrollX != scrollX) {
221ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mLastScrollX = scrollX;
222ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
223ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Cancel the previous event
224ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mHandler.removeCallbacks(mScrollEndedRunnable);
225ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
226ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Post a new event
227ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mHandler.postDelayed(mScrollEndedRunnable, 300);
228ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
229ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final int scrollY = getScrollY();
230ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (mIsScrolling) {
231ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                for (ScrollViewListener listener : mScrollListenerList) {
232ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    listener.onScrollProgress(this, scrollX, scrollY, mAppScroll);
233ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
234ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
235ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mIsScrolling = true;
236ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
237ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                for (ScrollViewListener listener : mScrollListenerList) {
238ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    listener.onScrollBegin(this, scrollX, scrollY, mAppScroll);
239ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
240ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
241ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
242ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
24397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
24497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    @Override
24597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    protected void dispatchDraw(Canvas canvas) {
24697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        super.dispatchDraw(canvas);
24797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
24897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final int playheadOffset = (Integer)getTag(R.id.playhead_offset);
24997c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final int startX;
25097c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        if (playheadOffset < 0) {
25197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            // Draw the playhead in the middle of the screen
25297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            startX = mHalfParentWidth + getScrollX();
25397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        } else {
25497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            // Draw the playhead at the specified position (during trimming)
25597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            startX = playheadOffset;
25697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        }
25797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
25820e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi        final int playheadType = (Integer)getTag(R.id.playhead_type);
259c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng        final int halfPlayheadWidth = mNormalPlayheadDrawable.getIntrinsicWidth() / 2;
26020e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi        switch (playheadType) {
26120e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            case PLAYHEAD_NORMAL: {
26220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                // Draw the normal playhead
263c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                mNormalPlayheadDrawable.setBounds(
264c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        startX - halfPlayheadWidth,
265c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        mPlayheadMarginTop,
266c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        startX + halfPlayheadWidth,
267c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        getHeight() - mPlayheadMarginBottom);
26820e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                mNormalPlayheadDrawable.draw(canvas);
26920e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                break;
27020e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            }
27120e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi
27220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            case PLAYHEAD_MOVE_OK: {
27320e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                // Draw the move playhead
274c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                mMoveOkPlayheadDrawable.setBounds(
275c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        startX - halfPlayheadWidth,
276c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        mPlayheadMarginTopOk,
277c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        startX + halfPlayheadWidth,
278c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        mPlayheadMarginTopOk + mMoveOkPlayheadDrawable.getIntrinsicHeight());
27920e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                mMoveOkPlayheadDrawable.draw(canvas);
28020e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                break;
28120e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            }
28220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi
28320e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            case PLAYHEAD_MOVE_NOT_OK: {
28420e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                // Draw the move playhead
285c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                mMoveNotOkPlayheadDrawable.setBounds(
286c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        startX - halfPlayheadWidth,
287c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        mPlayheadMarginTopNotOk,
288c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        startX + halfPlayheadWidth,
289c051f87aba46745baa3c32d4c40dda288e94c819Shih-chia Cheng                        mPlayheadMarginTopNotOk + mMoveNotOkPlayheadDrawable.getIntrinsicHeight());
29020e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                mMoveNotOkPlayheadDrawable.draw(canvas);
29120e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                break;
29220e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            }
29320e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi
29420e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            default: {
29520e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi                break;
29620e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi            }
29720e4a3762d9be4801bd9f988b99e65a1b844a96dGil Dobjanschi        }
29897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    }
299ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi}
300