Ich habe eine, ImageView
die ein PNG anzeigt, das ein größeres Seitenverhältnis als das des Geräts hat (vertikal gesprochen - was bedeutet, dass es länger ist). Ich möchte dies anzeigen, während das Seitenverhältnis beibehalten, die Breite des übergeordneten Elements angepasst und die Bildansicht am oberen Bildschirmrand fixiert wird.
Das Problem bei der Verwendung CENTER_CROP
als Skalierungstyp besteht darin, dass das skalierte Bild (verständlich) zentriert wird, anstatt die Oberkante an der Oberkante der Bildansicht auszurichten.
Das Problem dabei FIT_START
ist, dass das Bild zur Bildschirmhöhe passt und nicht die Breite ausfüllt.
Ich habe dieses Problem gelöst, indem ich eine benutzerdefinierte ImageView verwendet und onDraw(Canvas)
diese manuell mithilfe der Zeichenfläche überschreibe und handhabe . Das Problem bei diesem Ansatz ist, dass 1) ich befürchte, dass es eine einfachere Lösung gibt, 2) ich beim Aufrufen super(AttributeSet)
des Konstruktors eine VM-Mem-Ausnahme erhalte, wenn ich versuche, ein src-Bild von 330 KB festzulegen, wenn der Heap 3 MB frei hat (mit einer Heap-Größe von 6 MB) und kann nicht herausfinden, warum.
Irgendwelche Ideen / Vorschläge / Lösungen sind herzlich willkommen :)
Vielen Dank
ps ich dachte, dass eine Lösung darin bestehen könnte, einen Matrixskalentyp zu verwenden und es selbst zu tun, aber das scheint die gleiche oder mehr Arbeit zu sein als meine aktuelle Lösung!
Antworten:
Ok, ich habe eine funktionierende Lösung. Die Eingabeaufforderung von Darko hat mich dazu gebracht, die ImageView-Klasse erneut zu betrachten (danke) und die Transformation mithilfe einer Matrix angewendet (wie ich ursprünglich vermutet hatte, aber bei meinem ersten Versuch keinen Erfolg hatte!). In meiner benutzerdefinierten Klasse Imageview Ich rufe
setScaleType(ScaleType.MATRIX)
nachsuper()
im Konstruktor, und haben die folgende Methode.Ich habe int in die
setFrame()
Methode eingefügt, da sich der Aufruf von in ImageViewconfigureBounds()
innerhalb dieser Methode befindet. Dort findet das gesamte Skalierungs- und Matrixmaterial statt. Dies erscheint mir logisch (sagen Sie, wenn Sie nicht einverstanden sind).Unten finden Sie die Methode super.setFrame () von AOSP
Die vollständige Klasse src finden Sie hier
quelle
Hier ist mein Code zum Zentrieren unten. Übrigens. in Doris Code ist ein kleiner Fehler: Da der
super.frame()
ganz am Ende aufgerufen wird, gibt diegetWidth()
Methode möglicherweise den falschen Wert zurück. Wenn Sie es oben zentrieren möchten, entfernen Sie einfach die postTranslate-Zeile und Sie sind fertig. Das Schöne ist, dass Sie ihn mit diesem Code an eine beliebige Stelle verschieben können. (rechts, Mitte => kein Problem;)quelle
(r-l)
stattdessen verwenden?if((frameWidth > originalImageWidth) || (frameHeight > originalImageHeight))
umgekehrt werden? Mit anderen Worten, sollten Sie nicht testen, ob das Bild größer als der Rahmen ist? Ich schlage vor, es durchif((originalImageWidth > frameWidth ) || (originalImageHeight > frameHeight ))
((View) getParent()).getWidth()
seit demImageView
hatMATCH_PARENT
Sie müssen keine benutzerdefinierte Bildansicht schreiben, um die
TOP_CROP
Funktionalität zu erhalten. Sie müssen nur das ändernmatrix
derImageView
.Stellen Sie das
scaleType
aufmatrix
fürImageView
:Legen Sie eine benutzerdefinierte Matrix für Folgendes fest
ImageView
:Auf diese Weise erhalten Sie die
TOP_CROP
Funktionalität.quelle
scaleType
auf,centerCrop
sonst sehe ich Leerzeichen an den Kanten.Dieses Beispiel funktioniert mit Bildern, die nach dem Erstellen des Objekts + einer Optimierung geladen werden. Ich habe einige Kommentare in den Code eingefügt, die erklären, was los ist.
Denken Sie daran, anzurufen:
oder
Java-Quelle:
quelle
Basierend auf Dori verwende ich eine Lösung, die das Bild entweder basierend auf der Breite oder Höhe des Bildes skaliert, um immer den umgebenden Container zu füllen. Auf diese Weise kann ein Bild skaliert werden, um den gesamten verfügbaren Platz zu füllen, wobei der obere linke Punkt des Bildes anstelle der Mitte als Ursprung verwendet wird (CENTER_CROP):
Ich hoffe das hilft - funktioniert wie ein Vergnügen in meinem Projekt.
quelle
Keine dieser Lösungen funktionierte für mich, da ich eine Klasse wollte, die eine beliebige Ernte entweder aus horizontaler oder vertikaler Richtung unterstützt, und ich wollte, dass ich die Ernte dynamisch ändern kann. Ich brauchte auch Picasso Kompatibilität, und Picasso setzt Bildzeichnungen träge.
Meine Implementierung wird direkt aus ImageView.java im AOSP angepasst. Um es zu verwenden, deklarieren Sie es in XML wie folgt:
Wenn Sie von der Quelle aus eine Top-Ernte wünschen, rufen Sie an:
Wenn Sie eine Bodenernte wünschen, rufen Sie an:
Wenn Sie eine Ernte von 1/3 des Weges nach unten wünschen, rufen Sie an:
Wenn Sie sich für eine andere Zuschneidemethode wie fit_center entscheiden, können Sie dies auch tun, und keine dieser benutzerdefinierten Logik wird ausgelöst. (Bei anderen Implementierungen können Sie NUR deren Zuschneidemethoden verwenden.)
Zuletzt habe ich eine Methode hinzugefügt, redraw (). Wenn Sie also Ihre Zuschneidemethode / Ihren Skalentyp dynamisch im Code ändern möchten, können Sie das Neuzeichnen der Ansicht erzwingen. Beispielsweise:
Rufen Sie Folgendes auf, um zu Ihrer benutzerdefinierten Ernte in der oberen Mitte und im dritten Drittel zurückzukehren:
Hier ist die Klasse:
quelle
Vielleicht gehen Sie in den Quellcode für die Bildansicht auf Android und sehen Sie, wie es die mittlere Ernte usw. zeichnet .. und kopieren Sie vielleicht einen Teil dieses Codes in Ihre Methoden. Ich weiß nicht wirklich nach einer besseren Lösung als dieser. Ich habe Erfahrung mit der manuellen Größenänderung und dem Zuschneiden der Bitmap (Suche nach Bitmap-Transformationen), wodurch die tatsächliche Größe verringert wird, aber dennoch ein gewisser Overhead entsteht.
quelle
}}
quelle
onLayout
spart mir viel! Vielen Dank! Ich bin auf ein Problem gestoßen, bei dem die Matrix berechnet wird, das Bild jedoch nicht sofort angezeigt wird und das HinzufügenonLayout
des Codes mein Problem löst.Wenn Sie Fresco (SimpleDraweeView) verwenden , können Sie dies ganz einfach tun mit:
Dieser wäre für eine Spitzenernte.
Weitere Infos unter Referenzlink
quelle
Hier gibt es zwei Probleme mit den Lösungen:
Diese kleine Änderung behebt das Problem (platzieren Sie den Code in onDraw und überprüfen Sie die Skalierungsfaktoren für Breite und Höhe):
quelle
Einfachste Lösung: Schneiden Sie das Bild aus
quelle