我有一个自定义的ViewGroup,它有一个子ViewPager。ViewPager由PagerAdapter馈送,该LinearLayout提供到在高度和宽度上都具有WRAP_CONTENT的ViewPager的LayoutParams。
视图可以正确显示,但是在ViewPager上调用child.measure()方法时,它不会返回LinearLayout的实际尺寸,但似乎会填满所有剩余空间。
你知道为什么会发生这种情况,以及如何修正吗?
发布于 2013-02-20 23:34:01
我对被接受的答案不是很满意(也不是对评论中的预膨胀-所有视图解决方案),所以我组合了一个ViewPager,它的高度取自第一个可用的孩子。它通过执行第二次测量来实现这一点,允许您窃取第一个孩子的身高。
更好的解决方案是在android.support.v4.view包中创建一个新类,该类实现更好版本的onMeasure (可以访问包可见的方法,如populate())
不过,就目前而言,下面的解决方案很适合我。
public class HeightWrappingViewPager extends ViewPager {
public HeightWrappingViewPager(Context context) {
super(context);
}
public HeightWrappingViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec)
== MeasureSpec.AT_MOST;
if(wrapHeight) {
/**
* The first super.onMeasure call made the pager take up all the
* available height. Since we really wanted to wrap it, we need
* to remeasure it. Luckily, after that call the first child is
* now available. So, we take the height from it.
*/
int width = getMeasuredWidth(), height = getMeasuredHeight();
// Use the previously measured width but simplify the calculations
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
/* If the pager actually has any children, take the first child's
* height and call that our own */
if(getChildCount() > 0) {
View firstChild = getChildAt(0);
/* The child was previously measured with exactly the full height.
* Allow it to wrap this time around. */
firstChild.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
height = firstChild.getMeasuredHeight();
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}发布于 2012-02-16 23:10:45
查看兼容性jar中ViewPager类的内部结构:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// For simple implementation, or internal size is always 0.
// We depend on the container to specify the layout size of
// our view. We can't really know what it is since we will be
// adding and removing different arbitrary views and do not
// want the layout to change as this happens.
setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
...
}看起来,ViewPager实现并没有测量子视图,而只是根据父视图传入的内容将ViewPager设置为一个标准视图。当您传递wrap_content时,由于视图分页实际上并不测量其内容,因此它占据了整个可用区域。
我的建议是根据子视图的大小在ViewPager上设置一个静态大小。如果这是不可能的(例如,子视图可能不同),您将需要选择一个最大大小并处理某些视图中的额外空间,或者扩展ViewPager并提供一个测量子视图的onMeasure。您将遇到的一个问题是,视图分页程序的设计不会因为显示不同的视图而改变宽度,因此您可能会被迫选择一个大小并继续使用它
发布于 2014-03-02 02:41:08
如果你在你的PageAdapter的instantiateItem中定位(SetTag):
@Override
public Object instantiateItem(ViewGroup collection, int page) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = (View) inflater.inflate(R.layout.page_item , null);
view.setTag(page);然后,可以使用OnPageChangeListener检索视图(适配器的页面),测量它,并调整ViewPager的大小:
private ViewPager pager;
@Override
protected void onCreate(Bundle savedInstanceState) {
pager = findViewById(R.id.viewpager);
pager.setOnPageChangeListener(new SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
resizePager(position);
}
});
public void resizePager(int position) {
View view = pager.findViewWithTag(position);
if (view == null)
return;
view.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
//The layout params must match the parent of the ViewPager
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width , height);
pager.setLayoutParams(params);
}
}https://stackoverflow.com/questions/9313554
复制相似问题