Android: ListView with multiple choice and subitems enabled - android

I'm trying to get my contacts on a list view. Now I know that using simple_list_item_multiple_choice enables me to select multiple contacts, but it views names only without numbers.
On the other side, simple_list_item_2 can be used to show both name and number, but supports selection of only one contact.
Is there any template that combine them both? If not, how could I build my customized list with both features?
EDIT: This is the code I'm using
CursorLoader cl = new CursorLoader(this,ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC");
Cursor c = cl.loadInBackground();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_multiple_choice, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME},
new int[] { android.R.id.text1},0);
setListAdapter(adapter);
Here, the second parameter of SimpleCursorAdapter is simple_list_item_multiple_choice but it supports only dealing with android.R.id.text1. So I can use items only, not subitems.
But in the following code
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ,ContactsContract.CommonDataKinds.Phone.NUMBER},
new int[] { android.R.id.text1,android.R.id.text2},0);
I can give it both ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME and NUMBER to be written in android.R.id.text1 and android.R.id.text2, but can't use multiple choice feature.

As Dipu said, you should make your own customized layout.
To show name and contact, you need two text views, and one check box for checking.
You can start coding from this tutorial:
http://www.mysamplecode.com/2012/07/android-listview-checkbox-example.html
Add one more text view to country_info.xml will solve your problem.
ADDED
To use a custom list view layout, you have to implement your own adapter.
This tutorial (2. Custom ArrayAdapter example) will help you figure out how to do that.
http://www.mkyong.com/android/android-listview-example/

The answer provided by Heejin is excellent, but it's not important to implement a custom ArrayAdaptor. What only I needed to do is to write a custom layout and send it to the SimpleCursorAdaptor constructor.
The custom layout represent the layout of each item in the list view. I need each row to contain a CheckedTextView and another small TextView as a subitem. So I've made a layout called row_view.xml with the following content
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<CheckedTextView
android:id="#+id/checkedTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:text="CheckedTextView" />
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
Then I've just used it in the constructor
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.row_view, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER},
new int[] { R.id.checkedTextView, R.id.textView},0);
setListAdapter(adapter);
This is the full code
public class MultipleContacts extends ListActivity implements OnItemClickListener {
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone._ID
,ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
,ContactsContract.CommonDataKinds.Phone.NUMBER
};
SimpleCursorAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multiple_contacts);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
getListView().setOnItemClickListener(this);
// Get a cursor with all people
CursorLoader cl = new CursorLoader(this,ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
PROJECTION, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC");
Cursor c = cl.loadInBackground();
adapter = new SimpleCursorAdapter(this,
R.layout.row_view, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER},
new int[] { R.id.checkedTextView, R.id.textView},0);
setListAdapter(adapter);
}
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
//what to do when an item is clicked
CheckedTextView checkedTextView = (CheckedTextView) v.findViewById(R.id.checkedTextView);
Toast.makeText(this, checkedTextView.getText(), Toast.LENGTH_SHORT).show();
}
}
Please note that I've two layouts, one for the list view itself(called multiple_contacts) and the provided layout here (called row_view) is the layout for each item in the list view. All what I need from multiple_contacts is to write setContentView(R.layout.multiple_contacts);

Related

View data from SQLite database using ListView on Android

I am quite new to Android development. I managed to get data saved to SQLite database. Now, what I want is to view these data when I call viewData(). I have viewData() which shows data as a Toast as I made it as a sample. Now I need these data to show on a new activity using a ListView, but the number of data to show is depending on how many data is in the database at the moment, If user saved 10 items then I want all the 10 items to shown up. How can I do it?
I hope my question is clear.
Thanks in advance.
you could use ListView
declare it in your layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#+id/list"
android:layout_height="wrap_content"
android:layout_width="match_parent">
</ListView>
</LinearLayout>
in yor activity declare a globar var:
ListView listView;
and onCreate
listView = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, values);
// Assign adapter to ListView
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id){
// ListView Clicked item index
int itemPosition = position;
// ListView Clicked item value
String itemValue = (String) listView.getItemAtPosition(position);
}
});
datos can be an array that you can populate with data that you extract from your data base and that's the most simple way to show it. if you want to customizise your listView you can create a custom adapter, or in other way the newest element that replace listView is ReciclerView. I hope tihs help you
You can use a SimpleCursorAdapter:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView answerList=(ListView)findViewById(R.id.answerList);
Cursor mCursor = getData();
startManagingCursor(mCursor);
// now create a new list adapter bound to the cursor.
// SimpleListAdapter is designed for binding to a Cursor.
ListAdapter adapter = new SimpleCursorAdapter(this, // Context.
android.R.layout.two_line_list_item,
mCursor, // Pass in the cursor to bind to.
// Array of cursor columns to bind to.
new String[] {"_id", "answer"};
// Parallel array of which template objects to bind to those
// columns.
new int[] { android.R.id.text1,android.R.id.text2 });
// Bind to our new adapter.
answerList.setAdapter(adapter);
}
private Cursor getData() {
String sq = "Select _id, answer from foo";
Cursor c = db.rawQuery(sql);
return c;
}
I will try to give an in-depth answer to this.
Whenever you want to fetch and display a list of data from the database, you can use a ListView, GridView, Spinner, etc for it.
You can use a CursorAdapter which can make the job of querying and displaying data much more simple and easy.
Here is a basic visual representation of it,
Step 1
Firstly, you need to create a database. As mentioned in your question, it is clear that you know how to create a database and put some data into it. So I am not going into the depths of it.
Step 2
We need to define the layout to be used for the individual items in the ListView and save it as res/layout/item_todo.xml This is just a sample layout, you can design any kind of layout you want to.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/tvBody"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Study cursors"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/tvPriority"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="3"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
Step 3
Now we need to define an adapter. Here we are using a CursorAdapter which converts a Cursor (that you provide) into Views (defined by your layout).
There are two methods, newView and bindView which we need to override. The newView is responsible for inflating newViews for the first time and the bindView is responsible for binding the data to the Views.
public class TodoCursorAdapter extends CursorAdapter {
public TodoCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_todo, parent, false);
}
// The bindView method is used to bind all data to a given view
// such as setting the text on a TextView.
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView tvBody = (TextView) view.findViewById(R.id.tvBody);
TextView tvPriority = (TextView) view.findViewById(R.id.tvPriority);
// Extract properties from cursor
String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
int priority = cursor.getInt(cursor.getColumnIndexOrThrow("priority"));
// Populate fields with extracted properties
tvBody.setText(body);
tvPriority.setText(String.valueOf(priority));
}
}
Step 4
Now as you can clearly see, that the constructor needs a Context and a Cursor. Now we need to query the database and retrieve the data into a Cursor and pass it to the adapter.
// TodoDatabaseHandler is a SQLiteOpenHelper class connecting to SQLite
TodoDatabaseHandler handler = new TodoDatabaseHandler(this);
// Get access to the underlying writeable database
SQLiteDatabase db = handler.getWritableDatabase();
// Query for items from the database and get a cursor back
Cursor todoCursor = db.rawQuery("SELECT * FROM todo_items", null);
Step 5
This is the last step where we need to instantiate the adapter and attach the ListView with the adapter to populate the data.
// Find ListView to populate
ListView lvItems = (ListView) findViewById(R.id.lvItems);
// Setup cursor adapter using cursor from last step
TodoCursorAdapter todoAdapter = new TodoCursorAdapter(this, todoCursor);
// Attach cursor adapter to the ListView
lvItems.setAdapter(todoAdapter);

Adding items to the top of a dynamic listview in Android

I am new to android and not a killer in programming. I am trying to implement a dynamic listview in which items must be added to the top, rather than getting added to the bottom by default. Is there a way to achieve this? Below is the code I used to create a dynamic listview. Please help!
private void populateListView() {
Cursor cursor = myDb.getAllRows();
startManagingCursor(cursor);
String[] fromFieldNames = new String[]
{DBadapter.KEY_FIELD1,DBadapter.KEY_FIELD2};
int[] toViewIDs = new int[]
{R.id.field1,R.id.field2};
SimpleCursorAdapter myCursorAdapter =
new SimpleCursorAdapter(
this,
R.layout.inner_list_view,
cursor,
fromFieldNames,
toViewIDs
);
ListView myList = (ListView) findViewById(R.id.sampleList);
myList.setAdapter(myCursorAdapter);
myCursorAdapter.notifyDataSetChanged();
}
ListViews support stacking the items from the bottom. You can either set it in the XML with android:stackFromBottom or you can set it programmatically by invoking setStackFromBottom(boolean).
I don't understand the 2nd part of your question.
you can use the "insert" method. It allows you to define position to add new items
myCursorAdapter.insert(newItem, 0);
Use a loop if you have multiple elements

Adding Delete button to a data binding ListView

I've created a ListView and bind it to an adaptor to display data from a table. It works great. I can select on a row and it display the product name that I'm selecting. Now I've added an ImageView in the layout that will act as delete buttons on each row. My problem is I can't figure out how to add the code to make it so that when a user select the ImageView (delete button), it will delete the row. I've searched and found a lot of articles on this topic and tried a lot of them and none really work my code. Do I need to create a getView function? Also I've tried inserting the getTag(), but I couldn't make it work. Can you help me with a sample code that may work with my simple code or point me to the right direction? Here is my code:
private void displayListView() {
prodinputHelper = new DBAdaptorProductInput(this);
prodinputHelper.open();
Cursor cursor = prodinputHelper.fetchAllProductInput();
// The desired columns to be bound
String[] columns = new String[] {
DBAdaptorProductInput.KEY_PRODUCTTYPE,
DBAdaptorProductInput.KEY_PRODUCTNAME,
DBAdaptorProductInput.KEY_MANUFACTURER,
DBAdaptorProductInput.KEY_VISC40,
DBAdaptorProductInput.KEY_VISC100,
DBAdaptorProductInput.KEY_VI,
DBAdaptorProductInput.KEY_DEN15C,
DBAdaptorProductInput.KEY_VISCTEXT,
DBAdaptorProductInput.KEY_BASEOILTYPE,
DBAdaptorProductInput.KEY_BASEOIL,
DBAdaptorProductInput.KEY_ADDITIVES,
DBAdaptorProductInput.KEY_OTHERADDITIVES,
DBAdaptorProductInput.KEY_THICKENER,
DBAdaptorProductInput.KEY_NLGI,
DBAdaptorProductInput.KEY_COMMENT,
DBAdaptorProductInput.KEY_PACKAGES,
DBAdaptorProductInput.KEY_AREA,
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.code,
R.id.name,
R.id.manufacturer,
R.id.visc40,
R.id.visc100,
R.id.viscindex,
R.id.den15c,
R.id.visctext,
R.id.baseoiltype,
R.id.baseoil,
R.id.additives,
R.id.otheradditives,
R.id.thickener,
R.id.nlgi,
R.id.comments,
R.id.packages,
R.id.area,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.activity_product_review_info, cursor, columns, to, 0);
ListView listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
//SetOnItemClickListener for the ListView
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the Customer Name from this row in the database.
String countryCode = cursor.getString(cursor.getColumnIndexOrThrow("ProductName"));
Toast.makeText(getApplicationContext(), countryCode, Toast.LENGTH_SHORT).show();
}
});
}
You need to have a custom adapter that extends BaseAdapter or SimpleCursorAdapter.
In the adapter's getView() method set the onClickListener for your ImageView.

Android SimpleCursorAdapter results not displaying in AlertDialog

I was looking for an alternative to a spinner, since the first item is always selected (which causes me issues), and I found some examples for using an AlertDialog with a list instead.
I am having two problems:
The list is displaying and is formatted ok, but there are no values in it. I know the query is returning, and the cursor/adapter has the data in it.
This may be a symptom of #1 - but when I select a blank row, the Cursor cursor2 = (Cursor) ((AdapterView) dialog).getItemAtPosition(which); statement causes a crash (it's a ClassCastException).
I had similar code previously which set the adapter to a spinner object, and the data was displaying fine.
I don't think the adapter is getting set correctly, and I have been unable to come up with a solution thus far.
Any thoughts?
Thanks!
btnDenomination.setOnClickListener(new View.OnClickListener()
{
public void onClick(View w)
{
Cursor cursor = coinDB.myDataBase.rawQuery("select _id, denomination_desc from denomination", null); // must select the _id field, but no need to use it
startManagingCursor(cursor); // required in order to use the cursor in
String[] from = new String[] {"denomination_desc" }; // This is the database column name I want to display in the spinner
int[] to = new int[] { R.id.tvDBViewRow }; // This is the TextView object in the spinner
cursor.moveToFirst();
SimpleCursorAdapter adapterDenomination = new SimpleCursorAdapter(CoinsScreen.this,
android.R.layout.simple_spinner_item, cursor, from, to );
adapterDenomination.setDropDownViewResource(R.layout.db_view_row);
new AlertDialog.Builder(CoinsScreen.this)
.setTitle("Select Denomination")
.setAdapter(adapterDenomination, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Cursor cursor2 = (Cursor) ((AdapterView<?>) dialog).getItemAtPosition(which);
strDenomination_id = cursor2.getString(0); // Gets column 1 in a zero based index, the first column is the PKID. this could
// be avoided by using a select AS statement.
Log.d("Item Selected", strDenomination_id );
TextView txtDenomination = (TextView) findViewById(R.id.textDenomination);
txtDenomination.setText(cursor2.getString(1));
dialog.dismiss();
}
}).create().show();
}
});
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:text=""
android:id="#+id/tvDBViewRow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF0000" />
</LinearLayout>
Are you sure R.id.tvDBViewRow is the id of the TextView in the layout android.R.layout.simple_spinner_item ? From this, the TextView's id should be android.R.id.text1.
So new answer for the second issue :)
I think you should reuse the initial cursor instead of trying to get a new one... Can you try to do :
adapterDenomination.moveToPosition(which);
strDenomination_id = adapterDenomination.getString(0);
in the onClick() ?

How do I bind a GridView to a Custom ContentProvider

I'm trying to bind a customer ContentProvider to my activity that holds a GridView
String[] projection = { SAppsDatabase.ID, SAppsDatabase.COL_APP_TITLE};
String[] uiBindFrom = { SAppsDatabase.COL_APP_TITLE };
int[] uiBindTo = { R.id.title };
Cursor apps = managedQuery(
MyProvider.CONTENT_URI, projection, null, null, null);
GridView gridview = (GridView) findViewById(R.id.gridview);
CursorAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), R.layout.grid_app_list, apps,
uiBindFrom, uiBindTo);
gridview.setAdapter(adapter);
This is not working.
I manage to bind it to a ListActivity by doing the same as above, and setting:
setListAdapter(adapter);
This will not work for a GridView as the name indicates it is a grid of views
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.
but you are providing it a cursor adapter which doesn't make much sense.
Take a look at this sample
If you want to provide a custom adapter then you will have extend adapter and return the view content in the adapter.

Categories

Resources