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?
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% Unterklasse ImageView und überschreiben onMeasure
und übergeben an
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
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% 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).
Tags und Links android android-custom-view measure