The slides on this page are screen shots from Vivz slidenerd videos on youtube. Full video can be seen on the bottom of this page.
Below we have the modified communicator design pattern which is better than the previous example because out interface isn’t exposed (used as a separate class) and is only accessible to where it’s needed. In java, a general rule is ‘do not expose something more that it needs to be’. In our example, only FragmentA and MainActivity need use of the communicator so we place it WITHIN Fragment A. Since Fragment B doesn’t care about the communicator, we can hide it in Fragment A.
The full design pattern including the orientation switching.
MainActivity.java
package com.jamesfroggatt.fragments5.app;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
public class MainActivity extends Activity implements FragmentA.Communicator {
// create references to the fragments
FragmentA f1;
FragmentB f2;
FragmentManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialise the fragment manager
manager=getFragmentManager();
// initialise fragment A because this fragment will ALWAYS be there in
// portrait and landscape mode
f1 = (FragmentA) manager.findFragmentById(R.id.fragment);
f1.setCommunicator(this); // this = we're passing an object of type MainActivity
}
// this method is generated from the Communicator interface (in Fragment A) as
// we're implementing it here in MainActivity
@Override
public void respond(int position) {
// we need to check, are we in portrait or landscape mode
f2= (FragmentB) manager.findFragmentById(R.id.fragment2);
if (f2!=null && f2.isVisible())
{
// we are ˙in landscape mode
f2.changeData(position);
}else
{
// we are in portrait mode
// start the new activity
Intent intent= new Intent(this,AnotherActivity.class);
intent.putExtra("index",position);
startActivity(intent);
}
}
}
FragmentA.java
package com.jamesfroggatt.fragments5.app;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class FragmentA extends Fragment implements AdapterView.OnItemClickListener {
// create a reference to the ListView
ListView list;
// create a reference to the Communicator
Communicator communicator;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//return super.onCreateView(inflater, container, savedInstanceState);
// link the layout to the view object
View view=inflater.inflate(R.layout.fragment_a, container, false);
// find the ListView object from the inflated view and attach it to list
list= (ListView) view.findViewById(R.id.listView);
// now we set an adapter which will contain our datasource
ArrayAdapter adapter = ArrayAdapter.createFromResource(getActivity(),R.array.chapters,android.R.layout.simple_list_item_1);
// set the adapter
list.setAdapter(adapter);
// set the on
list.setOnItemClickListener(this);
return view;
}
// this is the generated onItemClick listener for the listView
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
communicator.respond(position);
}
// COMMUNICATOR INTERFACE - method "respond" is responsible for carrying data from
// fragment A to fragment B
public interface Communicator{
public void respond(int position); // calls the respond method inside MainActivity
}
// method to set the communicator
public void setCommunicator(Communicator communicator){
this.communicator=communicator;
}
}
FragmentB.java
package com.jamesfroggatt.fragments5.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 {
// get a reference to the textView
TextView text;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//return super.onCreateView(inflater, container, savedInstanceState);
// link the layout to the view object
View view=inflater.inflate(R.layout.fragment_b, container, false);
// find the TextView object from the inflated view and attach it to text
text= (TextView) view.findViewById(R.id.textView);
return view;
}
// we need a method to change the contents of our TextView
public void changeData(int index){
String[] descriptions=getResources().getStringArray(R.array.description);
text.setText(descriptions[index]);
}
}
AnotherActivity.java
package com.jamesfroggatt.fragments5.app;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class AnotherActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_another);
Intent intent=getIntent();
int index = intent.getIntExtra("index",0);
// get a reference to fragment B
FragmentB f2= (FragmentB) getFragmentManager().findFragmentById(R.id.fragment2);
if (f2!=null){
f2.changeData(index);
}
}
}
layout/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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="#FF3399"
tools:context="com.jamesfroggatt.fragments5.app.MainActivity">
<fragment
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="com.jamesfroggatt.fragments5.app.FragmentA"
android:id="@+id/fragment"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
layout/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="#AA4499">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true" />
</LinearLayout>
layout/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="#FFBB00">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"/>
</LinearLayout>
layout/activity_another.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="com.jamesfroggatt.fragments5.app.FragmentB"
android:id="@+id/fragment2"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
tools:layout="@layout/fragment_b" />
</LinearLayout>
layout-land/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:name="com.jamesfroggatt.fragments5.app.FragmentA"
android:id="@+id/fragment"
android:layout_gravity="left|center_vertical"/>
<fragment
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:name="com.jamesfroggatt.fragments5.app.FragmentB"
android:id="@+id/fragment2"
android:layout_gravity="left|center_vertical" />
</LinearLayout>
values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Fragments5</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<!-- used for populating the listView using the ArrayAdapter -->
<string-array name="chapters">
<item>Washing Machines</item>
<item>Computers</item>
<item>Phones</item>
<item>Countries</item>
</string-array>
<string-array name="description">
<item>Washing machines are quite popular and we\'ve got loads of them.</item>
<item>Computers do quite alot of good stuff these days as they\'re powerful enough</item>
<item>Most people have a phone. There are many models and types, many run Android</item>
<item>How any are there, tonnes of them. France, Spain, Germany, loads of them</item>
</string-array>
</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jamesfroggatt.fragments5.app" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.jamesfroggatt.fragments5.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>
<activity
android:name="com.jamesfroggatt.fragments5.app.AnotherActivity"></activity>
</application>
</manifest>
Final product.
This is the full tutorial on youtube


