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

  • Antworten:3
Jonas Rudolph
  • Forum-Beiträge: 3

18.11.2013, 23:21:43 via Website

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):

(Kann leider kein Bild posten. Google-Bilder suche nach "iOS 7 delete mail")

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
1private View topView = null, leftView = null, rightView = null;
2
3 @Override
4 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5 setLevelViews(); // hier werden einfach nur die Variablen topView, leftView und rightView "gefüllt"
6
7 Log.i("SlidableLayout", "MWidth:" + MeasureSpec.getSize(widthMeasureSpec)
8 + " MHeight:" + MeasureSpec.getSize(heightMeasureSpec));//Ergibt 0
9
10 int heightSpec = MeasureSpec.makeMeasureSpec(
11 MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.AT_MOST);
12
13 if(topView!=null){
14 topView.measure(
15 MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST),
16 heightSpec);
17 }
18
19 int widthSpec = MeasureSpec.makeMeasureSpec(
20 MeasureSpec.getSize(widthMeasureSpec)/2, MeasureSpec.AT_MOST);
21
22 if(leftView!=null){
23 leftView.measure(widthSpec, heightSpec);
24 }
25
26 if(rightView!=null){
27 rightView.measure(widthSpec, heightSpec);
28 }
29
30 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
31
32 Log.i("SlidableLayout", "Width:" + getMeasuredWidth() + " height:" + getMeasuredHeight());
33 }
34
35@Override
36 protected void onLayout(boolean changed, int l, int t, int r, int b) {
37 if(changed){
38 if(topView!=null){
39 topView.layout(offset, 0, topView.getMeasuredWidth(), topView.getMeasuredHeight());
40 }
41 if(leftView!=null){
42 leftView.layout(0, 0, leftView.getMeasuredWidth(), leftView.getMeasuredHeight());
43 }
44 if(rightView!=null){
45 rightView.layout(r-rightView.getMeasuredWidth(), 0, 0, rightView.getMeasuredHeight());
46 }
47 }
48 }
49
50 @Override
51 protected void dispatchDraw(Canvas canvas) {
52
53 if(leftView!=null){
54 leftView.draw(canvas);
55 }
56 if(rightView!=null){
57 rightView.draw(canvas);
58 }
59 if(topView!=null){
60 topView.draw(canvas);
61 }
62 }

Die xml-datei aus der das List-Item generiert wird sieht so aus:
1<?xml version="1.0" encoding="utf-8"?>
2
3<de.meineapp.SlidableLayout
4 xmlns:android="http : //schemas.android.com/apk/res/android"
5 xmlns:app="http : //schemas.android.com/apk/res/de.meineapp"
6 android:layout_width="match_parent"
7 android:layout_height="wrap_content"
8 android:background="@color/standard_green">
9
10 <RelativeLayout
11 android:id="@+id/foodResult"
12 android:layout_width="match_parent"
13 android:layout_height="match_parent"
14 app:level="front">
15
16 <TextView
17 android:layout_width="match_parent"
18 android:layout_height="match_parent"
19 android:text="@string/app_name"/>
20
21 </RelativeLayout>
22
23 <ImageButton
24 android:id="@+id/foodResult_fav"
25 android:layout_height="match_parent"
26 android:layout_width="wrap_content"
27 android:contentDescription="@string/image_description"
28 android:src="@drawable/ic_launcher"
29 app:level="left"/>
30
31 <ImageButton
32 android:id="@+id/foodResult_falsePrice"
33 android:layout_height="match_parent"
34 android:layout_width="wrap_content"
35 android:contentDescription="@string/image_description"
36 android:src="@drawable/ic_launcher"
37 app:level="right"/>
38
39
40</de.meineapp.SlidableLayout >

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

— geändert am 18.11.2013, 23:23:49

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

19.11.2013, 00:17:49 via Website

Es gibt diverse DevBytes, hast du da mal nachgeschaut die solches verhalten addressieren

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Jonas Rudolph
  • Forum-Beiträge: 3

21.11.2013, 19:06:45 via Website

Ja, habe ich danke für den Tipp =) Das einzige relevante, was da behandelt wird ist, einen Listeneintrag aus einer Liste "rauszuwischen". Für die Animation hilft mir das weiter, aber nicht bei dem Problem, das ich derzeit habe.

Weiß niemand, was ich falsch gemacht habe?

Liebe Grüße,

Jonas

Antworten
tomte
  • Forum-Beiträge: 36

30.01.2014, 11:53:35 via Website

Jonas Rudolph
Wenn ich in der Methode onMeasure(int widthMeasureSpec, int heightMeasureSpec) mir die höhe auslesen lasse ist diese 0.
Bei mir blieb die Hoehe immer -1, bis ich lGroupView.measure( widthMeasureSpec, heightMeasureSpec) aufgerufen habe.
Ich bin noch ziemlicher Anfaenger, aber:
Bei Dir darfst Du vermutlich nicht erwarten, dass in onMeasure() die zu messende Height schon gesetzt ist.

Was ist, wenn Du stattdessen oder vorher measure(widthMeasureSpec, heightMeasureSpec) aufrufst?

Was mit measure() gesetzt wird, kann danach mit getMeasuredHeight() ausgelesen werden.

Vielleicht blindlings mein erstes Blindes-Huhn-Korn gefunden? Wuerde mich freuen.
tomte

— geändert am 30.01.2014, 13:45:05

Antworten