2010-12-01 10 views
8

Edited mehr Details hinzuzufügen: (ursprünglich fragt vor fast zwei Monaten ... hat noch keine Lösung gefunden)Erzwingen Sie eine Aktivität im Vollbildmodus, um bei der Fortsetzung erneut zu messen/neu zu zeichnen?

Ich habe eine Tätigkeit mit einer etwas komplizierten Ansicht. Technisch gesehen nicht kompliziert ... da ist gerade viel los. Alle Aktivitäten in dieser bestimmten App sind auf FullScreen NoTitleBar eingestellt und alle sind auf Querformat ausgerichtet. Ich bemerkte schon früh in der Entwicklung, als die App ausgeblendet wurde und dann wieder aktiv war. Es gab eine seltene Tendenz, dass das Layout vertikal nach unten rutschte, als ob es Platz für die Titelleiste und die Statusleiste schaffen würde.

Später in der Entwicklung ruft die App nun zu verschiedenen externen Absichten. Ich merke jetzt, dass es mehr eine Tendenz gibt, diese gleiche Verschiebung zu machen, wenn ich von einer extern gehandhabten abgefeuerten Absicht fortfahre (wie das Erstellen einer "Auswahl" Absicht oder die Auswahl eines Bildes). Ich kann es mit genau den gleichen Schritten inkonsistent reproduzieren ... manchmal passiert es manchmal nicht. Es scheint, als gäbe es zwischen verschiedenen Phasen des Messens und Auslegens eine Wettlaufsituation. Ich gehe davon aus, dass einer dieser Schritte, die das System für mich ausführt, ist, nach Vollbild und Nichtlibelle zu suchen und die notwendige Verschiebung vorzunehmen. Dies passiert wahrscheinlich in einigen Fällen zu spät.

Ich habe eine Reihe von Protokollierung und Aufrufe von invalidate(), requestLayout(), etc. versucht, vielleicht die Race-Bedingung zu fangen, aber das Problem scheint außerhalb meiner Layouts. Die oberen() und unteren() Werte meines Root-Layouts sind immer 0 und die Höhe meines Bildschirms, selbst wenn ich dies protokolliere, während das Problem auftritt.

Gibt es eine andere Methode des Fensters, WindowManager oder jedes andere systemansichtsbezogene Objekt, das ich eine vollständige erneute Messung erzwingen, neu zeichnen, erneut auf aktuelle Thema/Stil Flags überprüfen kann?

Antwort

9

Ich hatte genau das gleiche Problem und probierte auch mehrere aproches (wie die oben genannten). Keiner von ihnen hat funktioniert.Allerdings fand ich die folgende Abhilfe:

protected void onResume() { 
    super.onResume(); 
    handler.postDelayed(new Runnable() { 
     public void run() { 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
          WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     } 
    }, 1000);  
} 

die Ansicht wird in diesem Verfahren ein kurzes Flackern, aber zumindest doensn't es croped bleiben. Eine saubere Lösung muss noch gefunden werden. Allerdings unterstützt dies Ihre These, dass es ein Timing- oder Race-Problem gibt.

+0

Also, in Ihrem Fall passiert es auch manchmal und nicht andere? In dem Fall, in dem das Problem nicht auftritt (Fenster ist bei Wiederaufnahme ordnungsgemäß Vollbild), verursacht dies auch ein Flimmern? Oder ist es nur, wenn das Problem auftritt und diese Situation es behebt? Was saugt ist, dass es keine Möglichkeit gibt, das Auftreten zur Laufzeit zu erkennen und diesen Code bedingt auszuführen. Ich werde das in meiner App testen und Sie wissen lassen, ob es funktioniert. Vielen Dank! – Rich

+0

@Rich: es passiert im Emulator sehr reproduzierbar (fast immer) auf Geräten erscheint es weniger häufig (je nach Gerät denke ich). Flimmern/springen, wenn das Problem auftritt. (Ich habe regelmäßig Flimmern auf einem Bildschirm, aber ich denke, es ist ein anderes Problem) –

+0

Ja ... das scheint die beste Lösung zu sein. Danke noch einmal. – Rich

0

bin ich nicht sicher, ob es funktionieren, aber Sie könnten dies in dieser Methode versuchen:

this.getWindow().getDecorView().invalidate(); 

Wenn das nicht auf seine eigenen funktioniert, versuchen Sie, die OnDraw Zugabe (Canvas) mische die Anweisungen, die notwendig sind, um die Titelleiste zu entfernen, und führe ähnliche Anpassungen durch, die deine Aktivität möglicherweise beim Start ausführt.

Hoffnung, das hilft.

0

Haben Sie Fullscreen NoTitleBar in Ihrem Manifest oder im Code festgelegt? Wenn Sie Code verwenden, kann es sein, dass es gerendert wird, bevor Ihr Code einsetzt?

<application android:label="@string/app_name" android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> 

Ich verstehe, dass Sie Themen für einzelne Aktivitäten in einer Anwendung festlegen können. Machst du? und stehen sie in Konflikt mit den Anwendungseinstellungen?

+0

Ich glaube, ich habe fast jede Kombination ausprobiert. Ich kann es vielleicht noch einmal sorgfältiger tun, um das zu überprüfen, aber ich habe es im Code versucht, im Manifest, sowohl App-Level nur, activitly nur Level, und beides. Ich schätze, ich werde eine Matrix aller möglichen Kombinationen aufstellen und eins nach dem anderen testen, aber mein derzeitiger Gedanke ist, dass es eine Race Condition ist, die eine hackyere Lösung benötigt (daher die 250 pt Bounty). – Rich

1

Haben Sie das in onResume() versucht?

this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
           WindowManager.LayoutParams.FLAG_FULLSCREEN); 
+0

Ich habe das in onResume, onPostResume, onWindowConfigurationChanged, etc ... Sie nennen es. Toller Vorschlag, aber es ist etwas seltsamer als das. Es passiert zu seltsamen Zeiten und es korrigiert sich, wenn ich bestimmte Ansichten ein-/ausgeblendet habe oder wenn ein Dialog erscheint. Ich wünschte, es gäbe einen Rückruf, der passiert, nachdem alle Zeichnungen abgeschlossen sind. Ich denke, das ist, was ich suche, aber nicht sicher, ob die Aktivitätsklasse es aufdeckt. – Rich

+0

Das ist wirklich seltsam ... Wenn Sie eine Antwort finden, posten Sie es bitte hier, ich werde es gerne lesen. – gnclmorais

+0

Es gibt keinen Rückruf, nachdem das Zeichnen abgeschlossen ist, aber ich denke, dass Sie einen Rückruf bevorzugen würden, nachdem das Layout abgeschlossen ist. Es ist die Layout-Phase, die die Positionen der Dinge bestimmt, nicht die Zeichenphase. Verwenden Sie ['View.getViewTreeObserver()'] (http://developer.android.com/reference/android/view/View.html#getViewTreeObserver%28%29) und ['OnPreDrawListener'] (http: // developer. android.com/reference/android/view/ViewTreeObserver.OnPreDrawListener.html). Ich weiß nicht, wie sehr dir das wirklich helfen wird, da das Forcen des Layouts für dich nicht zu funktionieren scheint. –

1

In meinem Fall wurde dieses Verhalten durch die Wiederaufnahme vom Sperrbildschirm ausgelöst. Keine Ahnung warum aber nach dem Hinzufügen der leeren überladenen Funktion wurde es behoben (aber ich habe es nur auf meinem HTC Wilfire getestet). Es könnte ein anderer Fehler sein.

@Override 
public void onWindowFocusChanged(boolean hasFocus) { 
    super.onWindowFocusChanged(hasFocus); 
    /* Workaround a probable Android bug with fullscreen activities: 
    * on resume status bar hides and black margin stays, 
    * reproducible half of the time when coming back from lock screen 
    * (tested on HTC Wildfire) 
    * No idea why but this empty overload method fixed it. 
    */ 
} 
+0

Hast du irgendwelche anderen Geräte versucht? FWIW, die angenommene Antwort oben wurde auf einer Tonne verschiedener Geräte (sowohl Telefon als auch Tablet) getestet und arbeitete für mich. Könnte nicht das gleiche Problem sein, aber wahrscheinlich verwandt. – Rich

+0

Nein Ich habe nicht die Möglichkeit, es auf einem anderen Gerät zu testen, aber ich hoffe, es wird auch funktionieren;) Ich habe es gestern herausgefunden. –

0

Ich habe eine Lösung für dieses gefunden:

@Override 
    protected void onResume() { 
     Log.e("", "onResume"); 
     super.onResume(); 

     //this is a simple Splash with "Game paused" Text inside! in my main.xml 
     final LinearLayout gamePause_text = (LinearLayout) findViewById(R.id.gamePause_text); 
     OnGlobalLayoutListener asdf = new OnGlobalLayoutListener(){ 
      public void onGlobalLayout() { 
       Log.e("", "onGlobalLayout"); 
       getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
            WindowManager.LayoutParams.FLAG_FULLSCREEN); 
       gameSurface.onResume(); //OpenGL Surface onResume(); 
       gamePause_text.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
     }; 
     gamePause_text.getViewTreeObserver().addOnGlobalLayoutListener(asdf); 
    } 
0

ich es behoben, durch das Thema für die Anwendung einstellen, anstatt für einzelne Aktivitäten.

<application 
     android:icon="@drawable/icon" 
     android:installLocation="auto" 
     android:label="@string/app_name" 
     android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" > 

Das funktionierte für mich. Dieses Problem tritt auf, wenn die nächste Aktivität, die wir starten, keine Vollbildaktivität und aktuelle Aktivität eine Vollbildaktivität ist.

Verwandte Themen