【问题标题】:Android long-touch eventAndroid 长按事件
【发布时间】:2011-04-02 23:05:39
【问题描述】:

我有两个按钮,每次按下都会增加和减少一个值,并且它们与 onClickListener 一起工作得很好。我看到存在一个 onLongClickListener,我假设它是用于触摸和按住事件。如果按住按钮,我如何让数字快速增加/减少?

我是否正确假设 onLongClickListener 每次长按只触发一次?在我不知道的地方是否有更合适的监听器或属性?

【问题讨论】:

  • 尝试使用developer.android.com/reference/android/view/… 在ontouch 中,它会给你一个动作事件。您可以检查行动向下和行动向上。您实际上是在自己实现 on touch 和 onlongtouch
  • 我想要的只是一个 x-- 和一个 TextView.setText 每 200 毫秒左右,同时按住一个按钮。抱歉,我对 Java 没有那么丰富的经验,我的大部分经验都是 ASP/PHP 类型的东西,没有太多的交互性。如果有人可能有示例代码或者可以向我指出正确的方法,我将不胜感激,我什至不知道从哪里开始。
  • 使用 Handler.sendDelayedMessage() 每 x 毫秒向自己发送一条消息,直到您收到 up 事件。

标签: java android listener


【解决方案1】:

你可以按照下面的代码来实现它。

package org.me.rapidchange;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.TextView;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends Activity implements OnKeyListener, 
        OnTouchListener, OnClickListener {
    private class UpdateCounterTask implements Runnable {
        private boolean mInc;

        public UpdateCounterTask(boolean inc) {
            mInc = inc;
        }

        public void run() {
            if (mInc) {
                mHandler.sendEmptyMessage(MSG_INC);
            } else {
                mHandler.sendEmptyMessage(MSG_DEC);
            }
        }
    }

    private static final int MSG_INC = 0;
    private static final int MSG_DEC = 1;

    private Button mIncButton;
    private Button mDecButton;
    private TextView mText;
    private int mCounter;

    private Handler mHandler;
    private ScheduledExecutorService mUpdater;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_INC:
                        inc();
                        return;
                    case MSG_DEC:
                        dec();
                        return;
                }
                super.handleMessage(msg);
            }
        };
        mIncButton = (Button) findViewById(R.id.inc_button);
        mDecButton = (Button) findViewById(R.id.dec_button);
        mText = (TextView) findViewById(R.id.text);
        mIncButton.setOnTouchListener(this);
        mIncButton.setOnKeyListener(this);
        mIncButton.setOnClickListener(this);
        mDecButton.setOnTouchListener(this);
        mDecButton.setOnKeyListener(this);
        mDecButton.setOnClickListener(this);
    }

    private void inc() {
        mCounter++;
        mText.setText(Integer.toString(mCounter));
    }

    private void dec() {
        mCounter--;
        mText.setText(Integer.toString(mCounter));
    }

    private void startUpdating(boolean inc) {
        if (mUpdater != null) {
            Log.e(getClass().getSimpleName(), "Another executor is still active");
            return;
        }
        mUpdater = Executors.newSingleThreadScheduledExecutor();
        mUpdater.scheduleAtFixedRate(new UpdateCounterTask(inc), 200, 200,
                TimeUnit.MILLISECONDS);
    }

    private void stopUpdating() {
        mUpdater.shutdownNow();
        mUpdater = null;
    }

    public void onClick(View v) {
        if (mUpdater == null) {
            if (v == mIncButton) {
                inc();
            } else {
                dec();
            }
        }
    }

    public boolean onKey(View v, int keyCode, KeyEvent event) {
        boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER;
        boolean isReleased = event.getAction() == KeyEvent.ACTION_UP;
        boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN
                && event.getAction() != KeyEvent.ACTION_MULTIPLE;

        if (isKeyOfInterest && isReleased) {
            stopUpdating();
        } else if (isKeyOfInterest && isPressed) {
            startUpdating(v == mIncButton);
        }
        return false;
    }

    public boolean onTouch(View v, MotionEvent event) {
        boolean isReleased = event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL;
        boolean isPressed = event.getAction() == MotionEvent.ACTION_DOWN;

        if (isReleased) {
            stopUpdating();
        } else if (isPressed) {
            startUpdating(v == mIncButton);
        }
        return false;
    }
}

【讨论】:

  • 这非常有效,我想我什至理解它是如何工作的,哈哈。谢谢!
【解决方案2】:

我有同样的目标,最终使用 OnLongClick 来捕获向下部分以通过处理程序启动重复事件,然后使用正常的 OnClick 来捕获释放并停止它。对我来说效果很好。

mOngoingRunnable = new Runnable() {
    public void run() {
        // do stuff
        mHandler.postDelayed(mOngoingRunnable, delayMsecs);
    }
};

public boolean onLongClick(View view) {
    mHandler.post(mOngoingRunnable);
    mOngoing = true;
    return false;
}

public void onClick(View view) {
    if (mOngoing) {
        mHandler.removeCallbacks(mOngoingRunnable);
        mOngoing = false;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多