Android: Fetch data from database into ListFragment - android

Fetching data from database into LisFragment. I need to use this ListFragment file content into MainActivity.java.
SecondActivity which extends ListFragment:
String DB = "TestDB";
String TABLE_NAME = "addcamera";
SQLiteDatabase sampleDB = null;
ArrayList<String> results = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sampleDB = SQLiteDatabase.openOrCreateDatabase(DB, null);
Cursor c = sampleDB.rawQuery("SELECT CameraName FROM " + TABLE_NAME , null);
if (c != null) {
if (c.moveToFirst()) {
do {
String CameraName = c.getString(c.getColumnIndex("CameraName"));
results.add(CameraName);
}while (c.moveToNext());
}
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, results);
}
main.xml:
<?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="fill_parent">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.exercise.FragmentTest.SecondActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/image_list_fragment">
</fragment>
</LinearLayout>
Can anyone helpme?

Well, first thing's first - your Activity should not be extending ListFragment, your own Fragment class should be doing so. Hopefully I haven't misunderstood anything. :-)
However, you could easily see your ListFragment derivative as a ListActivity, ie you can use the getListView() method to get the ListView corresponding element (#android:id/list) from your XML.
Seeing that you already have a Cursor ready, you should consider using a SimpleCursorAdapter and let it manage the cursor for you and *all* you need to do is to specify what fields to populate elements with.
Example:
getListView().setAdapter(
new SimpleCursorAdapter(
getActivity(),
R.layout.your_list_item_layout,
cursor,
new String[] { "database_table_1", "database_table_2" },
new int[] { R.id.element_1, R.id.element_2 }
)
);
Update:
Here's what your custom ListFragment could look like:
public class CustomListFragment extends ListFragment {
// Attributes
private Context mContext;
private LayoutInflater mLayoutInflater;
private SQLiteDatabase mSampleDb;
private List<String> mResults;
private Cursor mCursor;
// Elements
private ListView mListView;
private SimpleCursorAdapter mListAdapter;
// Constants
private final String DB = "TestDB";
private final String TABLE_NAME = "addcamera";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Set our attributes
mContext = getActivity();
mLayoutInflater = inflater;
// Let's inflate & return the view
View view = mLayoutInflater.inflate(R.layout.your_fragment_layout, container, false);
// Get the database handler & the cursor
mSampleDb = SQLiteDatabase.openOrCreateDatabase(DB, null);
mCursor = mSampleDb.rawQuery("SELECT CameraName FROM " + TABLE_NAME , null);
// Init
init(view);
// Return
return view;
}
public void init(View v) {
// Setup the listAdapter
mListAdapter = new SimpleCursorAdapter(
mContext,
R.layout.your_list_item_layout,
cursor,
new String[] { "database_table_1", "database_table_2" },
new int[] { R.id.element_1, R.id.element_2 }
)
);
mListView.setAdapter(mListAdapter);
}
#Override
public void onListItemClick(ListView l, View v, int pos, long id) {
Toast.makeText(mContext, "CLICKED ON POS #" + pos + "!", Toast.LENGTH_SHORT).show();
}
}

Related

How can I manipulate my Android fragment from within a subclass of SimpleCursorAdapter?

My app uses Fragments in association with a ViewPager to create tabs.
On one tab, I use a ListView to display contents of my database in a table. I have extended SimpleCursorAdapter in order to perform some custom tasks on each row of my list (e.g., alternate row color, buttons, etc.). At one point, I want to click an icon within a row and have it switch tabs, but I am having issues accessing the FragmentManager and ViewPager from within my CustomSimpleCursorAdapter class. I can do this within the fragment itself (see the commented-out section), but when I switched to using the CustomSimpleCursorAdapter, I lost that ability.
So, how can I access my FragmentManager and ViewPager from within my custom class?
note: I have marked the location within CustomSimpleCursorAdapter.java where I am having trouble with
// THIS IS WHERE I AM HAVING ISSUES WITH:
Home.java
package myPackage;
public class Home extends Fragment {
private View rootView;
private CustomSimpleCursorAdapter mySimpleCursorAdapter;
private ViewPager myViewPager;
private SwipeRefreshLayout studentSwipeRefresh;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.home, container, false);
myViewPager = (ViewPager) getActivity().findViewById(R.id.pager);
studentSwipeRefresh = (SwipeRefreshLayout) rootView.findViewById(R.id.student_swipe_refresh);
return rootView;
}
#Override
public void onViewCreated(View rootView, Bundle savedInstanceState) {
super.onViewCreated(rootView, savedInstanceState);
drawTheStudentView();
studentSwipeRefresh.setColorSchemeColors(Color.parseColor(Constants.RED), Color.parseColor(Constants.ORANGE), Color.parseColor(Constants.YELLOW), Color.parseColor(Constants.GREEN), Color.parseColor(Constants.BLUE), Color.parseColor(Constants.INDIGO), Color.parseColor(Constants.VIOLET));
studentSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
studentSwipeRefresh.setRefreshing(false);
drawTheStudentView();
}
});
}
private void drawTheStudentView(){
DatabaseHelper myDBHelper = new DatabaseHelper(getActivity());
Cursor studentCursor = myDBHelper.getStudentsCursor();
String[] fromColumns = {"_id","studentID","location"};
int[] toViews = {R.id.student_number_textview, R.id.student_id_textview, R.id.student_location.textview};
mySimpleCursorAdapter = new CustomSimpleCursorAdapter(getActivity(), R.layout.student_layout, studentCursor, fromColumns, toViews, 0);
// Replace the _id column with a student count
mySimpleCursorAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
String counter = Integer.toString((cursor.getPosition()+1));
TextView modifiedTextView = (TextView) view;
if(columnIndex == 0){
modifiedTextView.setText(counter);
return true;
}
return false;
}
});
ListView myListView = (ListView) rootView.findViewById(R.id.student_row);
// I COMMENTED THIS OUT. THIS WORKS FOR CLICKING THE ENTIRE ROW AND HAVING AN ACTION PERFORMED.
// Listen for somebody clicking on a Student ID, and process
// myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// #Override
// public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Cursor subCursor = (Cursor) mySimpleCursorAdapter.getItem(position);
// String studentIDNumber = subCursor.getString(subCursor.getColumnIndex("studentID"));
//
// StudentInformation studentInformation = (StudentInformation) getFragmentManager().findFragmentByTag(getFragmentTag(Constants.TAB_INDEX_PATIENT_VITALS));
// studentInformation.setStudendIDNumber(studentIDNumber);
//
// myViewPager.setCurrentItem(Constants.TAB_INDEX_STUDENT_LOCATION);
// }
// });
// Draw the list
myListView.setAdapter(mySimpleCursorAdapter);
myDBHelper.close();
}
// Pass me a tab index (see Constants.java) and I'll return a refrence to that tab.
private String getFragmentTag(int tagID){
return "android:switcher:" + R.id.pager + ":" + tagID;
}
}
CustomSimpleCursorAdapter.java
package myPackage;
public class CustomSimpleCursorAdapter extends SimpleCursorAdapter {
private Context context;
private Cursor cursor;
public CustomSimpleCursorAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to, int flags) {
super(context, layout, cursor, from, to, flags);
this.context = context;
this.cursor = cursor;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent){
// Alternate the color of the data rows.
View row = super.getView(position, convertView, parent);
if(position % 2 == 0){
row.setBackgroundColor(Color.parseColor(Constants.WHITE));
} else {
row.setBackgroundColor(Color.parseColor(Constants.LIGHTGREY));
}
// If the "Information" icon/button is clicked, set the information and switch to that tab/fragment.
ImageView statusButton = (ImageView)row.findViewById(R.id.student_status_button);
statusButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View myView) {
cursor.moveToPosition(position);
String studentID = cursor.getString(1);
Toast statusToast = Toast.makeText(context, "Showing information for student " + studentID, Toast.LENGTH_SHORT);
statusToast.show();
// THIS IS WHERE I AM HAVING ISSUES WITH:
// * getFragmentManager()
// * myViewPager.setCurrentItem()
StudentInformation studentInformation = (StudentInformation) getFragmentManager().findFragmentByTag(getFragmentTag(Constants.TAB_INDEX_STUDENT_INFORMATION));
studentInformation.setStudentNumber(studentID);
myViewPager.setCurrentItem(Constants.TAB_INDEX_STUDENT_INFORMATION);
}
});
// If the "Location" button is clicked, then show a Toast with the information.
ImageView locationButton = (ImageView)row.findViewById(R.id.student_location_button);
locationButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View myView) {
cursor.moveToPosition(position);
String studentID = cursor.getString(1);
Toast statusToast = Toast.makeText(context, "Sending location for student " + studentID + " to MESA", Toast.LENGTH_LONG);
statusToast.show();
}
});
return row;
}
// Pass me a tab index (see Constants.java) and I'll return a refrence to that tab.
private String getFragmentTag(int tagID){
return "android:switcher:" + R.id.pager + ":" + tagID;
}
}
UPDATE:
I tried passing in FragmentManager and ViewPager references into the constructor of my CustomSimpleCursorAdapter, but that didn't seem to work.
1) Create an interface for example:
public interface MyTabChanger{
public void changeTabTo(int nextTabIndex);
}
2) implement that interface with your fragment.
3) inside changeTabTo call in your fragment you can use below code:
myViewPager.setCurrentItem(nextTabIndex);
4) change the constructor of your Adapter
...
public class CustomSimpleCursorAdapter extends SimpleCursorAdapter {
private Context context;
private Cursor cursor;
private MyTabChanger mCallback;
public CustomSimpleCursorAdapter(MyTabChanger myTabChanger,Context context, int layout, Cursor cursor, String[] from, int[] to, int flags) {
super(context, layout, cursor, from, to, flags);
this.context = context;
this.cursor = cursor;
mCallback = myTabChanger;
}
...
5) then in your adapter when you want to change the viewpager simply call changeTabTo. For example:
mCallback.changeTabTo(Constants.TAB_INDEX_STUDENT_INFORMATION);
I think this is the general and cleanest solution you can use. In this way you can use the adapter with any Fragment and Activity as long as they implements MyTabChanger.
You can use cast the Context you initialize the adapter with to your activity (provided you use the activity as the context)
public CustomSimpleCursorAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to, int flags) {
super(context, layout, cursor, from, to, flags);
this.context = context;
this.cursor = cursor;
//Where you need to...
((MyActivity)context).mViewPager.setCurrentItem()
}
Hopefully this gives you a good idea of what you need to do :)

ListView multichoice implementation only one click more than one selection

I try to implement a listview multichoice. I achive display all my contact in a listview with checkBox item. My problem is that when check ONLY one item there is lots of element are being cheked. Could you please help?
public class SelectNewGroupChatMembers extends ListFragment implements
LoaderCallbacks<Cursor>, OnItemClickListener {
/** Defines a tag for identifying log entries */
private static final String TAG = "SelectNewGroupChatMembers";
/** The main query adapter */
private ContactsAdapter mAdapter;
/** ListView which will display contacts */
ListView mListView;
/** Fragments require an empty constructor. */
public SelectNewGroupChatMembers() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create the main contacts adapter
mAdapter = new ContactsAdapter(getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container, false);
mListView = (ListView)view.findViewById(android.R.id.list);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "clicked");
mListView.setAdapter(mAdapter);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mListView.setOnItemClickListener(this);
// Initialize the loader, and create a loader identified by ContactsQuery.QUERY_ID
getLoaderManager().initLoader(ContactsQuery.QUERY_ID, null, this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle savedInstanceState) {
// If this is the loader for finding contacts in the Content Provider
if (id==ContactsQuery.QUERY_ID) {
Uri contentUri = ContactsQuery.CONTENT_URI;
Log.i(TAG, contentUri.toString());
// Create a new CursorLoader with the following query parameters.
return new CursorLoader(getActivity(),
contentUri,
ContactsQuery.PROJECTION,
ContactsQuery.SELECTION,
null,
ContactsQuery.SORT_ORDER);
}
Log.i(TAG, "onCreateLoader - incorrect ID provided ( "+ id +" )");
return null;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// This swaps the new cursor into the adapter.
if (loader.getId() == ContactsQuery.QUERY_ID) {
Log.i(TAG,cursor.toString());
// The asynchronous load is complete and the data
// is now available for use. Only now can we associate
// the queried Cursor with the SimpleCursorAdapter.
mAdapter.swapCursor(cursor);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
if (loader.getId() == ContactsQuery.QUERY_ID) {
// When the loader is being reset, clear the cursor from the adapter.
// This allows the cursor resources to be freed.
mAdapter.swapCursor(null);
}
}
private class ContactsAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public ContactsAdapter(Context context) {
super(context, null, 0);
// Stores the inflater for the later use
mInflater = LayoutInflater.from(context);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
// Inflate the list item layout
final View itemLayout =
mInflater.inflate(R.layout.fragment_select_new_group_chat_members, viewGroup, false);
// Use ViewHolder design pattern to store each view resource.
// This allows bindView() to retrieve stored references instead of
// calling findViewById for each instance of the layout.
final ViewHolder holder = new ViewHolder();
holder.contactName = (TextView)itemLayout.findViewById(R.id.userName);
holder.contactNo = (TextView)itemLayout.findViewById(R.id.userInfo);
// Store the resourceHolder instance in Layout.
// This makes resourceHolder available to bindView
// and other methods that receive a handle to the item view
itemLayout.setTag(holder);
return itemLayout;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Get handles to individual view sources
final ViewHolder holder = (ViewHolder) view.getTag();
final String contactName = cursor.getString(ContactsQuery.DISPLAY_NAME);
final String contactNumber = cursor.getString(ContactsQuery.PHONE_NUMBER);
holder.contactName.setText(contactName);
holder.contactNo.setText(contactNumber);
}
private class ViewHolder {
public TextView contactName, contactNo;
}
}
public interface ContactsQuery {
// This query ID will be used in Loader
final static int QUERY_ID = 1;
// A content URI for the Contacts table
final static Uri CONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
final static String SELECTION = null;
final static String SORT_ORDER = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME;
final static String [] PROJECTION = {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
SORT_ORDER,
};
final static int ID = 0;
final static int LOOKUP_KEY = 1;
final static int DISPLAY_NAME = 2;
final static int PHONE_NUMBER = 3;
final static int SORT_KEY = 4;
}
}
My layout file is as below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dip" >
<ImageView
android:id="#+id/userImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="6dip"
android:src="#drawable/ic_action_user" />
<CheckBox
android:id="#+id/checkBox"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBottom="#id/userImage"
android:layout_alignTop="#id/userImage"
android:layout_alignParentRight="true"
android:focusable="false"
android:gravity="center" />
<TextView
android:id="#+id/userName"
android:layout_alignTop="#id/userImage"
android:layout_toRightOf="#id/userImage"
android:layout_toLeftOf="#id/checkBox"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:gravity="center_vertical"
android:text="ContactName"
android:textStyle="bold" />
<TextView
android:id="#+id/userInfo"
android:layout_alignBottom="#id/userImage"
android:layout_toRightOf="#id/userImage"
android:layout_toLeftOf="#id/checkBox"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:gravity="center_vertical"
android:text="UserInfo" />
</RelativeLayout>
At final my code is like above. This code queries contacts and display them on a listview which including a checkBox. I tried some different code snippets but with all my tries i get same result. My problem is that when check ONLY one item there is lots of element are being cheked. Could you help please?
I don't see where you are manipulating the checkbox on item click in this code. Ideally onItemClick you should get the Holder object out of the view tag by calling view.getTag. In your holder there is a checkbox view instance so you can enable the checkbox there. So something like this on your onItemClick method.
Holder holder = (Holder) view.getTag();
holder.checkbox.setChecked(!checkbox.isChecked());

filling ListView from database in Android

I'm new in Android programming and I'm wondering witch is the most appropriate way to fill a ListView from DataBase.
Here the method I'm using in database to get my items
// Getting All stats
public List<StatParcours> getAllSats() {
List<StatParcours> statList = new ArrayList<StatParcours>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_STATS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
StatParcours stat = new StatParcours();
stat.setID(Integer.parseInt(cursor.getString(0)));
stat.setDate(cursor.getString(1));
stat.setDuration(cursor.getString(2));
stat.setDistance(Double.parseDouble(cursor.getString(3)));
stat.setSpeed(Double.parseDouble(cursor.getString(4)));
stat.setCondition(cursor.getString(5));
// Adding contact to list
statList.add(stat);
} while (cursor.moveToNext());
}
// return contact list
return statList;
}
and in the main activity, I'm using this. I know there is something wrong with the populateMyStatsList method, but I still don't know how to fix it.
public class History extends Activity {
public DatabaseHandler db;
private List<StatParcours> MyStats = new ArrayList<StatParcours>();
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("oncreate", "ok");
super.onCreate(savedInstanceState);
setContentView(R.layout.history);
populateMyStatsList ();
populateListView();
registerClickCallback();
}
private void populateMyStatsList (){
MyStats = db.getAllSats();
}
private void populateListView() {
ArrayAdapter<StatParcours> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.HistListView);
list.setAdapter(adapter);
Log.i("Populate", "ok");
}
private void registerClickCallback() {
ListView list = (ListView) findViewById(R.id.HistListView);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View viewClicked,
int position, long id) {
StatParcours clickedCar = MyStats.get(position);
String message = "You clicked position " + position
+ " Which is car make " + clickedCar.getDate();
Toast.makeText(History.this, message, Toast.LENGTH_LONG).show();
}
});
}
private class MyListAdapter extends ArrayAdapter<StatParcours> {
public MyListAdapter() {
super(History.this, R.layout.item_view, MyStats);
Log.i("MyListAdapter", "ok");
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
if (itemView == null) {
Log.i("Make sure", "ok");
itemView = getLayoutInflater().inflate(R.layout.item_view, parent, false);
}
Log.i("getview", "ok");
StatParcours currentStat = MyStats.get(position);
TextView makeText = (TextView) itemView.findViewById(R.id.item_txtMake);
makeText.setText(currentStat.getDate());
TextView yearText = (TextView) itemView.findViewById(R.id.item_txtYear);
yearText.setText("" + currentStat.getDistance());
TextView condionText = (TextView) itemView.findViewById(R.id.item_txtCondition);
condionText.setText(currentStat.getCondition());
return itemView;
}
}
}
You need to use a SimpleCursor Adapter. I can't reach the developer site for the documentation but here is an example with your code above.
EDIT: Here is the link to the android developer website.
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html
SECOND EDIT: This would go in the populateListView()
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_STATS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Set your layout to int[]
int[] to = new int[]{R.id.item_txtMake,R.id.item_txtYear,R.id.item_txtCondition};
//set your columns to string[]; fill in your actual column names
string[] from = new string[]{"make","year","condition"};
//set up adapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),R.layout.item_view, cursor, from,to,null);
//set adapter to listview
ListView list = (ListView) findViewById(R.id.HistListView);
list.setAdapter(adapter);
Since you only have TextView in your ListView you can just simply use SimpleCursorAdapter.
// Getting All stats
public Cursor getAllSats() {
List<StatParcours> statList = new ArrayList<StatParcours>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_STATS;
SQLiteDatabase db = this.getWritableDatabase();
return db.rawQuery(selectQuery, null);
}
And in your History class
public class History extends Activity {
public DatabaseHandler db;
private List<StatParcours> MyStats = new ArrayList<StatParcours>();
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("oncreate", "ok");
super.onCreate(savedInstanceState);
setContentView(R.layout.history);
Cursor c = getAllSats();
String[] fromColumns = {Your database column name for date,
Your database column name for distance,
Your database column name for condition};
int[] toViews = {R.id.item_txtMake,
R.id.item_txtYear,
R.id.item_txtCondition};
adapter = new SimpleCursorAdapter(this, R.layout.item_view,
c, fromColumns, toViews, 0);
ListView list = (ListView) findViewById(R.id.HistListView);
list.setAdapter(adapter);
registerClickCallback();
}

Make list from two database items

I want to make a list from some data that I have in my database.
The first two sets of data in my database are first name and last name.
I want my list to show both first and last name instead of now where it only shows the first name. How do I do that? My code looks like this:
private void fillData()
{
Cursor contactCursor = mDbHelper.fetchAllReminders();
startManagingCursor(contactCursor);
String[] from = new String[]{DbAdapter.KEY_FIRST};
int[] to = new int[]{R.id.contactlist};
SimpleCursorAdapter contacts = new SimpleCursorAdapter(this, R.layout.list, contactCursor, from, to);
setListAdapter(contacts);
}
Here is a full implementation. You will need to create a custom row and a custom Array adapter.
Here is a full tutorial http://commonsware.com/Android/excerpt.pdf
This will tell you everything you need to know to get this done.
Also refer here where ive posted another example.
How to add an EditText to a ListView
EDIT: How to build a custom listview and return data from a databse
You first create a listview activity.
public class meeting_list extends ListActivity {
Cursor model = null;
meetingAdapter adapter = null;
//This should be what ever your database helper is from your SQLite base.
meetingHelper helper = null;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.meeting_list);
helper = new meetingHelper(this);
model = helper.getAll();
startManagingCursor
(model);
adapter = new meetingAdapter(model);
setListAdapter(adapter);
registerForContextMenu(getListView());
//Ondestroy is used to close the database to free up resources
#Override
public void onDestroy(){
super.onDestroy();
helper.close();
}
#Override
public void onListItemClick(ListView list, View view, int position, long id){
Intent i = new Intent(meeting_list.this, meeting_create_edit.class);
//
i.putExtra(ID_EXTRA, String.valueOf(id));
startActivity(i);
}
//Here create a class to extend the Cursor Adapter
class meetingAdapter extends CursorAdapter{
meetingAdapter(Cursor c){
super(meeting_list.this, c);
}
#Override
public void bindView(View row, Context ctxt, Cursor c) {
meetingHolder holder = (meetingHolder)row.getTag();
holder.populateFrom(c, helper);
}
#Override
public View newView(Context ctxt, Cursor c, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.mrow, parent, false);
meetingHolder holder = new meetingHolder(row);
row.setTag(holder);
return row;
}
}
//Here create a class to actually hold the view for the row in the listview.
static class meetingHolder{
private TextView mtitle = null;
private TextView maddress = null;
private ImageView Icon = null;
meetingHolder(View row){
mtitle=(TextView)row.findViewById(R.id.mtitle);
maddress = (TextView)row.findViewById(R.id.address);
Icon = (ImageView)row.findViewById(R.id.Micon);
}
//Here populate the row with the data from your database
void populateFrom(Cursor c, meetingHelper helper){
mtitle.setText(helper.getMettingTitle(c));
maddress.setText(helper.getAddress(c));
This should do it. Just substitute your informations where it should be. This is a tutorial ive put together for you.
Now i have tried to edit the code according to your guide, what i have done for now looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
mDbHelper = new DbAdapter(this);
mDbHelper.open();
fillData();
}
private void fillData()
{
Cursor contactCursor = mDbHelper.fetchAllReminders();
startManagingCursor(contactCursor);
String[] from = new String[]{DbAdapter.KEY_FIRST};
int[] to = new int[]{R.id.contactlist};
SimpleCursorAdapter contactsfirst = new SimpleCursorAdapter(this, R.layout.list, contactCursor, from, to);
String[] from2 = new String[]{DbAdapter.KEY_LAST};
int[] to2 = new int[]{R.id.contactlist};
SimpleCursorAdapter contactslast = new SimpleCursorAdapter(this, R.layout.list, contactCursor, from2, to2);
setListAdapter(contactsfirst,last);
}
And my xml file looks like this:
<?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:orientation="horizontal"
>
<TextView
android:id="#+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
/>
<TextView
android:id="#+id/last"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
/>
</LinearLayout>

Android ListView causing CheckBoxes and CheckedTextViews to disappear

I've seen other similar problems to this around, but nothing that quite addresses the issues.
My problem is that Checkboxes and CheckedTextViews are randomly disappearing from my list. That is, they are the the first time the ListView is loaded, as well as the first scroll all the way to the bottom. Any random scrolling causes the CheckBoxes to just drop out and disappear.
Here is the code for my extended SimpleCursorAdapter.
public class CheckBoxCursorAdapter extends SimpleCursorAdapter{
static final String TAG = "CheckBoxCursorAdapter";
final Context contextMain;
Cursor c;
SQLiteDatabase db;
public CheckBoxCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to, SQLiteDatabase db) {
super(context, layout, c, from, to);
this.contextMain = context;
this.c = c;
this.db = db;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
CheckedTextView cb = (CheckedTextView)view.findViewById(R.id.cb);
cb.setOnClickListener(null);
TextView cbFull = (TextView)view.findViewById(R.id.fullname);
TextView cbAbbrev = (TextView)view.findViewById(R.id.abbrev);
cb.setCheckMarkDrawable(android.R.drawable.btn_default);
final String abbrv = cursor.getString(cursor.getColumnIndexOrThrow(BuildingOpenHelper.C_ABBRV));
cbFull.setText(cursor.getString(cursor.getColumnIndexOrThrow(BuildingOpenHelper.C_NAME)));
cbAbbrev.setText(abbrv);
cb.setChecked(cursor.getInt(cursor.getColumnIndexOrThrow(BuildingOpenHelper.C_DISPLAYED)) == 1 ? true : false);
Log.v(TAG, "displayed = " + Long.toString(cursor.getInt(cursor.getColumnIndexOrThrow(BuildingOpenHelper.C_DISPLAYED))));
cb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(((CheckedTextView) v).isChecked()) {
Log.v(TAG, "Calling isChecked==true!");
db.execSQL("UPDATE buildinglist SET displayed='1' WHERE abbrv='"+ abbrv +"'");
((CheckedTextView) v).setChecked(true);
}
else {
Log.v(TAG, "Calling isChecked==false!");
db.execSQL("UPDATE buildinglist SET displayed='0' WHERE abbrv='"+ abbrv +"'");
//(CheckedTextView) v).setChecked(false);
((CheckedTextView) v).setChecked(false);
}
}
});
final int latitude = cursor.getInt(cursor.getColumnIndexOrThrow(BuildingOpenHelper.C_YCOORD));
final int longitude = cursor.getInt(cursor.getColumnIndexOrThrow(BuildingOpenHelper.C_XCOORD));
view.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// Log.v(TAG, "Calling isChecked==true!");
// db.execSQL("UPDATE buildinglist SET displayed='1' WHERE abbrv='"+ abbrv +"'");
// ((CheckedTextView) v).setChecked(true);
Intent i = new Intent(contextMain,View_map.class);
i.putExtra("lat", latitude);
i.putExtra("long", longitude);
Log.d(TAG,"Latitude onLongClick" + latitude + "");
Log.d(TAG,"Longitude onLongClick" + longitude +"");
contextMain.startActivity(i);
return false;
}
});
}
}
I am using a ListActivity, here is the initiation.
public class Buildings_List extends ListActivity{
BuildingOpenHelper opener;
SQLiteDatabase db;
SQLiteDatabase dbWrite;
static final String[] FROM = {BuildingOpenHelper.C_NAME, BuildingOpenHelper.C_ABBRV, BuildingOpenHelper.C_DISPLAYED};
static final int[] TO = { R.id.fullname, R.id.abbrev, R.id.cb };
private static final String TAG = "Buildings_List";
SimpleCursorAdapter adapt;
Cursor myCur = null;
Bundle savedInstanceState2;
#Override
public void onCreate(Bundle savedInstanceState) {
savedInstanceState2 = savedInstanceState;
super.onCreate(savedInstanceState2);
ListView awesome = getListView();
opener = new BuildingOpenHelper(this);
db = opener.getReadableDatabase();
dbWrite = opener.getWritableDatabase();
try {
myCur = db.query(BuildingOpenHelper.TABLE,null,null,null,null,null,BuildingOpenHelper._ID + " DESC");
}
catch(SQLException e){
Log.d(TAG,"Query Went Bad");
}
startManagingCursor(myCur);
//using depracated SimpleCursorAdapter. Not quite sure what the flags need to be when using updated constructor
adapt = new CheckBoxCursorAdapter(this, R.layout.buildinglisting, myCur, FROM, TO, dbWrite);
setListAdapter(adapt);
}
I know it's not the onClickListeners that are the problem, as I have tried removing those and the problem still persists. I have read multiple accounts of the CheckBoxes not recycling correctly, but the problem is still there with CheckTextViews as well. Is there something really simple that I have missed?
Its because listview reuses the rows.
You may refer to a similar question of mine: scrolling listview causes buttons to be invisible

Categories

Resources