5

Ich füge dynamisch Ansichten zu einem relativen Layout hinzu und definiere sie programmatisch. Die Ansichten können auf dem Bildschirm verschoben werden, sodass sich ihre Position ändert.Dynamische Einstellung von Ansichten mit der Einstellung LayoutParams.addRule an die letzte Position der Ansicht

Wenn ich versuche, eine Ansicht (button2) unterhalb einer anderen Ansicht (button1) festzulegen, wird button2 an der alten Position von button1 platziert (der Standardposition, an der Ansichten hinzugefügt werden, bevor sie verschoben werden). Ich habe Bilder verlinkt, um das besser zu vermitteln.

Dies ist das ursprüngliche Layout Original Layout

-Layout nach Button2 neu positioniert wird Re-positioned Layout

Ich habe einen Hintergrund LinkedList die Verfolgung aller Ansicht, die Änderungen und Ansichtsattribute für das Layout, wenn das einen Unterschied macht.

Hier sind die Code-Funktionen:

wie ich Neupositionierung Button1:

Buttons b = (Buttons) viewIndex; 
           positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams()); 
           positioningLayout.addRule(RelativeLayout.CENTER_VERTICAL); 
           b.setLayoutParams(positioningLayout); 
           baseLayout.addView(b); 

Ansichten unter einem anderen Ansicht Codefragment Neupositionierung:

Buttons b = (Buttons) viewIndex; 
           positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams()); 
           positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue()); 
           b.setLayoutParams(positioningLayout); 
           b.invalidate(); 

Wie ich hinzufüge die Ansichten zum Layout.

uiList.addView(new Buttons(this), "BUTTON"); 
      setDialogView(uiList.getLast()); 
      showDialog(SET_ID); 
      reloadUI(); 

setDialogView läuft gerade den Blick auf den Dialog set_id so dass ich manuell eine ID zu der Ansicht (zum Testen) zuweisen. reloadUI() findet nur die letzte zum Hintergrund LinkedList hinzugefügte Ansicht und fügt sie zur RelativeLayout mit .addView hinzu;

Wenn Sie mehr Code benötigen, lassen Sie es mich bitte wissen. Fehle ich einen Anruf, um die Ansichtslayouts zu aktualisieren, nachdem ich die untergeordneten Ansichten relativLayout geändert habe? Es sieht so aus, als ob die Ansicht visuell neu positioniert wird, aber die tatsächlichen LayoutParams werden nicht aktualisiert. Wenn Sie also Button2 auf Button1 setzen, erhält es die alte Position.

Gibt es eine Möglichkeit, eine relative Layoutansicht zu erzwingen?

+0

Können Sie die wichtigsten Layout zeigen? –

+0

Die Benutzeroberfläche wird vollständig dynamisch erstellt, so dass kein XML verwendet wird:/ – Sevros

Antwort

2

Ich denke, Sie sollten versuchen, einfache Lösung - ersetzen b.invalidate() mit b.requestLayout(). Für mehr Hintergrund überprüfen Sie this link. Ich habe es nicht getestet, aber ich hoffe, es wird funktionieren. So sollte der Code wie folgt aussehen:

Buttons b = (Buttons) viewIndex; 
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams()); 
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue()); 
b.setLayoutParams(positioningLayout); 
b.requestLayout(); 

Oder vielleicht können Sie vereinfachen dies:

Buttons b = (Buttons) viewIndex; 
((RelativeLayout.LayoutParams) b.getLayoutParams()).addRule(RelativeLayout.BELOW, viewIdFromList.intValue()); 
b.requestLayout(); 
+0

Das hat funktioniert, danke! Können Sie erklären, warum requestlayout() funktioniert, aber nicht ungültig()? Ich dachte nicht, dass requestlayout() die Ansicht aktualisiert hat, als sie aufgerufen wurde. – Sevros

+0

Sicher, 'requestLayout()' sollte aufgerufen werden, wenn die Position oder Grenzen der Ansicht im übergeordneten Layout geändert wurden, während 'invalidate() 'aufgerufen werden sollte, wenn das Erscheinungsbild der Ansicht geändert wurde. Auf der einen Seite, wenn Sie 'requestLayout()' aufrufen, werden 'onLayout()' und 'onMeasure()' Methoden der View ausgelöst, auf der anderen Seite wenn Sie 'invalidate()' aufrufen, dann 'onDraw () 'Methode wird ausgelöst. – rom4ek

+0

Also, 'invalidate() 'nur neu anzeigen selbst, wenn' requestLayout() 'Position und Grenzen der Ansicht aktualisiert. Gern geschehen, und ich bin auf der Suche nach Ihrem Kopfgeld: D – rom4ek

1

Sie scheinen auf dem richtigen Weg zu sein, machen aber einen kleinen Fehler. Ohne mehr Code ist es ziemlich schwierig, die tatsächliche Lösung bereitzustellen. Aber ich werde versuchen, auf den Fehler hinzuweisen.

See, zu relativ positionen programmatisch in einem RelativeLayout Sie müssen eindeutige IDs zuweisen zu jedem von ihnen.

Wie,

Button b = new Button(this); 
b.setId(1); 

Button c = new Button(this); 
c.setId(2); 

Jedes Element sollte eindeutige IDs haben.

Nun, wenn Sie die Taste b in der Mitte vertikal platziert werden soll,

layout.addRule(RelativeLayout.CENTER_VERTICAL); 
b.setLayoutParams(layout); 

Nun, wenn Sie darunter platzieren Taste c wollen,

layout.addRule(RelativeLayout.BELOW, b.getId()); 
layout.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 
b.setLayoutparams(layout); 

Dies wird sicherlich die Taste c platzieren unter dem Knopf b.Wie Sie gesagt haben, können Sie eine beliebige Datenstruktur Ihrer Wahl verwenden, um die IDs der einzelnen Elemente zu verfolgen.

1

Dies ist nur ein Detailbeispiel, wie Sie die Schaltfläche richtig bewegen. So Erstellen Sie zunächst eine eindeutige ID für die View, erstellen also eine neue XML-Ressourcendatei in res/values/, und nennen Sie es ids.xml:

structure

und der Gehalt an ids.xml ist:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <item name="button_1" type="id"/> 
    <item name="button_2" type="id"/> 
</resources> 

Wir Legen Sie eine ID zu Ihrem Hauptlayout fest:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/layout_main"> <!-- the id --> 

    <!-- content of this layout --> 

</RelativeLayout> 

Dann erstellen wir th e Button s:

RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_main); 

    final Button button1 = new Button(this); 
    button1.setId(R.id.button_1); 
    button1.setText("BUTTON 1"); 
    button1.setTextColor(Color.BLACK); 

    final Button button2 = new Button(this); 
    button2.setId(R.id.button_2); 
    button2.setText("BUTTON 2"); 
    button2.setTextColor(Color.BLACK); 

    relativeLayout.addView(button1, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 
      RelativeLayout.LayoutParams.WRAP_CONTENT)); 
    relativeLayout.addView(button2, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 
      RelativeLayout.LayoutParams.WRAP_CONTENT)); 

    RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) button1.getLayoutParams(); 
    params1.addRule(RelativeLayout.CENTER_IN_PARENT); // set to the center of screen 
    button1.setLayoutParams(params1); 

    final RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) button2.getLayoutParams(); 
    params2.addRule(RelativeLayout.ALIGN_PARENT_TOP); 
    params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 
    button2.setLayoutParams(params2); 

    button2.setOnClickListener(new View.OnClickListener() { 
     @SuppressLint("NewApi") 
     @Override 
     public void onClick(View v) { 
      /* We need to remove the existing rules and update it! 
      * For API 16 and earlier, set the rule to 0, e.g. --> layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0); 
      * For API 17 and higher, call layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_LEFT); 
      */ 

      int api = android.os.Build.VERSION.SDK_INT; 
      if (api >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // API level 17 
       params2.removeRule(RelativeLayout.ALIGN_PARENT_TOP); 
       params2.removeRule(RelativeLayout.ALIGN_PARENT_LEFT); 
      }else if (api < Build.VERSION_CODES.JELLY_BEAN_MR1) { 
       params2.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0); 
       params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0); 
      } 

      params2.addRule(RelativeLayout.CENTER_IN_PARENT); 
      params2.addRule(RelativeLayout.BELOW, R.id.button_1); // place below button1 
      button2.setLayoutParams(params2); 
     } 
    }); 

Also, wenn Sie auf button2 klicken, wird es auf unter button1 bewegen.

+0

Danke für die schnelle Antwort, aber leider hat dies nicht funktioniert – Sevros

Verwandte Themen