40
MobAppDev Fragments & ViewGroups, Fragment Management, Fragment Creation, Activity vs Fragment Lifecycles Vladimir Kulyukin www.vkedco.blogspot.com

MobAppDev (Fall 2014): Fragments

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: MobAppDev (Fall 2014): Fragments

MobAppDev

Fragments & ViewGroups, Fragment Management, Fragment Creation,

Activity vs Fragment Lifecycles

Vladimir Kulyukin

www.vkedco.blogspot.com

Page 2: MobAppDev (Fall 2014): Fragments

Outline

● Fragments & ViewGroups● Fragment Management● Fragment Creation● Activity vs. Fragment Lifecycle

Page 3: MobAppDev (Fall 2014): Fragments

Fragments & ViewGroups

Page 4: MobAppDev (Fall 2014): Fragments

Fragment Lifecycle

source image at http://developer.android.com/guide/components/fragments.html

Page 5: MobAppDev (Fall 2014): Fragments

Fragments & ViewGroups

● When a fragment is added to an activity layout, it becomes a component in a ViewGroup (a container that may contain other views called children) inside the activity's view hierarchy

● A fragment may define its own view layout● A fragment can be inserted into the activity's layout file via the

tags <fragment></fragment>

Page 6: MobAppDev (Fall 2014): Fragments

Example: ListFragment Inside LinearLayout<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="match_parent"

android:layout_height="match_parent">

<fragment class="org.vkedco.mobappdev.rumi_quatrain_fragments.QuatrainNumberListFragment"

android:id="@+id/quatrain_numbers"

android:layout_width="match_parent"

android:layout_height="match_parent" />

</LinearLayout>

Page 7: MobAppDev (Fall 2014): Fragments

Fragments & ViewGroups● Fragments are not required to be a part of the activity layout; there

may be fragments w/o UIs as background workers for activities● A Fragment should be designed as a modular and reusable activity

component● Why? Since fragments may define their own layouts and have their

own lifecycle callbacks, one fragment may be included in multiple activities

● Direct manipulation of one fragment from another fragment should be avoided: breaks modularity and leads to cycle-related errors

Page 8: MobAppDev (Fall 2014): Fragments

Fragments on Tablets

Here is a useful link to the design and implementation practices of how to design fragments for reuse if you want to develop for multiple screen sizes:

http://developer.android.com/guide/practices/tablets-and-handsets.html

Page 9: MobAppDev (Fall 2014): Fragments

Fragment Management

Page 10: MobAppDev (Fall 2014): Fragments

Managing Fragments● Fragments are managed with the FragmentManager class

● FragmentManager object can be obtained via Activity. getFragmentManager()

● FragmentManager is used to:

Find fragments in an activity either with findFragmentById() (for fragments that have IDs) or findFragmentByTag() (for fragments that do not have UIs)

Pop fragments off the back stack, with popBackStack() (this is the same as the user's pressing Back button)

Register a listener for changes to the back stack, with addOnBackStackChangedListener()

open FragmentTransaction objects to add and remove fragments

Page 11: MobAppDev (Fall 2014): Fragments

Fragment Transactions● FragmentTransactions are used to add, remove, replace, and

perform other actions with them, in response to UI gestures● A transaction is a set of changes that must be committed with respect

to the activity● It is also possible to save each transaction to a back stack managed

by the activity● The user can navigate navigate back through the fragment changes

Page 12: MobAppDev (Fall 2014): Fragments

Beginning & Ending Transactions

FragmentManager fragmentManager = getFragmentManager();

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// some code

// each transaction must be committed to take effect

fragmentTransaction.commit();

Page 13: MobAppDev (Fall 2014): Fragments

A Typical Transaction Sequence

// 1) create new fragment and transaction

Fragment newFrgmnt = new SomeFragment();

FragmentTransaction trans = getFragmentManager().beginTransaction();

// 2) replace the contents of the view container with the newly created fragment,

// 3) add the transaction to the back stack

trans.replace(R.id.view_container, newFrgmnt);

trans.addToBackStack(null);

// 4) commit the transaction

transaction.commit();

Page 14: MobAppDev (Fall 2014): Fragments

Fragment Creation

Page 15: MobAppDev (Fall 2014): Fragments

Fragment Creation

● To create a fragment, the developer must either create a subclass of Fragment or a subclass of an existing subclass of Fragment

● The Fragment class has code that looks a lot like an Activity in that it contains callbacks such as onCreate(), onStart(), onPause(), & onStop()

● In many cases, converting existing activities to fragments is as simple as moving code from the activities' callback methods into the corresponding methods of fragments

Page 16: MobAppDev (Fall 2014): Fragments

Fragment Layouts

● To provide a layout for a fragment, the onCreateView() callback must be implemented

● Android system calls this method when the fragment is ready to draw its layout

● The implementation of this method must return the View root of the fragment's layout

● Fragments typically implement UI parts of the host activity

Page 17: MobAppDev (Fall 2014): Fragments

Programmatic Addition of Fragments

// getFragmentManager() is a method of the Activity class

FragmentManager fragmentManager = getFragmentManager();

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// Create a fragment and use the transaction to add the fragment to the view container

SomeFragment frgmnt = new SomeFragment();

fragmentTransaction.add(R.id.view_container, frgmnt);

fragmentTransaction.commit();

Page 18: MobAppDev (Fall 2014): Fragments

Order of Multiple Fragments

● A call to commit() must be last● When multiple fragments are added to the same container, then the

order in which they are added determines the order they appear in the view hierarchy

● If there is no call to addToBackStack() in a transaction removes a fragment, the removed fragment is destroyed after the transaction is committed and the user cannot navigate back to it

Page 19: MobAppDev (Fall 2014): Fragments

Finding Fragments w/in Activity

FragmentManager fm = getFragmentManager();

SomeFragment fragment =

(SomeFragment) fm.findFragmentById(R.id.some_fragment);

Page 20: MobAppDev (Fall 2014): Fragments

Three Important States

● Resumed: fragment is visible● Paused: another activity is in the foreground and has

focus.● Stopped: fragment is not visible

Page 21: MobAppDev (Fall 2014): Fragments

Activity vs Fragment Lifecycles

source image at http://developer.android.com/guide/components/fragments.html

Page 22: MobAppDev (Fall 2014): Fragments

Rumi's Quatrains with Fragments

source code is at https://github.com/VKEDCO/RumiQuatrainFragments

Page 23: MobAppDev (Fall 2014): Fragments

Application Requirements

● Develop an application that uses fragments to display texts of several fragments by Rumi

● The application should work in two modes: landscape and portrait● In portrait mode, only one quatrain can be displayed● In landscape mode, the user can select the quatrains to display

Page 24: MobAppDev (Fall 2014): Fragments

Sample Screenshots

landscape

portrait

Page 25: MobAppDev (Fall 2014): Fragments

Application Class Contents

● RumiQuatrainMainActivity.java – main activity● QuatrainNumberListFragment.java – ListFragment associated with

main activity● QuatrainTextDisplayActivity.java – host activity for

QuatrainTextDisplayFragment.java● QuatrainTextDisplayFragment.java – fragment to display quatrain

texts● The texts of the quatrains and their numbers are in quatrains.xml

Page 26: MobAppDev (Fall 2014): Fragments

AndroidManifest.xml<application android:icon="@drawable/rumi" android:label="Rumi's Quatrains">

<activity android:name="org.vkedco.mobappdev.rumi_quatrain_fragments.RumiQuatrainMainActivity"

android:label="Rumi's Fragments">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity android:name="org.vkedco.mobappdev.rumi_quatrain_fragments.QuatrainTextDisplayActivity"

android:label="Quatrain's Text">

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

</application>

Page 27: MobAppDev (Fall 2014): Fragments

AndroidManifest.xml<application android:icon="@drawable/rumi" android:label="Rumi's Quatrains">

<activity android:name="org.vkedco.mobappdev.rumi_quatrain_fragments.RumiQuatrainMainActivity"

android:label="Rumi's Fragments">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity android:name="org.vkedco.mobappdev.rumi_quatrain_fragments.QuatrainTextDisplayActivity"

android:label="Quatrain's Text">

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

</application>

Page 28: MobAppDev (Fall 2014): Fragments

XML Layout of the Main Activity: Main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="match_parent"

android:layout_height="match_parent">

<fragment class="org.vkedco.mobappdev.rumi_quatrain_fragments.QuatrainNumberListFragment"

android:id="@+id/quatrain_numbers"

android:layout_width="match_parent"

android:layout_height="match_parent" />

</LinearLayout>

Page 29: MobAppDev (Fall 2014): Fragments

XML Layout of the Secondary Activity: quatrain_text_display.xml

<LinearLayout>

<ScrollView android:id="@+id/scvQuatrainText"

android:layout_width="match_parent"

android:layout_height="match_parent">

<TextView

android:id="@+id/tvQuatrainText"

android:layout_width="match_parent"

android:layout_height="match_parent" />

</ScrollView>

</LinearLayout>

Page 30: MobAppDev (Fall 2014): Fragments

RumiQuatrainMainActivity.javapublic class RumiQuatrainMainActivity extends Activity {

static final String LOGTAG = RumiQuatrainMainActivity.class.getSimpleName() + "_TAG";

static Resources mRes = null;

static FragmentManager mFrgmntMngr = null;

static RumiQuatrainMainActivity mThisAct = null;

public void onCreate(Bundle savedInstanceState) {

Log.d(LOGTAG, "onCreate()");

super.onCreate(savedInstanceState);

FragmentManager.enableDebugLogging(true);

setContentView(R.layout.main);

mRes = getResources();

mFrgmntMngr = getFragmentManager();

mThisAct = this;

}

Page 31: MobAppDev (Fall 2014): Fragments

Determining Device's Orientation

static boolean isInLandscapeOrientation() {

return mRes.getConfiguration().orientation

== Configuration.ORIENTATION_LANDSCAPE;

}

Page 32: MobAppDev (Fall 2014): Fragments

RumiQuatrainMainActivity.java

● The real workhorse of is displayQuatrainText(int quatrain_index)● It finds a fragment by id and replaces it with a newly created fragment● It also shows how to check the orientation● If the orientation is landscape, then two fragments are displayed● If the orientation is portrait, then a new activity is launched

Page 33: MobAppDev (Fall 2014): Fragments

Displaying Quatrain's Text in Landscape Orientation if ( isInLandscapeOrientation() ) {

// Check what fragment is shown, replace if needed.

QuatrainTextDisplayFragment qTxtFrgmnt = (QuatrainTextDisplayFragment)

mFrgmntMngr.findFragmentById(R.id.quatrain_text);

if (qTxtFrgmnt == null || qTxtFrgmnt.getDisplayedQuatrainIndex() != quatrain_index) {

// Make new fragment to show this selection.

qTxtFrgmnt = QuatrainTextDisplayFragment.newInstance(quatrain_index);

// Execute a transaction, replacing any existing

// fragment inside the frame with the new one.

FragmentTransaction frag_trans = mFrgmntMngr.beginTransaction();

frag_trans.setCustomAnimations(R.animator.bounce_in_down, R.animator.fade_out);

frag_trans.setCustomAnimations(R.animator.bounce_in_down, R.animator.slide_out_right);

frag_trans.replace(R.id.quatrain_text, qTxtFrgmnt);

frag_trans.commit();

}

Page 34: MobAppDev (Fall 2014): Fragments

Displaying Quatrain's Text in Portrait Orientation

Intent intent = new Intent();

intent.setClass(mThisAct, QuatrainTextDisplayActivity.class);

intent.putExtra(mRes.getString(R.string.quat_index_key), quatrain_index);

this.startActivity(intent);

Page 35: MobAppDev (Fall 2014): Fragments

XML Animations

Page 36: MobAppDev (Fall 2014): Fragments

Animating Bounces

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:interpolator/bounce"

android:valueFrom="-1200"

android:valueTo="0"

android:valueType="floatType"

android:propertyName="Y"

android:duration="2000" />

Page 37: MobAppDev (Fall 2014): Fragments

Animating Left Slides

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:interpolator/accelerate_decelerate"

android:valueFrom="-1200"

android:valueTo="0"

android:valueType="floatType"

android:propertyName="X"

android:duration="2000" />

Page 38: MobAppDev (Fall 2014): Fragments

Animating Right Slides

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:interpolator/accelerate_decelerate" android:valueFrom="0" android:valueTo="1280" android:valueType="floatType" android:propertyName="X" android:duration="2000" />

Page 39: MobAppDev (Fall 2014): Fragments

Animating Left Slides

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:interpolator/accelerate_decelerate"

android:valueFrom="-1280"

android:valueTo="0"

android:valueType="floatType"

android:propertyName="X"

android:duration="2000" />

Page 40: MobAppDev (Fall 2014): Fragments

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

● S. Komatineni & D. MaClean. Pro Android 4. APRESS

● R. Meier. Pro Android 4 Application Development. WROX