What is the best way to implement a ListFragment using SQLite database. Currently I have created an DBAdapter to facilitate opening, closing, and fetching records into a SimpleCursorAdapter. I have my MainActivity which implements an ActionBar with Navigation Tabs which I would like to display a different ListView for each tab.
Here is my ListFragment:
public class MaterialsListFragment extends ListFragment {
public DBAdapter db;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.portrait_material_view, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create new DBAdapter
db = new DBAdapter(getActivity());
db.open();
Cursor c = db.getAllRecords();
String[] from = new String[] { DBAdapter.KEY_IDNO, DBAdapter.KEY_MATERIAL };
int[] to = new int[] { R.id.idno, R.id.materials };
// Now create an array adapter and set it to display using our row
MyListAdapter materials = new MyListAdapter(this, R.layout.list_cell, c, from, to);
setListAdapter(materials);
}
Here is MyListAdapter code which for now is in it's own class file:
public class MyListAdapter extends SimpleCursorAdapter {
public MyListAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to) {
super(context, layout , cursor, from, to);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Create the idno textview with background image
TextView idno = (TextView) view.findViewById(R.id.idno);
idno.setText(cursor.getSring(3));
// create the material textview
TextView materials = (TextView) view.findViewById(R.id.materials);
materials.setText(cursor.getString(1));
}
}
Is this the way to go about this? I would appreciate any suggestion you may have or if you know of any good examples.
I was able to get this to work, so I think I'm on the right track. I had to make this modification to get it to run, but it seems to be working well.
MyListAdapter materials = new MyListAdapter(getActivity(), R.layout.list_cell, c, from, to);
I would still be interested in any suggestions or ways to improve this approach.
Related
I know this has been discussed extensively on StackOverflow, and on the internet in general, but I can't find any good, solid information that helps me with my situation. At least none that I can understand and translate for my situation.
I have data in the database that I am retrieving with a Cursor. I am sticking this data into a ListView within a Fragment. On each line of my list, there is a button I use to delete that item. This all works, but I cannot figure out how to use notifydatasetchanged so that the ListView automatically refreshes itself, and the user can see that the deletion took place.
I have the List embedded in a SwipeRefreshLayout and the list item does disappear when I swipe it after deletion. However, what I want is for the list to automatically update on its own, which is what I thought the notifydatasetchanged was supposed to provide. Is this not the case? Is my understanding of notifydatasetchanged 100% incorrect?
Anyway, here is what I have:
My Home.java fragment:
public class Home extends Fragment{
private MainActivity mainActivity;
private View rootView;
private SwipeRefreshLayout personSwipeRefresh;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.home, container, false);
personSwipeRefresh = (SwipeRefreshLayout) rootView.findViewById(R.id.person_swipe_refresh);
mainActivity = (MainActivity)getActivity();
return rootView;
}
#Override
public void onViewCreated(View rootView, Bundle savedInstanceState) {
super.onViewCreated(rootView, savedInstanceState);
drawThePersonView();
personSwipeRefresh.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));
personSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
personSwipeRefresh.setRefreshing(false);
drawThePersonView();
}
});
}
#Override
public void onResume() {
super.onResume();
drawThePersonView();
}
public void drawThePersonView(){
Context context = getContext();
DatabaseHelper myDBHelper = new DatabaseHelper(context);
Cursor personCursor = myDBHelper.getPersonCursor();
String[] fromColumns = {"_id","personNumber","location","status"};
int[] toViews = {R.id.person_number_textview, R.id.personNumber_textview, R.id.person_location_textview, R.id.person_status_textview};
CustomSimpleCursorAdapter mySimpleCursorAdapter = new CustomSimpleCursorAdapter(context, R.layout.person_layout, personCursor, fromColumns, toViews, 0, mainActivity);
ListView myListView = (ListView) rootView.findViewById(R.id.person_row);
// Draw the list
myListView.setAdapter(mySimpleCursorAdapter);
myDBHelper.close();
}
}
My CustomSimpleCursorAdapter.java
public class CustomSimpleCursorAdapter extends SimpleCursorAdapter {
private Context 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;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent){
DatabaseHelper dbHelper = new DatabaseHelper(context);
View row = super.getView(position, convertView, parent);
cursor.moveToPosition(position);
final Integer ID = cursor.getInt(cursor.getColumnIndex("_id"));
final String PERSON_NUMBER = cursor.getString(cursor.getColumnIndex("personNumber"));
// Make the delete button clickable.
Button deletePersonButton = (Button)row.findViewById(R.id.remove_person);
deletePersonButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DatabaseHelper databaseHelper = new DatabaseHelper(context);
databaseHelper.deletePerson(PERSON_NUMBER);
}
});
return row;
}
}
Here is something I did try that I thought would work, but it did not:
Button deletePersonButton = (Button)row.findViewById(R.id.remove_person);
final CustomSimpleCursorAdapter csca = (CustomSimpleCursorAdapter)this;
...
databaseHelper.deletePerson(PERSON_NUMBER);
csca.notifydatasetchanged();
Thank you for taking the time to read this.
Have a good day. :-)
UPDATE: I found out my issue is that my cursor does not refresh when I delete from the database. If I had 5 items in the list before deletion, the cursor.getCount() says 5, but after I delete the item from the database, the `cursor.getCount()`` still says 5. How do I get my cursor to refresh from within my custom SimpleCursorAdapter?
Hi I'm trying to create a ListView that has separator or header that looks like below using the SimpleCursorAdapter
my data is from my local database that's why i i tried using SimpleCursorAdapter but i'm having difficulties creating the header
by using my header it will separate the activities by its day
I create a separate layout.xml for my header and another layout.xml file for my items_list
here is my code
public class List_of_Activities extends Fragment {
DBHelper dbHelper;
private SimpleCursorAdapter dataAdapter;
private SimpleCursorAdapter headerAdapter;
String[] details = new String[] {
DBHelper.KEY_TITLE,
DBHelper.KEY_TIME
};
String[] header_column = new String[] {DBHelper.KEY_DISPLAY};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.title,
R.id.desc,
};
int[] header_to = new int[] {
R.id.header,
};
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_programme, container, false);
initialazeDatabase();
Cursor cursor = dbHelper.getDetailsItems();
Cursor header_cursor = dbHelper.getDayHeader();
headerAdapter =new SimpleCursorAdapter( getActivity(), R.layout.text_list_item_layout, header_cursor, header_column, header_to, 0);
dataAdapter = new SimpleCursorAdapter( getActivity(), R.layout.text_list_item_layout, cursor, columns, to, 0);
ListView listView = (ListView) v.findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
return v;
}
in my code it only shows the details. How can i combined them?
can anyone give me an idea on how to do this? or a sample code for it? Thank you so much for the help
I'm using SimpleCursorAdapter to manage my query to the database and then showing the results in a ListView.
Here is my code:
database.open();
ListView listContent = (ListView)findViewById(android.R.id.list);
Cursor c = database.getData();
startManagingCursor(c);
String[] from = new String[]{Database._GROUP_NAME};
int[] to = new int[]{android.R.id.text1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, query, from, to);
listContent.setAdapter(adapter);
database.close();
Although, at first look, it it working as expected, I believe that this should NOT be the way to proceed since there is CursorAdapter.
I know that this is a noob question but since just started now programming in Android I still don't know much.
How can I pass this from using SimpleCursorAdapter to CursorAdapter?
Already searched on internet but wasn't able to understand how this can be done.
Not asking code just some directions.
Thanks
favolas
UPDATE FOLLOWING mainu COMMENT
database.open();
ListView listContent = (ListView)findViewById(android.R.id.list);
Cursor c = database.getData();
MyAdapt cursorAdapter = new MyAdapt(this, query);
listContent.setAdapter(adapter);
database.close();
MyAdapt class:
public class MyAdapt extends CursorAdapter {
private final LayoutInflater mInflater;
public MyAdapt(Context context, Cursor c) {
super(context, c);
mInflater = LayoutInflater.from(context);
mContext = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView groupName = (TextView) view.findViewById(android.R.id.text1);
groupName.setText(cursor.getString(cursor
.getColumnIndex(Database._GROUP_NAME)));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final View view = mInflater.inflate(
android.R.layout.simple_list_item_1, parent, false);
return view;
}
}
Is this the correct way?
favolas
SimpleCursorAdapter is the simplest form of Adapter you can use for a custom adapter.
You should use SimpleCursorAdapter only, by when you dont need any customization.
I have a ListFragment that is being called from a Tab Navigation in an ActionBar. I have a custom adapter to display two different textviews for each list item. I'm having trouble implementing my onItemClickListener. Here is my ListFragment code:
public class MaterialsListFragment extends SherlockListFragment {
public ERGAdapter db;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.portrait_material_view, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create new DBAdapter
db = new ERGAdapter(getActivity());
// ---- get all records
db.open(); // Open database
// Get all of the notes from the database and create the item list
Cursor c = db.getAllRecords();
String[] from = new String[] { ERGAdapter.KEY_IDNO, ERGAdapter.KEY_MATERIAL };
int[] to = new int[] { R.id.idno, R.id.materials };
// Now create an array adapter and set it to display using our row
MyListAdapter materials = new MyListAdapter(getActivity(), R.layout.list_cell, c, from, to);
setListAdapter(materials);
// get the list view and the set the listener
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.i("MATERIAL"," - position: "+Integer.toString(position));
}
});
}
public class MyListAdapter extends SimpleCursorAdapter {
public MyListAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to) {
super(context, layout , cursor, from, to);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Create the idno textview with background image
TextView idno = (TextView) view.findViewById(R.id.idno);
String unidno = String.format("%1$.0f", cursor.getDouble(3));
idno.setText(unidno);
// create the material textview
TextView materials = (TextView) view.findViewById(R.id.materials);
materials.setText(cursor.getString(1));
}
}
}
I'm getting a fatal exception with this line: ListView lv = getListView();
Here is the pertinent logcat:
05-25 16:32:45.802: E/AndroidRuntime(660): Caused by: java.lang.IllegalStateException: Content view not yet created
05-25 16:32:45.802: E/AndroidRuntime(660): at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
05-25 16:32:45.802: E/AndroidRuntime(660): at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
05-25 16:32:45.802: E/AndroidRuntime(660): at com.cca.ergpro.MaterialsListFragment.onCreate(MaterialsListFragment.java:80)
I think that I need to make it part of my custom CursorAdapter, but I'm not sure how to proceed. Any suggestions would be greatly appreciated.
I was able to get it working using the solution from this question:
Creating custom simple cursor adapter
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>