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 に答える
4

回答を投稿しようとしたとき、誰かがすでに何らかの解決策を持っていることがわかりました....

しかし、これが私のもので、シンプルで魅力的です。フラグは 1 つだけです ;)

このコードは、ショートプレスとロングプレスを検出します。ロングプレスが発生すると、ショートプレスは起動されません!

注:通常の音量の上下動作が必要な場合は、次のように onKeyPress メソッドで 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すべてのイベントを無視することができます。KeyDownKeyLongPressed

「正しい」イベント (前のステップで無視したもの) を取得するために、現在のシステム時刻と(名前を付けます)KeyDownとの時差が十分に大きいかどうかをチェックするスレッドを持つことができます。連続プレスと見なされます。tLasttDelta

KeyDown短期間に多くのイベントがスローされることを考えると、理論的には、イベントの間隔が十分にある場合 (tDeltaが固定値より大きい場合)、音量ボタンが連続して押されていないと判断できます。

このソリューションの欠点は、ユーザーが音量ボタンを非常に速く押した場合 (tDeltaプレス間の間隔が連続プレスを評価するために使用される固定値よりも低い場合)、複数のキープレスが無視されるか、連続キープレスと見なされることです。 .

もう 1 つの (マイナーな) 欠点は、通常のキー押下を解釈する前に遅延が発生することです。これは、通常のキー押下tDeltaを処理しているか、連続したキー押下を処理しているかを評価するときに使用される固定値よりも大きくする必要があるためです。

よろしく、

ルシアン

編集: うーん... 考え直し: KeyListenerAndroid 実装を使用していませんか?

onKeyUpこれを使用している場合は、このために定義されたメソッドを確認してください。

このクラス (またはその派生クラスの 1 つ) を拡張し、このonKeyUpメソッドを使用して連続プレスを処理しているかどうかを判断すると (つまり、ボタンが押されている時間が固定値)。

この方法が使える方は是非やってみてください。また、上記の回避策よりも効率的で、保守が容易で、簡単です。

KeyListener Javadoc

于 2012-10-18T08:47:48.817 に答える