Browse through more Android tutorials. If you'd like to see a tutorial on any particular topic, do leave a comment in the wishlist page. We frequently post new tutorials along with app releases. You may subscribe to our newsletter to get all updates in your inbox.
Now you can get the latest Java source bundled with each app update. Install the app from Google Play and go to Settings > Extras.

«  Create an instant messaging app Create a currency converter app  »

Create a Notepad and To-do list combined app in Android

DownloadDownload

Keywords: TabHost ListView ExpandableListActivity SQLite SimpleCursorAdapter SimpleCursorTreeAdapter PreferenceActivity AlertDialog ContextMenu Spinner Gallery ScrollView Camera

Contents

2 « Prev Page

6. Develop the UI

The main screen is implemented using a TabHost with a custom TabIndicator (without the icon).
Here is the main.xml layout file which is set as the content view for this screen.
	<?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:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:orientation="vertical" >
			
			<TabWidget
				android:id="@android:id/tabs"
				android:layout_width="fill_parent"
				android:layout_height="wrap_content" >
			</TabWidget>
			<View android:layout_width="fill_parent" 
				  android:layout_height="2dip" 
				  android:background="#696969" />

			<FrameLayout
				android:id="@android:id/tabcontent"
				android:layout_width="fill_parent"
				android:layout_height="0dip"
				android:background="@drawable/pad_bg_repeat"
				android:layout_weight="1" >
			</FrameLayout>
		</LinearLayout>
	</TabHost>			
						
The background of tabcontent is set as a bitmap drawable with tile mode set to repeat.
	<?xml version="1.0" encoding="utf-8"?>
	<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
		android:src="@drawable/pattern8_pattern_58c"
		android:tileMode="repeat" />			
						
The MainActivity extends TabActivity and the following lines of code sets up the tabs in onCreate() method.
	TabHost tabHost = getTabHost();
	TabHost.TabSpec spec;
	Intent intent;
	
	tabHost.getTabWidget().setDividerDrawable(R.drawable.tab_divider);
	
	// Browse
	intent = new Intent().setClass(this, BrowseActivity.class);
	spec = tabHost.newTabSpec(TAB_BROWSE)
				.setIndicator(createTabIndicator(getResources().getString(R.string.browse)))
				.setContent(intent);
	tabHost.addTab(spec);
	
	// Manage
	intent = new Intent().setClass(this, ManageActivity.class);
	spec = tabHost.newTabSpec(TAB_MANAGE)
				.setIndicator(createTabIndicator(getResources().getString(R.string.manage)))
				.setContent(intent);
	tabHost.addTab(spec);
					
The createTabIndicator() method creates a custom view which is set as indicator for the tab.
    private View createTabIndicator(String label) {
    	View tabIndicator = getLayoutInflater().inflate(R.layout.tabindicator, null);
    	TextView tv = (TextView) tabIndicator.findViewById(R.id.label);
    	tv.setText(label);
    	return tabIndicator;
    }
					
The tabindicator.xml is a simple layout file with a TextView.
	<?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="wrap_content"
		android:background="@drawable/tab_bg_selector"
		android:gravity="center_horizontal" >
		<TextView
			android:id="@+id/label"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content" />
	</LinearLayout>			
						
The active or inactive state of the tab indicator determines its background through a selector drawable.
	<?xml version="1.0" encoding="utf-8"?>
	<selector xmlns:android="http://schemas.android.com/apk/res/android">
		<item android:state_selected="false" android:drawable="@drawable/tab_unselected" />
		<item android:state_selected="true" android:drawable="@drawable/tab_selected" />
		<item android:drawable="@android:color/transparent" />
	</selector>
						
The tab_selected and tab_unselected are shape drawables with different gradient.
	<?xml version="1.0" encoding="utf-8"?>
	<shape xmlns:android="http://schemas.android.com/apk/res/android"
		android:shape="rectangle">
		<gradient android:startColor="#A8A8A8" android:centerColor="#7F7F7F"
			android:endColor="#696969" android:angle="-90" />
	</shape>
						
The content of each tab is set to be an intent. We will create two Activity for this purpose and add the folowing lines to the <application> tag in AndroidManifest.xml.
	<activity android:name=".BrowseActivity"></activity>
	<activity android:name=".ManageActivity"></activity>			
					

7. The Browse tab

The Browse tab is implemented using a ListView and a SimpleCursorAdapter used to fetch the list items. Here is a brief outline of BrowseActivity class.
	public class BrowseActivity extends Activity implements AdapterView.OnItemClickListener {
		private ListView noteList;
		private TextView emptyView;

		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.tab_browse);
			
			noteList = (ListView) findViewById(R.id.note_list);
			emptyView = (TextView) findViewById(android.R.id.empty);
					
			noteList.setOnItemClickListener(this);
			noteList.setEmptyView(emptyView);
		}

		@Override
		protected void onResume() {
			super.onResume();
			
			Cursor c = Note.list(SmartPad.db);
			startManagingCursor(c);
			SimpleCursorAdapter adapter = new SimpleCursorAdapter(
					this, 
					R.layout.row_note, 
					c, 
					new String[]{Note.COL_TITLE, Note.COL_TYPE, Note.COL_MODIFIEDTIME},
					new int[]{android.R.id.text1, R.id.icon, android.R.id.text2});
			
			noteList.setAdapter(adapter);
		}

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			// TODO open the note
		}
	}
					
Each list item is rendered using the layout row_note.xml.
Here is an excerpt from the file.
	<RelativeLayout
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent"
	    android:background="@drawable/note_bg" >
	    <ImageView
	        android:id="@+id/icon"
	        android:layout_alignParentLeft="true"
	        android:layout_alignParentTop="true"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content" />
	    <TextView
	        android:id="@android:id/text1"
	        android:layout_toRightOf="@id/icon"
	        android:layout_width="fill_parent"
	        android:layout_height="wrap_content"
	        android:textColor="@android:color/white"
	        android:textSize="18sp" />
	    <View 
	        android:id="@+id/line"
	        android:layout_toRightOf="@id/icon"
	        android:layout_below="@android:id/text1"
	        android:layout_width="fill_parent" 
	        android:layout_height="1dip"
	        android:background="#777777" />
	    <TextView
	        android:id="@android:id/text2"
	        android:layout_alignParentRight="true"
	        android:layout_below="@id/line"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:textColor="#555555"
	        android:textSize="10sp" />
	</RelativeLayout>			
						
The translucent and round corner effect is obtained by setting the background using note_bg.xml shape drawable.
	<?xml version="1.0" encoding="utf-8"?>
	<shape xmlns:android="http://schemas.android.com/apk/res/android" >
		<solid
			android:color="#99ffffff" />
		<corners
			android:radius="4dp" />
		<padding
			android:left="10dp"
			android:top="10dp"
			android:right="10dp"
			android:bottom="10dp" />
	</shape>			
						
We have written a separate article which discusses exclusively about how to create some awesome Android UI effects.
The icon next to the title is set programatically by specifying a ViewBinder to the adapter. Here is the lines of code which we need to add in onResume() after creating the SimpleCursorAdapter.
	adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
		
		@Override
		public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
			String value = cursor.getString(columnIndex);
			
			switch (view.getId()) {
			case R.id.icon:
				int icon = 0;
				if (Note.BASIC.equals(value))
					icon = R.drawable.document;
				else if (Note.CHECKLIST.equals(value))
					icon = R.drawable.checklist;
				else if (Note.SNAPSHOT.equals(value))
					icon = R.drawable.pictures;
				
				((ImageView)view).setImageResource(icon);
				return true;					
				
			case android.R.id.text2:
				((TextView)view).setText("Last edited on " + value);
				return true;					
			}
			return false;
		}
	});
					
The bottom portion of the screen is a LinearLayout with two ImageButton. The background of the LinearLayout is a bitmap drawable with tile mode set to repeat whereas the background of the ImageButton is an oval shape drawable.
Here is some relevant portion of the tab_browse.xml layout file.
	<ListView
		android:id="@+id/note_list"
		android:layout_width="fill_parent"
		android:layout_height="0dip"
		android:layout_weight="1"
		android:cacheColorHint="#00000000"
		android:divider="@android:color/transparent"
		android:drawSelectorOnTop="false" />
	<TextView
		android:id="@android:id/empty"
		android:layout_width="fill_parent"
		android:layout_height="0dip"
		android:layout_weight="1"
		android:gravity="center"
		android:text="@string/no_data" />
	<View android:layout_width="fill_parent" 
		  android:layout_height="2dip" 
		  android:background="#333333" />
	<LinearLayout
		android:id="@+id/menubar"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:gravity="center"
		android:background="@drawable/bar_bg_repeat" >
		<ImageButton
			android:id="@+id/new_btn"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:background="@drawable/btn_bg"
			android:src="@drawable/new_doc" />
		<ImageButton
			android:id="@+id/sort_btn"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:background="@drawable/btn_bg"
			android:src="@drawable/sort" />
	</LinearLayout>			
					

We have learned some useful UI stuff in this chapter which can be reused in developing other screens. Next, we will develop the Manage tab.
Share the love:  

Next Page » 2

App Gen
App Name:
Project Name:
Package:
Screens:
Splash
Login
Help
Main
List  Grid  Pager
Detail
Settings
Options:
Action Bar
Navigation Drawer
Dummy Data
Generate
Free Apps