Android BorderLayout

jf

Bekanntes Mitglied
Hallo ich habe den Versuch gestartet, das BorderLayout für Android umzusetzen. Doch leider will dieses nicht so, wie ich will... :bahnhof:

Weil Schlingel mich darauf hinwies, ViewGroups nicht zu tief zu verschachteln, habe ich das BorderLayout aber in zwei separate Komonenten aufgeteilt:
  • BorderRowsLayout
  • BorderColsLayout

Dabei sollen, wie beim BorderLayout von Swing, die äußeren Container die enthaltenen Views eng umschließen und den restlichen Platz dem mittleren Container überlassen. Die Klasse selber wiederum soll den maximal verfügbaren Raum einnehmen (FILL_PARENT).

Wenn ich meine Klasse einsetze, dann wird aber nur die View im linken Container angezeigt. - Den Rest des Platzes nimmt der mittlere Container ein. Dabei wird dieser mittlere Container umgebrochen, auch wenn er gar keine eigenen Views beinhaltet! Wenn ich die View aus dem rechten Container entferne, dann verschwindet dieser Umbruch.

Hier der Code:

Java:
public class BorderColsLayout extends LinearLayout {

	public static final long LEFT   = BorderStandardLayout.LEFT;
	public static final long CENTER = BorderStandardLayout.CENTER;
	public static final long RIGHT  = BorderStandardLayout.RIGHT;
	
	private LinearLayout leftCol   = null;
	private LinearLayout centerCol = null;
	private LinearLayout rightCol  = null;

	
	public BorderColsLayout(Context context) {
		super(context);

		leftCol   = new LinearLayout(context);
		centerCol = new LinearLayout(context);
		rightCol  = new LinearLayout(context);
		
		this.     setOrientation( HORIZONTAL );
		leftCol.  setOrientation( VERTICAL   );
		centerCol.setOrientation( VERTICAL   );
		rightCol. setOrientation( VERTICAL   );
		
		this.     setLayoutParams( new LinearLayout.LayoutParams( FILL_PARENT,  FILL_PARENT ) );
		leftCol.  setLayoutParams( new LinearLayout.LayoutParams( WRAP_CONTENT, FILL_PARENT ) );
		centerCol.setLayoutParams( new LinearLayout.LayoutParams( FILL_PARENT,  FILL_PARENT ) );
		rightCol. setLayoutParams( new LinearLayout.LayoutParams( WRAP_CONTENT, FILL_PARENT ) );
		
		leftCol.  setWeightSum(0);
		centerCol.setWeightSum(1);
		rightCol. setWeightSum(0);

		this.addView( leftCol   );
		this.addView( centerCol );
		this.addView( rightCol  );
	}

	public void addView(View child, long container) {
		switch( (int)container ) {
			case (int)LEFT:	  leftCol.  addView(child); break;
			case (int)CENTER: centerCol.addView(child); break;
			case (int)RIGHT:  rightCol. addView(child); break;
		}
	}

}

Kann mir hier jemand helfen?
 

jf

Bekanntes Mitglied
Das oben beschriebene Verhalten zeigt sich auch, wenn man dieses "BorderLayout" (einzeilig, 3 Spalten mit FILL_PARENT für die mittlere Zelle) in XML umsetzt. - Allerdings nur, wenn man dahinter eine Java-View setzt. Programmiert man komplett in XML, dann passiert dies nicht. Es scheint sich hierbei um einen Bug zu handeln. Mir sind bisher dabei zwei Probleme aufgefallen:

Variante 1: wenn die mittlere Zelle das FILL-PARENT-Attribut besitzt
Hier wird die View aus der linken Zelle korrekt dargestellt, die rechte View fehlt, die mittlere Zelle ist umgebrochen.
(Zelle ist höher als die View in der linken Zelle)

Wahrscheinlich rührt dies daher, weil die Views der Reihe nach dem LinearLayout hinzugefügt werden:
- Zunächst wird die linke View in die 1. Zelle gesetzt (eng umschlungen, da WRAP_CONTENT).
- Dann wird die mittlere Zelle definiert. Da diese das FILL_PARENT-Attribut aufweist, wird sie bis ganz rechts außen vergrößert.
- Nun fehlt der Platz für die dritte Zelle, weshalb irgendwie die zweite Zelle umgebrochen wird (dies passiert nämlich nicht, wenn man die dritte Zelle ebenfalls leer lässt!). Android bekommt es dann einfach nicht gebacken, die rechte View überhaupt darzustellen.

Variante 2: wenn mittlere Zelle kein FILL_PARENT-Attribut besitzt
Die Java-View, welche eigentlich unterhalb des BorderLayouts platziert werden soll, weil der alles umschließende äußere Container (LinearLayout) die Orientierung VERTICAL besitzt, landet leider hinter dem BorderLayout in der gleichen Zeile!

=> Das ist echt ein Armutszeugnis für die Googler! Die sollten wirklich lieber bei ihrem Web-Scripting bleiben...
(Und ja, ich weiß das XML-Layouting empfohlen wird - aber wenn auch Java-UIs erlaubt sind, dann sollte das Layouting auf diesem Weg auch anständig funktionieren! ;))

Übrigens:
Ich verwandte die 7er API (Android 2.1), um höchstmögliche Kompatibilität zu gewährleisten.
Nun bin ich aber auf die 8er-Version gewechselt (Android 2.2), weil hier das Attribut FILL_PARENT als deprecated ausgewiesen und durch MATCH_PARENT ersetzt wird.
Ich hoffte, dass der Grund dieser Umstellung durch eine größere Änderung am Code hervorgerufen und damit evtl. das Problem korrigiert wurde. Doch leider weit gefehlt: gleiches Verhalten wie mit FILL_PARENT! - Scheinbar ändert Google lieber die API nach gutdünken, als Fehler zu korrigieren... :noe:

Hat jemand von euch evtl. schon von diesem Problem gehört?
Und gibts es evtl. bereits eine Korrektur (wenn ja ab welcher API-Version?) oder zumindest einen Workaround hierfür?
 
Zuletzt bearbeitet:

jf

Bekanntes Mitglied
Es ist einfach eine Katastrophe!

Habe nun verschiedene Layouts ausprobiert: als ich ein FrameLayout in ein LinearLayout setzte, wurde gleich mal überhaupt nichts angezeigt. Auch das TableLayout zeigte Probleme...

Bin jetzt zur Notlösung XML-Layout übergegangen - aber auch hiermit funktioniert es nicht:
alles Views werden wraped angezeigt: rechts bleibt immer ein freier Fleck!

XML:
[XML]<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:eek:rientation="horizontal" >

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/leftCol"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:eek:rientation="vertical" >
</LinearLayout>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/centerCol"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:eek:rientation="vertical" >
</LinearLayout>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rightCol"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:eek:rientation="vertical" >
</LinearLayout>

</LinearLayout>[/XML]

Java:
Java:
public class BorderColsLayoutWA extends FrameLayout {
	public static final long LEFT   = BorderStandardLayout.LEFT;
	public static final long CENTER = BorderStandardLayout.CENTER;
	public static final long RIGHT  = BorderStandardLayout.RIGHT;
	
	public BorderColsLayoutWA(Context context) {
		super(context);
		LayoutInflater inflater;
		inflater = LayoutInflater.from(context);
		LinearLayout container = (LinearLayout)inflater.inflate(R.layout.border_cols_layout, null);
		this.addView(container);

	}

	public void addView(View child, long container) {
		switch( (int)container ) {
			case (int)LEFT:	  ( (LinearLayout)findViewById(R.id.leftCol)   ).addView(child); break;
			case (int)CENTER: ( (LinearLayout)findViewById(R.id.centerCol) ).addView(child); break;
			case (int)RIGHT:  ( (LinearLayout)findViewById(R.id.rightCol)  ).addView(child); break;
		}
	}
}

So ihr Freunde des XML-Layoutings, zeigt doch bitte mal, wie man das richtig macht... ;)


PS: die R-Klasse wird immer in einem Package erstellt, welches den Namen eines bereits lange gelöschten Src-Packages trägt. - Was soll der Mist? Wie kann man das ändern?
 

jf

Bekanntes Mitglied
Will, oder kann mir hier keiner helfen? :D

Egal, ich habe einen Workaround gefunden: zunächst habe ich mit den verschiedenen Layouts rumgespielt. Dabei musste ich festellen, dass (zumindest in meinem Fall) alle Views in dem LinearLayout nicht dargestellt wurden, sobald ich ein FrameLayout-Objekt hinzufügte. Mit dem TableLayout konnte ich mein Ziel erreichen... Schön ist das aber nicht! - Und auch keine generische Lösung.

Aber auch hier Bugs ohne Ende:
Wenn ich ich nur die mittlere von 3 Spalten strecken mit folgendem Code stecken möchte...
Java:
.setColumnStretchable( 0, false );
.setColumnStretchable( 1, true  );
.setColumnStretchable( 2, false );
... dann entsteht wiederum rechts ein freier Raum, obwohl die Tabelle auf FILL_PARENT für die Breite gesetzt ist.

Ich musste also zwingend
Code:
setStretchAllColumns(true)
verwenden, dann funktioniert es. :eek:
Die beiden äußeren Views werden dadruch zwar größer dargestellt als eigentlich gewollt, hat aber den Vorteil, dass sie sich leichter antippen lassen.


Naja, alles in allem kann man sagen "Schuster bleib bei deinen Leisten!". Google macht zwar sehr gute Web-Anwendungen - aber von allem, was nicht im Browser oder auf einem Server läuft, sollten die Google-Mannen lieber die Finger lassen...

Leider gibt es im mobilen Segment aktuell keine Alternative zu Android (iOS scheidet dabei einfach preislich aus und Windows Phone an der Verbreitung - WebOS und alle anderen brauchen wir eigentlich gar nicht erwähnen...)
 

jf

Bekanntes Mitglied
[WR]Kommando zurück!!![/WR]
[TIPP]Es funktioniert! - War wohl doch mein Fehler... :D
Ich meinte, die Gewichtigung über
Code:
setWeightSum()
setzten zu müssen. - Das "Sum" hat mich dabei zwar gestört, aber es gab leider keine andere Methode in dieser Richtung. In der Tat wird die Gewichtung aber mit über die LayoutParams festgelegt.[/TIPP]
Bin da gerade drüber gestolpert und wollte es euch nur wissen lassen.
Da hier niemand geantwortet hat, dachte ich mir, dass diese Info auch noch bei anderen fehlen könnte...

Gemerkt habe ich es übrigens durch ein Code-Snippet, über welches ich bei einer anderen Android-Recherche gestolpert bin.
=> Beipiele bringen eben doch mehr, als reine Doku... :D
 
Zuletzt bearbeitet:

Neue Themen


Oben