web-dev-qa-db-ja.com

Androidオーバーレイですべてのタッチを取得して渡しますか?

私は基本的に、システムオーバーレイのようなものからすべてのタッチイベントデータを取得し、このタッチデータに基づいてスプライトを移動し、OS/homescreen/browserが必要に応じてデータを操作できるようにします(またはその逆)。私は同様の質問を見つけましたが、私がまだ行ったことのない場所に私を導くものは何もありません:

すべてのタッチイベントを受け取っているビューを取得する

(実装、結果は以下) システムオーバーレイウィンドウを作成する(常に上部に表示)

私にできること:

私はすべてのタッチイベントを取得し、スプライトを移動してOS/homescreen/browserにそれらを表示させないようにアクションを実行できますOR ELSEタッチイベントの通過を許可できます私のアプリが動作するための「TOUCH_OUTSIDE」のみを取得します。

私の未達成の目標:

私の人生では、両方でデータを処理する方法を理解できません。私が考えることができる、実装できない唯一の方法は、APPのデータをインターセプトしてOS/homescreen/browserに渡し、OS/homescreen/browserが最初にデータを取得できるようにし、次に何らかの方法で情報を含むコールバックを取得するOS/homescreen/browserがデータを取得し、データを操作し、スクロール/位置の値をポーリングして、私のAPPでそれを操作できるようにします。

私はこれが不可能であるのではないかと心配しています。ドキュメントのどこかで今は見つけられないところを読んだと思います。「それはすべてか、何でもない。ビューはすべてのイベントを取得するか、まったく取得しない」

(混乱を避けるために、2つのビューがあることを意味するわけではありません。つまり、OS /ホームスクリーン/ブラウザーをオーバーレイするアクティビティ/サービスによって制御される1つのビューがあることを意味します。ガラスのペインのように。)

あなたが提供できる有用な情報をありがとう、それは非常に感謝しています!

[更新]混乱しないように、以下の問題について自分のドキュメントを投稿しました。

24
While-E

両方を行うことは不可能であるとほとんど述べているこのドキュメントを見つけました: Android:マルチタッチとTYPE_SYSTEM_OVERLAY

彼らは回避策について話し合っていますが、実際に私がやろうとしていることでうまくいくとは思えません。どちらも基になるアプリにイベントを与え、自分のために行動するためにそれらをスヌープすることができました。

オーバーレイビューを作成するには、LayoutParamsを設定するときに、タイプをTYPE_SYSTEM_OVERLAYに設定し、フラグFLAG_WATCH_OUTSIDE_TOUCHを使用する必要があります。 Androidのドキュメンテーションに記載されているように、これは問題を示します:「完全な下/移動/上ジェスチャーを受信せず、最初のダウンの位置のみをACTION_OUTSIDEとして受信します。」 TYPE_SYSTEM_ALERTタイプを使用するために必要なタッチイベントの完全な配列ですが、これによりオーバーレイが画面を引き継ぎ、他の要素との相互作用を停止します。

誰もが私が良い知らせを聞いてみたいと思います:-D

16
While-E

GestureOverlayViewを使用できます。描画する線を非表示にする場合は、色を透明#00000000に設定して表示されないようにし、すべてのタッチとジェスチャーをキャプチャできます。

http://developer.Android.com/resources/articles/gestures.html

2
emalamisura

同じものを探していました。

このフラグは私のためのトリックFLAG_NOT_TOUCH_MODAL

Android 7および8の設定で以下のように動作します。

これまでに実装した唯一のアクションは、オーバーレイウィンドウを閉じるタッチです。

また、ここからコードを使用しました Githubのシステムオーバーレイコードの例 イベントを取得するために必要でした。

ちなみに、Googleマップは、Android 8.でこれを使用して、本当に素晴らしい仕事をしています。オーバーレイウィンドウをドラッグしたり、サイズを変更したり、閉じたりすることができます。他のすべてのアプリは、起動中に問題なく動作します。

    var type = 0

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
    {
        type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    {
        type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
    }

    var flags = FLAG_NOT_TOUCH_MODAL

    mOverlayLayoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, type, flags, PixelFormat.TRANSLUCENT)
1
mswlogo

これは最適なソリューションではありませんが、機能します。タッチできないフラグを切り替えてサービスを再起動します。前の状態トグル値を決定するためにサービスを開始するために使用されるIntentにブール値を追加します。より良い実装は、ウィンドウがリスニングしているときはタッチで、リスニングしていないときは一定期間後にインテントを発火することです。

public class bleh extends Service {
    public void onCteqwer(int i) {

        Context context; Class <bleh> context1 = bleh.class;

        WindowManager.LayoutParams params = null;
        WindowManager mang = (WindowManager) getSystemService(WINDOW_SERVICE);

        //check previous state of service
        if(i==0)
            params = new WindowManager.LayoutParams(arg0,arg1,arg2,arg3,arg4,arg5);

        if(i==1)
            params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,arg0,arg1,arg2,arg3,arg4);

        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        View mViw = inflater.inflate(arg, null);

        mViw.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

        mang.addView(mViw, params);

        Intent z = new Intent(context, context1);

        if(i==0)
            z.putExtra("name", 1);
        if(i==1)
            z.putExtra("name", 0);

        stopSelf();
        startService(z);
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Bundle i=intent.getExtras();
        int userName = 0;

        if (i != null)
        {
            userName = i.getInt("name");
            onCteqwer(userName);
        }
    }
}
0
Rico