BottomSheetDialogFragment 中包含 ViewPager

10

我试图在BottomSheetDialogFragment中设置一个viewpager,但总是出现相同的结果:

java.lang.IllegalStateException: Fragment does not have a view

setupDialog

代码:

@Override
public void setupDialog(Dialog dialog, int style) {
    Log.d(TAG, "setupDialog");
    super.setupDialog(dialog, style);

    View root = View.inflate(getContext(), R.layout.fragment_daily_detail, null);
    dialog.setContentView(root);
    CoordinatorLayout.LayoutParams layoutParams =
            (CoordinatorLayout.LayoutParams) ((View) root.getParent()).getLayoutParams();
    CoordinatorLayout.Behavior behavior = layoutParams.getBehavior();

    if (behavior != null && behavior instanceof BottomSheetBehavior) {
        bottomSheetBehavior = (BottomSheetBehavior) behavior;
        bottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);
        bottomSheetBehavior.setPeekHeight((int) getResources().getDimension(R.dimen.fragment_forgot_password_min_height));
        Log.d(TAG, "State: " + bottomSheetBehavior.getState());

        imageClose = root.findViewById(R.id.imageViewClose);
        textViewTitle = (TextView) root.findViewById(R.id.textViewTitle);
        peekLayout = root.findViewById(R.id.peekLayout);
        tabLayout = (TabLayout) root.findViewById(R.id.tabs);
        viewPager = (ViewPager) root.findViewById(R.id.viewPager);

        recyclerView = (RecyclerView) root.findViewById(R.id.recyclerView);

        timesheetDay = timesheetDayList.get(pageNumber);

        imageClose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            }
        });
        textViewTitle.setText(timesheetDay.getDate());

        sectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
        viewPager.setAdapter(sectionsPagerAdapter);
        tabLayout.setupWithViewPager(viewPager);
    }
}

FragmentPagerAdapter

代码:

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return PageFragment.getInstance(timesheetDayList.get(position));
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return timesheetDayList.get(position).getDate();
    }
}

LAYOUT 代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_material_light"
android:clickable="true"
android:orientation="vertical"
tools:context=".ui.dialogs.bottomsheets.ForgotUsernameFragment">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginLeft="0dp"
    android:layout_marginTop="0dp">

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

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            android:background="@color/colorPrimary"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/imageViewClose"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="?attr/selectableItemBackgroundBorderless"
                android:clickable="true"
                android:padding="16dp"
                app:srcCompat="@drawable/ic_close_white_24dp"
                tools:ignore="MissingPrefix"
                tools:src="@drawable/ic_close_white_24dp" />

            <TextView
                android:id="@+id/textViewTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Daily Detail"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="@color/colorWhite" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/linearLayout2"
            android:orientation="vertical">

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorPrimary"
                app:tabMode="scrollable" />

            <android.support.v4.view.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </LinearLayout>

    </RelativeLayout>
</RelativeLayout>

如果有人了解这个实现,对我来说会非常有用。

祝福并提前感谢!


我能看到 SectionsPagerAdapter 吗? - pRaNaY
4个回答

12

更新

我解决了在 "onCreateView()" 中扩展视图的问题。无论如何,我已经在ViewPager中设置了一个RecyclerView,但是RecyclerView的垂直滚动非常不稳定,有时有效,有时无效,因此我将尝试以另一种方式实现这个屏幕。

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.d(TAG, "onCreateview");

    View root = inflater.inflate(R.layout.fragment_daily_detail, container);

    mImageClose = root.findViewById(R.id.imageViewClose);
    mTextViewTitle = (TextView) root.findViewById(R.id.textViewTitle);
    mPeekLayout = root.findViewById(R.id.peekLayout);
    mTabLayout = (TabLayout) root.findViewById(R.id.tabs);
    mViewPager = (ViewPager) root.findViewById(R.id.viewPager);

    mImageClose.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getDialog().dismiss();
        }
    });

    mTextViewTitle.setText("Daily detail");

    mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mTabLayout.setupWithViewPager(mViewPager);

    mViewPager.setCurrentItem(mPageNumber);

    mPeekLayout.getViewTreeObserver().addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {

                    BottomSheetDialog dialog = (BottomSheetDialog) getDialog();

                    FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
                    mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);

                    // gets called after layout has been done but before display
                    // so we can get the height then hide the view
                    int height = mPeekLayout.getHeight();
                    Log.d(TAG, "Height: " + height);
                    mBottomSheetBehavior.setPeekHeight(height);
                    mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);
                }
            });

    return root;
}

1
太棒了!这个简直救了我一天的工作!:) - Ajay Shrestha
@Buntupana,你刚刚救了我的命,我相信你也会拯救成千上万的其他人 :D。当我使用onCreateDialog时,这是一个重大问题,但当我改用onCreateView时,它就正常工作了。 - Houssem Chlegou

1
尝试将您的代码更改如下:

...
LayoutInflater inflater = getActivity().getLayoutInflater();
root = inflater.inflate(R.layout.fragment_daily_detail, null);
...
sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
//Use getSupportFragmentManager() instead of getChildFragmentManager(),
...

1
BottomSheetDialogFragment中没有getSupportFragmentManager()方法,只能使用getFragmentManager()方法。我已经尝试过了,结果是java.lang.IllegalArgumentException: No view found for id 0x7f0e010e。我认为如果要在一个fragment中设置另一个fragment,应该使用getChildFragmentManager()方法,对吗? - Buntupana
如果您在片段中使用BottomSheetDialogFragment,片段无法直接调用getSupportFragmentManger(),但是活动可以。因此,您可以使用getActivity来调用片段所在的当前活动并获取getSupportFragmentManager()。 - pRaNaY
同样的结果。我认为getFragmentManager返回的是与getActivity().getSupportFragmentManager相同的内容,因为BottomSheetDialogFragment已经扩展了AppCompatDialogFragment。所以它们使用了支持库。 - Buntupana
我不在一个Fragment中使用BottomSheetDialogFragment。我是从Activity中调用它的。我试图在一个已经是Fragment的BottomSheetDialogFragment中显示一个ViewPager,所以我认为正确的方法是使用getChildFragmentManager(),但我不确定。 - Buntupana

0

你只需要启用视图页面的滚动即可:

ViewCompat.setNestedScrollingEnabled(viewPager2, true);

如果滚动仍然不存在,请将NestedScrollView添加到所有您的ViewPager子片段中。


0
我想指出另一种方法来实现这个:
当你想要在BottomSheetDialogFragment中使用带有片段的ViewPager时,不要覆盖onCreateDialog或setupDialog,而是覆盖onStart。
override fun onStart() {
        super.onStart()
        bottomSheet =
            dialog!!.findViewById(com.google.android.material.R.id.design_bottom_sheet) as ViewGroup // notice the R root package
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet) 
        // SETUP YOUR BEHAVIOR HERE AND ADD THE BOTTOMSHEETCALLBACK HERE

然后在onCreateView方法中填充您自己的布局

override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
    
    val myview: View = inflater.inflate(R.layout.layout_bottom_sheet, container, false)
        
    // SETUP THE VIEWPAGER AND THE TABLAYOUT HERE. ALSO THE FRAGMENT PAGER ADAPTER
        

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接