Wie kann onMeasure () richtig überschrieben werden? Ich habe verschiedene Ansätze gesehen. Beispielsweise verwendet die professionelle Android-Entwicklung MeasureSpec, um die Abmessungen zu berechnen, und endet dann mit einem Aufruf von setMeasuredDimension (). Beispielsweise:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
}
Auf der anderen Seite besteht gemäß diesem Beitrag die "richtige" Methode darin, MeasureSpec zu verwenden, setMeasuredDimensions () aufzurufen, gefolgt von einem Aufruf von setLayoutParams (), und mit einem Aufruf von super.onMeasure () zu enden. Beispielsweise:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Welches ist der richtige Weg? Keiner der beiden Ansätze hat bei mir zu 100% funktioniert.
Ich denke wirklich, was ich frage, ist, dass jemand ein Tutorial kennt, das onMeasure (), Layout, Abmessungen von untergeordneten Ansichten usw. erklärt?
quelle
Antworten:
Die anderen Lösungen sind nicht umfassend. In einigen Fällen können sie funktionieren und sind ein guter Ausgangspunkt, aber es kann nicht garantiert werden, dass sie funktionieren.
Wenn onMeasure aufgerufen wird, haben Sie möglicherweise das Recht, die Größe zu ändern. Die Werte, die an onMeasure (
widthMeasureSpec
,heightMeasureSpec
) übergeben werden, enthalten Informationen darüber, was Ihre untergeordnete Ansicht tun darf. Derzeit gibt es drei Werte:MeasureSpec.UNSPECIFIED
- Sie können so groß sein, wie Sie möchtenMeasureSpec.AT_MOST
- So groß wie Sie möchten (bis zur Spezifikationsgröße). Dies istparentWidth
in Ihrem Beispiel.MeasureSpec.EXACTLY
- Keine Wahl. Elternteil hat gewählt.Dies geschieht so , dass Android mehrere Durchgänge machen , die richtige Größe für jeden Artikel zu finden, siehe hier für weitere Details.
Wenn Sie diese Regeln nicht befolgen, kann nicht garantiert werden, dass Ihr Ansatz funktioniert.
Wenn Sie beispielsweise überprüfen möchten, ob Sie die Größe überhaupt ändern dürfen, können Sie Folgendes tun:
Anhand dieser Informationen wissen Sie, ob Sie die Werte wie in Ihrem Code ändern können. Oder wenn Sie etwas anderes tun müssen. Eine schnelle und einfache Möglichkeit, die gewünschte Größe aufzulösen, ist die Verwendung einer der folgenden Methoden:
int resolveSizeAndState (int size, int MeasureSpec, int childMeasuredState)
int resolveSize (int size, int MeasureSpec)
Während die erste nur für Honeycomb verfügbar ist, ist die zweite für alle Versionen verfügbar.
Hinweis: Sie können feststellen , dass
resizeWidth
oderresizeHeight
sind immer falsch. Ich fand dies der Fall, wenn ich darum batMATCH_PARENT
. Ich konnte dies beheben, indemWRAP_CONTENT
ich in meinem übergeordneten Layout und dann während der UNSPECIFIED-Phase eine Größe von anforderteInteger.MAX_VALUE
. Auf diese Weise erhalten Sie die maximale Größe, die Ihre Eltern beim nächsten Durchgang durch onMeasure zulassen.quelle
Die Dokumentation ist die Autorität in dieser Angelegenheit: http://developer.android.com/guide/topics/ui/how-android-draws.html und http://developer.android.com/guide/topics/ui/custom -components.html
Zusammenfassend: Am Ende Ihrer überschriebenen
onMeasure
Methode sollten Sie aufrufensetMeasuredDimension
.Sie sollten nicht
super.onMeasure
nach dem Anruf anrufensetMeasuredDimension
, da dies nur das löscht, was Sie eingestellt haben. In einigen Situationen möchten Sie möglicherweise densuper.onMeasure
ersten aufrufen und dann die Ergebnisse durch Aufrufen ändernsetMeasuredDimension
.Rufen Sie nicht
setLayoutParams
anonMeasure
. Das Layout erfolgt in einem zweiten Durchgang nach dem Messen.quelle
Ich denke, es hängt vom Elternteil ab, was Sie überschreiben.
Wenn Sie beispielsweise eine ViewGroup (wie FrameLayout) erweitern und die Größe gemessen haben, sollten Sie wie folgt aufrufen
weil Sie ViewGroup möglicherweise für die Restarbeit verwenden möchten (einige Aufgaben in der untergeordneten Ansicht ausführen)
Wenn Sie eine Ansicht erweitern (wie ImageView), können Sie einfach aufrufen
this.setMeasuredDimension(width, height);
, da die übergeordnete Klasse genau das tut, was Sie normalerweise getan haben.super.onMeasure()
Kurz gesagt , wenn Sie einige Funktionen wünschen, die Ihre Elternklasse kostenlos anbietet, sollten Sie aufrufen (normalerweise MeasureSpec.EXACTLY-Modus messen), andernfalls ist ein Aufrufthis.setMeasuredDimension(width, height);
ausreichend.quelle
So habe ich das Problem gelöst:
}}
Darüber hinaus war es für die ViewPager-Komponente erforderlich
quelle
super.onMeasure
löscht die mitsetMeasuredDimension
.Wenn Sie die Ansichtsgröße innerhalb von
onMeasure
allem ändern, was Sie brauchen, ist dersetMeasuredDimension
Anruf. Wenn Sie die Größe außerhalb von ändernonMeasure
, müssen Sie anrufensetLayoutParams
. Ändern Sie beispielsweise die Größe einer Textansicht, wenn der Text geändert wird.quelle
Hängt von der Steuerung ab, die Sie verwenden. Die Anweisungen in der Dokumentation gelten für einige Steuerelemente (TextView, Button, ...), nicht jedoch für andere (LinearLayout, ...). Die Art und Weise, wie es für mich sehr gut funktioniert hat, war, den Super anzurufen, sobald ich fertig bin. Basierend auf dem Artikel im folgenden Link.
http://humptydevelopers.blogspot.in/2013/05/android-view-overriding-onmeasure.html
quelle
Ich denke, setLayoutParams und die Neuberechnung der Messungen sind eine Problemumgehung, um die Größe der untergeordneten Ansichten korrekt zu ändern, wie dies normalerweise in onMeasure der abgeleiteten Klasse erfolgt.
Dies funktioniert jedoch selten richtig (aus welchem Grund auch immer ...), rufen Sie besser MeasureChildren auf (wenn Sie eine ViewGroup ableiten) oder versuchen Sie bei Bedarf etwas Ähnliches.
quelle
Sie können diesen Code als Beispiel für onMeasure () verwenden ::
quelle