Я установил простой ViewPager, который имеет ImageView с высотой 200dp на каждой странице.
Вот мой пейджер:
pager = new ViewPager(this);
pager.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
pager.setBackgroundColor(Color.WHITE);
pager.setOnPageChangeListener(listener);
layout.addView(pager);
Несмотря на высоту, заданную как wrap_content, пейджер всегда заполняет экран, даже если просмотр изображения только 200dp. Я попытался заменить высоту пейджера на «200», но это дает мне разные результаты с несколькими разрешениями. Я не могу добавить «dp» к этому значению. Как добавить 200dp в макет пейджера?
Ответы:
Переопределение параметра «Измерить ваше»
ViewPager
следующим образом позволит ему получить рост самого большого ребенка, которого он имеет в настоящее время.источник
Другое более общее решение -
wrap_content
просто начать работать.Я расширил,
ViewPager
чтобы переопределитьonMeasure()
. Высота оборачивается вокруг первого дочернего вида. Это может привести к неожиданным результатам, если дочерние представления имеют разную высоту. Для этого класс можно легко расширить, скажем, до размера текущего представления / страницы. Но мне это не нужно.Вы можете использовать этот ViewPager в своих XML-макетах так же, как и оригинальный ViewPager:
Преимущество: этот подход позволяет использовать ViewPager в любом макете, включая RelativeLayout, для наложения других элементов пользовательского интерфейса.
Остается один недостаток: если вы хотите использовать поля, вы должны создать два вложенных макета и дать внутреннему желаемые поля.
Вот код:
источник
Я основал свой ответ на Даниэле Лопесе Лакалье и на этом посте http://www.henning.ms/2013/09/09/viewpager-that-simply-dont-measure-up/ . Проблема с ответом Даниэля в том, что в некоторых случаях мои дети имели нулевой рост. Решение было, к сожалению, измерить дважды.
Это также позволяет вам установить высоту на ViewPager, если вы этого хотите, или просто wrap_content.
источник
scaleType
и аналогично,layout_width=match_parent
а такжеlayout_height=wrap_content
? там как 20dp там не хватает.// super has to be called in the beginning so the child views can be initialized.
<----- Это была причина, пришлось вызывать ее в начале и в конце функции onMeasure. Yippiii, виртуальная пятерка на мне сегодня!Я просто отвечал на очень похожий вопрос по этому поводу, и случайно нашел его, когда искал ссылку для подтверждения своих утверждений, так что удачи вам :)
Мой другой ответ:
ViewPager не поддерживает,
wrap_content
поскольку у него (как правило) никогда не загружаются все его дочерние элементы одновременно, и поэтому он не может получить соответствующий размер (можно использовать пейджер, который меняет размер при каждом переключении страница).Тем не менее, вы можете установить точный размер (например, 150dp) и
match_parent
работает также.Вы также можете динамически изменять размеры из своего кода, изменив
height
-attribute в егоLayoutParams
.Для ваших нужд вы можете создать ViewPager в своем собственном xml-файле с значением layout_height, равным 200dp, а затем в своем коде, вместо создания нового ViewPager с нуля, вы можете надуть этот xml-файл:
источник
layout_height
установленным значениемwrap_content
, но это еще хуже, поскольку простой обходной путь для установки ее на фиксированную величину не работает.Используя ответ Daniel López Localle , я создал этот класс в Котлине. Надеюсь, это сэкономит вам больше времени
источник
Я уже сталкивался с этой проблемой в нескольких проектах и никогда не имел полного решения. Поэтому я создал проект github WrapContentViewPager в качестве замены ViewPager на месте.
https://github.com/rnevet/WCViewPager
Решение было вдохновлено некоторыми ответами здесь, но улучшается:
Обновлен для поддержки библиотеки версии 24, которая сломала предыдущую реализацию.
источник
Я просто столкнулся с той же проблемой. У меня был ViewPager, и я хотел показать объявление на кнопке. Решение, которое я нашел, состояло в том, чтобы вставить пейджер в RelativeView и установить его layout_above с идентификатором представления, который я хочу видеть под ним. это сработало для меня.
вот мой макет XML:
источник
Я также столкнулся с этой проблемой, но в моем случае у меня была страница,
FragmentPagerAdapter
которая снабжалаViewPager
ее страницами. Проблема, с которой я столкнулся, заключалась в том, чтоonMeasure()
методViewPager
вызывался до того, как какой-либо изFragments
них был создан (и поэтому не мог правильно определить размер).После нескольких проб и ошибок я обнаружил, что
finishUpdate()
метод FragmentPagerAdapter вызывается послеFragments
инициализации (изinstantiateItem()
inFragmentPagerAdapter
), а также после / во время прокрутки страницы. Я сделал небольшой интерфейс:который я передаю в мой
FragmentPagerAdapter
и называю:что в свою очередь позволяет мне обратиться
setVariableHeight()
к моейCustomViewPager
реализации:Я не уверен, что это лучший подход, хотел бы услышать комментарии, если вы думаете, что это хорошо / плохо / зло, но, похоже, в моей реализации это работает довольно хорошо :)
Надеюсь, это поможет кому-то там!
РЕДАКТИРОВАТЬ: я забыл добавить
requestLayout()
после вызоваsuper.measure()
(в противном случае это не перерисовать представление).Я также забыл добавить отступы родителя до конечной высоты.
Я также прекратил сохранять исходные параметры MeasureSpec ширины / высоты в пользу создания нового по мере необходимости. Обновили код соответствующим образом.
Еще одна проблема, с которой я столкнулся, заключалась в том, что он не мог правильно
ScrollView
определить размер в a и обнаружил, что виновник измерял ребенкаMeasureSpec.EXACTLY
вместоMeasureSpec.UNSPECIFIED
. Обновлено, чтобы отразить это.Все эти изменения были добавлены в код. Вы можете проверить историю, чтобы увидеть старые (неправильные) версии, если хотите.
источник
Другое решение заключается в обновлении
ViewPager
высоты в соответствии с текущей высотой страницыPagerAdapter
. Предполагая, что вы создаете своиViewPager
страницы таким образом:Где
mPages
внутренний списокPageInfo
структур, динамически добавляемый вPagerAdapter
иCustomImageView
просто обычныйImageView
с переопределеннымonMeasure()
методом, который устанавливает его высоту в соответствии с заданной шириной и сохраняет пропорции изображения.Вы можете форсировать
ViewPager
высоту вsetPrimaryItem()
методе:Обратите внимание
Math.max(height, 1)
. Это исправляет досадную ошибку,ViewPager
которая не обновляет отображаемую страницу (показывает ее пустой), когда предыдущая страница имеет нулевую высоту (то есть нулевую отрисовку вCustomImageView
), каждый нечетный пролистывание назад и вперед между двумя страницами.источник
item.mImageView.measure(..)
правильные измерения вgetMeasuredXXX()
методы.Если вы используете статический контент внутри виджета, и вам не нужна необычная анимация, вы можете использовать следующий вид пейджер.
источник
источник
Исходя из исходного кода приложения Popcorn time для Android, я нашел это решение, которое динамически регулирует размер окна просмотра с приятной анимацией в зависимости от размера текущего потомка.
https://git.popcorntime.io/popcorntime/android/blob/5934f8d0c8fed39af213af4512272d12d2efb6a6/mobile/src/main/java/pct/droid/widget/WrappingViewPager.java
источник
В случае, если вам нужен ViewPager, который настраивает его размер для каждого дочернего элемента , а не только для самого большого, я написал фрагмент кода, который это делает. Обратите внимание, что анимация после этого изменения отсутствует (в моем случае это не обязательно)
android: флаг minHeight также поддерживается.
источник
Улучшенный ответ Даниэля Лопеса Лакалье , переписанный в Котлине :
источник
Я столкнулся с той же проблемой, и мне также пришлось заставить ViewPager обернуть его содержимое, когда пользователь прокручивал страницы. Используя приведенный выше ответ Cybergen, я определил метод onMeasure следующим образом:
Таким образом, метод onMeasure устанавливает высоту текущей страницы, отображаемой ViewPager.
источник
Ничто из предложенного выше не помогло мне. Мой вариант использования имеет 4 пользовательских ViewPager в
ScrollView
. Верхняя часть из них измеряется в зависимости от соотношения сторон, а остальное просто имеетlayout_height=wrap_content
. Я пробовал киберген , Daniel López Lacalle . Никто из них не работает полностью для меня.Я думаю, почему киберген не работает на странице> 1, потому что он вычисляет высоту пейджера на основе страницы 1, которая скрыта, если вы прокручиваете дальше.
В моем случае предложения кибергена и Даниэля Лопеса Лакалля ведут себя странно: 2 из 3 загружены нормально, а 1 случайно высотой равно 0. Появляется, что
onMeasure
был вызван до того, как дети были заполнены. Итак, я придумал смесь этих 2 ответов + мои собственные исправления:Идея состоит в том, чтобы позволить
ViewPager
рассчитать размеры детей и сохранить вычисленную высоту первой страницы в параметрах макетаViewPager
. Не забудьте установить высоту макета фрагмента,wrap_content
иначе вы можете получить высоту = 0. Я использовал это:Обратите внимание, что это решение прекрасно работает, если все ваши страницы имеют одинаковую высоту . В противном случае вам нужно пересчитать
ViewPager
высоту на основе текущего активного ребенка. Мне это не нужно, но если вы предложите решение, я буду рад обновить ответ.источник
Для людей, имеющих эту проблему и программирующих для Xamarin Android в C #, это также может быть быстрым решением:
Это в основном полезно, если ваши детские взгляды имеют одинаковую высоту. В противном случае вам потребуется хранить какое-то значение «минимума» по всем дочерним элементам, с которыми вы проверяете, и даже в этом случае вы можете не захотеть, чтобы пустые места были видны под вашими дочерними представлениями меньшего размера.
Однако само по себе решение не является достаточным для меня, но это потому, что мои дочерние элементы являются listViews, и их MeasuredHeight, похоже, вычисляется неправильно.
источник
У меня есть версия WrapContentHeightViewPager, которая работала правильно до API 23, которая будет изменять размер высоты родительского представления в текущем выбранном дочернем представлении.
После обновления до API 23 он перестал работать. Оказывается, старое решение использовалось
getChildAt(getCurrentItem())
для получения текущего дочернего представления для измерения, которое не работает. Смотрите решение здесь: https://stackoverflow.com/a/16512217/1265583Ниже работает с API 23:
источник
requestLayout()
так, что высота регулируется при переходе от одной вкладки к другой. Ты помнишь, почемуsuper
нужно звонить дважды? Я заметил, что иначе это не сработает.Код ниже - единственное, что сработало для меня
1. Используйте этот класс, чтобы объявить HeightWrappingViewPager:
2. Вставьте пейджер просмотра переноса высоты в ваш xml-файл:
3. Объявите свой вид пейджер:
источник
Я редактирую ответ cybergen для make viewpager, чтобы изменить высоту в зависимости от выбранного элемента. Класс такой же, как у cybergen, но я добавил Вектор целых чисел, который является высотой дочерних представлений всех viewpager, и мы можем получить к нему доступ при изменении страницы для обновления высоты.
Это класс:
Затем в вашей деятельности добавьте OnPageChangeListener
А вот и XML:
Пожалуйста, исправьте мой английский, если необходимо
источник
heights
Список может увеличиться в бесконечность.measure
он будет вызываться несколько раз. Это может увеличить список высот. Другая ситуация - пользователь может вызватьrequestLayout
(илиsetLayoutParams
метод, точно так же, как вы сделали) для этого viewPager вручную, а также будет измерять несколько раз.Если
ViewPager
вы используете дочерний элементScrollView
AND, у которого естьPagerTitleStrip
дочерний элемент, вам нужно будет слегка изменить уже предоставленные отличные ответы. Для справки мой XML выглядит так:В ваших
onMeasure
вы должны ADD в measuredHeight изPagerTitleStrip
если один найден. В противном случае его высота не будет считаться самой большой из всех детей, даже если она занимает дополнительное место.Надеюсь, это поможет кому-то еще. Извините, что это немного взломать ...
источник
Кажется, что большинство решений, которые я вижу здесь, выполняют двойное измерение: сначала измеряют дочерние представления, а затем вызывают
super.onMeasure()
Я пришел к заказу,
WrapContentViewPager
который является более эффективным, хорошо работает с RecyclerView и FragmentВы можете проверить демо здесь:
GitHub / ssynhtn / WrapContentViewPager
и код класса здесь: WrapContentViewPager.java
источник
У меня похожий (но более сложный сценарий). У меня есть диалог, который содержит ViewPager.
Одна из дочерних страниц короткая, со статической высотой.
Другая дочерняя страница всегда должна быть максимально высокой.
Другая дочерняя страница содержит ScrollView, и страница (и, следовательно, весь диалог) должна WRAP_CONTENT, если содержимому ScrollView не нужна полная высота, доступная для диалога.
Ни один из существующих ответов не работал полностью для этого конкретного сценария. Держись - это ухабистая поездка.
Большое спасибо @Raanan за код для измерения видов и измерения высоты декора. Я столкнулся с проблемами с его библиотекой - анимация заикалась, и я думаю, что мой ScrollView не будет прокручиваться, когда высота диалога была достаточно короткой, чтобы этого потребовать.
источник
в моем случае добавление
clipToPadding
решило проблему.Ура!
источник
В моем случае добавление Android: fillViewport = "true" решило проблему
источник
В моем случае мне понадобился просмотрщик с wrap_content для выбранного в данный момент элемента и анимация при применении размера. Ниже вы можете увидеть мою реализацию. Может кому-нибудь пригодится.
Добавьте attrs.xml в проект:
И использовать:
источник
Этот ViewPager изменяет размеры только для текущих видимых потомков (не самый большой из его реальных потомков)
Идея от https://stackoverflow.com/a/56325869/4718406
}
источник
Измерьте высоту ViewPager:
вызов setPrimaryView (Просмотр) :
источник
Предоставить родительский макет ViewPager как
NestedScrollView
Не забудьте установить
android:fillViewport="true"
Это растянет scrollview и его дочернее содержимое, чтобы заполнить область просмотра.
https://developer.android.com/reference/android/widget/ScrollView.html#attr_android:fillViewport
источник
Вы можете переключиться на ViewPager2. Это обновленная версия ViewPager. Он делает то же самое, что и ViewPager, но умнее и эффективнее. ViewPager2 поставляется с множеством новых функций. Конечно, проблема с Wrap Content была решена ViewPager2.
Из документов Android: «ViewPager2 заменяет ViewPager, решая большинство проблем его предшественника, включая поддержку разметки справа налево, вертикальную ориентацию, изменяемые коллекции фрагментов и т. Д.»
Я рекомендую эту статью для начинающих:
https://medium.com/google-developer-experts/exploring-the-view-pager-2-86dbce06ff71
источник