1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.music; 18 19 import android.content.Context; 20 import android.os.SystemClock; 21 import android.util.AttributeSet; 22 import android.view.KeyEvent; 23 import android.view.MotionEvent; 24 import android.view.View; 25 import android.widget.ImageButton; 26 27 /** 28 * A button that will repeatedly call a 'listener' method 29 * as long as the button is pressed. 30 */ 31 public class RepeatingImageButton extends ImageButton { 32 private long mStartTime; 33 private int mRepeatCount; 34 private RepeatListener mListener; 35 private long mInterval = 500; 36 RepeatingImageButton(Context context)37 public RepeatingImageButton(Context context) { 38 this(context, null); 39 } 40 RepeatingImageButton(Context context, AttributeSet attrs)41 public RepeatingImageButton(Context context, AttributeSet attrs) { 42 this(context, attrs, android.R.attr.imageButtonStyle); 43 } 44 RepeatingImageButton(Context context, AttributeSet attrs, int defStyle)45 public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) { 46 super(context, attrs, defStyle); 47 setFocusable(true); 48 setLongClickable(true); 49 } 50 51 /** 52 * Sets the listener to be called while the button is pressed and 53 * the interval in milliseconds with which it will be called. 54 * @param l The listener that will be called 55 * @param interval The interval in milliseconds for calls 56 */ setRepeatListener(RepeatListener l, long interval)57 public void setRepeatListener(RepeatListener l, long interval) { 58 mListener = l; 59 mInterval = interval; 60 } 61 62 @Override performLongClick()63 public boolean performLongClick() { 64 mStartTime = SystemClock.elapsedRealtime(); 65 mRepeatCount = 0; 66 post(mRepeater); 67 return true; 68 } 69 70 @Override onTouchEvent(MotionEvent event)71 public boolean onTouchEvent(MotionEvent event) { 72 if (event.getAction() == MotionEvent.ACTION_UP) { 73 // remove the repeater, but call the hook one more time 74 removeCallbacks(mRepeater); 75 if (mStartTime != 0) { 76 doRepeat(true); 77 mStartTime = 0; 78 } 79 } 80 return super.onTouchEvent(event); 81 } 82 83 @Override onKeyDown(int keyCode, KeyEvent event)84 public boolean onKeyDown(int keyCode, KeyEvent event) { 85 switch (keyCode) { 86 case KeyEvent.KEYCODE_DPAD_CENTER: 87 case KeyEvent.KEYCODE_ENTER: 88 // need to call super to make long press work, but return 89 // true so that the application doesn't get the down event. 90 super.onKeyDown(keyCode, event); 91 return true; 92 } 93 return super.onKeyDown(keyCode, event); 94 } 95 96 @Override onKeyUp(int keyCode, KeyEvent event)97 public boolean onKeyUp(int keyCode, KeyEvent event) { 98 switch (keyCode) { 99 case KeyEvent.KEYCODE_DPAD_CENTER: 100 case KeyEvent.KEYCODE_ENTER: 101 // remove the repeater, but call the hook one more time 102 removeCallbacks(mRepeater); 103 if (mStartTime != 0) { 104 doRepeat(true); 105 mStartTime = 0; 106 } 107 } 108 return super.onKeyUp(keyCode, event); 109 } 110 111 private Runnable mRepeater = new Runnable() { 112 public void run() { 113 doRepeat(false); 114 if (isPressed()) { 115 postDelayed(this, mInterval); 116 } 117 } 118 }; 119 doRepeat(boolean last)120 private void doRepeat(boolean last) { 121 long now = SystemClock.elapsedRealtime(); 122 if (mListener != null) { 123 mListener.onRepeat(this, now - mStartTime, last ? -1 : mRepeatCount++); 124 } 125 } 126 127 public interface RepeatListener { 128 /** 129 * This method will be called repeatedly at roughly the interval 130 * specified in setRepeatListener(), for as long as the button 131 * is pressed. 132 * @param v The button as a View. 133 * @param duration The number of milliseconds the button has been pressed so far. 134 * @param repeatcount The number of previous calls in this sequence. 135 * If this is going to be the last call in this sequence (i.e. the user 136 * just stopped pressing the button), the value will be -1. 137 */ onRepeat(View v, long duration, int repeatcount)138 void onRepeat(View v, long duration, int repeatcount); 139 } 140 } 141