Skip to content

Instantly share code, notes, and snippets.

@lamprosg
Last active December 17, 2015 07:58
Show Gist options
  • Select an option

  • Save lamprosg/5576368 to your computer and use it in GitHub Desktop.

Select an option

Save lamprosg/5576368 to your computer and use it in GitHub Desktop.
(Android) Fragments
Official Info:
http://developer.android.com/guide/components/fragments.html
Same lifecycle methods with the Activity lifecycle methods apply
extends DialogFragment
Displays a floating dialog. Using this class to create a dialog is a good alternative to using the dialog helper methods in the Activity class, because you can incorporate a fragment dialog into the back stack of fragments managed by the activity, allowing the user to return to a dismissed fragment.
extends ListFragment
Displays a list of items that are managed by an adapter (such as a SimpleCursorAdapter), similar to ListActivity. It provides several methods for managing a list view, such as the onListItemClick() callback to handle click events.
extends PreferenceFragment
Displays a hierarchy of Preference objects as a list, similar to PreferenceActivity. This is useful when creating a "settings" activity for your application.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<TextView
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="It's TextView in main Activity"
android:background="#555555"/>
<fragment
class="com.exercise.FragmentTest.ExampleFragment"
android:id="@+id/myfragment"
android:layout_width="0px"
android:layout_weight="4"
android:layout_height="match_parent" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="It's Fragment" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher"/>
</LinearLayout>
//ExampleFragment class
//subclass of Fragment that loads a layout from the example_fragment.xml file
public class ExampleFragment extends Fragment {
@Override
//Called when the UI is ready to draw the Fragment
//this method must return a View that is the root of your fragment's layout.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
public class SomeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the user interface layout for this Activity (main.xml)
setContentView(R.layout.main);
//Generally
//R.java file have all the resources IDs provided to resources(drawables, layouts, styles etc)
}
//Add the fragment to the activity by code
FragmentManager fragmentManager = getFragmentManager();
//Each set of changes that you commit to the activity is called a transaction
//such as add(), remove(), and replace()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//Initialize our fragment
ExampleFragment fragment = new ExampleFragment();
//R.id.fragment_container is the VieGroup id (specified in the layout xml) where the fragment will be embedded
fragmentTransaction.add(R.id.fragment_container, fragment);
//If we don't put a view id but just a string-key instead the fragment will run in the background (with no UI)
//OR REPLACE A Fragment
transaction.replace(R.id.fragment_container, newFragment);
//Before you call commit(), however, you might want to call
fragmentTransaction.addToBackStack("optional name for this back stack state, or null");
//in order to add the transaction to a back stack of fragment transactions
//allowing the user to navigate backward through the fragment changes (similar to navigating backward through activities)
//Otherwise the fragment will be destroyed
//If you add multiple changes to the transaction then all changes applied before you call commit()
//are added to the back stack as a single transaction and the Back button will reverse them all together.
//Animation
fragmentTransaction.setTransition(TRANSIT_FRAGMENT_CLOSE); //TRANSIT_NONE TRANSIT_FRAGMENT_OPEN,
fragmentTransaction.commit();
//OR
//fragmentTransaction.commitAllowingStateLoss(); //allows the commit to be executed after an activity's state is saved (Dangerous)
//If you want to get a fragment that exists in the activity (with UI)
Fragment frag = findFragmentById (R.layout.fragmentID);
//without UI
Fragment frag = findFragmentByTag("string-key");
//OR
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
//Simulate a back button for the fragment
frag.popBackStack();
//For a specific view
frag.popBackStack (R.layout.someID, 0);
//A given instance of a fragment is directly tied to the activity that contains it
//Get a View from the current Activity
View listView = getActivity().findViewById(R.id.list);
}
//In some cases, you might need a fragment to share events with the activity.
//Define a callback interface inside the fragment and require that the host activity implement it.
//Ex. Fragment A is a list of articles and Fragment B must show an article when selected
public class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
//the activity that hosts the fragment implements the OnArticleSelectedListener interface
//and overrides onArticleSelected() to notify fragment B of the event from fragment A
//Override the onAttach callback, called when the fragment is attached to the Activity
//to ensure that the host activity implements this interface
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//If the activity has not implemented the interface, then the fragment throws a ClassCastException.
//On success, the mListener member holds a reference to activity's implementation of OnArticleSelectedListener
try {
//Get the Activity's implemenation of the interface (with casting)
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
//Each time the user clicks a list item, the system calls onListItemClick() in the fragment
//ListFragment delegate method
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id); //id is the row id
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
}
//Example with the previous fragment with callback
public class MainActivity extends Activity
implements FragmentA.OnArticleSelectedListener{
//Implemenation of the fragment callback function
public void onArticleSelected(Uri articleUri) {
//The host activity can deliver messages to a fragment by capturing the Fragment instance with findFragmentById().
//Then directly call the fragment's public methods.
FragmentB articleFrag = (ArticleFragment) getSupportFragmentManager().findFragmentById(R.id.article_fragment);
if (articleFrag != null) {
// If article frag is available, we're in two-pane layout...
// Call a method in the ArticleFragment to update its content
articleFrag.updateArticleView(position);
}
else
{
// Otherwise, we're in the one-pane layout and must swap frags...
// Create fragment and give it an argument for the selected article
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
}
/*
Avoid instantiating Dialog directly. Instead, use one of the following subclasses:
AlertDialog
A dialog that can show a title, up to three buttons, a list of selectable items, or a custom layout.
DatePickerDialog or TimePickerDialog
A dialog with a pre-defined UI that allows the user to select a date or time.
you should use a DialogFragment as a container for your dialog.
The DialogFragment class provides all the controls you need to create your dialog and manage its appearance,
instead of calling methods on the Dialog object.
*/
//Alert dialog with a text and 2 buttons below ("Cancel" and "Fire")
public class FireMissilesDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
//Builder is a static class within AlertDialog (class: AlertDialog.builder)
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//You can chain together various setter methods
//Ex.
builder.setMessage(R.string.dialog_message).setTitle(R.string.dialog_title);
//OR add the buttons too
builder.setMessage(R.string.dialog_fire_missiles)
//Explanation for the below funtion:
//2d parameter expects DialogInterface.OnClickListener interface
//Here we create what appears to be a new instance of the interface, but really what is happening is that
//we create and instantiated a class that implements the interface returning a reference of that interface.
//if A->interface and B->class that implements it
//you can get a reference like so "A obj = new B();"
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create(); // AlertDialog dialog = builder.create();
}
//OR
//A traditional single-choice list
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_color);
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
}
});
return builder.create();
}
//OR
//A persistent multiple-choice list (checkboxes)
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mSelectedItems = new ArrayList(); // Where we track the selected items
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Set the dialog title
builder.setTitle(R.string.pick_toppings)
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
//putting setSingleChoiceItems() will make these radio buttons
.setMultiChoiceItems(R.array.toppings, null,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// User clicked OK, so save the mSelectedItems results somewhere
// or return them to the component that opened the dialog
...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
...
}
});
return builder.create();
}
}
//Create a layout for the custom dialog
public class MyDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null)) // dialog_signin.xml
// Add action buttons
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}
}
/*
//TIP:
Tip: If you want a custom dialog, you can instead display an Activity as a dialog instead of using the Dialog APIs.
Simply create an activity and set its theme to Theme.Holo.Dialog in the <activity> manifest element:
<activity android:theme="@android:style/Theme.Holo.Dialog" >
That's it. The activity now displays in a dialog window instead of fullscreen.
*/
public class NoticeDialogFragment extends DialogFragment {
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface NoticeDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
NoticeDialogListener mListener;
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener");
}
}
....
....
}
public class MainActivity extends FragmentActivity implements NoticeDialogFragment.NoticeDialogListener{
...
public void showNoticeDialog() {
// Create an instance of the dialog fragment and show it
DialogFragment dialog = new NoticeDialogFragment();
dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
//Normally it closes on its own, but in other cases
dialog.dismiss(); //close the dialog
}
//OR FOR FULL SCREEN DIALOG
public void showFullScreenDialog() {
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
}
// The dialog fragment receives a reference to this Activity through the
// Fragment.onAttach() callback, which it uses to call the following methods
// defined by the NoticeDialogFragment.NoticeDialogListener interface
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User touched the dialog's positive button
...
}
@Override
public void onDialogNegativeClick(DialogFragment dialog) {
// User touched the dialog's negative button
...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment