Zoomlayout: Изменения в ширине / высоте ZoomLayout не обновляют дочернее преобразование, чтобы сохранить работу с кадрированием по центру

Созданный на 16 окт. 2020  ·  5Комментарии  ·  Источник: natario1/ZoomLayout

Опишите ошибку

  • Версия библиотеки: 1.8.0
  • Воспроизводится в официальном демонстрационном приложении: Да
  • Версия устройства / Android: Pixel 3, API 29

Я использую ZoomLayout для отображения портретных / альбомных изображений. Я отключил Zoom и OverScroll. Я использую горизонтальное и вертикальное панорамирование только с CenterCrop. За один раз, как и ожидалось, можно выполнить панорамирование только в одном направлении (поскольку масштабирование отключено). Это позволяет мне показать часть изображения, в то время как другую часть можно просмотреть с помощью панорамирования.

Как я понял, центральная обрезка работает путем выравнивания containerHeight с childHeight или containerWidth с childWidth . Верно? Представьте себе загрузку пейзажных / портретных изображений в квадратный ImageView. Для пейзажных изображений childHeight будет выровнено с containerHeight для выполнения центрального кадрирования, и теперь панорамирование может выполняться по горизонтали. Точно так же для портретных изображений панорамирование может выполняться по вертикали.

Это прекрасно работает.

Но, если я изменяю ширину / высоту ZoomLayout таким образом, преобразование не применяется к дочернему представлению.

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

Воспроизводить

Шаги по воспроизведению поведения, возможно, в демонстрационном приложении:

  1. Отключите масштабирование и прокрутку.
  2. Включите панорамирование по горизонтали и вертикали.
  3. Поместите дочерний View в ZoomLayout в XML. Сохраняйте ширину / высоту, чтобы обернуть содержимое.
  4. Добавьте длинный пейзаж с возможностью рисования. Протестировано при разрешении 780 x 180.
  5. Установите этот объект в качестве фона для дочернего представления в ZoomLayout в XML.
  6. Беги, выполняй Панорамирование по горизонтали.
  7. Используйте кнопку, чтобы увеличить высоту ZoomLayout. Трансформация на ребенка не производится.

Ожидаемое поведение

Когда высота контейнера изменяется, дочернее преобразование применяется для сохранения CenterCrop.

Макет XML (Extended 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
)

И еще одно изменение в onGlobalLayout() ZoomLayout

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

Это мне помогает. Дочерний элемент правильно выровнен с родительским, чтобы сохранить функциональность центральной обрезки. Но, это код рождения №185 вопроса. Очевидно, теперь я знаю причину, по которой Pan сбрасывается (подсказка # 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 Если это ожидается / необходимо, для этого поведения должен быть установлен флаг

Еще со вторника занимаюсь кодом библиотеки. Я почти ничего не знаю о том, как работают матрицы, векторы или шейдеры. Я стараюсь читать и изменять, чтобы учиться. Но я уже попробовал ваше предложение, прежде чем сообщать о проблеме. В результате панорамирование включено как для горизонтального, так и для вертикального направлений. И центральное кадрирование больше не доступно, так как контент / дочерний элемент, кажется, увеличен.

Спасибо за помощь. Мне очень жаль, что мне потребовалось больше времени, чтобы ответить.

@rupinderjeet Я попытался воспроизвести ваш пример, но при применении измененного LayoutParams к экземпляру ZoomLayout я получил собственное сообщение об ошибке:

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

Я что-то упускаю?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги