TimelineHorizontalScrollView.java revision 97c784156f2df509683c59c6ce0e23ef5126a4b3
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
17ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipackage com.google.videoeditor.widgets;
18ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
19ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport java.util.ArrayList;
20ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport java.util.List;
21ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
2297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport com.google.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;
30ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet;
3197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschiimport android.view.Display;
32ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.MotionEvent;
33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.ScaleGestureDetector;
34ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.widget.HorizontalScrollView;
35ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/**
37ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * The timeline scroll view
38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */
39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class TimelineHorizontalScrollView extends HorizontalScrollView {
40ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // Instance variables
41ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final List<ScrollViewListener> mScrollListenerList;
42ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final Handler mHandler;
4397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    private final int mPlayheadMarginTop, mPlayheadMarginBottom;
4497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    private final Drawable mPlayheadDrawable;
4597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    private final int mHalfParentWidth;
46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private ScaleGestureDetector mScaleDetector;
47ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mLastScrollX;
48ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mIsScrolling;
49ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mAppScroll;
50ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mEnableUserScrolling;
51ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
52ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // The runnable which executes when the scrolling ends
53ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private Runnable mScrollEndedRunnable = new Runnable() {
54ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        /*
55ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         * {@inheritDoc}
56ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         */
57ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        public void run() {
58ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mIsScrolling = false;
59ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
60ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            for (ScrollViewListener listener : mScrollListenerList) {
61ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                listener.onScrollEnd(TimelineHorizontalScrollView.this, getScrollX(),
62ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        getScrollY(), mAppScroll);
63ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
64ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mAppScroll = false;
66ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
67ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    };
68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
69ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
72ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public TimelineHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
73ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super(context, attrs, defStyle);
74ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
75ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mEnableUserScrolling = true;
76ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListenerList = new ArrayList<ScrollViewListener>();
77ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mHandler = new Handler();
7897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
7997c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Compute half the width of the screen (and therefore the parent view)
8097c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
8197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mHalfParentWidth = display.getWidth() / 2;
8297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
8397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // This value is shared by all children. It represents the width of
8497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // the left empty view.
8597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        setTag(R.id.left_view_width, mHalfParentWidth);
8697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        setTag(R.id.playhead_offset, -1);
8797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
8897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final Resources resources = context.getResources();
8997c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
9097c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Get the playhead margins
9197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadMarginTop = (int)resources.getDimension(R.dimen.playhead_margin_top);
9297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadMarginBottom = (int)resources.getDimension(R.dimen.playhead_margin_bottom);
9397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
9497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Prepare the playhead drawable
9597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadDrawable = resources.getDrawable(R.drawable.playhead);
96ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
97ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
98ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
99ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
100ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
101ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public TimelineHorizontalScrollView(Context context, AttributeSet attrs) {
102ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, attrs, 0);
103ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
104ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
105ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public TimelineHorizontalScrollView(Context context) {
109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, null, 0);
110ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
111ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
112ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
113ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Invoked to enable/disable user scrolling (as opposed to programmatic scrolling)
114ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param enable true to enable user scrolling
115ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
116ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void enableUserScrolling(boolean enable) {
117ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mEnableUserScrolling = enable;
118ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
119ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
120ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
121ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
122ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
123ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
124ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean onInterceptTouchEvent(MotionEvent ev) {
125ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScaleDetector.onTouchEvent(ev);
126ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return mScaleDetector.isInProgress() || super.onInterceptTouchEvent(ev);
127ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
128ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
129ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
130ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
132ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean onTouchEvent(MotionEvent ev) {
134ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mEnableUserScrolling) {
135ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mScaleDetector.onTouchEvent(ev);
136ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
137ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (!mScaleDetector.isInProgress()) {
138ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                return super.onTouchEvent(ev);
139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                return true;
141ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
142ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
143ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return true;
144ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
145ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
146ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
148ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The scale listener
149ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
150ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setScaleListener(ScaleGestureDetector.SimpleOnScaleGestureListener listener) {
151ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScaleDetector = new ScaleGestureDetector(getContext(), listener);
152ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
153ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
154ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
155ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The listener
156ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
157ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void addScrollListener(ScrollViewListener listener) {
158ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListenerList.add(listener);
159ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
160ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
161ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
162ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The listener
163ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void removeScrollListener(ScrollViewListener listener) {
165ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListenerList.remove(listener);
166ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
167ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
168ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
169ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return true if scrolling is in progress
170ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
171ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean isScrolling() {
172ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return mIsScrolling;
173ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
174ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
175ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
176ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * The app wants to scroll (as opposed to the user)
177ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
178ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param scrollX Horizontal scroll position
179ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param smooth true to scroll smoothly
180ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
181ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void appScrollTo(int scrollX, boolean smooth) {
182ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (getScrollX() == scrollX) {
183ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return;
184ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
185ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
186ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mAppScroll = true;
187ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
188ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (smooth) {
189ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            smoothScrollTo(scrollX, 0);
190ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
191ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            scrollTo(scrollX, 0);
192ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
193ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
194ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
195ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
196ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * The app wants to scroll (as opposed to the user)
197ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
198ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param scrollX Horizontal scroll offset
199ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param smooth true to scroll smoothly
200ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
201ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void appScrollBy(int scrollX, boolean smooth) {
202ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mAppScroll = true;
203ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
204ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (smooth) {
205ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            smoothScrollBy(scrollX, 0);
206ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
207ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            scrollBy(scrollX, 0);
208ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
209ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
210ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
211ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
212ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
213ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
214ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void computeScroll() {
215ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super.computeScroll();
216ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
217ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int scrollX = getScrollX();
218ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mLastScrollX != scrollX) {
219ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mLastScrollX = scrollX;
220ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
221ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Cancel the previous event
222ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mHandler.removeCallbacks(mScrollEndedRunnable);
223ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
224ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Post a new event
225ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mHandler.postDelayed(mScrollEndedRunnable, 300);
226ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
227ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final int scrollY = getScrollY();
228ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (mIsScrolling) {
229ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                for (ScrollViewListener listener : mScrollListenerList) {
230ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    listener.onScrollProgress(this, scrollX, scrollY, mAppScroll);
231ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
232ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
233ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mIsScrolling = true;
234ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
235ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                for (ScrollViewListener listener : mScrollListenerList) {
236ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    listener.onScrollBegin(this, scrollX, scrollY, mAppScroll);
237ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
238ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
239ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
240ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
24197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
24297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    /*
24397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi     * {@inheritDoc}
24497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi     */
24597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    @Override
24697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    protected void dispatchDraw(Canvas canvas) {
24797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        super.dispatchDraw(canvas);
24897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
24997c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final int playheadOffset = (Integer)getTag(R.id.playhead_offset);
25097c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final int startX;
25197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        if (playheadOffset < 0) {
25297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            // Draw the playhead in the middle of the screen
25397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            startX = mHalfParentWidth + getScrollX();
25497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        } else {
25597c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            // Draw the playhead at the specified position (during trimming)
25697c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi            startX = playheadOffset;
25797c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        }
25897c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi
25997c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        // Draw the playhead
26097c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        final int halfPlayheadWidth = mPlayheadDrawable.getIntrinsicWidth() / 2;
26197c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadDrawable.setBounds(startX - halfPlayheadWidth, mPlayheadMarginTop,
26297c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi                startX + halfPlayheadWidth, getHeight() - mPlayheadMarginBottom);
26397c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi        mPlayheadDrawable.draw(canvas);
26497c784156f2df509683c59c6ce0e23ef5126a4b3Gil Dobjanschi    }
265ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi}
266