home.


Tagged: android-fragments


Android: DialogFragment

You call a DialogFragment into existence by making a new dialogue object using a static constructor with its data (see below) and then issuing the show() method, passing in your FragmentManager and optional tag.

 newFragment = BasicDialogueFragment.newInstance("title", "message");
 newFragment.show(context.getSupportFragmentManager(), "tag");      

Now here’s the BasicDialogFragment class. Note the static newInstance() which takes in the parameters and stores them in a bundle which retained in the fragment through setRetainInstance(true);

We use newInstance() instead of passing arguments into the Fragment’s constructor since the documentation and lint warn us against that, since the Fragment may be reinitialised via a call to the Fragment’s constructor with no arguments.

 public class BasicDialogueFragment extends android.support.v4.app.DialogFragment {
  private String mTitle;
  private String mMessage;

  public static BasicDialogueFragment newInstance(String title, String message) {
    BasicDialogueFragment dialogue = new BasicDialogueFragment();
    dialogue.mTitle = title;
    dialogue.mMessage = message;
    return dialogue;
  }

  @Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {
    setRetainInstance(true);
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setMessage(mMessage);
    builder.setTitle(mTitle);   
    return builder.create();
  }

  @Override
  public void onDestroyView() {
   // Used because of a bug in the support library
   if (getDialog() != null && getRetainInstance())
      getDialog().setDismissMessage(null);
   super.onDestroyView();
  }      
 }
android android-dialogues android-fragments android-dialogfragment

Android: Testing fragments

Update: I would not recomment this anymore. Although it may work, there are new mockito testing tutorials on the Android documentation site, which you should look at first. And, these days, I use the MVP architecture, allowing me to place all the logic in the presenter layer, which I then test via normal Java unit testing tools in isolation from the Android specfic code, and test the UI, including the fragments, with the UI testing library and framework, Espresso.

If you want to test a fragment in isolation, you need to create a Test FragmentActivity so your test can use that. The test activity will look something like this. Remember to declare it in your application’s manifest:

 public class TestFragmentActivity extends FragmentActivity {
   @Override
   protected void onCreate(Bundle arg0) {
     super.onCreate(arg0);
     setContentView(R.layout.activity_fortests);
   }
 }

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"
    >
   <LinearLayout
        android:id="@+id/activity_test_fragment_linearlayout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        />
 </RelativeLayout>

AndroidManifest:

 ...
 <activity
  android:name="your.package.name.TestFragmentActivity">
 </activity>
 ...

Then in your test project, you can have a class like this to start the fragment:

  public class FrameworkObjectsGeneratorFragmentTest 
      extends ActivityInstrumentationTestCase2<TestFragmentActivity> {
    private TestFragmentActivity mActivity;

    public FrameworkObjectsGeneratorFragmentTest() {
      super(TestFragmentActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
      super.setUp();
      mActivity = getActivity();
    }

    private Fragment startFragment(Fragment fragment) {
      FragmentTransaction transaction = mActivity.getSupportFragmentManager().beginTransaction();
      transaction.add(R.id.activity_test_fragment_linearlayout, fragment, "tag");
      transaction.commit();
      getInstrumentation().waitForIdleSync();
      Fragment frag = mActivity.getSupportFragmentManager().findFragmentByTag("tag");
      return frag;
    }

   public void testFragment() {
      FrameworkObjectsGeneratorFragment fragment = new FrameworkObjectsGeneratorFragment() {
         //Override methods and add assertations here.
      };

      Fragment frag = startFragment(fragment);
    }
  }

The startFragment() method adds a fragment you specify to the ViewGroup in the TestActivity.

The good thing about testing fragments, as opposed to Activities, is that you can extends the Fragment to override protected fields and methods within which you can add assertions.

android android-testing android-fragments

Android: Fragments: Communicating events

In your Fragment class, if you create listener on a particular interface, and make the parent implement that interface, you can communicate via events.

First create the interface:

    public interface OnNewFragmentPressed {
       void onNewFragmentPressed();
    }

Then create a listener method of that interface.

    public static class NewFragment extends Fragment {
        private OnNewFragmentPressed mListener;
    }

Then in the onAttach() method of your Fragment, use the passed in Activity to make sure it implements the interface, and set the listener to that.

    @Override
    public void onAttach(Activity activity) {
       super.onAttach(activity);
       try {
          mListener = (OnNewFragmentPressed) activity;
       } catch(ClassCastException e) {
          throw new ClassCastException(activity.toString() + ??? didn???t implement OnNewFragmentPressed???);
       }
    }   

Now you can call methods of that interface, thereby interacting with your parent Activity.

android android-fragments

Android: Fragments: Communicating between FragmentActivity and Fragment

In your FragmentActivity, you can call getSupportFragmentManager().findFragmentByTag(???tag???), or findFragmentById(R.id.frag), to access the child Fragment. From there you can call its methods.

Similarly, in the Fragment, you can call getActivity() to get access to the parent FragmentActivity().

You can also do this via events. See the android-fragments-events post.

android android-fragments

Android: Fragments: Replacing with back stack and animation

You can replace an existing fragment, like you added one. But this time with a back stack, meaning pressing back reverts to transaction, and some simple animations.

You can, however, only delete and replace fragments which you???ve added via the FragmentManager, not ones you???ve initiated using XML.
Call this code to replace an existing Fragment you added with another.

    FragmentManager fragManager = getSupportFragmentManager();
    FragmentTransaction fragTransaction = fragManager.beginTransaction();
    fragTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    NewFragment f = new NewFragment();
    fragTransaction.replace(R.id.frag_container1, f);
    fragTransaction.addToBackStack(null);
    fragTransaction.commit();

(If you???re in a Fragment, and not a FragmentActivity, replace getSupportFragmentManger wiht getFragmentManager.)

Note we???re setting a transition, TRANSIT_FRAGMENT_OPEN. And we???re added it to a back stack. So we we press back this transition is reversed.

android android-fragments

Page 1 of 2
Next