android - 具有动态高度的 Viewpager 不起作用(始终使用第一个 fragment 的高度)

标签 android android-fragments android-viewpager

我关注了thisthat答案,我也找到了this链接。

我使用这些资源进行试错。现在我的自定义 ViewPager 成功测量了它的内容,但只显示了第一个。仅供引用,我的 ViewPager 包含一些复杂的 View ,例如 ExpendableListView - 这就是为什么这些资源中的代码都无法正常工作,我需要自己修改代码。

我有 4 个 fragment (内容),所以我使用 pager.setOffscreenPageLimit(3);

这是我的自定义 ViewPager :

public class CustomViewPager extends ViewPager{

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

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

    @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);
        int width = getMeasuredWidth();
        int tabHeight = tab.getMeasuredHeight();

        if (wrapHeight) {
            // Keep the current measured width.
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
        }

        int fragmentHeight = measureFragment(((Fragment) getAdapter().instantiateItem(this, getCurrentItem())).getView());
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(tabHeight + fragmentHeight + (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()), MeasureSpec.AT_MOST);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}

这是我的CustomPagerTabStrip:

int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
android.view.ViewGroup.LayoutParams params =  getLayoutParams();
params.height = getMeasuredHeight();

这是我的 XML:

        <RelativeLayout
            android:id="@+id/relativePager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <com.xxx.yyy.util.CustomViewPager
                android:id="@+id/detailPager"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >

                <com.xxx.yyy.util.CustomPagerTabStrip
                    android:id="@+id/detailTab"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#161C28"
                    android:textColor="#FFFFFF" />
            </com.xxx.yyy.util.CustomViewPager>

        </RelativeLayout>

案例:

如果第一个 fragment 的高度为 100px,则所有其他 fragment 都将保持在 100px。 因此,如果第二个 fragment 的高度为 130px,它将被剪切为 100px。

当我尝试调试时,当 Activity 为创建,但他们都只读了第一个 fragment 。 onMeasure 从未在那之后再次被调用,即使当我从一个 fragment 更改(向左/向右滑动)到另一个 fragment 时也是如此。

请帮帮我,我花了很多时间才让这个东西工作。 如果您需要更多信息,请问我,感谢您抽出时间。

最佳答案

嗨,Blaze 发现有些东西用完了,下面的解决方案对我有用。

它包括自定义 ScrollView 和自定义 View 寻呼机。自定义 View 分页器的目的是根据其子项的高度动态计算高度,其高度最初设置为包装内容, ScrollView 的目的是处理触摸事件,如果用户垂直滚动屏幕,它将不会通过触摸甚至滚动,因此用户能够滚动页面。

自定义 ScrollView

public class CustomScrollView extends ScrollView {

private GestureDetector mGestureDetector;

public CustomScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mGestureDetector = new GestureDetector(context, new YScrollDetector());
    setFadingEdgeLength(0);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return super.onInterceptTouchEvent(ev)
            && mGestureDetector.onTouchEvent(ev);
}

// Return false if we're scrolling in the x direction
class YScrollDetector extends SimpleOnGestureListener {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
            float distanceX, float distanceY) {
        return (Math.abs(distanceY) > Math.abs(distanceX));
    }
}
}

自定义 View 寻呼机

public class CustomPager extends ViewPager{

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

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

@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);
    int width = getMeasuredWidth();
    int tabHeight = tab.getMeasuredHeight();

    if (wrapHeight) {
        // Keep the current measured width.
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
    }

    int fragmentHeight = measureFragment(((Fragment) getAdapter().instantiateItem(this, getCurrentItem())).getView());
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(tabHeight + fragmentHeight + (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()), MeasureSpec.AT_MOST);

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public int measureFragment(View view) {
    if (view == null)
        return 0;

    view.measure(0, 0);
    return view.getMeasuredHeight();
}
}

布局文件

<com.example.demo2.activity.widget.CustomScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        style="@style/text"
        android:text="Text 1" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 2" />


        <com.example.demo2.activity.widget.CustomPager
          android:id="@+id/myViewPager"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 4" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 5" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 6" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 7" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 8" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 9" />

    <View style="@style/text_divider" />

    <TextView
        style="@style/text"
        android:text="Text 10" />
</LinearLayout>

Activity

public class MainActivity extends FragmentActivity {



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    MyPagerAdapter pageAdapter = new MyPagerAdapter(getSupportFragmentManager());
    ViewPager pager = (ViewPager)findViewById(R.id.myViewPager);
    pager.setAdapter(pageAdapter);

}



}

fragment 适配器

具有不同高度的 fragment 被添加到 viewpager,FragmentBlue、Green 等只是用于添加到 viewpager 的 fragment 你可以使用你自己的 fragment ,要记住的一件事是它们的外部布局应该是相同的在我的情况下我使用了衬里所有人的布局

public class MyPagerAdapter extends FragmentPagerAdapter {

private List<Fragment> fragments;

public MyPagerAdapter(FragmentManager fm) {
    super(fm);
    this.fragments = new ArrayList<Fragment>();
    fragments.add(new FragmentBlue());
    fragments.add(new FragmentGreen());
    fragments.add(new FragmentPink());
    fragments.add(new FragmentRed());
}

@Override
public Fragment getItem(int position) {
    return fragments.get(position);
}

@Override
public int getCount() {
    return fragments.size();
}
}

关于android - 具有动态高度的 Viewpager 不起作用(始终使用第一个 fragment 的高度),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23560375/

相关文章:

Android Viewpager 保存数据和 View

java - Java 代码在单个线程中的执行是否保证是顺序的?

android - 即使未调用 onCreateView 也刷新当前 Fragment

android - 使用 backstack 时 fragment 未替换

java - Kotlin ViewPager2 : Class 'ScreenSlidePagerAdapter' is not abstract and does not implement base class member

android - 带有 viewpager 的协调器布局,滚动不起作用

android - Android fragment 问题

Android imageview 长按提示

android - 在android中获取微录音频的指纹/语音打印

Android 音频控制前进和后退