Android Custom ViewGroup onMeasure() - heightMeasureSpec ist 0. Warum?

jonas.r

Mitglied
Hey ihr lieben,
ich programmiere gerade eine Android-App. In dieser will ich eine ListView haben, in die ich mehrere Elemente meiner eigenen ViewGroup einfügen will.
Das Anzeigen anderer Elemente (aus einer xml-datei) in dieser Liste funktioniert, nur nicht mit meiner eigenen View.

Ich musste eine eigene ViewGroup implementieren, da ich will, dass wenn der Benutzer über den Listen-Eintrag von links nach rechts streicht die View nach rechts "slided" also, dem finger folgt. Links wird darunter ein button erscheinen. Das gleiche wenn man von rechts nach links streicht, nur dass die View dem Finger nun nach links folgt und rechts ein button erscheint (so, wie die lösch-funktion bei iOS):

20130923_swipetodelete.jpg


Nur halt, dass man auch nach einem Strich nach rechts einen button hat.

Also habe ich mir folgendes gedacht:
Ich brauche eine ViewGroup, in die ich bis zu 3 Elemente einfügen kann. Für jedes Element setzt man als Attribut ein level ("front", "left" oder "right").

Beim Messen (onMeasure()):
-wird der View, welche mit dem Attribut "front" versehen ist die Größe gleich der Größe der ViewGroup gegeben.
-wird der View, welche mit "left" versehen ist maximal die halbe breite der ViewGroup gesetzt. genauso bei der View, die mit "right" versehen ist.

Beim Layouter (onLayout()):
-bekommt die front View einfach die maße der ViewGroup (sie soll ja den ganzen Platz einnehmen)
-die linke View wird rechts bis zur motte orientiert, die rechte rechtsbündig

Beim zeichnen (dispatchDraw()):
-werden natürlich zuerst die linke und die rechte view gezeichnet. Dann - darüber - die front view.

Soweit habe ich es jetzt programmiert (Die touch-geste noch nicht). Ich bekomme auch keine Exception und alles funktioniert, wie es soll.

Bis darauf, dass das ganze gar nicht gezeichnet wird. Wenn ich in der Methode onMeasure(int widthMeasureSpec, int heightMeasureSpec) mir die höhe auslesen lasse ist diese 0. Die breite (so wie es auch sein soll) so breit wie die parent-View.

Ich denke, ich zeige mal den relevanten code:

SlidableLayout.java
Java:
private View topView = null, leftView = null, rightView = null;

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setLevelViews(); // hier werden einfach nur die Variablen topView, leftView und rightView "gefüllt"
		
		Log.i("SlidableLayout", "MWidth:" + MeasureSpec.getSize(widthMeasureSpec)
				+ " MHeight:" + MeasureSpec.getSize(heightMeasureSpec));//Ergibt 0
		
		int heightSpec = MeasureSpec.makeMeasureSpec(
				MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.AT_MOST);
		
		if(topView!=null){
			topView.measure(
					MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST),
					heightSpec);
		}
		
		int widthSpec = MeasureSpec.makeMeasureSpec(
				MeasureSpec.getSize(widthMeasureSpec)/2, MeasureSpec.AT_MOST);
		
		if(leftView!=null){
			leftView.measure(widthSpec, heightSpec);
		}
		
		if(rightView!=null){
			rightView.measure(widthSpec, heightSpec);
		}
		
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
		Log.i("SlidableLayout", "Width:" + getMeasuredWidth() + " height:" + getMeasuredHeight());
	}

@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if(changed){
			if(topView!=null){
				topView.layout(offset, 0, topView.getMeasuredWidth(), topView.getMeasuredHeight());
			}
			if(leftView!=null){
				leftView.layout(0, 0, leftView.getMeasuredWidth(), leftView.getMeasuredHeight());
			}
			if(rightView!=null){
				rightView.layout(r-rightView.getMeasuredWidth(), 0, 0, rightView.getMeasuredHeight());
			}
		}
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {

		if(leftView!=null){
			leftView.draw(canvas);
		}
		if(rightView!=null){
			rightView.draw(canvas);
		}
		if(topView!=null){
			topView.draw(canvas);
		}
	}

Die xml-datei aus der das List-Item generiert wird sieht so aus:
[XML]
<?xml version="1.0" encoding="utf-8"?>

<de.meineapp.SlidableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/de.meineapp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/standard_green">

<RelativeLayout
android:id="@+id/foodResult"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:level="front">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/app_name"/>

</RelativeLayout>

<ImageButton
android:id="@+id/foodResult_fav"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:contentDescription="@string/image_description"
android:src="@drawable/ic_launcher"
app:level="left"/>

<ImageButton
android:id="@+id/foodResult_falsePrice"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:contentDescription="@string/image_description"
android:src="@drawable/ic_launcher"
app:level="right"/>


</de.meineapp.SlidableLayout >
[/XML]

Das mit dem level-setzen funktioniert. Auch werden die views erkannt und in die variablen eingesetzt.

Was habe ich falsch gemacht? Es wäre echt super-lieb, wenn mir jemand helfen kann!

Liebe Grüße,
Jonas
 
Zuletzt bearbeitet:

dzim

Top Contributor
Schau mal hier - der macht das zwar mit einer Animation nach unten weg, aber ich denke, die Idee könnte man anpassen.
Cool toolbar for ListView items | udinic

Du müsstest dann nur irgendwie eine Halbtransparenz über den noch sichtbaren Bereich legen - oder aber du machst es vollständig unsichtbar... Was denkst du?

#edit: mehr Links wenn du android listview slide als Stichwort in der Google-Suche verwendest...
 
Zuletzt bearbeitet:

jonas.r

Mitglied
Hm, das wäre schonmal eine Idee, danke!
Weiß trotzdem jemand, was ich bis jetzt falsch gemacht habe, so dass garnichts angezeigt wird?

Liebe Grüße,
Jonas
 

Neue Themen


Oben