You are on page 1of 8

Gallery

Gallery is a layout widget used to display items in a horizontally scrolling list and positions the current selection at the center of the view. In this tutorial, you'll create a gallery of photos and then display a toast message each time a gallery item is selected.

1. Start a new project named HelloGallery. 2. Find some photos you'd like to use, or use these sample images. Save the images into the
project's res/drawable/ directory.

3. Open the res/layout/main.xml file and insert the following:


<?xml version="1.0" encoding="utf-8"?> <Gallery xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gallery" android:layout_width="fill_parent" android:layout_height="wrap_content" />

4. Open the HelloGallery.java file and insert the following code for the onCreate() method:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Gallery gallery = (Gallery) findViewById(R.id.gallery); gallery.setAdapter(new ImageAdapter(this)); gallery.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show(); } }); } This starts by setting the main.xml layout as the content view and then capturing the Gallery from the layout with findViewById(int). A custom BaseAdapter calledImageAdapter is instantiated and applied to the Gallery with setAdapter(). (The ImageAdapter class is defined next.) Then an anonymousAdapterView.OnItemClickListener is instantiated. The onItemClick(AdapterView, View, int, long) callback method receives the AdapterView where the click occurred, the specific View that received the click, the position of the View clicked (zero-based), and the row ID of the item clicked (if applicable). In this example, all that's needed is the position of the click to show a Toast message that says the position of the item, using makeText(Context, CharSequence, int) and show() (in a real world scenario, this ID could be used to get the full sized image for some other task). 5. Create a new XML file in the res/values/ directory named attrs.xml. Insert the following: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="HelloGallery"> <attr name="android:galleryItemBackground" /> </declare-styleable> </resources> This is a custom styleable resource that can be applied to a layout. In this case, it will be applied to the individual items placed into the Gallery widget. The <attr> element defines a specific attribute for the styleable, and in this case, it refers to an existing platform attribute, galleryItemBackground, which defines a border styling for gallery items. In the next step, you'll see how this attribute is referenced and then later applied to each item in the gallery. 6. Go back to the HelloGallery.java file. After the onCreate(Bundle) method, define the custom ImageAdapter class:

public class ImageAdapter extends BaseAdapter { int mGalleryItemBackground; private Context mContext; private Integer[] mImageIds = { R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7 }; public ImageAdapter(Context c) { mContext = c; TypedArray attr = mContext.obtainStyledAttributes(R.styleable.HelloGallery); mGalleryItemBackground = attr.getResourceId( R.styleable.HelloGallery_android_galleryItemBackground, 0); attr.recycle(); } public int getCount() { return mImageIds.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = new ImageView(mContext); imageView.setImageResource(mImageIds[position]); imageView.setLayoutParams(new Gallery.LayoutParams(150, 100)); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setBackgroundResource(mGalleryItemBackground); return imageView; } } First, there are a few member variables, including an array of IDs that reference the images saved in the drawable resources directory (res/drawable/). Next is the class constructor, where the Context for an ImageAdapter instance is defined and the styleable resource defined in the last step is acquired and saved to a local field. At the end of the constructor, recycle() is called on the TypedArray so it can be re-used by the system. The methods getCount(), getItem(int), and getItemId(int) are methods that must be implemented for simple queries on the Adapter. The method does the work to apply an image to an {@link android.widget.ImageView that will be embedded in the Gallery. In this method, the member Context is used to create a newImageView. The ImageView is prepared by applying an image from the local array of drawable resources, setting the Gallery.LayoutParams height and width for the image, setting the scale to fit the ImageView dimensions, and then finally setting the background to use the styleable attribute acquired in the constructor. See ImageView.ScaleType for other image scaling options.

7. Run the application. You should see something like this:

Tab Layout
To create a tabbed UI, you need to use a TabHost and a TabWidget. The TabHost must be the root node for the layout, which contains both the TabWidget for displaying the tabs and a FrameLayout for displaying the tab content. You can implement your tab content in one of two ways: use the tabs to swap Views within the same Activity, or use the tabs to change between entirely separate activities. Which method you want for your application will depend on your demands, but if each tab provides a distinct user activity, then it probably makes sense to use a separate Activity for each tab, so that you can better manage the application in discrete groups, rather than one massive application and layout. In this tutorial, you'll create a tabbed UI that uses a separate Activity for each tab.

1. Start a new project named HelloTabWidget. 2. First, create three separate Activity classes in your project: ArtistsActivity, AlbumsActivity,
and SongsActivity. These will each represent a separate tab. For now, make each one display a simple message using a TextView. For example: public class ArtistsActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView textview = new TextView(this); textview.setText("This is the Artists tab"); setContentView(textview); } } Notice that this doesn't use a layout file. Just create a TextView, give it some text and set that as the content. Duplicate this for each of the three activities, and add the corresponding<activity/> tags to the Android Manifest file.

3. You need an icon for each of your tabs. For each icon, you should create two versions: one for when the tab is
selected and one for when it is unselected. The general design recommendation is for the selected icon to be a dark color (grey), and the unselected icon to be a light color (white). (See the Icon Design Guidelines.) For example:

For this tutorial, you can copy these images and use them for all three tabs. (When you create tabs in your own application, you should create customized tab icons.) Now create a state-list drawable that specifies which image to use for each tab state: 1. Save the icon images in your project res/drawable/ directory.

2. Create a new XML file in res/drawable/ named ic_tab_artists.xml and insert the following:

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- When selected, use grey --> <item android:drawable="@drawable/ic_tab_artists_grey" android:state_selected="true" /> <!-- When not selected, use white--> <item android:drawable="@drawable/ic_tab_artists_white" /> </selector> This is a state-list drawable, which you will apply as the tab image. When the tab state changes, the tab icon will automatically switch between the images defined here. 4. Open the res/layout/main.xml file and insert the following: <?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" /> </LinearLayout> </TabHost> This is the layout that will display the tabs and provide navigation between each Activity created above. The TabHost requires that a TabWidget and a FrameLayout both live somewhere within it. To position the TabWidget and FrameLayout vertically, a LinearLayout is used. The FrameLayout is where the content for each tab goes, which is empty now because the TabHost will automatically embed each Activity within it. Notice that the TabWidget and the FrameLayout elements have the IDs tabs and tabcontent, respectively. These names must be used so that the TabHost can retrieve references to each of them. It expects exactly these names.

5. Now open HelloTabWidget.java and make it extend TabActivity:


public class HelloTabWidget extends TabActivity {

6. Use the following code for the onCreate() method:


public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Resources res = getResources(); // Resource object to get Drawables TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent; // The activity TabHost // Resusable TabSpec for each tab

// Reusable Intent for each tab

// Create an Intent to launch an Activity for the tab (to be reused) intent = new Intent().setClass(this, ArtistsActivity.class);

// Initialize a TabSpec for each tab and add it to the TabHost spec = tabHost.newTabSpec("artists").setIndicator("Artists", res.getDrawable(R.drawable.ic_tab_artists)) .setContent(intent); tabHost.addTab(spec); // Do the same for the other tabs intent = new Intent().setClass(this, AlbumsActivity.class); spec = tabHost.newTabSpec("albums").setIndicator("Albums", res.getDrawable(R.drawable.ic_tab_albums)) .setContent(intent); tabHost.addTab(spec); intent = new Intent().setClass(this, SongsActivity.class); spec = tabHost.newTabSpec("songs").setIndicator("Songs", res.getDrawable(R.drawable.ic_tab_songs)) .setContent(intent); tabHost.addTab(spec); tabHost.setCurrentTab(2); } This sets up each tab with their text and icon, and assigns each one an Activity. A reference to the TabHost is first captured with getTabHost(). Then, for each tab, a TabHost.TabSpec is created to define the tab properties. The newTabSpec(String)method creates a new TabHost.TabSpec identified by the given string tag. For each TabHost.TabSpec, setIndicator(CharSequence, Drawable) is called to set the text and icon for the tab, and setContent(Intent) is called to specify the Intent to open the appropriate Activity. Each TabHost.TabSpec is then added to the TabHost by calling addTab(TabHost.TabSpec). At the very end, setCurrentTab(int) opens the tab to be displayed by default, specified by the index position of the tab. Notice that not once was the TabWidget object referenced. This is because a TabWidget must always be a child of a TabHost, which is what you use for almost all interaction with the tabs. So when a tab is added to the TabHost, it's automatically added to the child TabWidget.

7. Now open the Android Manifest file and add the NoTitleBar theme to the HelloTabWidget's <activity> tag.
This will remove the default application title from the top of the layout, leaving more space for the tabs, which effectively operate as their own titles. The <activity> tag should look like this: <activity android:name=".HelloTabWidget" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar"> 8. Run the application. Your application should look like this (though your icons may be different):

Grid View
GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid. The grid items are automatically inserted to the layout using a ListAdapter. In this tutorial, you'll create a grid of image thumbnails. When an item is selected, a toast message will display the position of the image.

1. Start a new project named HelloGridView. 2. Find some photos you'd like to use, or download these sample images. Save the image files into the
project's res/drawable/ directory.

3. Open the res/layout/main.xml file and insert the following:


<?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="90dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" /> This GridView will fill the entire screen. The attributes are rather self explanatory. For more information about valid attributes, see the GridView reference.

4. Open HelloGridView.java and insert the following code for the onCreate() method:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); GridView gridview = (GridView) findViewById(R.id.gridview); gridview.setAdapter(new ImageAdapter(this)); gridview.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show(); } }); } After the main.xml layout is set for the content view, the GridView is captured from the layout with findViewById(int). The setAdapter() method then sets a custom adapter (ImageAdapter) as the source for all items to be displayed in the grid. The ImageAdapter is created in the next step. To do something when an item in the grid is clicked, the setOnItemClickListener() method is passed a new AdapterView.OnItemClickListener. This anonymous instance defines the onItemClick() callback method to show a Toast that displays the index position (zero-based) of the selected item (in a real world scenario, the position could be used to get the full sized image for some other task). 5. Create a new class called ImageAdapter that extends BaseAdapter: public class ImageAdapter extends BaseAdapter { private Context mContext; public ImageAdapter(Context c) { mContext = c; }

public int getCount() { return mThumbIds.length; } public Object getItem(int position) { return null; } public long getItemId(int position) { return 0; } // create a new ImageView for each item referenced by the Adapter public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { // if it's not recycled, initialize some attributes imageView = new ImageView(mContext); imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setPadding(8, 8, 8, 8); } else { imageView = (ImageView) convertView; } imageView.setImageResource(mThumbIds[position]); return imageView; } // references to our images private Integer[] mThumbIds = { R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7 }; } First, this implements some required methods inherited from BaseAdapter. The constructor and getCount() are selfexplanatory. Normally, getItem(int) should return the actual object at the specified position in the adapter, but it's ignored for this example. Likewise, getItemId(int) should return the row id of the item, but it's not needed here. The first method necessary is getView(). This method creates a new View for each image added to the ImageAdapter. When this is called, a View is passed in, which is normally a recycled object (at least after this has been called once), so there's a check to see if the object is null. If it is null, an ImageView is instantiated and configured with desired properties for the image presentation: o setLayoutParams(ViewGroup.LayoutParams) sets the height and width for the Viewthis ensures that, no matter the size of the drawable, each image is resized and cropped to fit in these dimensions, as o appropriate. setScaleType(ImageView.ScaleType) declares that images should be cropped toward the center (if necessary).

setPadding(int, int, int, int) defines the padding for all sides. (Note that, if the images have different aspect-ratios, then less padding will cause for more cropping of the image if it does not match the dimensions given to the ImageView.)

If the View passed to getView() is not null, then the local ImageView is initialized with the recycled View object. At the end of the getView() method, the position integer passed into the method is used to select an image from the mThumbIds array, which is set as the image resource for theImageView. All that's left is to define the mThumbIds array of drawable resources. 6. Run the application. Your grid layout should look something like this:

Try experimenting with the behaviors of the GridView and ImageView elements by adjusting their properties. For example, instead of usingsetLayoutParams(ViewGroup.LayoutParams), try using setAdjustViewBounds(boolean).