2012-06-01 11 views
26

WzywamonTouchEvent() nie zostanie uruchomiony, jeżeli setSystemUiVisibility (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) jest wywoływana

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) 

kiedy moja aplikacja uruchamia się, aby moja aplikacja może wyświetlić na pełnym ekranie.

Chcę, aby interfejs mojej aplikacji pojawił się po dotknięciu ekranu, ale Activity.onTouchEvent() nie zostanie wyzwolony, dopóki ekran nie zostanie dotknięty po raz drugi. Przy pierwszym dotknięciu wyświetlane są tylko klawisze wirtualne.

Więc muszę wywołać mojej aplikacji UI do pop-up na

public void onSystemUiVisibilityChange(int visibility) { 
    if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) { 
     // show my APP UI 
    } 
} 

ale onSystemUiVisibilityChange z View.SYSTEM_UI_FLAG_VISIBLE zostanie wywołany nie raz za touch (3 razy na moim Galaxy Nexus) przez system, zwłaszcza jeśli użytkownik dotyka ekranu bardzo szybko/często.

projekt lib 4.0 lub 4.03. Samsung Galaxy (9250) z 4.03.

+0

Mogę również potwierdzić, że to się dzieje. Pluskwa? – dell116

+0

zrobiłeś to jako usługę? –

+0

Ja też. Nie mogę używać gestów w moim widoku wideo. –

Odpowiedz

0

Czy próbowałeś dodać kod, aby wyświetlał swój interfejs tylko po zmianie stanu? Trzeba zachować ostatnią znaną widoczność i tylko pokazać swoje UI przy pierwszym powstają widoczne: próbka

int mLastSystemUiVis; 

@Override 
public void onSystemUiVisibilityChange(int visibility) { 
    int diff = mLastSystemUiVis^visibility; 
    mLastSystemUiVis = visibility; 
    if ((diff&SYSTEM_UI_FLAG_VISIBLE) != 0 
      && (visibility&SYSTEM_UI_FLAG_VISIBLE) == 0) { 
     // DISPLAY YOUR UI 
    } 
} 

Kod przyjęty z Android docs

+0

Nie sądzę, że zrozumiałeś problem. To nie rozwiązuje zadanego pytania. – peedee

-1

Metoda Activity.onTouchEvent() jest wywoływana na koniec łańcucha respondenta (czyli po tym, jak wszystkie inne poglądy miały szansę pochłonąć to wydarzenie). Jeśli dotkniesz widoku, który jest zainteresowany dotykiem (np. Button lub EditText), istnieje duża szansa, że ​​Twoja aktywność nigdy nie zobaczy tego wydarzenia.

Jeżeli chcesz mieć dostęp do detali zanim każdy uzyskać wysyłane do widoku (ów), zastępują Activity.dispatchTouchEvent() zamiast tego, który jest metoda zwana w zaczynają łańcucha zdarzeń:

@Override 
public boolean dispatchTouchEvent(MotionEvent event) { 
    //Check the event and do magic here, such as... 
    if (event.getAction() == MotionEvent.ACTION_DOWN) { 

    } 

    //Be careful not to override the return unless necessary 
    return super.dispatchTouchEvent(event); 
} 

Uważaj, aby nie zastąpić wartości zwracanej przez tę metodę, chyba że celowo chcesz wykraść elementy dotykowe z pozostałych widoków, niepotrzebny return true; w tym miejscu przerwie inne operacje dotykowe.

+0

Niestety, to nie działa. – user1256821

+0

Ten koncepcyjnie poprawny i dobry do zapamiętania ogólnie, ale zawodzi w tym konkretnym problemie. Funkcja dispatchTouchEvent również nie została wywołana przy pierwszym dotknięciu, gdy próbowałem. – peedee

0

Miałem bardzo podobny problem z próbą aktualizacji interfejsu użytkownika z onTouchEvent() wymagającym dwóch dotknięć do pracy, a ja spróbowałem kilku skomplikowanych rzeczy, zanim w końcu udało mi się go uruchomić przy pierwszym kliknięciu.

W moim przypadku pokazywałem poprzednio ukryty przedmiot, a następnie jego wysokość, a następnie przesunięcie przycisku o tę wysokość. Problemem, który napotkaliśmy, było to, że wysokość była wyświetlana jako 0 do momentu zakończenia pierwszego zdarzenia dotyku. Byłem w stanie rozwiązać ten problem, wywołując show() podczas ACTION_UP dla onTouchEvent() zamiast jego ACTION_DOWN.Może to by działało, gdybyś zrobił coś podobnego?

+0

To nie działa, jeśli potrzebujesz pozycji pierwszego ACTION_DOWN. – peedee

0

spróbuje użyć:

getWindow() getDecorView() setSystemUiVisibility (View.GONE);..

zamiast:

getWindow() getDecorView() setSystemUiVisibility (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)

Po tym można użyć normalnej aktywności w pełnym ekranie i jeśli chcesz klucze nav trzeba przesunąć palcem od dołu do.. w górę. Praca dla mnie w Galaxy Tab 2 z Androidem 4.1.2

1

ta nie działa dla mnie:

setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { 
     @Override 
     public void onSystemUiVisibilityChange(int visibility) { 
      if ((visibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { 
       // show my app UI 
      } 
     } 
    }); 
+1

jak to pomaga reagować na pierwsze zdarzenie dotykowe opisane w pytaniu? – peedee

1

Co robiłem to pierwszy importowany android.view.GestureDetector więc można go używać do wykrywania gestów. Android ma wiele domyślnych gestów, które są automatycznie wykrywane w GestureDector class. Większość z tych informacji znajduje się pod numerem here, ale poniżej jest kod w formie, którą użyłem w rzeczywistym projekcie, który działa.

Najpierw zrobiłem anonimową klasę w mojej Działalności (może to być zagnieżdżone gdziekolwiek, ale mam tendencję do tworzenia moich anonimowych klas na dole, tuż przed nawiasem zamykającym). UWAGA: Możesz również zaimplementować OnGestureListener jako część swojej klasy.

Poniższy kod służy do korzystania z funkcji wykrywania gestów w celu prostego ukrywania/pokazywania.

Ogłosiłem i zdefiniowałem pasek działań (mój UI, który jest początkowo ukryty) jako zmienną instancji, więc mogę uzyskać do niego dostęp tutaj i gdziekolwiek indziej, ale można go zastąpić getActionBar().show() i getActionBar().hide() w przypadku nie chcesz zadeklarować go jako zmiennej instancji. Zastąpić swoje UI w miejscu actionBar tutaj:

public class Example extends ActionBarActivity { 

    // declared in onCreate() method 
    private android.support.v7.app.ActionBar actionBar; 
    private GestureDetectorCompat mDetector; 
    private YourView view1; 
    private YourView view2; 
    private YourView view3; 
    private YourView view4; 

    // some other code 

    class GestureListener extends GestureDetector.SimpleOnGestureListener { 

    private static final String DEBUG_TAG = "Gestures in Example Class"; 

     @Override 
     public boolean onDoubleTap(MotionEvent event) { 

      Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); 
      // if there is a double tap, show the action bar 
      actionBar.show(); 

      return true; 
     } 

     @Override 
     public boolean onSingleTapConfirmed(MotionEvent event) { 

      Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); 

      // if the tap is below the action bar, hide the action bar 
      if (event.getRawY() > getResources().getDimension(R.dimen.abc_action_bar_default_height)) { 
       actionBar.hide(); 
       return true; 
      } 

      return false; 
     } 

     @Override 
     public boolean onDown(MotionEvent event) { 

      return true; 

     } 

} // end-of-Example Class 

potem w moim onCreate() Mam oświadczył mój GestureDetector a także (opcjonalnie) Ustaw moją GestureListeners:

private GestureDetectorCompat mDetector; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // some code here 
    mDetector = new GestureDetectorCompat(this, new GestureListener()); 

    // this code is for more advanced view logic not needed for a basic set-up 
    //setGestureListeners(); 

} // end-of-method onCreate() 

Następnie, aby rzeczywiście wysłać gesty do przetworzenia podajemy instrukcje, aby to zrobić, są dwa sposoby, o których wiem, najpierw najprostszy:

/** 
* This method recognizes a touchEvent and passes it to your custom GestureListener 
* class. 
*/ 
@Override 
public boolean onTouchEvent(MotionEvent event){ 

    this.mDetector.onTouchEvent(event); 

    return super.onTouchEvent(event); 
} 

Drugi sposób jest bardziej złożony, ale jeśli chcesz rozpoznawać tylko zdarzenia dotykowe w niektórych układach View s w swoim układzie, tak jak w przypadku nakładających się widoków i można uzyskać dostęp tylko do najwyższego poziomu View, możesz utworzyć niestandardową klasę, aby przekazać wydarzenie wokół lub w górę:

class MyOnTouchListener implements View.OnTouchListener { 

    public boolean onTouch(View v, MotionEvent event) { 

     if (v.equals(view4)) { 
      return mDetector.onTouchEvent(event); 
     } else return false; 
    } 
} // end-of-class MyOnTouchListener 

a następnie użyć go tutaj:

public void setGestureListeners() { 

    /* when we return false for any of these onTouch methods 
    * it means that the the touchEvent is passed onto the next View. 
    * The order in which touchEvents are sent to are in the order they 
    * are declared. 
    */ 
    view1.setOnTouchListener(new MyOnTouchListener()); 

    view2.setOnTouchListener(new MyOnTouchListener()); 

    view3.setOnTouchListener(new MyOnTouchListener()); 

    view4.setOnTouchListener(new MyOnTouchListener()); 


} // end-of-method setGestureListeners() 

W mojej metody setGestureListeners, dałem im wszystko ten sam zestaw poleceń, które w zasadzie tylko rozpoznaje touchEvents na view4. W przeciwnym razie po prostu przechodzi touchEvent do następnego widoku.

To jest kod przy użyciu AppCompat, ale jeśli nie budujesz dla starszych wersji, możesz użyć zwykłego GestureDetector i ActionBar.

2

Android 4.4 (poziom API 19) wprowadza nową flagę SYSTEM_UI_FLAG_IMMERSIVE dla setSystemUiVisibility(), która pozwala Twojej aplikacji na prawdziwie "pełny ekran". Ta flaga, w połączeniu z flagami SYSTEM_UI_FLAG_HIDE_NAVIGATION i SYSTEM_UI_FLAG_FULLSCREEN, ukrywa paski nawigacji i stanu i pozwala aplikacji rejestrować wszystkie zdarzenia dotykowe na ekranie.

Powiązane problemy