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