0% found this document useful (0 votes)
63 views34 pages

Fragments 1

Android Fragments

Uploaded by

EmrikDml
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views34 pages

Fragments 1

Android Fragments

Uploaded by

EmrikDml
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

Fragments

Mobile Computing - Android

Introduction

There are many, many different sized


Android devices, making UI design a
challenge.

Fragments are an attempt to address this


problem. Instead of just a single layout, the
user interface can be divided into parts,
each represented by a Fragment.
Fragments combine to form the entire user
interface, and they are modular. They can
be reused in different Activities, and
swapped in and out of a single Activity
while it is running.

Note that Fragments are always part of an


Activity, and the Activity is still in charge:
while it is running it can add or remove
Fragments as needed.

1 Activity with multiple Fragments

The Fragment Lifecycle

In addition to its own UI, a Fragment have its own


lifecycle, intertwined with the Activity with which it is
associated.

Lifecycle methods include those found in the


Activity:

onCreate(), onStart(), onResume(), onPause(),


onSaveInstanceState(), on Stop() and onDestroy()

In addition, a Fragment has its own unique methods

Fragment Lifecycle
Methods

onAttach(Activity acty) -- called when a Fragment


is attached to an Activity (before onCreate())

onCreateView() - called before the Fragment


enters the resumed state

onViewCreated()

onActivityCreated() -- called when the associated


activity has been created and this Fragment's
view has been instantiated

onDestroyView() -- the counterpart to


onCreateView()

onDetach() -- called after onDestroy(), just before


the Fragment becomes eligible for garbage
collection

Three Famous Fragments

DialogFragment

ListFragment

Displays a dialog box

We will look at some of


these in detail later on

displays a ListView inside a Fragment (like the


ListActivity -- also includes OnListItemClick())

PreferenceFragment

Useful for creating settings for your app

Responsive Design

Often seen with a master/detail interface

Tap on a row and see detailed information about that item. The detailed fragment can
be either in the same activity (on a sufficiently wide screen), or in a different activity.

activity_item_twopane.xml

The ItemListActivity has 2


layouts, depending on the
size of the screen. If width
permits, it uses
activity_item_two_pane.xml,
with a fragment for the list
view and for the detailed view.
Otherwise, it uses
activity_item_list.xml, and a
second activity,
ItemDetailActivity, presents
the same detail Fragment as
above.

Creating A Fragment
1.Make a new Fragment (File >> New File >> Fragment >> Blank)
2.Override onCreateView() to create the Fragment's View
3.Edit the layout xml as needed (we'll just add a Button)
Aside: Android provides 5 Fragment subclasses which we will explore
later. Here the goal is to make our own subclass.

Overriding onCreateView()
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_blank, container, false);
Button btn = (Button) view.findViewById(R.id.clickMeBTN);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){ /* .... */ }
});
return view;
}
}

A Fragment's View must be returned by its onCreateView() method


LayoutInflater -- an object capable of taking an xml file, and making a View out of it
ViewGroup -- the ViewGroup (i.e., the activity's view) in which the fragment will be
embedded
Bundle -- data (if the fragment had been previously paused and is now resuming)

The Official Word on the


Subject (aka the API)

Your Fragment must override onCreateView()

Optional? If your Fragment extends ListFragment (discussed later) you


need not implement onCreateView() it will give you a ListView for free :-)

Adding a Fragment to an
Activity Using XML

Each fragment must appear in an activity's layout.


One way to do this is by specifying a fragment in an
activity's layout file with the <fragment> tag,
specifying the Fragments fully qualified name in the
android:name attribute (e.g.,
org.mprogers.SuperduperFragment).

The Fragment's layout will appear in the location


specified by the fragment tag, with the appropriate
size.

An Example
res/layout-large/news_articles.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

Specify fragments
in the activity's
layout file

<fragment



android:name="com.example.android.fragments.HeadlinesFragment"
android:id="@+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />

<fragment



android:name="com.example.android.fragments.ArticleFragment"
android:id="@+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />

</LinearLayout>

Load the layout in


the usual way ...

public class MainActivity extends Activity {


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

An Example, Enlarged
HeadlinesFragment

ArticleFragment

Placing Fragments
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<fragment
android:id="@+id/topFRG"
android:name="org.mprogers.fragmento.TopFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="26dp"
android:layout_marginTop="24dp"/>
<fragment
android:id="@+id/bottomFRG"
android:name="org.mprogers.fragmento.BottomFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/fragment1"
android:layout_below="@+id/fragment1"
android:layout_marginTop="31dp"
tools:layout="@layout/bottom_fragment" />
</RelativeLayout>

1. Drag <fragment> in xml


editor (under Custom)
2. When prompted choose
an existing Fragment
subclass.

public class MainActivity extends Activity {


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

Part II: Dynamic Fragments

The fragments that we have placed thus far are


known as static -- they appear where the
<fragment> tag appears in the Activity's layout,
and cannot be altered at runtime.

Building a More Flexible UI

If you place a fragment with the <fragment> tag in


the layout file, it is stuck there: that fragment cannot
be swapped out.

Q: Why would you want to swap out fragments?

A: 1. It is one solution to the problem of designing


multi-pane applications for tablets and single-pane
applications for smaller screens.
2. Swapping out fragments makes it possible to
add customized animations.

When There's Room

On a tablet, fragment A and B can


appear simultaneously

On a smaller device, tapping on


fragment A should lead to fragment B

It could be done with 2 activities, each


one hosting one fragment: tapping on
Fragment A would require an intent to
startActivity() for Fragment B.

This could be done with 1 Activity,


swapping out fragment A for B when
necessary: a concrete example of
Answer 1 on the previous slide.

Adding a Fragment at
Runtime

Ask a FragmentManager to make a FragmentTransaction

Can add(), remove(), replace() an existing fragment

The fragment must have a designated location, a container


view in the activity's layout.

A FrameLayout is a good choice if only 1 fragment will be


visible at a time

Add the initial fragment in the activity's onCreate(),


otherwise the user won't see anything :-0

An Example

Instead of 2 static fragments, just add 1, programmatically, in a FrameLayout, and


replace it when tapping on the article headline

The activity's layout will be considerably simpler

res/layout-large/news_articles.xml (when the layout is large)

<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:name="com.example.android.fragments.HeadlinesFragment"
android:id="@+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />

<fragment android:name="com.example.android.fragments.ArticleFragment"
android:id="@+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>

/res/layout/news_articles.xml
When the layout isn't so large ...

<FrameLayout xmlns:android="http://.../res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />

public class MainActivity extends Activity {


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles); // something slick is happening here ...

An Example, Continued

// Check that the activity is using the layout version with


// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {

// However, if we're being restored from a previous state,


// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null)
return;

// Create a new Fragment to be placed in the activity layout


HeadlinesFragment firstFragment = new HeadlinesFragment();

The app contains 2


layouts, the one used
depends on the device

// 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
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container, firstFragment);
transaction.commit();

}
}

where to add

what to add

Replacing Fragments
public void onArticleSelected(int position) {
// Create fragment and give it an argument specifying the article it should show
ArticleFragment articleFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
articleFragment.setArguments(args);
FragmentTransaction transaction = getFragmentManager().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, articleFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();

In Activity - triggered when


user clicks on a ListItem

Fragment => Activity


Communication

Fragments don't communicate directly. Instead, they talk


to the Activity in which they are embedded.

Preferred technique:

interface1

interface2

interface1

interface2

1. Define an interface, in the fragment, that the activity


implements
2. Capture the activity in the fragment's
onAttach(Activity activity) method
3. Invoke the interface method in the activity when
necessary.

Alternatively, to call an activity's public methods directly


(or don't mind continually getting the activity), the
Fragment defines this helpful method:

public Activity getActivity() // a fragment always knows


which activity it belongs to

The Essence of the


Communication
class MyFragment extends Fragment {
interface MyInterface {
void sayHi();}
}
MyInterface myInterface;
public void onAttach(Activity activity){
myInterface = (MyInterface)activity;
}
public void buttonHandler(View v){
myInterface.sayHi();
}
}

class MyActivity extends Activity


implements MyFragment.MyInterface{
void sayHi(){
Debug.Log(Hello);
}
}

Life Without Interfaces


class MyFragment extends Fragment {
//interface MyInterface {
//void sayHi();}
//}
// MyInterface myInterface;
MyActivity myActivity;
public void onAttach(Activity activity){
//myInterface = (MyInterface)activity;
myActivity = activity;
}
public void buttonHandler(View v){
//myInterface.sayHi();
myActivity.sayHi();
}

class MyActivity extends Activity


implements MyInterface{
void sayHi(){
Debug.Log(Hello);
}
}

Activity => Fragment


Communication

If a fragment has been defined with a <fragment>


tag, i.e., it is static, then
1. Access it in the Activity with the
FragmentManager method:

public Fragment findFragmentById(int id)


2. Call its public methods directly

An Example
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;// this will be the Activity
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnHeadlineSelectedListener) activity; // gotcha!
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Send the event to the host activity
mCallback.onArticleSelected(position);
}

Fragment Constructors

This sounds vaguely medical ...

Google recommends that a Fragment only use a default


constructor

So how do you initialize a Fragment to get into a particular state?

Embed whatever initial information you need in a Bundle, and


supply that to the Fragment via setArguments()

Retrieve them via getArguments()

In the Android Studio template, this happens in a factory method


called newInstance()

Arguments @ Work
public static BlankFragment newInstance(String param1, String param2) {
BlankFragment fragment = new BlankFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
Log.d("TAG", "Greetings from newInstance()");
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
Log.d("TAG", String.format("Greetings from onCreate() where
params are %s & %s", mParam1, mParam2));
}

An ICE: The Fragments


Template

Create an Android Studio project with a single


Fragment

Add a ListFragment and a BlankFragment

Examine the code ...

ListFragment

ListFragment extends Fragment

Recall how ListActivities worked:

a ListActivity came with a ListView "for free"

used setListAdapter() to establish the adapter (source of the ListView's


child views)

overrode onListItemClick() method to handle clicks

if all we wanted was a ListView, we didn't need to create a layout -- but if we


wanted a custom layout, we had to make it, and

A ListFragment works the same way

We've already used the ListFragment in the FragmentBasics-Gradle project

Exercises

What are Fragments?Why are they necessary? What is the relationship


between a Fragment and an Activity?

Whatis the Fragment hierarchy?

Which comes first, an Activity or a Fragment?

Write a Fragment's onCreateView() method. Assume that its layout is


defined in R.layout.my_fragment.

Describe the Fragment lifecycle.

How is the Fragment lifecycle affected by the Activity lifecycle? What


happens to a Fragment when an Activity is paused? destroyed?

What are the twoways of adding a Fragment to an Activity?

Exercises

Write the code to add a Fragment called SkinnyFragment -- with a layout in


R.layout.skinny_fragment -- to an Activity that uses a FrameLayout with an id of
android:id="@+id/fragment_container". Do so using a <fragment> tag, and

by using a FragmentManager().

What transactions can be performed with a FragmentManager?

Write the code necessary to instantiate a Fragment called FrangoMints and display
it in an activity's FrameLayout (assume the same is as in question 7)

Write the code necessary to instantiate a second Fragment called AndesMintes


and replace the current Fragment with it

Can you use a <fragment> tag with a FragmentManager?

What is the difference between /res/layout and /res/layout-large? Between /res/


layout-port and/res/layout-land?

Exercises

Can you have 2 files, both named my_layout.xml, defined in both /res/layout-port
and /res/layout-land? If so, when would each file be utilized?

What is the purpose of getArguments() and setArguments()?

Describe how ListFragments and WebViewFragments work.

Name the key methods of the WebViewFragment class What does loadUrl() do?
What does setWebClient() do?

What is the purpose of android.permission.INTERNET? Where, exactly is that


placed in an AndroidManifest.xml file?

Describe how Fragments communicate with Activities using interfaces.

What is the advantage of this communication?

Describe how Activities communicate with Fragment using findFragmentById()

Resources

http://developer.android.com/training/basics/fragments/index.html

http://developer.android.com/guide/components/fragments.html

http://developer.android.com/guide/practices/screens_support.html

http://stackoverflow.com/questions/6677136/member-variables-vssetarguments-in-fragments

http://stackoverflow.com/questions/6091194/how-to-handle-button-clicksusing-the-xml-onclick-within-fragments

http://stackoverflow.com/questions/19844244/fragmentbasics-gives-nullpointer-exception

http://stackoverflow.com/questions/26805863/android-studio-directory-creation

You might also like