Traversing an Android APP Project structure In this article, we will

Traversing an Android APP Project structure
In this article, we will look at the new Android UI API, the Fragments API. Part of the Android
3.0 SDK, it allows developers to use the large screen space available on tablets, efficiently, by
dynamically updating a portion of the screen area without moving to a different screen space.
Let’s build a simple application to explore how Fragments API works.
Initially, the Fragments API was available only in the Android 3.0 SDK. To overcome criticism
of “Android not being backward-compatible”, Google released a compatibility package that
allowed previous versions of the API to support this new feature. Along with the Fragments API,
this compatibility package also provides support for some other Google-specific APIs like
market billing and market licensing.
Fragments, as the name suggests, are nothing but small chunks of the UI, which constitute a
single Activity. They can be treated as individual portlets of a portal page. Though very similar
to an Activity in terms of looks, lifecycle, etc, a fragment is different from an Activity in the
sense that it should always reside in an Activity; fragments cannot exist independently.
Advantages of fragments





It can modularise a single Activity into smaller units of the UI, making it easier to
manage.
A fragment need not be used with the same host Activity, but can be reused by other
activities; and is hence very flexible.
A fragment could exist without a UI screen, which means it could be used as an invisible
worker for the Activity.
A fragment allows us to maintain a “back-stack” of its state, or transactions, so we can
traverse its transactions when we press the Back button on the device.
Makes the application compact, using less activities, by increasing the number of
fragments in a single Activity.
Before getting started on building the application, let’s get a head start on the Fragments API. To
create a Fragment, we need to extend the class with Fragment. There are different kinds of
fragments available, such as a ListFragment (similar to a ListActivity), a DialogFragment
(similar to a Dialog Interface) and a PreferenceFragment (similar to a PreferenceActivity).
Fragment callbacks
Let’s discuss callbacks during the fragment’s lifecycle (see Figure 2). As we already know, a
Fragment cannot exist on its own; it has to be associated with an Activity. Therefore, the Activity
class needs to be extended with FragmentActivity.
Figure : Fragment callbacks during its lifecycle
The initialisation of the fragment is done in the onAttach() method, which is invoked when the
fragment is associated with an Activity. The onCreate() method is invoked when the fragment
is created. A UI is associated with a fragment by invoking the method onCreateView(), which
associates the fragment id with a UI layout. If you don’t want to associate a UI with a fragment,
then you can pass “null”. Fragments are destroyed when the Activity is destroyed, and that’s
when the onDestroyView() and onDetach() methods are called.
Building the application
Now, let’s get started with building our application, EFY Group. Figure 3 gives you the complete
package structure of the application. It is clear that we will have two classes, one for the Activity
(FragmentTestActivity), and one for the fragment (TestFragment).
Figure : Package structure
In the beginning, I had discussed backward-compatibility support for fragments, in relation to
which
I
have
referenced
an
external
jar
file,
<android
sdk
home>/extras/android/support/v4/android-support-v4.jar. This library provides the
necessary API support for Fragments. In this application, I will be using the Android 2.2 library
(Froyo) to demonstrate the Fragments API. I have uploaded the application to GitHub, so you
can get the code for the application there.
To begin, let’s create an Android Project with the following specifications:






Then
Project Name: FragmentTest
Android Target: 2.2
Application Name: EFY Group
Package Name: com.android.saket.fragments
CreateActivity: FragmentTestActivity
MinSDKVersion: 8 (OPTIONAL)
let’s
create
another
class,
named
TestFragment,
with
the
superclass
android.support.v4.app.Fragment.
Next, we set the layout for our application. Referring back to Figure 1, you can see that there is a
ListView to list all the magazines published by the EFY Group, and an ImageView to display an
image of the selected magazine. Figure 4 shows you the layout structure in main.xml.
Figure : The main.xml file
We can also create a folder, layout-land, and emulate the same main.xml in this folder, so that
when the device orientation changes, the application layout changes from portrait to landscape,
and vice-versa.
Now that we have the layout defined, what remains is the code behind it. Let’s start with the
FragmentTestActivity class. In the onCreate() method, set the list adapter to hold a string
array of EFY Group magazine titles. Also set the listener on the list items, so that you can
perform some action when an item from the list is clicked.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView l = (ListView) findViewById(R.id.number_list);
ArrayAdapter<String>
magzTitles
ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,
new String[]{"Electronics For You",
"Linux For You",
"Facts For You"});
l.setAdapter(magzTitles);
l.setOnItemClickListener(this);
}
=
new
In the onItemClickListener() method, perform the main task of managing the fragment.
Obtain the instance of the fragment by passing the position of the clicked item. Now, you need to
replace the fragment element in main.xml with the new fragment TestFragment, which has a
meaningful UI associated with it.
To accomplish this, get the instance of the FragmentTransaction class. This API allows you to
add, remove and replace a fragment programmatically. Replace the R.id.the_frag, which
corresponds to the <fragment> element of main.xml, with the newly created fragment f. The
setTransition() method signifies the kind of transition that happens with the fragment. Some
of the transition values are shown below.





TRANSIT_FRAGMENT_CLOSE — Fragment is being removed from the stack.
TRANSIT_FRAGMENT_FADE — Fragment should simply fade in or out; i.e., there
should be
no strong navigation associated with it, except that it appears or disappears for some
reason.
TRANSIT_FRAGMENT_OPEN — Fragment is being added onto the stack.
TRANSIT_NONE — No animation for transition.
TRANSIT_UNSET — Not set-up for a transition.
The addToBackStack() method adds the fragment transaction to the fragment stack, so that
when the back button is pressed on the device, you go to the last transaction of the fragment, and
do not exit the application. After the transaction is set up, commit it, as follows:
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Fragment testFragment = new TestFragment(position+1);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.the_frag, testFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
Now, set up the fragment class, TestFragment. We initialise the position of the clicked item
from the list to a variable, magznumber. As discussed earlier, if a fragment is being associated
with a UI, then the onCreateView() method is used to inflate the view to the fragment. Here,
create a linear layout for the fragment, and then load it with the appropriate image of the
magazine in an ImageView, and this ImageView is added to the linear layout:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
saved) {
Context c = getActivity().getApplicationContext();
LinearLayout l = new LinearLayout(c);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT, 0);
l.setLayoutParams(params);
ImageView i = new ImageView(c);
switch(magznumber){
case 1:
i.setImageResource(R.drawable.efymag);
break;
case 2:
i.setImageResource(R.drawable.lfymag);
break;
case 3:
i.setImageResource(R.drawable.ffymag);
break;
}
l.addView(i);
return l;
}