Show DialogFragment over TabLayout
Asked Answered
O

1

0

I'm trying to show a DialogFragment full-screen such that the ActionBar is still visible but the tabs in a TabLayout are hidden.

The image on the left is what I've managed to achieve; the image on the right is what I'm aiming for:

enter image description here

There are two issues:

  1. The tabs are still shown, which the user can interact with;
  2. Because of the extra FrameLayout to show the dialog, the ViewPager content is still visible (the FAB button is not part of the dialog). This also means that the user can interact with the content in the pager, which includes the ability to change tabs.

Main Activity Layout (main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <!-- Use ThemeOverlay to make the toolbar and tablayout text
             white -->
        <android.support.design.widget.AppBarLayout
            android:id="@+id/abl_top"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:fitsSystemWindows="true"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_scrollFlags="scroll|enterAlways"/>

            <android.support.design.widget.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/CustomTabStyle"/>

        </android.support.design.widget.AppBarLayout>
    </android.support.design.widget.CoordinatorLayout>

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </FrameLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</LinearLayout>

MainActivity.java

package com.example.app;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MainActivity
    extends AppCompatActivity
{
    private static final String TAG = "MainActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Setup AppBar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
        }

        // Setup ViewPager
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        if (viewPager != null) {
            setupViewPager(viewPager);
        }

        // Setup TabLayout
        TabLayout tl = (TabLayout) findViewById(R.id.tab_layout);
        tl.setupWithViewPager(viewPager);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

    private void setupViewPager(ViewPager viewPager) {
        Adapter adapter = new Adapter(
            getSupportFragmentManager(), MainActivity.this);
        adapter.addFragment(
            new Fragment1(),
            "Tab 1", R.drawable.numeric_1_box_outline);
        adapter.addFragment(
            new Fragment2(),
            "Tab 2", R.drawable.numeric_2_box_outline);
        viewPager.setAdapter(adapter);
    }

    static class Adapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragments = new ArrayList<>();
        private final List<Integer> mFragmentIcons = new ArrayList<>();
        private final List<String> mFragmentTitles = new ArrayList<>();
        private Context context;

        public Adapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }

        public void addFragment(Fragment fragment, String title, int iconId) {
            mFragments.add(fragment);
            mFragmentTitles.add(title);
            mFragmentIcons.add(iconId);
        }

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

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

        @Override
        public CharSequence getPageTitle(int position) {
            Drawable image = context.getResources().getDrawable(
                    mFragmentIcons.get(position), null);
            image.setBounds(0, 0, image.getIntrinsicWidth(),
                    image.getIntrinsicHeight());
            SpannableString sb = new SpannableString("   " + mFragmentTitles.get(position));
            ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
            sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            return sb;
        }
     }

}
Oversubscribe answered 30/6, 2015 at 14:27 Comment(0)
M
2

If you want the dialog to be full screen, the root view should be a FrameLayout (instead of a LinearLayout). If you want the dialog to contain a Toolbar, you'll also need a second Toolbar since your first one is attached to the TabLayout.

Something like this should work:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/container">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <!-- Use ThemeOverlay to make the toolbar and tablayout text
             white -->
        <android.support.design.widget.AppBarLayout
            android:id="@+id/abl_top"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:fitsSystemWindows="true"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_scrollFlags="scroll|enterAlways"/>

            <android.support.design.widget.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        </android.support.design.widget.AppBarLayout>

        <android.support.design.widget.FloatingActionButton
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            app:layout_anchor="@id/toolbar_layout"
            app:layout_anchorGravity="bottom|right|end"
            app:borderWidth="0dp"
            android:layout_margin="20dp"
            android:clickable="true"/>

    </android.support.design.widget.CoordinatorLayout>


</FrameLayout>

MainActivity.java

...

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Setup AppBar
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    if (toolbar != null) {
        setSupportActionBar(toolbar);
    }

    // Setup ViewPager
    ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
    if (viewPager != null) {
        setupViewPager(viewPager);
    }

    // Setup TabLayout
    TabLayout tl = (TabLayout) findViewById(R.id.tab_layout);
    tl.setupWithViewPager(viewPager);


    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.add(R.id.container, new DialogFragment());
    transaction.addToBackStack("tag");
    transaction.commit();
}

...

fragment_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/fragment_toolbar"
        android:fitsSystemWindows="true"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="?attr/colorPrimaryDark"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@android:color/background_light">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="This is the dialog"/>
        </FrameLayout>

</LinearLayout>

DialogFragment.java

public class DialogFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_dialog, container, false);


        final Toolbar toolbar = (Toolbar) view.findViewById(R.id.fragment_toolbar);
        toolbar.setTitle("Dialog Title");
        toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white));
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getActivity().getSupportFragmentManager().popBackStack();
            }
        });
        return view;
    }
}

I would recommend using an Activity for the dialog instead of attaching a dialog fragment to the view, especially if you plan to put input text into the dialog. I experienced some odd behavior with animations and the soft keyboard when using a Fragment for the dialog. Creating a new Activity resolved all of these issues.

Mutazilite answered 30/6, 2015 at 16:0 Comment(3)
I've seen a lot of apps that use an Activity for such a dialog but the android docs seem to recommend a DialogFragment. I suppose I'm now discovering why. Also, won't using a FrameLayout as root mean that the toolbar + tabs become hidden, like when using android.R.id.content?Oversubscribe
In this case, there are already a number of views in the main Activity and with the need for a second Toolbar, I think it makes sense to create a second Activity. Each case is different, for a simpler view hierarchy, a Fragment makes more sense. The CoordinatorLayout handles the placement of the toolbar + tabs so the LinearLayout is not necessary. If you move away from using a Fragment for the dialog, the CoordinatorLayout could be your root view.Mutazilite
I was right about the root FrameLayout, the result is the same and with android.R.id.content. In any case, I think you're right that a DialogFragment is insufficient for anything other than completely-cover-the-whole-thing-full-screen so I'll be using an activity as well.Oversubscribe

© 2022 - 2024 — McMap. All rights reserved.