0

My main activity is a Swipe View with tabs in the action bar, which can be used to change to a particular fragment directly. I basically followed the developer guidelines on this. So far this works fine and as expected.

However, I now have a couple of items in the menu (Settings, About), which should not be displayed as part of the ViewPager, but rather should replace the ViewPager completely and set the "navigation up" affordance in the action bar. Following along with the answers to this question I know how to use the BackStack to manipulate the action bar and to show the "navigation up" affordance.

However I'm not sure what the best way to replace the ViewPager would be. As far as I know I can either try to disable all ViewPager functionality and make it appear as it would be a single fragment (e.g. disable tabs and swipe), or I could use nested fragments. Yet, I'm not convinced that either of this options is "clean".

Maybe I'm overlooking something here and there is a more intuitive way to achieve the same? What are you guys thinking about this and how do you implement something "basic" as this?

P.S.: Obviously I could use activities for this, but I think that an Activity is too heavy for a simple "About" text and in my understanding one should try to use Fragments wherever possible these days.

Karol Babioch
  • 666
  • 8
  • 16

2 Answers2

3

As I can understand, you could put the ViewPager inside a parent as FrameLayout and add() the "about" fragment with addToBackState() method above the ViewPager.
You will avoid to disable or refresh the ViewPager. Just add above it a new fragment.


UPDATE

I'm able to achieve it with add() method and a custom background on the added fragment to avoid the overlap issues. And finally make this background clickable to prevent the click events for the behind ViewPager.
See my activity layout:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.viewpageroverlap.MainActivity"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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

</FrameLayout>

My Menu item event:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        getSupportFragmentManager().beginTransaction()
            .add(R.id.container, OverlapFragment.newInstance(990), null).addToBackStack(null).commit();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

My Overlap Fragment layout:

<RelativeLayout 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"
    tools:context="com.example.viewpageroverlap.MainActivity$OverlapFragment"
    android:background="#FF0000"
    android:clickable="true" >

    <TextView
        android:id="@+id/section_label"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center" />

</RelativeLayout>  

This gives me this output:

Screenshot Viewpager Overlaped by Fragment

Note: I used a red background but you can try with Android Resources Color and avoid to use a color declared in your files as android:background="@android:color/white".

WITH TABS

You can do the same as above and reset the navigation with NAVIGATION_MODE_STANDARD:

if (id == R.id.action_settings) {
    getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    getSupportFragmentManager().beginTransaction()
        .add(R.id.container, OverlapFragment.newInstance(990), null).addToBackStack(null).commit();
    return true;
}  

Then, when the user come back to the ViewPager (when he presses the home button or hardware back button), reset the old navigation as:

// do the same with android.R.id.home inside onOptionsItemSelected
@Override
public void onBackPressed() {
    // check if the "about" fragment is still displayed
    if(this.getSupportFragmentManager().getBackStackEntryCount() > 0) {
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        this.getSupportFragmentManager().popBackStack();
    }
}
Blo
  • 11,903
  • 5
  • 45
  • 99
  • Could you elaborate on this please? Simply adding the about fragment to the FrameLayout doesn't do the trick as both Fragments are shown overlapped. – Karol Babioch May 02 '14 at 22:36
  • 1
    Yes, the fragments are overlapping 'cause of `add()` method and not `replace()`, @KarolBabioch. I think, just try to add a `background` attribute to the parent container inside the about-fragment's layout will hide the behind fragments. – Blo May 02 '14 at 23:09
  • Yes, by using replace() I kind of got it workign (see below). However I still see the tabs of the ActionBar and would have to handle them manually (setting the navigation mode). Is there a way to automate this, too? – Karol Babioch May 02 '14 at 23:22
  • 1
    I updated my answer @KarolBabioch. Personally, I tried with `add` instead of `replace` and it worked well if you add a **background clickable** which prevent the overlap events. This will avoid you to disable the ViewPager and the Tabs for each menu item clicked. – Blo May 04 '14 at 04:16
  • Thanks for your detailed answer. However, I don't see how this addresses the issue with the tabs (which you dont use). I would need to disable the tabs for some fragments and (re-)enable it for others. Is there an easy way to do this? For now I finally ended up using activities, because it is trivially easy to do this and there are the parent attributes for activities, so the action bar will automatically show the "navigation up" affordance. Implementing all of this with fragments seems to be a hassle. – Karol Babioch May 04 '14 at 09:54
  • 1
    Little (but important) missing thing indeed. I updated my answer and tested it @KarolBabioch, it works and hides the tabs when the new fragment is displayed above the ViewPager. Also for the "up indicator", simply use `((activity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);` works inside fragment. – Blo May 04 '14 at 10:54
  • Ok, thanks once again for all the effort you've put into this! After having implemented all of that, would you personally choose to use it? Or would you stick with the "traditional" way of doing things (i.e. Activities) and letting Android itself handling all of this? – Karol Babioch May 04 '14 at 11:08
  • 1
    All depends on *"what the app needs to do"*. In the case of few text with no more than two, three logos to be displayed in "about" section, I'd prefer the fragment. However, if I want to do something else that display just a text, I'd do it with activity. Now, there is no big difference in fragment or in activity. The only thing, I guess, that's important is to not overload the activity with too many fragments. Personally, I'd do an "about" screen with fragments (provided that my activity is not overload). @KarolBabioch – Blo May 04 '14 at 12:35
  • Thanks, once more! I'll probably stick with the Activity based solution, just because it is easier to understand for other developers and the way most other apps work, which makes it feel more "natural", because there is an "animation" when starting another activity, which is not true for replacing fragments. – Karol Babioch May 04 '14 at 12:54
  • 1
    You're welcome and yes, it's probably better to understand for new developers. However, keep in mind that you can have an ["animation" with fragments](http://stackoverflow.com/q/4817900/2668136) as activity by use `setCustomAnimations` method ;) Happy coding @KarolBabioch. – Blo May 04 '14 at 13:12
0

Just have the ViewPager in its own fragment and replace that when you want to change to another fragment using regular fragment transactions.

If you turn on addToBackStack those transactions will react to the back button in a natrual way.

pumpkee
  • 3,357
  • 3
  • 27
  • 34
  • This works, but I still need to handle the ActionBar myself (disable the tabs in the AboutFragment). Or am I still doing something wrong? – Karol Babioch May 02 '14 at 23:20