Zoomlayout: Änderungen an der Breite/Höhe von ZoomLayout aktualisieren die untergeordnete Transformation nicht, damit das Zuschneiden in der Mitte funktioniert

Erstellt am 16. Okt. 2020  ·  5Kommentare  ·  Quelle: natario1/ZoomLayout

Beschreibe den Fehler

  • Bibliotheksversion: 1.8.0
  • Reproduzierbar in offizieller Demo-App: Ja
  • Geräte-/Android-Version: Pixel 3, API 29

Ich verwende ZoomLayout, um Hoch- / Querformatbilder anzuzeigen. Ich habe Zoom & OverScroll deaktiviert. Ich verwende horizontales und vertikales Pan nur mit CenterCrop. Es kann wie erwartet nur in eine Richtung geschwenkt werden (da Zoom deaktiviert ist). Dadurch kann ich einen Teil des Bildes anzeigen, während der andere Teil mit Pan angezeigt werden kann.

Wie ich verstanden habe, funktioniert centercrop, indem entweder containerHeight an childHeight oder containerWidth an childWidth . Rechts? Stellen Sie sich vor, Bilder im Quer-/Hochformat in eine quadratische ImageView zu laden. Bei Bildern im Querformat wird childHeight mit containerHeight , um Centercrop auszuführen, und jetzt kann das Schwenken horizontal ausgeführt werden. Ebenso kann bei Hochformatbildern das Schwenken vertikal durchgeführt werden.

Dies funktioniert gut.

Wenn ich jedoch die Breite/Höhe von ZoomLayout so ändere, wird die Transformation nicht auf die untergeordnete Ansicht angewendet.

val layoutParams = zoomLayout.layoutParams
layoutParams.width = layoutParams.width + changedWidth
layoutParams.height = layoutParams.height + changedHeight
zoomLayout.layoutParams = layoutParams

Fortpflanzen

Schritte zum Reproduzieren des Verhaltens, ggf. in der Demo-App:

  1. Zoom und OverScroll deaktivieren.
  2. Aktivieren Sie Pan für Horizontal und Vertikal.
  3. Platzieren Sie eine untergeordnete Ansicht in ZoomLayout in XML. Behalten Sie die Breite/Höhe bei, um den Inhalt zu umbrechen.
  4. Fügen Sie eine lange Landschaftszeichnung hinzu. Getestet mit 780 x 180.
  5. Legen Sie dieses Zeichenobjekt als Hintergrund für die untergeordnete Ansicht in ZoomLayout in XML fest.
  6. Run, Pan horizontal ausführen.
  7. Verwenden Sie eine Schaltfläche, um die Höhe von ZoomLayout zu erhöhen. Die Transformation am Kind wird nicht durchgeführt.

Erwartetes Verhalten

Wenn sich die Containerhöhe ändert, wird eine untergeordnete Transformation angewendet, um CenterCrop beizubehalten.

XML-Layout (Erweitertes ZoomLayout)

init {
    setHorizontalPanEnabled(true)
    setVerticalPanEnabled(true)

    setOverScrollHorizontal(false)
    setOverScrollVertical(false)

    setAlignment(Alignment.TOP or Alignment.LEFT)
    setHasClickableChildren(true)
    setTransformation(
        ZoomApi.TRANSFORMATION_CENTER_CROP,
        ZoomApi.TRANSFORMATION_GRAVITY_AUTO
    )

    setZoomEnabled(false)
}

Screenshots

Screenshot
Screenshot

Protokolle

Gestartet

I/ZoomLayout: setHasClickableChildren: old: false new: false
I/ZoomLayout: setHasClickableChildren: old: false new: true

Horizontalen Hintergrund laden, der auf Kind gezeichnet werden kann.

W/ZoomEngine: onMatrixSizeChanged: firstTime: true oldZoom: NaN transformation: 1 transformationZoom: 0.0
I/ZoomEngine: computeTransformationZoom centerCrop scaleX: 1.0042135 scaleY: 5.860656
I/ZoomEngine: onMatrixSizeChanged: newTransformationZoom: 5.860656 newRealZoom: 5.8606563 newZoom: 1.0000001

Erhöhen Sie die ZoomLayout-Höhe mit dem obigen Code.

W/ZoomEngine: onMatrixSizeChanged: firstTime: false oldZoom: 5.8606563 transformation: 1 transformationZoom: 5.860656
I/ZoomEngine: computeTransformationZoom centerCrop scaleX: 1.0042135 scaleY: 6.2704916
I/ZoomEngine: onMatrixSizeChanged: newTransformationZoom: 6.2704916 newRealZoom: 5.8606563 newZoom: 0.93464065

Das Kind wird nicht transformiert, um die Centercrop-Funktionalität beizubehalten.

APK

Wird bei Bedarf zur Verfügung gestellt, aber sehr einfach zu verwendende Reproduktionsschritte.

enhancement discussion

Hilfreichster Kommentar

Ich mag, wie es gerade funktioniert, die Containergröße kann sich aus vielen Gründen ändern, und wenn der Inhalt bereits gezoomt/geschwenkt wurde, sollten wir die Transformation meiner Meinung nach nicht erneut anwenden. Sie sollten in der Lage sein, das zu erreichen, was Sie möchten, wie folgt:

zoomLayout.layoutParams = layoutParams
zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)

Oder vielleicht so

zoomLayout.layoutParams = layoutParams
zoomLayout.post {
    zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)
}

Wir könnten dies mit einer syncTransformation()-Funktion oder ähnlichem vereinfachen

Alle 5 Kommentare

Ich habe den folgenden Code verwendet, um dies zu umgehen.

val layoutParams = zoomLayout.layoutParams
layoutParams.width = layoutParams.width + changedWidth
layoutParams.height = layoutParams.height + changedHeight
zoomLayout.layoutParams = layoutParams

zoomLayout.engine.setContainerSize(
    layoutParams.width.toFloat(),
    layoutParams.height.toFloat(),
    applyTransformation = false // not applying transformation
)

Und eine weitere Änderung in ZoomLayouts onGlobalLayout()

engine.setContentSize(
    child.width.toFloat(), 
    child.height.toFloat(),
    applyTransformation = true // <-- this change
)

Dies hilft mir. Das Kind ist korrekt mit dem Elternteil ausgerichtet, um die Centercrop-Funktionalität beizubehalten. Aber dieser Code bringt das Problem #185 hervor. Jetzt kenne ich eindeutig den Grund, warum Pan zurückgesetzt wird (hint#global-layout).

Ich suche also immer noch nach einer Möglichkeit, ZoomLayout anzuweisen, die Transformation auf das Kind anzuwenden, wenn die Breite/Höhe des Containers geändert wird. Wenn ich weiter versuche, Hacks zu verwenden, werde ich nur noch mehr Fehler haben. Sie haben daran gearbeitet, Sie wissen es besser als ich. Bitte führen Sie mich.

Vielen Dank für den ausführlichen Bericht.
Ich denke, dies ist ein allgemeines Problem, bei dem ZoomLayout noch kein wirklich definiertes Verhalten beim Ändern der Abmessungen des Containers hat, da wir erwarten, dass der Container seine Abmessungen beibehält. Bitte korrigieren Sie mich, wenn ich falsch liege @natario1. So wie ich es verstehe, ist dies eher eine Funktionsanfrage als ein Fehler.

Wenn wir dies unterstützen wollen, müssen wir meiner Meinung nach eine Diskussion darüber führen, wie das erwartete Verhalten aussehen soll und wie Entwickler davon abweichen können.

Ich mag, wie es gerade funktioniert, die Containergröße kann sich aus vielen Gründen ändern, und wenn der Inhalt bereits gezoomt/geschwenkt wurde, sollten wir die Transformation meiner Meinung nach nicht erneut anwenden. Sie sollten in der Lage sein, das zu erreichen, was Sie möchten, wie folgt:

zoomLayout.layoutParams = layoutParams
zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)

Oder vielleicht so

zoomLayout.layoutParams = layoutParams
zoomLayout.post {
    zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)
}

Wir könnten dies mit einer syncTransformation()-Funktion oder ähnlichem vereinfachen

@markusressel Okay, ich verstehe. Außerdem habe ich das Gefühl, dass ich nur 25% des Potenzials dieser Bibliothek nutzen möchte. Das Deaktivieren des Verwendungszwecks der Bibliothek ist eigentlich etwas dagegen und erwartet, dass es funktioniert. Alles was ich brauche ist Center-Crop mit Pan und Fling. Wenn Sie etwas vorzuschlagen haben, tun Sie es bitte. Vielen Dank.

Die Containergröße kann sich aus vielen Gründen ändern und wenn der Inhalt bereits gezoomt/geschwenkt wurde, denke ich, dass wir die Transformation nicht erneut anwenden sollten

@natario1 Wenn dies erwartet/erforderlich ist, sollte es ein Opt-in-Flag für dieses Verhalten geben. Für mich fühlt es sich wie eine Anti-Default-Erwartung an. Wenn Center-Crop angewendet wird und die Containergröße geändert wird, sollte Center-Crop beibehalten werden. Wenn wir jedoch keine Größenänderungen in ZoomLayout unterstützen, wäre dies nicht einmal wichtig.

Außerdem bin ich mit dem Bibliothekscode vom Dienstag beschäftigt. Ich weiß ~viel~ nichts darüber, wie Matrizen, Vektoren oder Shader funktionieren. Ich versuche zu lesen und zu modifizieren, um zu lernen. Aber ich habe Ihren Vorschlag bereits ausprobiert, bevor ich das Problem gemeldet habe. Als Ergebnis davon ist Pan sowohl für die horizontale als auch für die vertikale Richtung aktiviert. Außerdem ist das Zuschneiden in der Mitte nicht mehr verfügbar, da der Inhalt/das untergeordnete Element gezoomt zu sein scheint.

Danke für deine Hilfe. Es tut mir leid, dass ich viel länger gebraucht habe, um zu antworten.

@rupinderjeet Ich habe versucht, Ihr Beispiel zu reproduzieren, aber wenn ich das modifizierte LayoutParams auf die Instanz ZoomLayout anwende, erhalte ich unsere eigene Fehlermeldung:

java.lang.RuntimeException: ZoomLayout must be used with fixed dimensions (e.g. match_parent)

Verpasse ich etwas?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

MohamedMedhat1998 picture MohamedMedhat1998  ·  6Kommentare

kuoliangkwong picture kuoliangkwong  ·  4Kommentare

Yahor10 picture Yahor10  ·  5Kommentare

natario1 picture natario1  ·  13Kommentare

lucasrsv picture lucasrsv  ·  3Kommentare