首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >测量ViewPager

测量ViewPager
EN

Stack Overflow用户
提问于 2012-02-16 23:01:37
回答 6查看 20.8K关注 0票数 18

我有一个自定义的ViewGroup,它有一个子ViewPager。ViewPager由PagerAdapter馈送,该LinearLayout提供到在高度和宽度上都具有WRAP_CONTENTViewPagerLayoutParams

视图可以正确显示,但是在ViewPager上调用child.measure()方法时,它不会返回LinearLayout的实际尺寸,但似乎会填满所有剩余空间。

你知道为什么会发生这种情况,以及如何修正吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2013-02-20 23:34:01

我对被接受的答案不是很满意(也不是对评论中的预膨胀-所有视图解决方案),所以我组合了一个ViewPager,它的高度取自第一个可用的孩子。它通过执行第二次测量来实现这一点,允许您窃取第一个孩子的身高。

更好的解决方案是在android.support.v4.view包中创建一个新类,该类实现更好版本的onMeasure (可以访问包可见的方法,如populate())

不过,就目前而言,下面的解决方案很适合我。

代码语言:javascript
复制
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);
        }
    }
}
票数 57
EN

Stack Overflow用户

发布于 2012-02-16 23:10:45

查看兼容性jar中ViewPager类的内部结构:

代码语言:javascript
复制
@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。您将遇到的一个问题是,视图分页程序的设计不会因为显示不同的视图而改变宽度,因此您可能会被迫选择一个大小并继续使用它

票数 12
EN

Stack Overflow用户

发布于 2014-03-02 02:41:08

如果你在你的PageAdapter的instantiateItem中定位(SetTag):

代码语言:javascript
复制
@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的大小:

代码语言:javascript
复制
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);
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9313554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档