5.User Interface/Layout
1. Writing the XML
Each layout file must contain exactly one root element, which must be a View or ViewGroup object.
Once you've defined the root element, you can add additional layout objects or widgets as child elements to gradually build a View hierarchy
that defines your layout.
2. Load the XML Resource
When you compile your application, each XML layout file is compiled into a View resource. You should load the layout resource from your
application code, in your Activity.onCreate()
callback implementation. Do so by calling
, passing it the reference to your setContentView()
layout resource in the form of: R.layout.layout_file_name
3. Common layouts
4. Building Layouts with an Adapter
When the content for your layout is dynamic or not pre-determined, you can use a layout that subclasses AdapterView
to populate the
layout with views at runtime. A subclass of the AdapterView
class uses an Adapter
to bind data to its layout. The Adapter
behaves as
a middle-man between the data source and the AdapterView
layout—the Adapter
retrieves the data (from a source such as an array
or a database query) and converts each entry into a view that can be added into the AdapterView
layout.
The two most common adapters are:
<1>ArrayAdapter
Use this adapter when your data source is an array
<2>SimpleCursorAdapter
Use this adapter when your data comes from a Cursor
.
For example, if you want to create a list of people's names and phone numbers, you can perform a query that returns a Cursor
containing a row for each person and columns for the names and numbers. You then create a string array specifying
which columns from the Cursor
you want in the layout for each result and an integer array specifying the corresponding views
that each column should be placed
If, during the course of your application's life, you change the underlying data that is read by your adapter, you should call
notifyDataSetChanged()
. This will notify the attached view that the data has been changed and it should refresh itself.
4.1 ListView
package mirror.android.listviewtest; import android.app.ListActivity; import android.app.LoaderManager.LoaderCallbacks; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.view.View; import android.widget.ListView; import android.widget.SimpleCursorAdapter; public class ListViewActivity extends ListActivity implements LoaderCallbacks<Cursor>{ // This is the Adapter being used to display the list's data private SimpleCursorAdapter mAdapter; // These are the Contacts rows that we will retrieve static final String[] PROJECTION = new String[] {ContactsContract.Data._ID, ContactsContract.Data.DISPLAY_NAME}; // This is the select criteria // = "((display_name NOTNULL) AND (display_name != '' ))" static final String SELECTION = "((" + ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Data.DISPLAY_NAME + " != '' ))"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /*// Create a progress bar to display while the list loads ProgressBar progressBar = new ProgressBar(this); progressBar.setLayoutParams(new LayoutParams(Gravity.CENTER)); progressBar.setIndeterminate(true); getListView().setEmptyView(progressBar); // Must add the progress bar to the root of the layout ViewGroup root = (ViewGroup) findViewById(android.R.id.content); root.addView(progressBar);*/ // For the cursor adapter, specify which columns go into which views String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME}; int[] toViews = {android.R.id.text1}; //// The TextView in simple_list_item_1 // Create an empty adapter we will use to display the loaded data. // We pass null for the cursor, then update it in onLoadFinished() mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, fromColumns, toViews, 0); setListAdapter(mAdapter); // Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this); } // Called when a new Loader needs to be created @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed return new CursorLoader(this, ContactsContract.Data.CONTENT_URI, //uri The URI PROJECTION, //list of which columns to return. Passing null will return all columns, which is inefficient. SELECTION, //filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). //Passing null will return all rows for the given URI. null, null); } // Called when a previously created loader has finished loading @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data); } // Called when a previously created loader is reset, making the data unavailable @Override public void onLoaderReset(Loader<Cursor> loader) { // This is called when the last Cursor provided to onLoadFinished() // above is about to be closed. We need to make sure we are no // longer using it. mAdapter.swapCursor(null); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { // Do something when a list item is clicked super.onListItemClick(l, v, position, id); } }
AndroidManifest.xml add permisssion "READ_CONTRACTS"
// This is the Adapter being used to display the list's data
private SimpleCursorAdapter mAdapter;