onMeasure()
ist Ihre Gelegenheit, Android zu sagen, wie groß Ihre benutzerdefinierte Ansicht von den Layoutbeschränkungen abhängen soll, die vom übergeordneten Element bereitgestellt werden; Es ist auch die Gelegenheit Ihrer benutzerdefinierten Ansicht, zu erfahren, was diese Layouteinschränkungen sind (falls Sie sich in einer match_parent
Situation anders als in einer wrap_content
Situation verhalten möchten). Diese Einschränkungen werden in die Werte MeasureSpec
verpackt, die an die Methode übergeben werden. Hier ist eine grobe Korrelation der Moduswerte:
- GENAU bedeutet der
layout_width
oder layout_height
Wert auf einen bestimmten Wert eingestellt wurde. Sie sollten wahrscheinlich Ihre Ansicht dieser Größe machen. Dies kann auch ausgelöst werden, wenn match_parent
verwendet wird, um die Größe genau auf die übergeordnete Ansicht einzustellen (dies ist vom Layout abhängig im Framework).
- AT_MOST bedeutet typischerweise der
layout_width
oder layout_height
Wert match_parent
oder wrap_content
eingestellt war, wo eine Maximalgröße benötigt wird (dies ist das Layout in dem Rahmen abhängig), und die Größe der Dimension Elternteil ist der Wert. Sie sollten nicht größer als diese Größe sein.
- bedeutet normalerweise
layout_width
oder layout_height
Wert wurde auf wrap_content
ohne Einschränkungen festgelegt. Sie können beliebig groß sein. Einige Layouts verwenden diesen Callback auch, um die gewünschte Größe herauszufinden, bevor Sie bestimmen, welche Spezifikationen Sie in einer zweiten Messanforderung tatsächlich erneut übergeben sollen.
Der Vertrag, der mit onMeasure()
existiert, ist, dass setMeasuredDimension()
MUST am Ende mit der Größe aufgerufen werden würden Sie die Ansicht gerne sein. Diese Methode wird von allen Framework-Implementierungen aufgerufen, einschließlich der Standardimplementierung, die in View
zu finden ist. Aus diesem Grund ist es ratsam, stattdessen super
aufzurufen, wenn dies zu Ihrem Anwendungsfall passt.
Zugegeben, da das Framework eine Standardimplementierung anwendet, ist es möglicherweise nicht notwendig, diese Methode zu überschreiben, aber Sie sehen möglicherweise Clipping in Fällen, in denen der Ansichtsbereich kleiner als Ihr Inhalt ist Sie legen Ihre benutzerdefinierte Ansicht mit wrap_content
in beide Richtungen, Ihre Ansicht wird möglicherweise nicht angezeigt, da das Framework nicht weiß, wie groß es ist!
Allgemeinen, wenn Sie View
und nicht ein anderes vorhandenes Widget zwingende, ist es wahrscheinlich eine gute Idee, eine Implementierung zur Verfügung zu stellen, auch wenn es so etwas wie dies so einfach ist:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
Hoffe, das hilft.
Hey @Devunwired nette Erklärung die beste, die ich bisher gelesen habe. Ihre Erklärung hat viele Fragen beantwortet und einige Zweifel ausgeräumt, aber dennoch bleibt eine übrig: Meine benutzerdefinierte Ansicht befindet sich innerhalb einer ViewGroup zusammen mit einigen anderen Ansichten (egal welche Typen), dass ViewGroup alle seine Kinder annimmt für jede einzelne Probe nach ihrer LayoutParams-Einschränkung und bitte jedes Kind, es entsprechend seinen Beschränkungen zu messen? – pharaoh
Ja, das ist die 'measureChildren()' Methode von 'ViewGroup' während des Measure/Layout Prozesses. – Devunwired
Beachten Sie, dass dieser Code nicht funktioniert, wenn Sie onMeasure einer ViewGroup-Unterklasse überschreiben. Ihre Unteransichten werden nicht angezeigt und haben alle eine Größe von 0x0. Wenn Sie OnMeasure einer benutzerdefinierten ViewGroup überschreiben müssen, ändern Sie widthMode, widthSize, heightMode und heightSize, kompilieren Sie sie mit MeasureSpec.makeMeasureSpec zurück zu measureSpecs und übergeben Sie die resultierenden Ganzzahlen an super.onMeasure. – Alexey