How to Combine two or more columns with Android SimpleCursorAdapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this,
R.layout.mytaskslayout,
cursor,
new String[] {"Aircraft","Discrepancy","ARR_FLT"},
new int[] {R.id.ac, R.id.discrepancy, R.开发者_如何学Goid.arrinfo}
);
Can I combine two or more columns and display in one R.id.XXX ? If yes, how ?
You can create a SimpleCursorAdapter.ViewBinder
to do this. See this answer for an example.
Basically your ViewBinder
will get called for each View. So when you get to the View that you want to have both columns, just retrieve both column values, combine them, and set the value on the View yourself.
Finally found a solution. I Had the same question as someone new to Android and Xamarin for Android. To be clear - I'm using Xamarin Studio, and Xamarin for Android written in C#.
Although it seems like the SimpleCursorAdapter can accommodate multiple fields, when binding to something like the SimpleListItem only one field gets used.
I first tried this:
string[] fromColumns = new string[]{ "checkListName","checkListDesc" };
int[] toControlIDs = new int[] {Android.Resource.Id.Text1, Android.Resource.id.Text1};
try{
listView.Adapter = new SimpleCursorAdapter(this,Android.Resource.Layout.SimpleListItem1 , c, fromColumns, toControlIDs, 0);
}
catch(SQLiteException e){
Console.WriteLine ("whoops, " + e.Message.ToString ());
}
But all I ever got was the last field in the cursor row.
I learned that a CUSTOM LISTVIEW was needed. Following are code files for four files:
- MainActivity.cs
- myList.xml
- Main.axml
- PreFloat.cs (this is the database part)
I have included all of this to provide as much as possible a completely working sample that is as close to real life as possible.
Here is MainActivity.cs which sets a content view, uses a cursor to get data from a SQLite database, and defines a
using System;
using Android.App;
using Android.Content;
using Android.Database;
using Android.Database.Sqlite;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace Darjeeling
{
[Activity (Label = "Darjeeling", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
ListView listView;
Darjeeling.PreFloatDatabase pdb;
ICursor c;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
listView = FindViewById<ListView> (Resource.Id.listView1);
pdb = new PreFloatDatabase (this);
// Assign the cursor to a query
c = pdb.ReadableDatabase.RawQuery ("select * from checkLists", null);
StartManagingCursor (c);
// A ListView needs an adapter -- so we'll assign our instantiated listView's adapter to our customized adapter called HomeScreenCursorAdapter.
listView.Adapter = (IListAdapter)new HomeScreenCursorAdapter (this,c);
}
// End onCreate method
// This handles the cursor when the user is done with the activity
protected override void OnDestroy()
{
StopManagingCursor(c);
c.Close ();
base.OnDestroy();
}
// Here's the magic --
public class HomeScreenCursorAdapter : CursorAdapter {
Activity context;
public HomeScreenCursorAdapter(Activity context, ICursor c)
: base (context, c)
{
this.context = context;
}
// This overridden BindView method is going to let me assign TextView controls that I've set up in an XML file, to specific fields in the cursor.
public override void BindView(View view, Context context, ICursor cursor)
{
var txtCheckListName = view.FindViewById<TextView> (Resource.Id.txtCheckListName); //(Android.Resource.Id.Text1);
var txtCheckListDesc = view.FindViewById<TextView> (Resource.Id.txtCheckListDesc); //(Android.Resource.Id.Text2);
// For testing purposes, I first assigned static values to txtCheckListName and txtCheckListDesc, for instance, txtCheckListName.Text = "Hello"; and txtCheckListDesc.Text = "World";
txtCheckListName.Text = cursor.GetString (3);
txtCheckListDesc.Text = cursor.GetString (4);
}
// This overridden View inflates each row (I think). This could inflate a built-in ListView control like SimpleListItem, OR, in this case, it references a custom written XML file called myList.
public override View NewView(Context context, ICursor cursor, ViewGroup parent)
{
return this.context.LayoutInflater.Inflate (Resource.Layout.myList, parent, false);
}
}
}
}
Here's the Main.axml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout1"
android:minWidth="25px"
android:minHeight="25px">
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView1" />
</LinearLayout>
And finally, the myList.xml file which is essentially the definition of the ListView row:
<?xml version="1.0" encoding="utf-8"?>
<!---<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="match_parent"
android:background="#FF0000FF">
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout1"
android:minWidth="25px"
android:minHeight="25px">
<TextView
android:id="@+id/txtCheckListName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/txtCheckListDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="" />
</LinearLayout>
<!---</FrameLayout>-->
And here's the database file:
using System;
using Android.Database.Sqlite;
using Android.Content;
namespace Darjeeling {
class PreFloatDatabase : SQLiteOpenHelper {
public static readonly string create_checkLists_table = "create table if not exists checkLists([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, checkListID INTEGER, checkListType INTEGER, checkListName TEXT, checkListDesc TEXT);";
public static readonly string DatabaseName = "prefloat.db";
public static readonly int DatabaseVersion = 1;
public PreFloatDatabase (Context context) : base (context, DatabaseName, null, DatabaseVersion){ }
public override void OnCreate(SQLiteDatabase db){
// fire the statement that creates the checkLists table
try{
db.ExecSQL (create_checkLists_table);
// Now pre-fill the checkLists table
db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (0, 0, 'Widgeon','Widgeon Daysailer');");
db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (1, 1, 'Widgeon','Widgeon Daysailer');");
db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (2, 0, 'Bowrider', 'Mo Motor, Mo Fun');");
db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (3, 1, 'Bowrider', 'Mo Motor, Mo Fun');");
db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (4, 0, 'HobieCat','Hang yer ass out fun');");
db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (5, 1, 'HobieCat','Hang yer ass out fun');");
}
catch(SQLiteException e){
Console.WriteLine ("Problem with the database " + e.Message.ToString ());
}
}
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
throw new NotImplementedException ();
}
} // matches with class PreFloatDatabase
} // matches with namespace Darjeeling
Questions: SHOULD a SimpleListItem control have more than a single field or at most a checkbox control and label? Should a grid control be used instead?
Alternatives: Instead of doing all these shenanigans, wouldn't it be easier to simple concatenate the needed values using SQL? Especially since coordinating the positioning of two text controls might be too complicated.
Full Disclosure: This code is an amalgam of code I read in other posts and forums, and customized to fit my own particular requirements.
精彩评论