ViewPager inside BottomSheetDialogFragment
Asked Answered
I

4

10

I'm trying to set a viewpager inside a BottomSheetDialogFragment but always with the same result:

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

setupDialog

Code:

@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

Code:

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

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

It would be very useful for me if anyone knows something about this implementation.

Cheers and thanks in advance!

Incontestable answered 12/4, 2016 at 11:5 Comment(1)
Can I see SectionsPagerAdapter ?Mccants
I
12

UPDATED

I solved the problem inflating the view in "onCreateView()". Anyway, I have setted a RecyclerView inside the ViewPager and the RecyclerView vertical scroll is very unstable, sometimes works and sometimes doesn't, so I'll try do this screen in another way.

@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;
}
Incontestable answered 15/4, 2016 at 14:27 Comment(2)
Awesome. It saves my day :)Agosto
@Incontestable , you have just saved my life, as i believe you will save millions of others :D . this was an major problem for me, when i was working with onCreateDialog, but when i changed to onCreateView, it worked fine.Solicitous
M
1

Try to change your code like below:

...
LayoutInflater inflater = getActivity().getLayoutInflater();
root = inflater.inflate(R.layout.fragment_daily_detail, null);
...
sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
//Use getSupportFragmentManager() instead of getChildFragmentManager(),
...
Mccants answered 12/4, 2016 at 11:16 Comment(4)
there is no getSupportFragmentManager() in BottomSheetDialogFragment, just getFragmentManager(). I have already tried it. The result was java.lang.IllegalArgumentException: No view found for id 0x7f0e010e. I think that to set a fragment inside other fragment I should use getChildFragmentManager(), isn't it?Incontestable
If you using BottomSheetDialogFragment into fragment , fragment is not capable of directly calling getSupportFragmentManger() but Activity can . Thus, you can use getActivity to call the current activity which the fragment is in and get getSupportFragmentManager().Mccants
Same result. I assume that getFragmentManager return the same that getActivity().getSupportFragmentManager because BottomSheetDialogFragment is already extending of AppCompatDialogFragment. So they use the support library.Incontestable
I don't use BottomSheetDialogFragment into a fragment. I call this from an Activity. I trying to show a ViewPager into a BottomSheetDialogFragment that is already a fragment, so I think that the proper way is with getChildFragmentManager(), but I don't know really.Incontestable
O
0

I would like to point one more way to do this:

When you want viewpager with fragments inside a BottomSheetDialogFragment, instead of overriding onCreateDialog or setupDialog just override 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

Then inflate your own layout in 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
        
Olli answered 29/3, 2021 at 6:43 Comment(0)
M
0

you just have to enable scrolling inti the view pager as:

ViewCompat.setNestedScrollingEnabled(viewPager2, true);

and if scrolling is still absent add NestedScrollView to all your viewpager child fragments.

Meaghanmeagher answered 12/5, 2022 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.