WindowManager не позволяет передавать касание

Я нарисовал наложение с помощью WindowManager. его ширина и высота WindowManager.LayoutParams.MATCH_PARENT с прозрачным фоном.

Мое представление должно совпадать с родительским элементом и обрабатывать прослушиватель касаний круга, а остальные касания должны передаваться на экран ниже

У меня два маленьких circle in left and right corner. Я делаю их перетаскиваемыми на экран, и это работает нормально. Но когда я нажимаю на видимую кнопку «Главный экран». WindowManager не позволяет щелкать видимый элемент.

        int LAYOUT_FLAG = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.
                LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE;

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,//changed it to full
                WindowManager.LayoutParams.MATCH_PARENT,
                LAYOUT_FLAG,

                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                |WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                ///| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, this flag can make it in touchable.
                ///WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                PixelFormat.TRANSLUCENT);

        mFloatingView = LayoutInflater.from(this).inflate(R.layout.item_circle_dragging, null);

        mFloatingView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return false;
            }
        });
        //Add the view to the window
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mFloatingView,params);

item_circle_drabbing.xml

<?xml version="1.0" encoding="utf-8"?>
<customviewpracticing.CircleDraggingView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</customviewpracticing.CircleDraggingView>

CircleDragginView onTouchEvent

@Override
public boolean onTouchEvent(MotionEvent event) {

   switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
          if(isPointInside(event.getRawX(),event.getRawY()))
            isAllowedToDrag = true;
          Log.d(TAG, "ACTION_DOWN:getRawX= " + event.getRawX() + " getRawY= " + event.getRawY() + " getX= "
                + event.getX() + " getY= " + event.getY());
          break;
        ///return true;
      case MotionEvent.ACTION_MOVE:
          Log.d(TAG, "ACTION_MOVE:getRawX= " + event.getRawX() + " getRawY= " + event.getRawY() + " getX= "
                + event.getX() + " getY= " + event.getY());
          if(isAllowedToDrag){
            center_circle_X = event.getRawX() ;
            center_circle_Y = event.getRawY();
            }/*this.animate().x(event.getRawX()).y(event.getRawY())
                    .setDuration(50).start();*/
          break;
      case MotionEvent.ACTION_UP:
         if(isAllowedToDrag)
            isAllowedToDrag = false;
         break;
      default:
        return true;//I changed it
   }
    // Force a view to draw again
    ///postInvalidate();
    invalidate();
    return true;
}

Также пытался возвратить false в onTouchEvent из CircleDraggingView, а также в основной mFloatingView (Root View).


person AndroidGeek    schedule 20.08.2018    source источник
comment
Удачи с этим?   -  person Aswin P Ashok    schedule 22.10.2018
comment
Любая удача в этом?   -  person Akash    schedule 17.07.2019
comment
любой ответ? у меня тоже такая же проблема   -  person limonik    schedule 20.04.2020
comment
Вы должны добавить два разных вида в оконный менеджер, один из них (который) покрывает весь экран, а другой - сенсорный круг (если есть 2 круга, вам нужно 3 вида), и после любого изменения вашего круга вы также следует обновить другое представление (которое охватывает весь экран)   -  person Amin    schedule 20.04.2021


Ответы (1)


Боюсь, вы не можете сделать это в том же представлении, потому что событие касания либо входит в ваше представление, либо нет. Используете ли вы перехват, возвращаете false и т. д. Все это зависит от того, действительно ли событие достигает вашего представления, и даже в этом случае возврат false не приведет к передаче события на экран ниже, потому что это разные процессы. В вашем случае событие не достигло бы вашего окна, а это означало бы, что вы вообще не можете его обработать.

Я не совсем уверен, что делает родитель, я полагаю, что вы пытаетесь переместить круговое представление сюда после прикосновения к нему с помощью операции перетаскивания или чего-то еще. Итак, я приведу пример того, как вы можете это сделать.

Добавление вида в левом и правом углу можно указать в параметрах макета, которые вы создаете. Например, верхний левый будет выглядеть так:

params.x = 0;
paramx.y = 0;

Верхний правый будет выглядеть так:

WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

Point size = new Point();

// Get the screen dimensions here
manager.getDefaultDisplay().getSize(point);
int screenWidth = point.x;

// Assuming your view has a 40 dp width and height,
// calculate its pixel variant
int circleWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DP, 40, getResources().getDisplayMetrics());

// Target the top-right corner of the screen.
params.x = screenWidth - circleWidth;

// Y coordinate would be 0.
params.y = 0;

И параметры просмотра будут выглядеть так:

// Assuming your view has a 40 dp width and height,
// calculate its pixel variant
int circleSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DP, 40, getResources().getDisplayMetrics());

WindowManager.LayoutParams params = new WindowManager.LayoutParams(circleSize /* width */, 
circleSize /* height */,
 0 /* x */,
 0 /* y */,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY /* windowType */,
 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH /* outsideTouch */,
 PixelFormat.TRANSLUCENT /* format */);

После этого перемещение представления фактически потребует изменения параметров макета и обновления макета представления. В вашем onTouchEvent вы можете сделать что-то вроде этого:

// Assuming you know the new x and y values of the view, you can
// update the layout params of the view like this:
((WindowManager.LayoutParams) getLayoutParams()).x = targetX;
((WindowManager.LayoutParams) getLayoutParams()).y = targetY;

// To update the view, you need to either call requestLayout() or
// do it from window manager directly.

// If the first way doesn't work, 2nd will work.

// First way:
requestLayout();

// Second way:

// This will get the same window manager the service has.
WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);

// Update the view layout afterwards.
manager.updateViewLayout(this, getLayoutParams());

Таким образом, вы можете перемещать представление с помощью сенсорного события.

Пара вещей, на которые следует обратить внимание:

  1. Если вы можете зафиксировать onTouchEvent, вы знаете, что коснулись круга, поэтому вам не нужно выполнять проверку координат, используя необработанные значения (я имею в виду функцию isPointInside()). Возврат true для всех из них поможет вам получить все события, но это не обязательно. Вы, вероятно, знаете, как работает жизненный цикл.
  2. Каждый круг должен быть добавлен в оконный менеджер как root с WindowManager.addView(), чтобы касания не мешали друг другу, а касание точки, в которой нет круга, приведет к передаче события на экран ниже.

Это было бы началом для вашего требования, и я думаю, что вы можете соответствовать этим вашим потребностям.

person Furkan Yurdakul    schedule 19.04.2021