2015-06-19 9 views
13

Was ich habe:getLocationOnScreen kehrt alte Position nach einer Drehung

  • Eine Aktivität mit android:configChanges="orientation|screenSize|keyboardHidden"
  • A DialogFragment auf sie
  • ViewA auf DialogFragment

Was ist das Problem:

Ich verwende ViewA.getLocationOnScreen, um den Standort auf dem Bildschirm der Ansicht zu erhalten. Wenn ich den Dialog zum ersten Mal öffne, ist die Position korrekt. Nachdem ich den Bildschirm gedreht habe, aktualisiert die Ansicht aufgrund von android:configChanges ihre Position irgendwie nicht, und selbst wenn der Dialog in der Aktivität richtig zentriert ist, verweist der getLocationOnScreen von ViewA auf den älteren Speicherort vor der Rotation.

Was ich versucht habe.

overrode ich die onConfigurationChanged des Dialogs und versucht, dies:

  • ViewA.requestLayout (nichts tun)
  • ViewA.getViewTreeObserver().addOnGlobalLayoutListener und auf die onGlobalLayout die topmargin auf 1 gesetzt und wieder requestLayout nennen. (Dies funktioniert, aber ich will nicht die Marge setzen, jedesmal wenn ich den Bildschirm drehen)

Was ich möchte wissen, ist, wie kann ich die Neupositionierung des Dialogs erzwingen, so dass getLocationOnScreen die richtigen Werte nach einer Rückkehr

Rotation

Bitte beachte, dass ich nicht will android:configChanges

+0

rufen Sie in der Lage sind, einige Ihres Code zu schreiben? Insbesondere der Code, der sich auf _when_ bezieht, überprüfen Sie "getLocationOnScreen". [Dies] (http: // stackoverflow.com/questions/13243914/getlocationonscreen-in-oncreate-just-returns-Nullen) ist nicht ganz dein Problem, aber ich frage mich, ob es eine ähnliche Ursache hat. – mpkuth

+0

Nein, das ist nicht der Fall. Die Ansicht ist bereits gezeichnet und korrekt positioniert. Das Problem ist mit 'android: configChanges', das die Aktivität Erholung deaktiviert. In diesem Fall wird der Dialog nicht zerstört, da die Aktivität nicht zerstört wird. Deshalb bleibt die Position der Ansicht die alte. Es ist kein Code erforderlich, da dies einfach zu reproduzieren ist. –

Antwort

-1

die Ansicht der Lage auf dem Bildschirm ändern, wird noch nicht aktualisiert wurde, wenn onConfigurationChanged genannt wird. Sie müssen der Ansicht eine OnLayoutChangeListener hinzufügen, um die gesuchten Aktualisierungen abzufangen. Siehe das Beispiel unten.

TestDialogFragment.java

public class TestDialogFragment extends DialogFragment { 

    private static final String TAG = "TestDialogFragment"; 

    View testView; 
    int[] testViewLocation = {0, 0}; 

    public TestDialogFragment() {} 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.test_fragment, container); 
     testView = view.findViewById(R.id.test_view); 
     testView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
      @Override 
      public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
       Log.d(TAG, "onLayoutChange"); 
       testView.getLocationOnScreen(testViewLocation); 
       Log.d(TAG, String.format("%s %s", testViewLocation[0], testViewLocation[1])); 
      } 
     }); 
     return view; 
    } 

    @Override 
    public void onConfigurationChanged(Configuration newConfig) { 
     super.onConfigurationChanged(newConfig); 
     Log.d(TAG, "onConfigurationChanged"); 
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { 
      Log.d(TAG, "landscape"); 
     } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ 
      Log.d(TAG, "portrait"); 
     } 

     testView.getLocationOnScreen(testViewLocation); 
     Log.d(TAG, String.format("%s %s", testViewLocation[0], testViewLocation[1])); 
    } 

} 

test_fragment.xml

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

    <View 
     android:id="@+id/test_view" 
     android:layout_height="50dp" 
     android:layout_width="match_parent" 
     android:layout_gravity="center"/> 

</FrameLayout> 

Protokollausgabe

06-24 16:20:05.682 D/TestDialogFragment﹕ onConfigurationChanged 
06-24 16:20:05.682 D/TestDialogFragment﹕ portrait 
06-24 16:20:05.682 D/TestDialogFragment﹕ 504 601 
06-24 16:20:05.852 D/TestDialogFragment﹕ onLayoutChange 
06-24 16:20:05.852 D/TestDialogFragment﹕ 84 1021 
06-24 16:20:08.695 D/TestDialogFragment﹕ onConfigurationChanged 
06-24 16:20:08.695 D/TestDialogFragment﹕ landscape 
06-24 16:20:08.695 D/TestDialogFragment﹕ 84 1021 
06-24 16:20:08.865 D/TestDialogFragment﹕ onLayoutChange 
06-24 16:20:08.865 D/TestDialogFragment﹕ 504 601 
06-24 16:20:13.550 D/TestDialogFragment﹕ onConfigurationChanged 
06-24 16:20:13.550 D/TestDialogFragment﹕ portrait 
06-24 16:20:13.550 D/TestDialogFragment﹕ 504 601 
+0

Danke, dass Sie mich daran erinnert haben, was ein globaler Listener ist, aber wie ich Ihnen sagte, löst das das Problem nicht. Hast du die Frage gelesen? Überprüfen Sie "was ich versucht habe" Nummer 2 –

+0

Auch für alles, was Wert ist, verwende ich OnClickListener, um die Ansichtsposition zu entleeren. Die Ansicht ist bereits gezeichnet und fertig, wenn ich ihre Position bekomme –

+0

Ich habe die Frage gelesen und in "Was ich versucht habe" Nummer 2 Sie notiert, dass Sie einen globalen Layout-Listener versucht und sagte, dass es funktioniert, außer dass Sie gezwungen waren Setzen Sie immer einen Rand und rufen Sie dann das Anforderungslayout erneut auf. Meine Antwort verwendet den globalen Layout-Listener, aber Sie müssen den Rand nicht zurücksetzen und ein zusätzliches Layout anfordern. – mpkuth

0

Um zu versuchen, zu erklären, wenn Sie dieses android:configChanges="orientation haben, wird keine Erholung von Activity stattfinden, was bedeutet, dass View s nicht gemessen wird, deshalb werden die alten Positionen berichtet, um auch eine volle Auslosung auf Ihrem View anzufordern, müssen Sie anrufen es auf den DialogFrament ‚s Ansicht Eltern so für das gesamte Spiel Ihrer DecorView - invalidate() & requestLayout()

+0

Das Layout für 'getActivity() .findViewById (R.id.container) 'oder' DialogFragment.getView(). GetRootView() 'ungültig machen und anfordern. Wie für den Rest der Antwort. Ja, das wusste ich bereits und sagte das bereits im Kommentarteil der Frage. –

Verwandte Themen