2013-03-06 10 views
9

Mam usługę, która uruchamia nakładkę systemową. Kiedy nakładka jest widoczna, chcę, aby była dotykalna/wykrywa dotyk, ale chcę zachować interakcję z ekranem za nią (z tyłu mam na myśli podstawowe działanie, na przykład obok nakładki).Dlaczego nakładka systemu przechwytuje wszystkie dotknięcia (nie jest możliwa interakcja z widokiem podstawowym)

Moja nakładka to bitmapa/PNG o wymiarach 128x128px. Zostaje narysowany, a kiedy go klikam, otrzymuję TOUCH! log, co jest dobre. Ale kiedy kliknę na inną część ekranu (oprócz nakładki) otrzymuję DOTYKĘ! log i brak interakcji z ekranem pod nim jest możliwe.

Oto części mojego kodu:

główny przedmiot, aby uruchomić usługę

buttonStart.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // start Service and return to Homescreen 
       Intent i = new Intent(MainActivity.this, MyService.class); 
       startService(i);     

       Intent newActivity = new Intent(Intent.ACTION_MAIN); 
       newActivity.addCategory(Intent.CATEGORY_HOME); 
       newActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
       startActivity(newActivity); 
      } 
     }); 

życzenie/Pokaż nakładki

@Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     myOverlay = new Overlay(MyService.this); 

     WindowManager.LayoutParams params = new WindowManager.LayoutParams(
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 
       WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
       WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
       PixelFormat.TRANSLUCENT); 
     params.gravity = Gravity.LEFT | Gravity.TOP; 

     wm = (WindowManager) getSystemService(WINDOW_SERVICE); 
     wm.addView(myOverlay, params); 

     myOverlay.setAnimation(new Waiting(MyService.this, 0, 0)); 
     myOverlay.postInvalidate(); 

     return super.onStartCommand(intent, flags, startId); 
    } 

Overlay

public MyOverlay(Context context) { 
     super(context);  
     this.context = context; 

     setOnTouchListener(new OnTouchListener() { 

      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       Log.i("TOUCH!", event.getAction() + ", x:"+event.getX()+", y:"+event.getY()); 
       return false; 
      } 
     }); 
    } 

Co robię źle? Wypróbowałem również WindowManager.LayoutParams.TYPE_PHONE zamiast WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, ale to samo zachowanie.

Nie używam flagi FLAG_WATCH_OUTSIDE_TOUCH, więc dlaczego akcenty nie są zarejestrowane obok nakładki?

EDIT

Wydaje Znalazłem problem, ale nadal nie wiem jak go rozwiązać chociaż ... Wyświetlany obraz w nakładce jest bardzo małe i nie ma problemu, ale (!) sama nakładka jest pełny ekran

dodałem następujący raport do nakładka/onTouch() imprezy:

Log.i("TOUCH!", "View: "+v.toString() +", size="+ v.getWidth()+"/"+v.getHeight()); 

które potem mówi mi Widok: package.overlay.myOverlay, size = 480/762

Teraz starałem się go zmusić, by nie być pełny ekran, dodając następujący wiersz w Serwisie:

@Override 
     public int onStartCommand(Intent intent, int flags, int startId) { 

      myOverlay = new Overlay(MyService.this); 
//HERE 
myOVerlay.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 

      WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT, 
        WindowManager.LayoutParams.WRAP_CONTENT, 
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
        PixelFormat.TRANSLUCENT); 
      params.gravity = Gravity.LEFT | Gravity.TOP; 

      wm = (WindowManager) getSystemService(WINDOW_SERVICE); 
      wm.addView(myOverlay, params); 

      myOverlay.setAnimation(new Waiting(MyService.this, 0, 0)); 
      myOverlay.postInvalidate(); 

      return super.onStartCommand(intent, flags, startId); 
     } 

Ale to nie pomaga ... nadal myOverlay ma rozmiar 480x762 ... Dlaczego jest tak duży i jak mogę go uzyskać, żeby miał rozmiar zawartego obrazu?

+1

Jak duża jest twoja nakładka? Czy obejmuje on cały podstawowy układ? Czy to przejrzysta rzecz? – abbath

+1

"ale chcę zachować interakcję z ekranem za nim" - na szczęście nie jest to już możliwe od Androida 4.0.3, aby zapobiec atakom typu "tapjacking", przynajmniej w przypadku dotknięć samej nakładki. Nakładka może odbierać zdarzenia dotykowe (i te nie są przesyłane dalej) lub nie otrzymywać zdarzeń dotyku (w rodzaju "Toast"). – CommonsWare

+0

@abbath Jest to mapa bitowa o wymiarach 128x128 px narysowana na płótnie. Ma przezroczyste tło, tak, co oznacza, że ​​powinienem sprawić, że będzie nieprzejrzysty, aby sprawdzić, czy to naprawdę tak małe ... wypróbuję to. –

Odpowiedz

-2

miałem ten sam problem, po prostu spróbuj dodać to do Twojego kodu:

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY 

jestem całkiem pewny, że kod będzie działać, jeśli nie po prostu sprawdzić kod dla niektórych innych błędów, ale jeśli chodzi o dotyk, to jest to twoje rozwiązanie. W każdym razie daj mi znać. i prawie zapomniałem drugiej części, po prostu zmień atrybuty na matchparent zamiast wrapcontent.

Powodzenia

+0

Myślę, że jest to przeciwieństwo tego, co chciał OP, dzięki temu widok pochłania wszystkie kliknięcia. – marmor

+1

@marmor, w najnowszych wersjach Androida, okna 'TYPE_SYSTEM_OVERLAY' nie mogą odbierać zdarzeń dotyku. – Sam

2

miałem również ten sam problem i rozwiązać ten problem, należy ustawić params.width & params.height. Wypróbuj to.

params.width = 128; 
params.height = 128; 

Mam nadzieję, że to pomoże.

8

Ten pracował dla mnie:

WindowManager.LayoutParams params = new WindowManager.LayoutParams(); 
params.height = WindowManager.LayoutParams.WRAP_CONTENT; 
params.width = WindowManager.LayoutParams.WRAP_CONTENT; 
params.type = WindowManager.LayoutParams.TYPE_TOAST; 
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 
    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 
    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 

użyć tej LayoutParams podczas dodawania View do WindowManager, to uniemożliwia jej uzyskaniem kliknięć, to możliwe, że TYPE_TOAST jest wystarczająca, ale dodałem flagi tylko do Upewnić się.

Powiązane problemy