我已经设置了一个简单的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添加到寻呼机的布局?


当前回答

我已经在几个项目中遇到过这个问题,从来没有一个完整的解决方案。所以我创建了一个WrapContentViewPager github项目作为ViewPager的替代。

https://github.com/rnevet/WCViewPager

解决方案的灵感来自这里的一些答案,但改进了:

根据当前视图(包括滚动时)动态更改ViewPager高度。 考虑像PagerTabStrip这样的“装饰”视图的高度。 考虑所有填充。

更新到支持库版本24,打破了以前的实现。

其他回答

在我的情况下,添加clipToPadding解决了这个问题。

<android.support.v4.view.ViewPager
    ...
    android:clipToPadding="false"
    ...
    />

干杯!

public CustomPager (Context context) {
    super(context);
}

public CustomPager (Context context, AttributeSet attrs) {
    super(context, attrs);
}

int getMeasureExactly(View child, int widthMeasureSpec) {
    child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    int height = child.getMeasuredHeight();
    return MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;

    final View tab = getChildAt(0);
    if (tab == null) {
        return;
    }

    int width = getMeasuredWidth();
    if (wrapHeight) {
        // Keep the current measured width.
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
    }
    Fragment fragment = ((Fragment) getAdapter().instantiateItem(this, getCurrentItem()));
    heightMeasureSpec = getMeasureExactly(fragment.getView(), widthMeasureSpec);

    //Log.i(Constants.TAG, "item :" + getCurrentItem() + "|height" + heightMeasureSpec);
    // super has to be called again so the new specs are treated as
    // exact measurements.
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

我只是在回答一个非常类似的问题,在寻找一个链接来支持我的说法时,碰巧发现了这个,你很幸运:)

我的另一个回答是: ViewPager不支持wrap_content,因为它(通常)不会同时加载所有的子页面,因此无法获得适当的大小(可以选择在每次切换页面时改变大小)。

然而,你可以设置一个精确的尺寸(例如150dp)和match_parent也可以。 您还可以通过更改其LayoutParams中的height-属性,从代码中动态修改维度。

根据你的需要,你可以在它自己的xml文件中创建ViewPager, layout_height设置为200dp,然后在你的代码中,而不是从头创建一个新的ViewPager,你可以扩展这个xml文件:

LayoutInflater inflater = context.getLayoutInflater();
inflater.inflate(R.layout.viewpagerxml, layout, true);

给ViewPager的父布局NestedScrollView

   <androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    android:fillViewport="true">
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </androidx.viewpager.widget.ViewPager>
    </androidx.core.widget.NestedScrollView>

别忘了设置android:fillViewport="true"

这将拉伸滚动视图及其子内容以填充视口。

https://developer.android.com/reference/android/widget/ScrollView.html#attr_android:fillViewport

我在这里看到的大多数解决方案似乎都在做双重测量:首先测量子视图,然后调用super.onMeasure()

我提出了一个自定义的WrapContentViewPager是更有效的,与RecyclerView和片段工作得很好

你可以在这里查看演示:

github/ssynhtn/WrapContentViewPager

这个类的代码是: WrapContentViewPager.java