11

我希望我的应用程序对音量按钮的正常和长按按键事件做出不同的反应。

我已经看到了这个,但是如果我按住音量按钮,我会KeyDown在收到事件之前收到很多KeyLongPressed事件。

我想要一个事件或另一个事件,而不是两者,这样我可以在短按时调整音量并在长按时跳过曲目。

你能帮帮我吗?

这是我的代码:

    @Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) 
    {
        Log.d("Test", "Long press!");
        return true;
    }
    return super.onKeyLongPress(keyCode, event);
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        event.startTracking();
        Log.d("Test", "Short");
        return true;
    }

    return super.onKeyDown(keyCode, event);
}

任何帮助表示赞赏!- 鸢尾花

4

4 回答 4

15

这是我写的代码。它就像一个魅力。也许你可以优化它以获得更好的逻辑。但你会明白的。关键是使用标志。短按是我们短按音量按钮并释放的按。所以onKeyUp可以帮助我们检测短按。

package com.example.demo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;

public class TestVolumeActivity extends Activity {
    boolean flag = false;

    boolean flag2 = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_splash_screen, menu);
        return true;
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            Log.d("Test", "Long press!");
            flag = false;
            flag2 = true;
            return true;
        }
        return super.onKeyLongPress(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            event.startTracking();
            if (flag2 == true) {
                flag = false;
            } else {
                flag = true;
                flag2 = false;
            }

            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {

            event.startTracking();
            if (flag) {
                Log.d("Test", "Short");
            }
            flag = true;
            flag2 = false;
            return true;
        }

        return super.onKeyUp(keyCode, event);
    }
}

所有长按的Logcat(未检测到短按):

10-18 02:06:15.369: D/Test(16834): Long press!
10-18 02:06:18.683: D/Test(16834): Long press!
10-18 02:06:21.566: D/Test(16834): Long press!
10-18 02:06:23.738: D/Test(16834): Long press!

适用于所有短按的 Logcat:

10-18 02:07:42.422: D/Test(16834): Short
10-18 02:07:43.203: D/Test(16834): Short
10-18 02:07:43.663: D/Test(16834): Short
10-18 02:07:44.144: D/Test(16834): Short
于 2012-10-18T09:05:07.277 回答
9

根据 SDK 处理长按按钮的正确方法。

import android.app.Activity;
import android.util.Log;
import android.view.KeyEvent;


public class TestVolumeActivity extends Activity
{
    private static final String TAG = TestVolumeActivity.class.getSimpleName();

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if( keyCode == KeyEvent.KEYCODE_VOLUME_UP || 
            keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
        {
            event.startTracking();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event)
    {
        if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
            Log.d(TAG, "Long press KEYCODE_VOLUME_UP");
            return true;
        }
        else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
            Log.d(TAG, "Long press KEYCODE_VOLUME_DOWN");
            return true;
        }
        return super.onKeyLongPress(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event)
    {
        if((event.getFlags() & KeyEvent.FLAG_CANCELED_LONG_PRESS) == 0){
            if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
                Log.e(TAG, "Short press KEYCODE_VOLUME_UP");
                return true;
            }
            else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
                Log.e(TAG, "Short press KEYCODE_VOLUME_DOWN");
                return true;
            }
        }
        return super.onKeyUp(keyCode, event);
    }
}
于 2013-09-14T07:30:44.460 回答
4

当我正要发布我的答案时,我发现有人已经有了某种解决方案....

但这是我的,简单,就像一个魅力。只有一个标志;)

此代码检测短按和长按,当长按发生时不会触发短按!

注意:如果您想要正常的音量上下行为,请将 onKeyPress 方法中的 return true 更改为 super 调用,如下所示:

event.startTracking();
if(event.getRepeatCount() == 0){
    shortPress = true;
}
//return true;
return super.onKeyDown(keyCode, event);

没有超级调用的代码:

private boolean shortPress = false;

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        shortPress = false;
        Toast.makeText(this, "longPress", Toast.LENGTH_LONG).show();
        return true;
    }
    //Just return false because the super call does always the same (returning false)
    return false;
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        if(event.getAction() == KeyEvent.ACTION_DOWN){
            event.startTracking();
            if(event.getRepeatCount() == 0){
                shortPress = true;
            }
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        if(shortPress){
            Toast.makeText(this, "shortPress", Toast.LENGTH_LONG).show();
        } else {
            //Don't handle longpress here, because the user will have to get his finger back up first
        }
        shortPress = false;
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

此处的代码是添加了音量增大键,只需选择您的一边;)

private boolean shortPress = false;

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        shortPress = false;
        Toast.makeText(this, "longPress Volume Down", Toast.LENGTH_LONG).show();
        return true;
    } else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
        shortPress = false;
        Toast.makeText(this, "longPress Volume Up", Toast.LENGTH_LONG).show();
        return true;
    }
    //Just return false because the super call does always the same (returning false)
    return false;
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
        if(event.getAction() == KeyEvent.ACTION_DOWN){
            event.startTracking();
            if(event.getRepeatCount() == 0){
                shortPress = true;
            }
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        if(shortPress){
            Toast.makeText(this, "shortPress Volume Down", Toast.LENGTH_LONG).show();
        } else {
            //Don't handle longpress here, because the user will have to get his finger back up first
        }
        shortPress = false;
        return true;
    } else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
        if(shortPress){
            Toast.makeText(this, "shortPress Volume up", Toast.LENGTH_LONG).show();
        } else {
            //Don't handle longpress here, because the user will have to get his finger back up first
        }
        shortPress = false;
        return true;

    }
    return super.onKeyUp(keyCode, event);
}
于 2012-10-18T09:20:33.770 回答
0

我不知道这个答案是否会为您的问题提供可接受的解决方案,因为它依赖于不断获取频繁 KeyDown的事件。

您可以尝试记住引发最后一个事件的系统时间KeyDown(我将命名它tLast),并忽略所有KeyDown事件,直到您收到一个KeyLongPressed事件。

为了获得“正确的”KeyDown事件(您在上一步中忽略的事件),您可以有一个线程检查当前系统时间和tLast(我将命名它tDelta)之间的时间差是否足够大,以免被认为是一个连续的新闻。

鉴于KeyDown在短时间内抛出了很多事件,您理论上可以确定当事件间隔足够时(tDelta大于固定值)时没有连续按下音量按钮。

该解决方案的缺点是,如果用户真的快速按下音量按钮(tDelta两次按下之间低于用于评估连续按下的固定值),则多次按键将被忽略/视为连续按键.

另一个(次要)缺点是在解释常规按键之前会有延迟,因为tDelta它必须大于在评估您是否正在处理常规或连续按键时使用的固定值。

问候,

卢西安

编辑:嗯......第二个想法:你不是在使用KeyListenerAndroid实现吗?

如果您正在使用它,请查看onKeyUp为此定义的方法。

我认为如果你只是扩展这个类(或它的派生类之一)并使用该onKeyUp方法来确定你是否正在处理连续按下(即按下按钮的时间大于一个固定值)。

如果您可以使用此方法,请执行此操作。它也比上面介绍的解决方法更有效、更容易维护和更直接。

KeyListener Javadoc

于 2012-10-18T08:47:48.817 回答