BottomSheetDialogFragment 中的 ViewPager

ViewPager inside BottomSheetDialogFragment

我正在尝试在 BottomSheetDialogFragment 中设置一个 viewpager,但结果始终相同:

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

设置对话框

代码:

@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();
    }
}

布局 代码:

<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>

如果有人对此实现有所了解,那将对我非常有用。

提前致谢!

尝试像下面这样更改您的代码:

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

已更新

我在 "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;
}

我想指出另一种方法:

当您想要在 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中inflate自己的layout

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
        

您只需启用视图寻呼机的滚动功能即可:

ViewCompat.setNestedScrollingEnabled(viewPager2, true);

如果仍然没有滚动,请将 NestedScrollView 添加到您所有的 viewpager 子片段中。