Home | History | Annotate | Download | only in music
      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 
     33     private long mStartTime;
     34     private int mRepeatCount;
     35     private RepeatListener mListener;
     36     private long mInterval = 500;
     37 
     38     public RepeatingImageButton(Context context) {
     39         this(context, null);
     40     }
     41 
     42     public RepeatingImageButton(Context context, AttributeSet attrs) {
     43         this(context, attrs, android.R.attr.imageButtonStyle);
     44     }
     45 
     46     public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) {
     47         super(context, attrs, defStyle);
     48         setFocusable(true);
     49         setLongClickable(true);
     50     }
     51 
     52     /**
     53      * Sets the listener to be called while the button is pressed and
     54      * the interval in milliseconds with which it will be called.
     55      * @param l The listener that will be called
     56      * @param interval The interval in milliseconds for calls
     57      */
     58     public void setRepeatListener(RepeatListener l, long interval) {
     59         mListener = l;
     60         mInterval = interval;
     61     }
     62 
     63     @Override
     64     public boolean performLongClick() {
     65         mStartTime = SystemClock.elapsedRealtime();
     66         mRepeatCount = 0;
     67         post(mRepeater);
     68         return true;
     69     }
     70 
     71     @Override
     72     public boolean onTouchEvent(MotionEvent event) {
     73         if (event.getAction() == MotionEvent.ACTION_UP) {
     74             // remove the repeater, but call the hook one more time
     75             removeCallbacks(mRepeater);
     76             if (mStartTime != 0) {
     77                 doRepeat(true);
     78                 mStartTime = 0;
     79             }
     80         }
     81         return super.onTouchEvent(event);
     82     }
     83 
     84     @Override
     85     public boolean onKeyDown(int keyCode, KeyEvent event) {
     86         switch (keyCode) {
     87             case KeyEvent.KEYCODE_DPAD_CENTER:
     88             case KeyEvent.KEYCODE_ENTER:
     89                 // need to call super to make long press work, but return
     90                 // true so that the application doesn't get the down event.
     91                 super.onKeyDown(keyCode, event);
     92                 return true;
     93         }
     94         return super.onKeyDown(keyCode, event);
     95     }
     96 
     97     @Override
     98     public boolean onKeyUp(int keyCode, KeyEvent event) {
     99         switch (keyCode) {
    100         case KeyEvent.KEYCODE_DPAD_CENTER:
    101         case KeyEvent.KEYCODE_ENTER:
    102             // remove the repeater, but call the hook one more time
    103             removeCallbacks(mRepeater);
    104             if (mStartTime != 0) {
    105                 doRepeat(true);
    106                 mStartTime = 0;
    107             }
    108         }
    109         return super.onKeyUp(keyCode, event);
    110     }
    111 
    112     private Runnable mRepeater = new Runnable() {
    113         public void run() {
    114             doRepeat(false);
    115             if (isPressed()) {
    116                 postDelayed(this, mInterval);
    117             }
    118         }
    119     };
    120 
    121     private  void doRepeat(boolean last) {
    122         long now = SystemClock.elapsedRealtime();
    123         if (mListener != null) {
    124             mListener.onRepeat(this, now - mStartTime, last ? -1 : mRepeatCount++);
    125         }
    126     }
    127 
    128     public interface RepeatListener {
    129         /**
    130          * This method will be called repeatedly at roughly the interval
    131          * specified in setRepeatListener(), for as long as the button
    132          * is pressed.
    133          * @param v The button as a View.
    134          * @param duration The number of milliseconds the button has been pressed so far.
    135          * @param repeatcount The number of previous calls in this sequence.
    136          * If this is going to be the last call in this sequence (i.e. the user
    137          * just stopped pressing the button), the value will be -1.
    138          */
    139         void onRepeat(View v, long duration, int repeatcount);
    140     }
    141 }
    142