Warum ist meine benutzerdefinierte Android-Ansicht nicht quadratisch?

8

Ich habe eine benutzerdefinierte Ansicht erstellt, um ein Spielbrett für ein Spiel anzuzeigen, das ich gerade entwickle. Das Spielbrett muss zu jeder Zeit ein Quadrat sein. Also mit und Höhe sollte gleich sein. Ich folgte dieses Tutorial , um dies zu erreichen.

Ich habe den folgenden Code zu meiner benutzerdefinierten Ansicht hinzugefügt:

%Vor%

Das Layout mit meiner benutzerdefinierten Ansicht sieht folgendermaßen aus:

%Vor%

Das Quadrat, das in der onDraw-Methode gezeichnet wird, ist immer ein Quadrat. Das funktioniert gut.

Im Layout füge ich die benutzerdefinierte Ansicht hinzu und gebe der Ansicht eine Hintergrundfarbe. Wenn ich es auf einem Gerät im Hochformat zeige, funktioniert alles gut und die Hintergrundfarbe füllt das Quadrat, das ich in der onDraw-Methode zeichne.

Wenn ich das Gerät in den Querformat-Modus umschalte, ist das Quadrat immer noch ein Quadrat, aber der Bereich der Hintergrundfarbe ist größer als das. Es hat die gleiche Höhe, aber mehr Breite. Aber ich habe keine Ahnung warum. Die Methoden getMeasuredWidth () und getMeasuredHeight () geben die korrekten Werte zurück. Wie kann es sein, dass die Aussicht noch größer ist als das?

    
Peter Fortuin 21.06.2013, 06:11
quelle

5 Antworten

5

Aus irgendeinem Grund funktioniert Ihre Ansicht in RelativeLayout nicht. Für die Querformat-Messung gilt folgende Beschränkung (auf meinem Handy):

width = MeasureSpec: GENAU 404; Höhe = MeasureSpec: AT_MOST 388

Aufgrund dieser tatsächlichen endet anders als gemessene Breite (auf meinem Handy gemessen = 388, tatsächliche = 404). Deshalb sehen Sie, dass sich der Hintergrund über Ihr Rect hinaus erstreckt. Sie können es selbst überprüfen, indem Sie onDraw und onMeasure etwas protokollieren.

Auch das Beachten des Messmodus hilft nicht, die Messung endet immer noch mit dem gleichen Ergebnis wie oben.

Die Lösung besteht darin, ein anderes Layout zu verwenden. LinearLayout und FrameLayout funktionierten für mich. Es ist auch eine gute Idee, die tatsächliche Ansichtsgröße in onDraw mit getWidth () und getHeight () zu verwenden.

Wenn Sie RelativeLayout wirklich benötigen, können Sie ein untergeordnetes FrameLayout hinzufügen, um Ihre Ansicht so zu halten:

%Vor%     
badd 04.07.2013, 08:18
quelle
1

Unterklasse ImageView und überschreiben onMeasure und übergeben an

%Vor%

die ganze Klasse:

%Vor%

Bearbeiten: Ich habe es mit einer normalen Ansicht versucht

%Vor%

und eine TestActivity

%Vor%

Es zeichnet ein quadratisches rotes Rechteck auf dem Bildschirm meines Handys

    
Blackbelt 27.06.2013 07:21
quelle
0

Das ist mein Code, ich benutze diesen Code und es funktioniert gut. Ist nicht genau das, was Sie suchen, aber vielleicht geben Sie Ihnen eine Idee. Basierend auf meiner Anforderung sollte die Höhe der Bildansicht genauso lang sein wie die Breite.

%Vor%

Definiert in xml als:

%Vor%

Und schließlich in Fragment ist es so etwas wie:

%Vor%     
Hesam 21.06.2013 08:47
quelle
0

Ich bin mir nicht sicher, welche Lösung dem Bedarf dienen wird, aber der Code aus dem Tutorial hat ein grundlegendes Designproblem - er interpretiert MeasureSpec Parameter von onMeasure() nicht richtig. Beantworten Sie onMeasure - Erklärung zu benutzerdefinierten Ansichten , um die korrekte Interpretation dieser Parameter zu erklären.

Was in diesem Beispiel passiert, wird onMeasure() zweimal für jedes Vorkommen von Zeichnungen für die benutzerdefinierte Ansicht aufgerufen.

Beim ersten Aufruf geben beide MeasureSpecs den Modus AT_MOST an und geben Anfangswerte ohne Berücksichtigung von Rändern und Padding an. Also, Code aus Tutorial legitimer macht Breite und Höhe passend.

Beim zweiten Aufruf berücksichtigt RelativeLayout jedoch Margen und Abstände und übergibt MeasureSpec für Width mit EXACT mode, während Height im Modus AT_MOST übergeben wird.

Für den vertikalen Bildschirm funktioniert das OK, weil Width um die Ränder reduziert wurde, und der Wert für die Höhe ist immer noch die Höhe des Bildschirms (auch um die Ränder reduziert). Also, während des zweiten Anrufs Code legitimer Höhe reduziert, um jetzt-kleiner-Breite zu entsprechen, und alles funktioniert ordnungsgemäß.

Für die horizontale Bildschirmausrichtung wird jedoch "Breite" auf den Wert gesetzt, der beim ersten Aufruf definiert wurde, während Height durch Ränder reduziert wird. Wenn Code Width auf Height zu setzen versucht, funktioniert diese Einstellung nicht ordnungsgemäß, da Width mode EXACT ist. Daher enden die Eigenschaften der Ansicht Width und MeasuredWidth mit unterschiedlichen Werten.

Es gibt einige einfache Möglichkeiten, um Code in Frage zu stellen: Sie können einfach vertikale Ränder entfernen:

%Vor%

Wenn die Ränder wichtig sind, können Sie das Layout auf absolut ändern:

%Vor%

In beiden Fällen scheint es sinnvoll zu sein, die Implementierung von onMeasure() in EXACT mode zu ändern (um zumindest ein Problem zu protokollieren).

    
amoiseyev 01.07.2013 17:44
quelle
0

Ihr onMeasure() Code ist nicht einfach. Ändern Sie Ihren Code wie folgt & amp; Setze match_parent als width & amp; Höhe in xml (Eigentlich ist es egal)

%Vor%     
vakman 03.07.2013 07:26
quelle