Mgamerz
Mgamerz

Reputation: 2890

FragmentManager multiple on-screen fragments?

On Android 3.0 and above, the android team is driving hard that you should use fragments over activities. And I see this being useful, but I want to be able to handle click events in my app. I'm using a list fragment on the right side of my app, so doing an onclick (or any click listeners) happens in the activity that hosts the fragment. So I had to move from putting a item in XML to using the fragment manager.

In the design documents they show this picture:Misleading Photo

http://developer.android.com/training/basics/fragments/fragment-ui.html

What I want is the Fragment A/B tablet UI. However, nowhere in this page does it actually give you an example of doing this - it seems that fragment manager only works with ONE fragment at a time - which is entirely opposite of what the picture portrays. Which makes me think it uses in XML... but then how would I get an onclick? These documents don't make a lot of sense to me. It shows one thing and then says something else. What if I wanted to remove fragment A on the tablet? Add fragment C that doesn't yet exist? Is that even possible if you tried to use Fragment Manager????

I guess I don't get if Fragment manager uses more than 1 fragment, and if it does, how am I supposed to use this to get an item in the picture like the tablet - the left (A) being a listview, and the right (B) being whatever. Without an ID of the fragment I don't how to access it.

Not sure if this is relevant but here is some of my code:

Adds a fragment to the single framelayout I made like in the guide

//Activity              
FragLaunch launchPane = new FragLaunch();
                // In case this activity was started with special instructions from an Intent,
                // pass the Intent's extras to the fragment as arguments
                // firstFragment.setArguments(getIntent().getExtras());

                // Add the fragment to the 'fragment_container' FrameLayout
                getFragmentManager().beginTransaction()
                        .add(R.id.launch_frag_container, launchPane).commit();
            }

Also, in portrait mode of 7" tablets, I want it to use a viewpager that is swipeable. It worked like a charm when I designed it in XML but now that I have to access the listfragment it doesn't work (no way to access since I can't have two fragments)

XML of FragLaunch's content view:

<LinearLayout 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"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:gravity="center_vertical"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/initial_directions"
        style="@style/textScalar.Roboto.Light"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/initial_directions"
        android:layout_marginBottom="30dp"
        tools:context=".Launch" />

</LinearLayout>

I want to have this one appear as Fragment A in the photo: FragHistory.java/xml for fragment:

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

    <Button
        android:id="@+id/spamhistory"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Spam History" />

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:drawSelectorOnTop="false" />

</LinearLayout>

Does anyone have any insight on this?

Upvotes: 3

Views: 7674

Answers (2)

Stephen Asherson
Stephen Asherson

Reputation: 1567

Another great way to allow communication between fragments is to use an event bus, such as the Otto event bus. Otto allows components to publish events and subscribe to events in a decoupled manner.

In your particular case, when a user selects an item in the list, your list fragment can publish an event (which can include the item that has been selected) and your content fragment can subscribe for these events and update its content accordingly when it receives a new event. This all being done without the two fragments being directly coupled and without having to define additional interfaces.

I know this doesn't answer your entire question, but thought it might be useful when it comes to the communications between your fragments....YMMV.

Upvotes: 1

Don
Don

Reputation: 526

If you want your fragments to be able to communicate then you need to use interfaces, like this.

For onClick events you simply set an onClickListener for the view that you need to receive the onClick event from. Like so:

sampleView.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        //Your code here
    }
});

As for fragment transactions, it says somewhere in there (I can't remember exactly where) that when two fragments are displayed on the screen at once (as with larger screens) that instead of swapping the fragments it simply updates it. All you have to worry about is making the correct calls. So if you want to remove fragment A just call remove(). Or if you want to replace it with fragment C call replace() and pass fragment C in as the parameter.

Can you clarify your question about the ViewPager? What do you mean "have to access it"?

Hope this helps!

EDIT: I apoplogize, I misunderstood your question. Here's kind of a quick run down of how to add more than one fragment to the screen at once.

1. Perform a runtime check to make sure that the device screen is big enough to display more than one fragment.

2. If the screen is big enough, set the content view to use a layout that has a FrameLayout for each fragment that you want to add.

3. After that grab a reference to each fragment that you want to use.

4. Then use the FragmentManager to add a fragment to each layout. Like this:

FirstExampleFragment fragment1 = new FirstExampleFragment();
SecondExampleFragment fragment2 = new SecondExampleFragment();

getSupportFragmentManager().beginTransaction().add(R.id.example_framelayout1, fragment1)
.add(R.id.example_framelayout2, fragment2).commit();

Upvotes: 1

Related Questions