1792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project/* 2792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * 4792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * you may not use this file except in compliance with the License. 6792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * You may obtain a copy of the License at 7792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * 8792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * 10792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * See the License for the specific language governing permissions and 14792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * limitations under the License. 15792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project */ 16792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 17792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectpackage com.android.music; 18792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 19792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.Context; 20792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.os.SystemClock; 21792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.util.AttributeSet; 22792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.view.KeyEvent; 23792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.view.MotionEvent; 24792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.view.View; 25792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.widget.ImageButton; 26792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 27792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project/** 28792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * A button that will repeatedly call a 'listener' method 29792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * as long as the button is pressed. 30792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project */ 31792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectpublic class RepeatingImageButton extends ImageButton { 32792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 33792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private long mStartTime; 34792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private int mRepeatCount; 35792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private RepeatListener mListener; 36792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private long mInterval = 500; 37792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 38792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public RepeatingImageButton(Context context) { 39792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project this(context, null); 40792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 41792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 42792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public RepeatingImageButton(Context context, AttributeSet attrs) { 43792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project this(context, attrs, android.R.attr.imageButtonStyle); 44792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 45792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 46792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) { 47792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project super(context, attrs, defStyle); 48792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project setFocusable(true); 49792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project setLongClickable(true); 50792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 51792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 52792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project /** 53792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Sets the listener to be called while the button is pressed and 54792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * the interval in milliseconds with which it will be called. 55792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * @param l The listener that will be called 56792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * @param interval The interval in milliseconds for calls 57792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project */ 58792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public void setRepeatListener(RepeatListener l, long interval) { 59792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mListener = l; 60792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mInterval = interval; 61792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 62792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 63792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project @Override 64792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public boolean performLongClick() { 65792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mStartTime = SystemClock.elapsedRealtime(); 66792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mRepeatCount = 0; 67792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project post(mRepeater); 68792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project return true; 69792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 70792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 71792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project @Override 72792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public boolean onTouchEvent(MotionEvent event) { 73792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project if (event.getAction() == MotionEvent.ACTION_UP) { 74792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project // remove the repeater, but call the hook one more time 75792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project removeCallbacks(mRepeater); 76792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project if (mStartTime != 0) { 77792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project doRepeat(true); 78792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mStartTime = 0; 79792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 80792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 81792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project return super.onTouchEvent(event); 82792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 83792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 84792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project @Override 8559316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen public boolean onKeyDown(int keyCode, KeyEvent event) { 8659316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen switch (keyCode) { 8759316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen case KeyEvent.KEYCODE_DPAD_CENTER: 8859316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen case KeyEvent.KEYCODE_ENTER: 8959316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen // need to call super to make long press work, but return 9059316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen // true so that the application doesn't get the down event. 9159316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen super.onKeyDown(keyCode, event); 9259316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen return true; 9359316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen } 9459316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen return super.onKeyDown(keyCode, event); 9559316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen } 9659316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen 9759316fd90ed4d1ef804c8cabfd12d86e6340c22dMarco Nelissen @Override 98792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 99792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project switch (keyCode) { 100792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 101792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project case KeyEvent.KEYCODE_ENTER: 102792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project // remove the repeater, but call the hook one more time 103792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project removeCallbacks(mRepeater); 104792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project if (mStartTime != 0) { 105792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project doRepeat(true); 106792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mStartTime = 0; 107792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 108792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 109792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project return super.onKeyUp(keyCode, event); 110792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 111792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 112792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private Runnable mRepeater = new Runnable() { 113792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public void run() { 114792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project doRepeat(false); 115792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project if (isPressed()) { 116792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project postDelayed(this, mInterval); 117792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 118792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 119792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project }; 120792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 121792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project private void doRepeat(boolean last) { 122792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project long now = SystemClock.elapsedRealtime(); 123792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project if (mListener != null) { 124792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project mListener.onRepeat(this, now - mStartTime, last ? -1 : mRepeatCount++); 125792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 126792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 127792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project 128792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project public interface RepeatListener { 129792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project /** 130792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * This method will be called repeatedly at roughly the interval 131792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * specified in setRepeatListener(), for as long as the button 132792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * is pressed. 133792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * @param v The button as a View. 134792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * @param duration The number of milliseconds the button has been pressed so far. 135792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * @param repeatcount The number of previous calls in this sequence. 136792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * If this is going to be the last call in this sequence (i.e. the user 137792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * just stopped pressing the button), the value will be -1. 138792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project */ 139792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project void onRepeat(View v, long duration, int repeatcount); 140792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project } 141792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project} 142