Zoomlayout: ZoomLayoutの幅/高さの変更は、中央の切り抜きが機能し続けるように子の変換を更新しません

作成日 2020年10月16日  ·  5コメント  ·  ソース: natario1/ZoomLayout

バグを説明する

  • ライブラリバージョン:1.8.0
  • 公式デモアプリで再現可能:はい
  • デバイス/ Androidバージョン: Pixel 3、API 29

ZoomLayoutを使用してポートレート/風景画像を表示しています。 ズームとオーバースクロールを無効にしました。 CenterCropのみで水平および垂直パンを使用しています。 予想どおり、一度に実行できる方向パンは1つだけです(ズームが無効になっているため)。 これにより、画像の一部を表示し、他の部分はパンを使用して表示できます。

私が理解しているように、centercropは、 containerHeightchildHeightまたはcontainerWidthchildWidth揃えることによって機能します。 右? 風景/ポートレート画像を正方形のImageViewにロードすることを想像してみてください。 横向きの画像の場合、 childHeightcontainerHeightに揃えてセンタークロップを実行し、パンを水平方向に実行できるようになりました。 同様に、ポートレート画像の場合、パンは垂直方向に実行できます。

これは正常に機能します。

しかし、このようにZoomLayoutの幅/高さを変更すると、変換は子ビューに適用されません。

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

再現するには

おそらくデモアプリで、動作を再現する手順:

  1. ズームとオーバースクロールを無効にします。
  2. 水平および垂直のパンを有効にします。
  3. XMLのZoomLayoutに子ビューを配置します。 コンテンツをラップするために幅/高さを維持します。
  4. 長い風景のドローアブルを追加します。 780 x180でテスト済み。
  5. このドローアブルをXMLのZoomLayoutの子ビューの背景として設定します。
  6. 実行し、水平方向にパンを実行します。
  7. ボタンを使用して、ZoomLayoutの高さを増やします。 子の変換は実行されません。

予想される行動

コンテナの高さが変更されると、CenterCropを維持するために子変換が適用されます。

XMLレイアウト(拡張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)
}

スクリーンショット

Screenshot
Screenshot

ログ

発売

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

子に描画可能な水平背景をロードします。

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

上記のコードを使用してZoomLayoutの高さを増やします。

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

子は、センタークロップ機能を維持するために変換されません。

APK

必要に応じて提供しますが、非常に使いやすい複製手順です。

enhancement discussion

最も参考になるコメント

私は今の動作が気に入っています。コンテナのサイズはさまざまな理由で変更される可能性があり、コンテンツがすでにズーム/パンされている場合は、変換を再適用する必要はないと思います。 あなたはこのようにあなたが望むものを達成することができるはずです:

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

または多分このように

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

syncTransformation()関数などを使用すると、これを簡単に行うことができます。

全てのコメント5件

私はこれを回避するために以下のコードを使用しました。

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
)

そして、ZoomLayoutのonGlobalLayout()の別の変更

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

これを行うことは私を助けます。 センタークロップ機能を維持するために、子は親と正しく位置合わせされます。 しかし、このコードは#185の問題を生み出します。 明らかに、パンがリセットされる理由がわかりました(ヒント#global-layout)。

そのため、コンテナの幅/高さが変更されたときに子に変換を適用するようにZoomLayoutに指示する方法をまだ探しています。 ハックを使い続けると、バグが増えるだけです。 あなたはこれに取り組んできました、あなたは私よりよく知っています。 案内してください。

詳細なご報告ありがとうございます。
これは、コンテナのサイズを変更するときに、ZoomLayoutの動作が実際には定義されていないという一般的な問題だと思います。コンテナはそのサイズを維持することが期待されるため、@ natario1が間違っている場合は修正してください。 ですから、私が理解しているように、これはバグというよりは機能要求です。

これをサポートしたいのであれば、期待される動作がどのように見えるか、そして開発者がそれからどのように逸脱できるかについて話し合う必要があると思います。

私は今の動作が気に入っています。コンテナのサイズはさまざまな理由で変更される可能性があり、コンテンツがすでにズーム/パンされている場合は、変換を再適用する必要はないと思います。 あなたはこのようにあなたが望むものを達成することができるはずです:

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

または多分このように

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

syncTransformation()関数などを使用すると、これを簡単に行うことができます。

@markusresselわかりました、わかりました。 また、私がやりたいのは、このライブラリの25%のポテンシャルしか使用していないことだと思います。 ライブラリの使用目的を無効にすることは、実際にはライブラリに反対し、ライブラリが機能することを期待することです。 必要なのは、パンとフリングを備えたセンタークロップだけです。 何か提案があれば、やってください。 ありがとう。

コンテナのサイズはさまざまな理由で変更される可能性があり、コンテンツがすでにズーム/パンされている場合は、変換を再適用する必要はないと思います

@ natario1これが予想される/必要な場合は、この動作にオプトインフラグが必要です。 私には、それはデフォルトの期待に反しているように感じます。 センタークロップを適用し、コンテナサイズを変更する場合は、センタークロップを維持する必要があります。 ZoomLayoutでサイズ変更をサポートしていない場合でも、これは問題ではありません。

また、火曜日から図書館のコードを扱っています。 行列、ベクトル、またはシェーダーがどのように機能するかについては、私は何も知りません。 私は学習するために読んで修正しようとします。 しかし、私は問題を報告する前にあなたの提案をすでに試しました。 その結果、パンは水平方向と垂直方向の両方で有効になります。 また、コンテンツ/子がズームされているように見えるため、中央の切り抜きは使用できなくなりました。

ご協力ありがとうございました。 返信に時間がかかってすみません。

@rupinderjeet例を再現しようとしましたが、変更されたLayoutParamsZoomLayoutインスタンスに適用すると、独自のエラーメッセージが表示されます。

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

私は何かが足りないのですか?

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

MohamedMedhat1998 picture MohamedMedhat1998  ·  6コメント

wakaztahir picture wakaztahir  ·  5コメント

kuoliangkwong picture kuoliangkwong  ·  4コメント

lucasrsv picture lucasrsv  ·  3コメント

YiHaoHuang picture YiHaoHuang  ·  10コメント