4) Getting fragments to talk to each other

Interface fragments1

Example below is from Vivz slide nerd videos on youtube

MainActivity.java

package com.jamesfroggatt.fragments4.app;


import android.app.Activity;
import android.app.FragmentManager;
import android.os.Bundle;

public class MainActivity extends Activity implements Communicator{

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


    @Override
    public void respond(String data) {

         // get reference to fragment 2
        FragmentManager manager=getFragmentManager();

        // gives reference to fragment b
        FragmentB f2=(FragmentB)manager.findFragmentById(R.id.fragment2);

        f2.changeText(data);

    }
}

FragmentA.java

package com.jamesfroggatt.fragments4.app;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;


public class FragmentA  extends Fragment implements View.OnClickListener {

    Button button;
    int counter=0;

    // create an interface reference variable
    // can refer to a subclass object
    // (dynamic runtime polymorphism)
    Communicator comm;

    //link the layout (fragment_a.xml) to the fragment class
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_a,container,false);
    }

    // initialise the button in fragment a
    // using onActivityCreated it is save to access
    // the view hierarchy as Activity has been create when
    // this method is called
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // in the left side we have an interface variable
        // on the right, a subclass object so we add the cast (Communicator)
        // This is possible because the activity implements the interface
        // which means the Activity is a subclass of the interface
        // comm is pointing to our mainActivity
        comm= (Communicator) getActivity();


        button= (Button) getActivity().findViewById(R.id.buttonInFragmentA);
        // set button on click listener
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        counter++;
        // comm.respond is in the mainActivity
        comm.respond("Button was clicked "+counter+" times");

    }
}

FragmentB.java

package com.jamesfroggatt.fragments4.app;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;



public class FragmentB extends Fragment {

    TextView text;
    //link the layout (fragment_b.xml) to the fragment class
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_b,container,false);
    }

    // initialise the TextView in fragment b
    // using onActivityCreated it is save to access
    // the view hierarchy as Activity has been create when
    // this method is called
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        text= (TextView) getActivity().findViewById(R.id.textViewInFragmentB);

    }

    public void changeText(String data){
        text.setText(data);
    }
}

activity_main.xml

<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"
    android:background="#00BBFF"
    android:id="@+id/my_layout">


    <fragment
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:name="com.jamesfroggatt.fragments4.app.FragmentA"
        android:id="@+id/fragment"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <fragment
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:name="com.jamesfroggatt.fragments4.app.FragmentB"
        android:id="@+id/fragment2"
        android:layout_below="@+id/fragment"
        android:layout_alignLeft="@+id/fragment"
        android:layout_alignStart="@+id/fragment"
        android:layout_marginTop="147dp" />
</RelativeLayout>

fragment_a.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:background="#772233">

    <Button
        android:layout_margin="30dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click this"
        android:id="@+id/buttonInFragmentA" />
</LinearLayout>

fragment_b.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFCCAA">


    <TextView
        android:layout_margin="30dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/textViewInFragmentB"
        android:layout_gravity="center_horizontal" />
</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jamesfroggatt.fragments4.app"
   >
 <uses-sdk android:minSdkVersion="11"></uses-sdk>
    <application

        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.jamesfroggatt.fragments4.app.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

When orientation changes – how do we remember the state of Fragment A and Fragment B?

Look for
// MODIFIED CODE BEGIN //
// MODIFIED CODE END //

in the code of:

FragmentA.java

package com.jamesfroggatt.fragments4.app;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;


public class FragmentA  extends Fragment implements View.OnClickListener {

    Button button;
    int counter=0;

    // create an interface reference variable
    // can refer to a subclass object
    // (dynamic runtime polymorphism)
    Communicator comm;

    // MODIFIED CODE BEGIN //
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState==null){
            counter=0;
        }else{
            counter=savedInstanceState.getInt("counter",0);
        }
    }
    // MODIFIED CODE END //

    //link the layout (fragment_a.xml) to the fragment class
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_a,container,false);

    }

    // initialise the button in fragment a
    // using onActivityCreated it is save to access
    // the view hierarchy as Activity has been create when
    // this method is called
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // in the left side we have an interface variable
        // on the right, a subclass object so we add the cast (Communicator)
        // This is possible because the activity implements the interface
        // which means the Activity is a subclass of the interface
        // comm is pointing to our mainActivity
        comm= (Communicator) getActivity();


        button= (Button) getActivity().findViewById(R.id.buttonInFragmentA);
        // set button on click listener
        button.setOnClickListener(this);
    }


    // MODIFIED CODE BEGIN //
    // this method is called just before fragment is destroyed when we
    // change orientation
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("counter",counter );
    }
    // MODIFIED CODE END //

    @Override
    public void onClick(View v) {
        counter++;
        // comm.respond is in the mainActivity
        comm.respond("Button was clicked "+counter+" times");

    }
}

FragmentB.java

package com.jamesfroggatt.fragments4.app;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;



public class FragmentB extends Fragment {

    TextView text;
    String data;



    //link the layout (fragment_b.xml) to the fragment class
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // MODIFIED CODE BEGIN //

        View view= inflater.inflate(R.layout.fragment_b,container,false);
        if (savedInstanceState==null){

        }else{
           data=savedInstanceState.getString("savedData");
           TextView myText=(TextView) view.findViewById(R.id.textViewInFragmentB);
            myText.setText(data);

        }

        return view;
        // MODIFIED CODE END //
    }

    // initialise the TextView in fragment b
    // using onActivityCreated it is save to access
    // the view hierarchy as Activity has been create when
    // this method is called
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        text= (TextView) getActivity().findViewById(R.id.textViewInFragmentB);

    }

    // MODIFIED CODE BEGIN //
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("savedData",data);
    }
    // MODIFIED CODE END //

    public void changeText(String data){
        text.setText(data);
    }
}

Leave a Reply