8

Ich entwickle derzeit eine Tablet-App, die intensiv das ViewPager Widget verwendet. Ich habe auch mehrere Viewpager auf dem Bildschirm auf einmal.Stop Android von Layouting alle meine Ansichten

Jetzt habe ich das folgende Problem: Wenn ein ViewPager zur nächsten/vorherigen Seite scrollt, muss er (natürlich) sein Layout neu berechnen und Ansichten hinzufügen/entfernen. Ich bemerkte, dass die requestLayout Anrufe bis an die Spitze der View-Hierarchie, daher ungültig ALL meiner Ansichten auf dem Tablet-Bildschirm (die eine Menge!) Sind. Dies ist sehr teuer.

jetzt meine Frage: Gibt es eine Möglichkeit, einen Rahmen um die ViewPager zu implementieren, die das ursprüngliche Layout-tun und dann ausbreitet nicht Layout- Anfragen die Ansichtshierarchie nach oben wie ich, dass nach dem ersten Layout kennen, der Rahmen bleibt gleich groß und ändert sich nicht.

Ich kam mit dem folgenden Frame, aber es funktioniert nicht ganz gut, weil es nicht 100% der Zeit funktioniert.

public class MyFrame extends FrameLayout 
{ 
    // VARIABLE CONTROLLING THE DISPATCH OF THE LAYOUT 
    // REQUEST UP THE VIEW HIERARCHY 
    private boolean doLayout = true; 

    public MyFrame(Context context) 
    { 
     super(context); 
     doLayout = true; 
    } 

    @Override 
    public void requestLayout() 
    { 
     if (doLayout) // DO THE LAYOUT REQUEST UP TO THE TOP 
      super.requestLayout(); 
     else 
     { 
      // JUST MEASURE MYSELF AND MY CHILDREN 
      measure(MeasureSpec.getMode(MeasureSpec.AT_MOST), 
      MeasureSpec.getMode(MeasureSpec.AT_MOST)); 
      layout(getLeft(), getTop(), getRight(), getBottom()); 
     } 
     doLayout = false; 
    } 
} 

Vielen Dank für jede Beratung!

Antwort

0

Ich wünschte wirklich, ich könnte Ihnen sagen, dass es einen besseren Weg gab, aber ich glaube nicht, dass es da ist. Wenn der ViewPager tatsächlich Ansichten hinzufügt/löscht, wird Ihr Layout fortlaufend gelöscht, auch wenn es nicht möglich ist. Es ist eine träge Annahme, dass sich die Inhalte ändern könnten (und somit nach oben hin ungültig werden), und es liegt an uns, knifflige Programme zu entwickeln, um einige dieser Annahmen zu entfernen.

Wenn Sie sicherstellen können, dass sich die Grenzen von FrameLayout niemals ändern, können Sie requestLayout überhaupt nicht überschreiben.

4

Ich weiß, die Frage ist ein bisschen alt, aber meine Antwort könnte jemand anderem helfen, da Ihre Frage und Colins Antwort mir geholfen haben.

Ich habe genau das gleiche Problem wie Sie. Und dafür gibt es zwei Lösungen. Zuerst müssen Sie sicherstellen, dass Ihr ViewPager seine * layout_width * und * layout_height * auf * match_parent * eingestellt hat, und diese Ansichtshierarchie ist so organisiert, dass Android nicht zu dem Schluss kommt, dass es neu zu layern ist eines der übergeordneten ViewPager-Layouts. Angenommen, Sie haben ein RelativeLayout mit zwei Ansichten fester Größe untereinander und einem ViewPager unterhalb der zweiten Ansicht. In diesem Fall wird jede Änderung an ViewPager an das übergeordnete Layout weitergegeben. Wenn Sie diese beiden Ansichten mit fester Größe und den ViewPager jedoch in ein LinearLayout einfügen, wird dies nicht passieren. Keine Layoutanforderung wird über ViewPager hinaus verbreitet. Was noch besser ist, Layout-Anfragen auf einer ViewPager-Seite werden auch nicht auf andere Seiten übertragen.

Die zweite Lösung (es tatsächlich mehr ist der zweite Teil der Lösung) ist Ihr FrameLayout, aber ich mag diese Änderung:

public class LayoutStopperFrameLayout extends FrameLayout { 

    private boolean doLayout; 

    public LayoutStopperFrameLayout(Context context) { 
     super(context); 
     doLayout = true; 
    } 

    public LayoutStopperFrameLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     doLayout = true; 
    } 

    public LayoutStopperFrameLayout(Context context, AttributeSet attrs, 
      int defStyle) { 
     super(context, attrs, defStyle); 
     doLayout = true; 
    } 

    public void setPropagateRequestLayout(boolean doLayout) { 
     this.doLayout = doLayout; 
    } 

    @Override 
    public void requestLayout() { 
     if (doLayout) { 
      // DO THE LAYOUT REQUEST UP TO THE TOP 
      super.requestLayout(); 
     } 
    } 
} 

In meiner Anwendung nenne ich setPropagateRequestLayout() in Fragment onStart und OnStop Methoden Layout-Anfragen werden jeweils aus- und eingeschaltet.