我已经设置了一个简单的ViewPager,每页都有一个高度为200dp的ImageView .
这是我的寻呼机:
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,但即使imageview仅为200dp,寻呼机也会填充屏幕 . 我试图用“200”替换寻呼机的高度,但这给了我多种分辨率的不同结果 . 我无法将“dp”添加到该值 . 如何在寻呼机的布局中添加200dp?
22 回答
我已经在几个项目中遇到过这个问题,从来没有一个完整的解决方案 . 所以我创建了一个WrapContentViewPager github项目作为ViewPager的就地替代品 .
https://github.com/rnevet/WCViewPager
解决方案的灵感来自于此处的一些答案,但改进了:
根据当前视图动态更改ViewPager高度,包括滚动时 .
考虑像PagerTabStrip这样的"decor"视图的高度 .
考虑所有Padding .
Updated for support library version 24 which broke previous implementation.
我也遇到了这个问题,但在我的情况下,我有一个
FragmentPagerAdapter
,它正在为ViewPager
提供其页面 . 我遇到的问题是ViewPager
的onMeasure()
在创建任何Fragments
之前被调用(因此无法正确调整大小) .经过一些试验和错误后,我发现在
Fragments
初始化之后(从FragmentPagerAdapter
中的instantiateItem()
)以及页面滚动之后/期间调用了FragmentPagerAdapter的finishUpdate()
方法 . 我做了一个小界面:我传入我的
FragmentPagerAdapter
并致电:这反过来允许我在我的
CustomViewPager
实现上调用setVariableHeight()
:我不确定这是最好的方法,如果你认为好/坏/邪恶会喜欢评论,但它似乎在我的实现中工作得很好:)
希望这有助于那里的人!
EDIT: 我忘了在调用
super.measure()
之后添加requestLayout()
(否则它不会重绘视图) .我也忘了将父级的填充添加到最终高度 .
我还保留原始宽度/高度MeasureSpecs,有利于根据需要创建一个新的 . 已相应更新了代码 .
我遇到的另一个问题是它在
ScrollView
中无法正确调整大小,并发现罪魁祸首是用MeasureSpec.EXACTLY
而不是MeasureSpec.UNSPECIFIED
测量孩子 . 更新以反映这一点 .这些更改都已添加到代码中 . 如果需要,您可以查看历史记录以查看旧版本(不正确) .
我遇到了同样的问题,当用户在页面之间滚动时,我还必须使ViewPager包装其内容 . 使用cybergen的上述答案,我将onMeasure方法定义如下:
这样,onMeasure方法设置ViewPager显示的当前页面的高度 .
我的情况添加android:fillViewport =“true”解决了这个问题
对于有这个问题并在C#中编写Xamarin Android的人来说,这也可能是一个快速的解决方案:
如果您的孩子视图具有相同的高度,这将非常有用 . 否则,您将需要为您检查的所有子项存储某种“minimumHeight”值,即使这样,您可能也不希望在较小的子视图下方显示空白空间 .
解决方案本身对我来说还不够,但这是因为我的子项是listViews,而且它们的MeasuredHeight计算不正确 .
在我的情况下添加
clipToPadding
解决了问题 .干杯!
另一种解决方案是根据
PagerAdapter
中的当前页面高度更新ViewPager
高度 . 假设您以这种方式创建ViewPager
页面:其中
mPages
是动态添加到PagerAdapter
的PageInfo
结构的内部列表,而CustomImageView
只是常规的ImageView
,其覆盖onMeasure()
方法根据指定的宽度设置其高度并保持图像宽高比 .您可以在
setPrimaryItem()
方法中强制ViewPager
高度:注意
Math.max(height, 1)
. 这修复了ViewPager
没有更新显示页面(显示为空白)的烦人的错误,当前一页面具有零高度(即CustomImageView
中为null drawable)时,每个奇数在两页之间来回滑动 .我有一个版本的WrapContentHeightViewPager,它在API 23之前正常工作,它将在所选的当前子视图上调整父视图的高度基础 .
升级到API 23后,它停止工作 . 事实证明,旧的解决方案是使用
getChildAt(getCurrentItem())
来获取当前子视图以测量哪些不起作用 . 请在此处查看解决方案:https://stackoverflow.com/a/16512217/1265583以下适用于API 23:
我刚刚碰到了同样的问题 . 我有一个ViewPager,我想在它的按钮上显示一个广告 . 我找到的解决方案是将寻呼机放入RelativeView并将其layout_above设置为我想在下面看到的视图ID它 . 这对我有用 .
这是我的布局XML:
使用Daniel López Localle回答,我在Kotlin中创建了这个类 . 希望它能为您节省更多时间
在viewpager中使用静态内容并且您不希望使用任何花哨的动画时,您可以使用以下视图寻呼机
从爆米花时间android应用程序的源代码我发现这个解决方案动态调整viewpager的大小与漂亮的动画取决于当前孩子的大小 .
https://git.popcorntime.io/popcorntime/android/blob/5934f8d0c8fed39af213af4512272d12d2efb6a6/mobile/src/main/java/pct/droid/widget/WrappingViewPager.java
另一个更通用的解决方案是让
wrap_content
正常工作 .我已经扩展
ViewPager
以覆盖onMeasure()
. 高度围绕第一个子视图 . 如果子视图的高度不完全相同,这可能会导致意外结果 . 为此,可以轻松扩展该类,让's say animate to the size of the current view/page. But I didn' t需要它 .您可以像原始ViewPager一样在您的XML布局中使用此ViewPager:
优点:此方法允许在包括RelativeLayout在内的任何布局中使用ViewPager来覆盖其他ui元素 .
仍然存在一个缺点:如果要使用边距,则必须创建两个嵌套布局,并为内部布局提供所需的边距 .
这是代码:
我的答案基于DanielLópezLacalle和这篇文章http://www.henning.ms/2013/09/09/viewpager-that-simply-dont-measure-up/ . Daniel的答案的问题在于,在某些情况下,我的孩子的身高为零 . 不幸的是,解决方案是两次测量 .
如果您想要或只是wrap_content,这也允许您在ViewPager上设置高度 .
上面没有任何建议对我有用 . 我的用例是在
ScrollView
中有4个自定义ViewPagers . 其中顶部是根据纵横比测量的,其余部分只有layout_height=wrap_content
. 我试过cybergen,Daniel López Lacalle解决方案 . 他们都不能完全为我工作 .我的猜测为什么 cybergen 在页面> 1上不起作用是因为它根据第1页计算寻呼机的高度,如果你进一步滚动则隐藏它 .
在我的情况下, cybergen 和 Daniel López Lacalle 建议都有奇怪的行为:3个中的2个加载正常,1个随机高度为0.看起来在填充子项之前调用了
onMeasure
. 所以我想出了这两个答案的混合我自己的修复:想法是让
ViewPager
计算儿童的尺寸,并在ViewPager
的布局参数中保存第一页的计算高度 . 将't forget to set fragment'的布局高度设置为wrap_content
否则可以获得height = 0 . 我用过这个:Please note that this solution works great if all of your pages have same height . 否则,您需要根据当前活动的子项重新计算
ViewPager
高度 . 我不需要它,但如果你建议解决方案,我很乐意更新答案 .我刚刚回答了一个非常相似的问题,并且在寻找支持我的索赔的链接时碰巧找到了这个,所以很幸运你:)
我的另一个答案:
ViewPager不支持
wrap_content
,因为它(通常)不会同时加载所有子项,因此无法获得适当的大小(选项是每次切换页面时都有一个更改大小的寻呼机) .但是,您可以设置精确尺寸(例如150dp)和
match_parent
也可以 .您还可以通过更改
LayoutParams
中的height
-attribute来动态修改维度 .根据您的需要,您可以在自己的xml文件中创建ViewPager,并将layout_height设置为200dp,然后在代码中,而不是从头开始创建新的ViewPager,您可以为该xml文件充气:
我有一个类似的(但更复杂的情况) . 我有一个包含ViewPager的对话框 .
其中一个子页面很短,具有静态高度 .
另一个子页面应该尽可能高 .
另一个子页面包含ScrollView,如果ScrollView内容不需要对话框可用的完整高度,则页面(以及整个对话框)应为WRAP_CONTENT .
现有的答案都没有完全适用于这种特定情况 . 坚持下去 - 这是一个坎坷的旅程 .
非常感谢@Rananan测量视图和测量装饰高度的代码 . 我遇到了他的图书馆的问题 - 动画结结巴巴,我认为当对话框的高度足够短以至于需要时,我的ScrollView不会滚动 .
如果你正在使用的
ViewPager
是ScrollView
的孩子并且有一个PagerTitleStrip
孩子,你需要稍微修改已经提供的好答案 . 作为参考,我的XML看起来像这样:在你的
onMeasure
中你必须添加PagerTitleStrip
的measuredHeight(如果找到一个) . 否则,它的高度将不会被视为所有孩子的最大高度,即使它占用额外的空间 .希望这有助于其他人 . 对不起,这有点像黑客......
如果您需要 adjust its size to every child 的ViewPager,而不仅仅是最大的那个,我已经编写了一段代码来完成它 . 请注意,在更改时没有动画(在我的情况下不是必需的)
android:minHeight标志也是支持的 .
我找到了一个解决方案,有点像合并这里提到的一些解决方案 .
我们的想法是测量ViewPager的当前视图 .
扩展ViewPager:
在ViewPager适配器中:
如果您使用RecyclerPagerAdapter library,获取"currentView"的方法是从您设置的pager-view-holder获取它:
按照以下方式覆盖
ViewPager
的测量将使其达到目前最大的孩子的身高 .