Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android在按住按钮时重复操作_Android - Fatal编程技术网

android在按住按钮时重复操作

android在按住按钮时重复操作,android,Android,我想在按住按钮时执行重复操作。示例:当用户单击并按住按钮时,它应该在固定的时间间隔内反复调用类似的方法,直到用户将手指从按钮上移开 您可以为该视图注册一个视图。OnKeyListener。请注意,最好取消此类回调,否则,如果您的方法做了一些稍微“沉重”的事情,UI将不会平滑。尽管这不是一个好主意。这可以通过在onKeyDown上启动计时器来完成,在您将光标移动一步并重新启动计时器的时间间隔内启动计时器。然后可以取消onKeyUp事件上的计时器。这在其他系统上的工作方式通常是先按下第一个键,然后稍

我想在按住按钮时执行重复操作。示例:当用户单击并按住按钮时,它应该在固定的时间间隔内反复调用类似的方法,直到用户将手指从按钮上移开

您可以为该视图注册一个
视图。OnKeyListener
。请注意,最好取消此类回调,否则,如果您的方法做了一些稍微“沉重”的事情,UI将不会平滑。

尽管这不是一个好主意。这可以通过在
onKeyDown
上启动计时器来完成,在您将光标移动一步并重新启动计时器的时间间隔内启动计时器。然后可以取消
onKeyUp
事件上的计时器。这在其他系统上的工作方式通常是先按下第一个键,然后稍等片刻,以确保用户确实按住了按钮。。。然后重复可以快一点。想象一个键盘自动重复。这应该可以工作,并且不会对ui线程产生负面影响。

有多种方法可以实现这一点,但一个非常简单的方法是在
处理程序上发布
可运行的
,并有一定的延迟。在它最基本的形式中,它看起来有点像这样:

Button button = (Button) findViewById(R.id.button);
button.setOnTouchListener(new View.OnTouchListener() {

    private Handler mHandler;

    @Override public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (mHandler != null) return true;
            mHandler = new Handler();
            mHandler.postDelayed(mAction, 500);
            break;
        case MotionEvent.ACTION_UP:
            if (mHandler == null) return true;
            mHandler.removeCallbacks(mAction);
            mHandler = null;
            break;
        }
        return false;
    }

    Runnable mAction = new Runnable() {
        @Override public void run() {
            System.out.println("Performing action...");
            mHandler.postDelayed(this, 500);
        }
    };

});
这个想法非常简单:当“向下”触摸动作发生时,在
处理程序上发布一个
Runnable
,其中包含重复动作。在此之后,在“向上”触摸操作完成之前,不要再次发布
Runnable
Runnable
将继续将自身发布到
处理程序中(“向下”触摸操作仍在发生),直到它被触摸操作删除-这就是启用“重复”功能的原因


根据按钮的实际行为及其所追求的onclick/ontouch,您可能希望毫不延迟地完成最初的post

这里是另一种方法,以防您使用普通视图单击。如果是这样,当您释放视图时,将调用click listener。因此,我利用长时间单击侦听器来完成第一部分

button.setOnLongClickListener(new OnLongClickListener() {

            private Handler mHandler;

            @Override
            public boolean onLongClick(View view) {
                final Runnable mAction = new Runnable() {
                    @Override
                    public void run() {
                        //do something here 
                        mHandler.postDelayed(this, 1000);
                    }
                };

                mHandler = new Handler();
                mHandler.postDelayed(mAction, 0);

                button.setOnTouchListener(new View.OnTouchListener() {

                    @SuppressLint("ClickableViewAccessibility")
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        switch (event.getAction()) {
                            case MotionEvent.ACTION_CANCEL:
                            case MotionEvent.ACTION_MOVE:
                            case MotionEvent.ACTION_UP:
                                if (mHandler == null) return true;
                                mHandler.removeCallbacks(mAction);
                                mHandler = null;
                                button.setOnTouchListener(null);
                                return false;
                        }
                        return false;
                    }

                });


                return true;
            }
        });

这是一个更独立的实现,可用于任何支持触摸事件的视图

import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;

/**
 * A class, that can be used as a TouchListener on any view (e.g. a Button).
 * It cyclically runs a clickListener, emulating keyboard-like behaviour. First
 * click is fired immediately, next one after the initialInterval, and subsequent
 * ones after the normalInterval.
 *
 * <p>Interval is scheduled after the onClick completes, so it has to run fast.
 * If it runs slow, it does not generate skipped onClicks. Can be rewritten to
 * achieve this.
 */
public class RepeatListener implements OnTouchListener {

    private Handler handler = new Handler();

    private int initialInterval;
    private final int normalInterval;
    private final OnClickListener clickListener;
    private View touchedView;

    private Runnable handlerRunnable = new Runnable() {
        @Override
        public void run() {
            if(touchedView.isEnabled()) {
                handler.postDelayed(this, normalInterval);
                clickListener.onClick(touchedView);
            } else {
                // if the view was disabled by the clickListener, remove the callback
                handler.removeCallbacks(handlerRunnable);
                touchedView.setPressed(false);
                touchedView = null;
            }
        }
    };

    /**
     * @param initialInterval The interval after first click event
     * @param normalInterval The interval after second and subsequent click 
     *       events
     * @param clickListener The OnClickListener, that will be called
     *       periodically
     */
    public RepeatListener(int initialInterval, int normalInterval, 
            OnClickListener clickListener) {
        if (clickListener == null)
            throw new IllegalArgumentException("null runnable");
        if (initialInterval < 0 || normalInterval < 0)
            throw new IllegalArgumentException("negative interval");

        this.initialInterval = initialInterval;
        this.normalInterval = normalInterval;
        this.clickListener = clickListener;
    }

    public boolean onTouch(View view, MotionEvent motionEvent) {
        switch (motionEvent.getAction()) {
        case MotionEvent.ACTION_DOWN:
            handler.removeCallbacks(handlerRunnable);
            handler.postDelayed(handlerRunnable, initialInterval);
            touchedView = view;
            touchedView.setPressed(true);
            clickListener.onClick(view);
            return true;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            handler.removeCallbacks(handlerRunnable);
            touchedView.setPressed(false);
            touchedView = null;
            return true;
        }

        return false;
    }

}

基于答案的兼容Kotlin版本和示例:

package com.kenargo.composite\u小部件
导入android.os.Handler
导入android.view.MotionEvent
导入android.view.view
导入android.view.view.OnTouchListener
/**
*一个类,可在任何视图(例如按钮)上用作TouchListener。
*它循环运行clickListener,模拟类似键盘的行为。弗斯特
*单击会立即触发,下一个在initialInterval之后触发,随后
*延迟后的一个。
*
*@param initialInterval首次单击事件后的间隔
*@param initialRepeat延迟第二次和后续单击事件后的间隔
*
*@param clickListener将调用的OnClickListener
*周期性
*
*间隔安排在onClick完成之后,因此它必须快速运行。
*如果运行缓慢,则不会生成跳过的onclick。可以重写为
*实现这一目标。
*
*用法:
*
*setOnTouchListener(新的RepeatListener(400100,新的OnClickListener)(){
*@覆盖
*公共void onClick(视图){
*//重复执行的代码
*  }
* }));
*
*科特林示例:
*setOnTouchListener(RepeatListener(defaultInitialTouchTime、defaultRepeatDelayTime、OnClickListener{
*//重复执行的代码
*  }))
*
*/
类RepeatListener(
初始间隔:Int,
initialRepeatDelay:Int,
clickListener:View.OnClickListener
):OnTouchListener{
private val handler=handler()
私有变量初始间隔:Int
私有变量initialRepeatDelay:Int
私有变量clickListener:View.OnClickListener
私有变量touchedView:视图?=null
初始化{
要求(!(initialInterval<0 | | initialRepeatDelay<0)){“不允许负间隔”}
this.initialInterval=initialRepeatDelay
this.initialRepeatDelay=初始间隔
this.clickListener=clickListener
}
private val handlerRunnable:Runnable=run{
可运行{
如果(touchedView!!.isEnabled){
handler.postDelayed(handlerRunnable,initialRepeatDelay.toLong())
clickListener.onClick(touchedView)
}否则{
//如果clickListener禁用了视图,请删除回调
handler.removeCallbacks(handlerRunnable)
touchedView!!.isPressed=false
touchedView=null
}
}
}
重写fun onTouch(视图:视图,运动事件:运动事件):布尔值{
何时(motionEvent.action){
MotionEvent.ACTION\u向下->{
handler.removeCallbacks(handlerRunnable)
handler.postDelayed(handlerRunnable,initialRepeatDelay.toLong())
touchedView=视图
touchedView!!.isPressed=true
单击Listener.onClick(视图)
返回真值
}
MotionEvent.ACTION\u向上,MotionEvent.ACTION\u取消->{
handler.removeCallbacks(handlerRunnable)
touchedView!!.isPressed=false
touchedView=null
返回真值
}
}
返回错误
}
}

但这是我的应用程序的需要。我想在用户按住按钮的同时不断移动光标。每次触摸都可以正常工作。我只想在用户按住按钮时重复操作。@JoxTraex:请在回答中详细说明您的观点,并查看它得到多少赞成票。如果我想在用户按住按钮5秒钟时做些额外的事,如何识别用户按住按钮5秒钟。您只需将另一个延迟的
Runnable
按到
处理程序上即可。如果它应该是一个
Button button = new Button(context);
button.setOnTouchListener(new RepeatListener(400, 100, new OnClickListener() {
  @Override
  public void onClick(View view) {
    // the code to execute repeatedly
  }
}));
package com.kenargo.compound_widgets

import android.os.Handler
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener

/**
 * A class, that can be used as a TouchListener on any view (e.g. a Button).
 * It cyclically runs a clickListener, emulating keyboard-like behaviour. First
 * click is fired immediately, next one after the initialInterval, and subsequent
 * ones after the initialRepeatDelay.
 *
 * @param initialInterval The interval after first click event
 * @param initialRepeatDelay The interval after second and subsequent click events
 *
 * @param clickListener The OnClickListener, that will be called
 * periodically
 *
 * Interval is scheduled after the onClick completes, so it has to run fast.
 * If it runs slow, it does not generate skipped onClicks. Can be rewritten to
 * achieve this.
 *
 * Usage:
 *
 * someView.setOnTouchListener(new RepeatListener(400, 100, new OnClickListener() {
 *  @Override
 *  public void onClick(View view) {
 *      // the code to execute repeatedly
 *  }
 * }));
 *
 * Kotlin example:
 *  someView.setOnTouchListener(RepeatListener(defaultInitialTouchTime, defaultRepeatDelayTime, OnClickListener {
 *      // the code to execute repeatedly
 *  }))
 *
 */
class RepeatListener(
    initialInterval: Int,
    initialRepeatDelay: Int,
    clickListener: View.OnClickListener
) : OnTouchListener {

    private val handler = Handler()

    private var initialInterval: Int
    private var initialRepeatDelay: Int

    private var clickListener: View.OnClickListener
    private var touchedView: View? = null

    init {
        require(!(initialInterval < 0 || initialRepeatDelay < 0)) { "negative intervals not allowed" }

        this.initialInterval = initialRepeatDelay
        this.initialRepeatDelay = initialInterval

        this.clickListener = clickListener
    }

    private val handlerRunnable: Runnable = run {
        Runnable {
            if (touchedView!!.isEnabled) {

                handler.postDelayed(handlerRunnable, initialRepeatDelay.toLong())
                clickListener.onClick(touchedView)
            } else {

                // if the view was disabled by the clickListener, remove the callback
                handler.removeCallbacks(handlerRunnable)
                touchedView!!.isPressed = false
                touchedView = null
            }
        }
    }

    override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {

        when (motionEvent.action) {
            MotionEvent.ACTION_DOWN -> {
                handler.removeCallbacks(handlerRunnable)
                handler.postDelayed(handlerRunnable, initialRepeatDelay.toLong())
                touchedView = view
                touchedView!!.isPressed = true
                clickListener.onClick(view)
                return true
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                handler.removeCallbacks(handlerRunnable)
                touchedView!!.isPressed = false
                touchedView = null
                return true
            }
        }

        return false
    }
}