I have the following code returning a list from a database. I want to use a checkbox list so people can do a search on beaches with certain facilities, but I can’t get it to show the check boxes, it just displays a normal list!
public class FacilitySearch extends ListActivity {
private DatabaseHelper dbBookHelper = null;
private Cursor ourCursor = null;
private BookAdapter adapter = null;
public final static String ID_EXTRA="com.fnesse.beachguide._ID";
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
ListView myListView = getListView();
myListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
myListView.setOnItemClickListener(onListClick);
dbBookHelper = new DatabaseHelper(this);
dbBookHelper.createDatabase();
ourCursor = dbBookHelper.getFacilities();
startManagingCursor(ourCursor);
adapter=new BookAdapter(ourCursor);
myListView.setAdapter(adapter);
myListView.setItemsCanFocus(false);
}
private AdapterView.OnItemClickListener onListClick = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent i = new Intent(FacilitySearch.this, Administration.class);
i.putExtra(ID_EXTRA, String.valueOf(id));
startActivity(i);
}
};
class BookAdapter extends CursorAdapter {
BookAdapter(Cursor c) {
super(FacilitySearch.this, c);
}
#Override
public void bindView(View row, Context ctxt, Cursor c) {
BookHolder holder = (BookHolder)row.getTag();
holder.populateFrom(c, dbBookHelper);
}
#Override
public View newView(Context ctxt, Cursor c, ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.row2, parent, false);
BookHolder holder=new BookHolder(row);
row.setTag(holder);
return(row);
}
}
static class BookHolder {
private TextView name = null;
BookHolder(View row) {
name=(TextView)row.findViewById(R.id.beachListText);
}
void populateFrom(Cursor c, DatabaseHelper r) {
name.setText(r.getName(c));
}
}
Any ideas?
Cheers,
Mike.
I think you need to include in your list item a CheckedTextView with
android:id="#android:id/text1"
as shown in the android.R.layout.simple_list_item_multiple_choice resource.
It's the same when you extend ListActivity and you define your own main layout you need to have a ListView with id
android:id="#id/android:list"
Related
I checked a lot of stack overflow question, and none of them helped.
How to refresh my listView after deleting item with onLongClickListener?
As you'll see nor adapter.notifyDataSetChanged(), nor listView.invalidateViews() don't work.
This is implementation with just necessary methods to figure out idea.
public class MainActivity extends AppCompatActivity {
public FloatingActionButton fabAddWord;
public Toolbar toolbar;
public ListView listView;
private RjecnikCursorAdapter adapter;
private RjecnikDB dbRjecnik;
private SQLiteDatabase db;
private Cursor cursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fabAddWord = (FloatingActionButton) findViewById(R.id.fabAddWord);
listView = (ListView) findViewById(R.id.listView);
dbRjecnik = new RjecnikDB(this);
db = dbRjecnik.getWritableDatabase();
String query = "SELECT * FROM " + RjecnikDB.TABLE;
cursor = db.rawQuery(query, null);
adapter = new RjecnikCursorAdapter(this, cursor);
listView.setAdapter(adapter);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
deleteOnLongClick(cursor.getString(cursor.getColumnIndex(RjecnikDB.COLUMN_RIJEC)));
adapter.notifyDataSetChanged();
listView.invalidateViews();
return true;
}
});
}
public void deleteOnLongClick(String rijec) {
SQLiteDatabase db = dbRjecnik.getWritableDatabase();
db.delete(RjecnikDB.TABLE, RjecnikDB.COLUMN_RIJEC + " = ?", new String[] {rijec} );
this.adapter.notifyDataSetChanged();
this.listView.invalidateViews();
db.close();
}
CustomAdapter
public class RjecnikCursorAdapter extends CursorAdapter {
public RjecnikCursorAdapter (Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_word, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tvSingleLineWord = (TextView) view.findViewById(R.id.tvSingleLineWord);
// Extract properties from cursor
String rijec = cursor.getString(cursor.getColumnIndex(RjecnikDB.COLUMN_RIJEC));
// Populate fields with extracted properties
tvSingleLineWord.setText(rijec);
}
}
The Adapter have a data cache, so data in ListView will not change when data in database changed. You should change the cursor.
#Override
public void changeCursor(Cursor cursor) {
mIndexer.setCursor(cursor);
super.changeCursor(cursor);
}
put code below to your OnItemLongClickListener
cursor = db.rawQuery(query, null);
adapter.changeCurosr(cursor);
You have to use just notifyDataSetChanged() to refresh your listView data, invalidateViews() will only redraw the visible items yet nothing on them has changed (changing font for example).
Note that is recommanded to run your notifyDataSetChanged() on UI thread.
EDIT 2 : you can use BaseAdapter instead of CursorAdapter like below
public class RjecnikCursorAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<String> rjecnikList;
public RjecnikCursorAdapter(Activity activity, List<String> rjecnikList) {
this.activity = activity;
this.rjecnikList = rjecnikList;
}
#Override
public int getCount() {
return rjecnikList.size();
}
#Override
public Object getItem(int location) {
return rjecnikList.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.item_word, null);
TextView tvSingleLineWord = (TextView) view.findViewById(R.id.tvSingleLineWord);
tvSingleLineWord.setText(String.valueOf(rjecnikList.get(position)));
return convertView;
}
}
And in your activity :
public class MainActivity extends AppCompatActivity {
public FloatingActionButton fabAddWord;
public Toolbar toolbar;
public ListView listView;
public List<String> mylist;
private RjecnikCursorAdapter adapter;
private RjecnikDB dbRjecnik;
private SQLiteDatabase db;
private Cursor cursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fabAddWord = (FloatingActionButton) findViewById(R.id.fabAddWord);
listView = (ListView) findViewById(R.id.listView);
dbRjecnik = new RjecnikDB(this);
db = dbRjecnik.getWritableDatabase();
String query = "SELECT * FROM " + RjecnikDB.TABLE;
cursor = db.rawQuery(query, null);
mylist = new ArrayList<>();
if (cursor.moveToFirst()){
do{
//change this with your column data
String data = cursor.getString(cursor.getColumnIndex("data");
mylist.add(data);
}while(cursor.moveToNext());
}
cursor.close();
adapter = new RjecnikCursorAdapter(this, mylist);
listView.setAdapter(adapter);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
deleteOnLongClick(cursor.getString(cursor.getColumnIndex(RjecnikDB.COLUMN_RIJEC)));
mylist.remove(position);
adapter.notifyDataSetChanged();
listView.invalidateViews();
return true;
}
});
}
public void deleteOnLongClick(String rijec) {
SQLiteDatabase db = dbRjecnik.getWritableDatabase();
db.delete(RjecnikDB.TABLE, RjecnikDB.COLUMN_RIJEC + " = ?", new String[] {rijec} );
this.adapter.notifyDataSetChanged();
this.listView.invalidateViews();
db.close();
}
first of all thank you all for your answers and sorry for the bad English used, have a controller class to populate a listview and an adapter class that extends CursorAdapter, my problem is that when I setAdapter, my class adapter is not running the Newview method BindView certainly not running. Here is the code used for this, they hope can help. regards
public class ListaAdaptador extends CursorAdapter {
public static class ContenedorView
{
TextView nombre;
TextView apellidos;
TextView dni;
TextView telefono;
ImageView img;
}
public ListaAdaptador(Context a, Cursor c)
{
super(a, c);
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.list_item,parent,false);
ContenedorView contenedor = null;
contenedor = new ContenedorView();
contenedor.nombre = (TextView) view.findViewById(R.id.txt_item_nombre);
contenedor.apellidos =(TextView) view.findViewById(R.id.txt_item_apellidos);
contenedor.dni = (TextView) view.findViewById(R.id.txt_item_dni);
contenedor.telefono = (TextView) view.findViewById(R.id.txt_item_telefono);
contenedor.img = (ImageView) view.findViewById(R.id.ImageViewItem);
view.setTag(contenedor);
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ContenedorView contenedor = (ContenedorView) view.getTag();
contenedor.nombre.setText(cursor.getString(cursor.getColumnIndex("nombre")));
contenedor.apellidos.setText(cursor.getString(cursor.getColumnIndex("apellidos")));
contenedor.dni.setText(cursor.getString(cursor.getColumnIndex("dni")));
contenedor.telefono.setText(cursor.getString(cursor.getColumnIndex("telefono")));
contenedor.img.setImageResource(R.drawable.img_nodisp);
}
}
clase ListaControlador
public class ListadoControlador extends ListActivity {
EditText aproximacion;
ListView lv;
ImageButton buscar;
SQLiteDatabase db;
Cursor cursor;
ListaAdaptador adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listado);
aproximacion = (EditText) findViewById(R.id.EditText01);
buscar =(ImageButton)findViewById(R.id.btnBuscar);
lv=getListView();
prepararBaseDeDatos();
obtenemosValores();
}
public void prepararBaseDeDatos()
{
AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this,"registro",null,1);
db = admin.getWritableDatabase();
}
public void obtenemosValores()
{
cursor = db.rawQuery("select _id,nombre,apellidos,dni,telefono from paciente", null);
adapter = new ListaAdaptador(ListadoControlador.this,cursor);
lv.setAdapter(adapter);
}
Remove the three Override methods getCount(), getItem() and getItemId() from your ListaAdaptador class. You don't need them since you're using a CursorAdapter.
The problem is as follows: When I click on the row, dialog opens where I enter new row value and click ok to save changes. The row is updated, but I need to exit view and go back again to see changes. How can I refresh view automatically when the sava button is clicked?
Here is my code for Dialog:
class EditListItemDialog extends Dialog implements View.OnClickListener {
MyDB dba;
private View editText;
private DiaryAdapter adapter;
private SQLiteDatabase db;
public EditListItemDialog(Context context) {
super(context);
dba = new MyDB(context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_dialog);//here is your xml with EditText and 'Ok' and 'Cancel' buttons
View btnOk = findViewById(R.id.button_ok);
editText = findViewById(R.id.edit_text);
btnOk.setOnClickListener(this);
dba.open();
}
private List<String> fragment_monday;
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Position is the number of the item clicked
//You can use your adapter to modify the item
adapter.getItem(position); //Will return the clicked item
}
public EditListItemDialog(Context context, DiaryAdapter adapter, int position) {
super(context);
this.fragment_monday = new ArrayList<String>();
this.adapter = adapter;
dba = new MyDB(context);
}
#Override
public void onClick(View v) {
fragment_monday.add(((TextView) v).getText().toString());//here is your updated(or not updated) text
dismiss();
try {
saveItToDB();
} catch (Exception e) {
e.printStackTrace();
}
}
private void saveItToDB() {
dba.open();
dba.updateDiaryEntry(((TextView) editText).getText().toString(), 2);
dba.close();
((TextView) editText).setText("");
}
}
And here is the code where I want to refresh view instead of doing it manually:
public class Monday extends ListActivity {
private SQLiteDatabase db;
private static final int MyMenu = 0;
MyDB dba;
DiaryAdapter myAdapter;
private class MyDiary{
public MyDiary(String t, String c){
title=t;
content=c;
}
public String title;
public String content;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
dba = new MyDB(this);
dba.open();
setContentView(R.layout.fragment_monday);
super.onCreate(savedInstanceState);
myAdapter = new DiaryAdapter(this);
this.setListAdapter(myAdapter);
}
public class DiaryAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<MyDiary> fragment_monday;
public DiaryAdapter(Context context) {
mInflater = LayoutInflater.from(context);
fragment_monday = new ArrayList<MyDiary>();
getdata();
ListView list = getListView();
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
new EditListItemDialog(Monday.this, null, position).show();
return true;
}
});
}
public void getdata(){
Cursor c = dba.getdiaries();
startManagingCursor(c);
if(c.moveToFirst()){
do{
String title =
c.getString(c.getColumnIndex(Constants.TITLE_NAME));
String content =
c.getString(c.getColumnIndex(Constants.CONTENT_NAME));
MyDiary temp = new MyDiary(title,content);
fragment_monday.add(temp);
} while(c.moveToNext());
}
}
#Override
public int getCount() {return fragment_monday.size();}
public MyDiary getItem(int i) {return fragment_monday.get(i);}
public long getItemId(int i) {return i;}
public View getView(int arg0, View arg1, ViewGroup arg2) {
final ViewHolder holder;
View v = arg1;
if ((v == null) || (v.getTag() == null)) {
v = mInflater.inflate(R.layout.diaryrow, null);
holder = new ViewHolder();
holder.mTitle = (TextView)v.findViewById(R.id.name);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.mdiary = getItem(arg0);
holder.mTitle.setText(holder.mdiary.title);
v.setTag(holder);
return v;
}
public class ViewHolder {
MyDiary mdiary;
TextView mTitle;
}
}
/** Called when the user clicks the Edit button */
public void visitDiary(View view) {
Intent intent = new Intent(this, Diary.class);
startActivity(intent);
}
/** Called when the user clicks the back button */
public void visitSchedule(View view) {
Intent intent = new Intent(this, DisplayScheduleScreen.class);
startActivity(intent);
}
}
I hope it's clear enough what I am looking for. Where my list is, I want the list to be refreshed automatically after updating row so the new content of the row shows up immediately instead of navigating to other view and going back. I will be appreciated for your help.
At some point, after you call EditListItemDialog and it finishes, you need to run NotifyDataSetChanged() on your listview adapter. onResume() is a good place to do it,
I have been searching through a lot of questions but they don't ask or answer what I'm looking for, so here is what I'm trying to do.
So far I have an project in witch I added a pre populated database, with a table that contains 6 columns of data, the main xml just displays the list view, I'm using a Adapter, Cursor, SQLiteHelper etc. all works fine and displays my custom itemlist.xml all good, now in every item of the list I display only 3 things (second, fourth and fifth column data) of each record (they all contain 6 coluns like I mention before), I want to be able with a onclickitemlistener to display in a toast the data from the third column for that item, how do I accomplish that? I'm able to get the list item id displayed, so can someone help me here, Thanks
here is som code:
Code from y main activity
public class DBlistActivity extends Activity {
private mediosHelper dbmediosHelper = null;
private Cursor ourCursor = null;
FancyAdapter adapter = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView myListView = (ListView) findViewById(R.id.mylistView);
dbmediosHelper = new mediosHelper(this);
try {
dbmediosHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
dbmediosHelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
try {
ourCursor = dbmediosHelper.getCursor();
startManagingCursor(ourCursor);
}catch(SQLException sqle){
throw sqle;
}
adapter = new FancyAdapter(ourCursor);
myListView.setAdapter(adapter);
myListView.setOnItemClickListener(onListClick);
}
class FancyAdapter extends CursorAdapter {
FancyAdapter(Cursor c) {
super (DBlistActivity.this, c);
}
public void bindView(View row, Context ctxt, Cursor c) {
ViewHolder holder = (ViewHolder) row.getTag();
holder.populateForm(c, dbmediosHelper);
}
public View newView(Context ctxt, Cursor c, ViewGroup parent){
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.listitem, parent, false);
ViewHolder holder = new ViewHolder(row);
row.setTag(holder);
return(row);
}
}
class ViewHolder{
public TextView nombre=null;
public TextView estado=null;
public TextView ciudad=null;
ViewHolder (View row){
nombre = (TextView) row.findViewById(R.id.medioName);
estado = (TextView) row.findViewById(R.id.medioEstado);
ciudad = (TextView) row.findViewById(R.id.medioCiudad);
}
void populateForm(Cursor c, mediosHelper r){
nombre.setText(r.getName(c));
estado.setText(r.getEstado(c));
ciudad.setText(r.getCiudad(c));
}
}
private AdapterView.OnItemClickListener onListClick=new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Toast.makeText(getApplicationContext(), String.valueOf(id), Toast.LENGTH_SHORT) .show();
}
};
And from my mediosHelper
public Cursor getCursor() {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(TABLE_NAME);
String[] asColumsToReturn = new String[] { COLUMN_ID, COLUMN_CODE, COLUMN_NAME, COLUMN_URL, COLUMN_ESTADO, COLUMN_CIUDAD};
Cursor mCursor = queryBuilder.query(myDataBase, asColumsToReturn, null, null, null, null, null);
return mCursor;
}
public CharSequence getId(Cursor c) {
return (c.getString(0));
}
public CharSequence getCode(Cursor c) {
return (c.getString(1));
}
public String getName(Cursor c){
return(c.getString(2));
}
public String getUrl(Cursor c) {
return (c.getString(3));
}
public String getEstado(Cursor c) {
return (c.getString(4));
}
public String getCiudad(Cursor c) {
return (c.getString(5));
}
you need to get the cursor you used to fill the adapter. once you have that move it to the position you get in the onItemClickedCallback with c.moveToPosition(position). Than you have access to all columns (cursor.getColumnIndex("_id"))
EDIT:
class MyActivity extends Activity implements OnItemClickListener{
FancyAdapter adapter = null;
...
adapter = new FancyAdapter(ourCursor);
myListView.setAdapter(adapter);
myListView.setOnItemClickListener(this);
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// TODO Auto-generated method stub
Cursor c = adapter.getCursor();
c.moveToPosition(position);
int id = c.getInt(c.getColumnIndex("_id");
}
}
I know that data is inserted in the database , and it is listed correctly but the notifydatasetchanges doesn't works , the list view doesn't get refreshed, so I have to restart my activity....
Cursor c = db.selectAll();
final ListView lv = (ListView) findViewById(R.id.listView1);
adapter=new MyContactsAdapter(this, c);
lv.setAdapter(adapter);
db.insertInTable("asd","asd");
//insertion in table works, I am sure, cause when I start the activity the new values are listed
//this the part that doesn't works
((MyContactsAdapter)lll.getAdapter()).notifyDataSetChanged();
adapter.notifyDataSetChanged();
lll.refreshDrawableState();
private class MyContactsAdapter extends CursorAdapter{
private Cursor mCursor;
private Context mContext;
private final LayoutInflater mInflater;
public MyContactsAdapter(Context context, Cursor cursor) {
super(context, cursor, true);
mInflater = LayoutInflater.from(context);
mContext = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView t = (TextView) view.findViewById(R.id.textView2);
t.setText(cursor.getString( 0 ));
t = (TextView) view.findViewById(R.id.TextView01);
t.setText(cursor.getString(1));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final View view = mInflater.inflate(R.layout.item, parent, false);
return view;
}
}//adapter
Ok, something like, From your code,
Cursor c;
#Override
onCreate(.... {
setContentView(...);
final ListView lv = (ListView) findViewById(R.id.listView1);
db.insertInTable("asd","asd");
c = db.selectAll();
adapter=new MyContactsAdapter(this, c);
lv.setAdapter(adapter);
// some button click...
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
db.insertInTable("xyz","xyz");
c = db.selectAll();
adapter.notifyDataSetChanged();
}
});
Try this, Let see what happen...