Deleting last element from listview - android

Ok, so I'm trying to delete elements from a ListView, and everything goes alright until I try to delete the last element, but only if I delete the second last element and the try to delete the last one. Here's my code:
public class TestActivity extends ListActivity {
ListView list;
PAdapter adapter;
static SQLiteDatabase db;
static ArrayList<Profesor> datos;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
db = openOrCreateDatabase("DBLogin", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS Profesor (Id integer primary key AUTOINCREMENT"
+ ", Nombre" + " varchar(30), Imagen varchar(15), Fecha" + " varchar(15)" +
", Direccion varchar(35), sexo varchar(10), Telefono varchar(15), creado int);");
list = (ListView) findViewById(android.R.id.list);
datos = new ArrayList<Profesor>();
datos = datos();
adapter = new PAdapter(this, R.layout.row, datos);
setListAdapter(adapter);
list.setOnItemLongClickListener(new OnItemLongClickListener(){
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
if (datos.get(arg2).getCreado() == 1) {
PopupMenu popup = new PopupMenu(TestActivity.this, list);
popup.getMenuInflater().inflate(R.menu.popup3, popup.getMenu());
final int id = arg2;
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
delete(datos.get((int)adapter.getItemId(id)));
datos = datos();
adapter = new PAdapter(TestActivity.this, R.layout.row, datos);
setListAdapter(adapter);
list.invalidateViews();
return true;
}
});
popup.show();
}
return false;
}
});
}
private ArrayList<Profesor> datos(){
ArrayList<Profesor> ap = new ArrayList<Profesor>();
Cursor cursor = db.rawQuery("SELECT * FROM Profesor", null);
if(cursor.moveToFirst()){
do {
Profesor p = new Profesor(null, null);
p.setId(cursor.getInt(0));
p.setNombre(cursor.getString(1));
p.setFecha(cursor.getString(3));
p.setDireccion(cursor.getString(4));
p.setSexo(cursor.getString(5));
p.setImagen(cursor.getString(2));
p.setCreado(cursor.getInt(7));
p.setTelefono(cursor.getString(6));
ap.add(p);
} while(cursor.moveToNext());
}
return ap;
}
public static void delete(Profesor p){
db.execSQL("DELETE FROM Profesor WHERE Id = " + p.getId() + ";");
}
Here is the class PAdapter:
public class PAdapter extends ArrayAdapter<Profesor> {
private Context context;
private int layout;
private ArrayList<Profesor> datos;
public PAdapter(Context context, int layout, ArrayList<Profesor> datos) {
super(context, layout, datos);
this.context = context;
this.layout = layout;
this.datos = datos;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View item = inflater.inflate(layout, parent, false);
ImageView imagen = (ImageView) item.findViewById(R.id.imageView1);
datos.get(position).imagen(imagen, context, false);
TextView nombre = (TextView) item.findViewById(R.id.tNombre);
nombre.setText(datos.get(position).getNombre());
return item;
}
}
Funny thing is, it executes the code following the delete but doesn't delete the last element, neither does it throw me an exception. And again, it only happens with the last element, and only after I delete the one before it, if I close and reopen the app afterwards I can delete it normally.

I assumed you passed pos = 3 as parameter value. Because the size of list is 3, last element's position should be 2.
*EDIT:
Remember, start index of listview and adapter is different. The ListView item pos starts from "1" as first position, adapter (such as array) starts from index "0" as first position.
adapter.remove(adapter.getItem(pos-1));

You have some mistakes in your code. My following suggestion dont promise will solve your current problem, but lets try it :
Pay attention when you setting the adapter setListAdapter(adapter);, the list will set its adapter each time user did onClick - which is a waste.Use adapter.add()/adapter.remove() instead of reset all data by doing setListAdapter again and again.
You called list.invalidateViews(), for what? In your case, adapter.notifyDataSetChanged() is enough.

Try this:It's working fine for me.
ListView list;
adapter = new MyListAdapter(this);
list = (ListView) findViewById(android.R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
AlertDialog.Builder adb=new AlertDialog.Builder(MyActivity.this);
adb.setTitle("Delete?");
adb.setMessage("Are you sure you want to delete " + position);
final int positionToRemove = position;
adb.setNegativeButton("Cancel", null);
adb.setPositiveButton("Ok", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
MyDataObject.remove(positionToRemove);
adapter.notifyDataSetChanged();
}});
adb.show();
}
});

I solved it by Adding this in the activity of the single item so if i get back to the ListView Activity it is refreshed because of finish(); function.[ 8 feb 2020]
#Override
public void onBackPressed() {
super.onBackPressed();
startActivity(new Intent(SingleItem.this, ListView.class));
finish();
}

Related

custom adapter do not refresh the listview for onclicklistener in android

I delete database entry using onclicklistener but it is not refreshing the listview. how can i refresh this listview?
This is main class for listview:
public class AFragment extends Fragment implements OnItemClickListener {
protected static final String file_name ="user";
ListView list;
Database entry;
View v;
String values[];
MySimpleArrayAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
SharedPreferences settings = getActivity().getSharedPreferences(file_name, 0);
String name = settings.getString("name", null);
entry = new Database(getActivity());
entry.open();
values=entry.planlist(name);
entry.close();
if(values.length>0){
v = inflater.inflate(R.layout.activity_afragment, container,false);
adapter = new MySimpleArrayAdapter(getActivity(), values);
list=(ListView)v.findViewById(R.id.list);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
list.setOnItemClickListener(this);
}else{
v = inflater.inflate(R.layout.activity_my_tabs_listener, container,false);
}
// Toast.makeText(getActivity(),String.valueOf(values.length), Toast.LENGTH_LONG).show();
return v;
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Intent i = new Intent(getActivity(),Details.class);
i.putExtra("sub", values[arg2]);
startActivity(i);
Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
}
}
Here i use onclicklistener to delete data from database but it is not refreshing:
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public Business aFragment = new Business();
int mypos =0;
ViewHolder holder;
View row;
public MySimpleArrayAdapter(Context context, String[] values) {
super(context,R.layout.activity_my_simple_array_adapter, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
mypos = position;
row = convertView;
holder = new ViewHolder();
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(R.layout.activity_my_simple_array_adapter, parent, false);
TextView textView = (TextView) row.findViewById(R.id.text);
Button btn = (Button) row.findViewById(R.id.button1);
holder.tv = textView;
holder.btn = btn;
row.setTag(holder);
}else{
holder = (ViewHolder)row.getTag();
}
holder.tv.setText(values[position]);
final int id = position;
holder.btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Database entry = new Database(context);
entry.open();
entry.delete(values[id]);
entry.close();
// Toast.makeText(getContext(), String.valueOf(id), Toast.LENGTH_LONG).show();
}
});
return row;
}
static class ViewHolder{
TextView tv;
Button btn;
}
}
as anil said, you should put notifyDataSetChanged(); inside the onClickListener
this basically tells the adapter to render the list again and will call getView() again for every visible item in the list, if your code crashes, you should check two things:
first - debug the program and check that the new data fits what you want, in your case, check that the entry was deleted properly.
second - debug the getView method, step through each call and see what gives you the crash.
in your case the problem is that you are only updating the database, but in fact your listview data is taken from the values[] array which is not updated after you delete the database entry, you should create a function for updating it.
Put adapter.notifyDataSetChanged(); on click of ListView
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Database entry = new Database(context);
entry.open();
entry.delete(values[id]);
entry.close();
adapter.notifyDataSetChanged();
// Toast.makeText(getContext(), String.valueOf(id), Toast.LENGTH_LONG).show();
}
If you do lots of adding and deleting to the list I think you should do the things below.
You should use ArrayList<String> instead of simple String[] so that you can easily delete. Database deletion do not effect the list directly unless you use Loaders
After you delete and item from the list, you should call notifyDataSetChanged() to the adapter. If you do not call this method, the list wont be updated.
adapter.notifyDataSetChanged();
you are removing it from the database but you are not removing it from the dataset that fills up your ListView. The simplest thing you can do is to change values from array to ArrayList, and since you are using an ArrayAdapter, you can call remove(int position). You need a List<T> of objects otherwise remove will throws an exception.
You can do one thing.
Firstly create a method called myAdapter().
In this put your creation of adapter code,so you can create new adapter for loading new data by simply calling myAdapter() method.
Whenever there should be modification in your ListView just called the following code,
listview.invalidate();
Then simply call the myAdapter().
That's it.Hope this is useful to you..:)

Pre-fill the CheckedTextViews in a ListView

Here is my first question on StackOverFlow, I usually always find an answer by myself but I am really stuck on a weird problem that I will explain here:
I implemented a ListView in a fragment activity, this listview contains a list of categories related to the current record that I get from the SQLLite database.
All is working fine, I created a SimpleCursorAdapter to retrieve the data from the DB and I display the categories correctly in the ListView.
The problem is related to the pre-fill of the checkboxes (it is a multiselection list), depending on how I try to pre-check the checkboxes, I get 2 cases:
First, the checkboxes are well pre-checked, but I cannot toggle the checkboxes anymore by clicking them. Second the click toggle well the checkboxes, but they are not pre-checked anymore...
Here is the part of the code where I have the problem:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.rate_fragment, container,false);
dbCategories = "";
displayCategories = resources.getText(R.string.no_categories).toString();
/** INITIALIZATION */
mViewSwitcher = (ViewSwitcher)v.findViewById(R.id.profileSwitcher);
/** Edition view */
rateGroup = (RadioGroup)v.findViewById(R.id.rate_group);
rateOne = (RadioButton)v.findViewById(R.id.one_button);
rateOne.setTag(1);
rateTwo = (RadioButton)v.findViewById(R.id.two_button);
rateTwo.setTag(2);
rateThree = (RadioButton)v.findViewById(R.id.three_button);
rateThree.setTag(3);
rateFour = (RadioButton)v.findViewById(R.id.four_button);
rateFour.setTag(4);
rateFive = (RadioButton)v.findViewById(R.id.five_button);
rateFive.setTag(5);
descET = (EditText)v.findViewById(R.id.editdescription);
descTextSize = descET.getTextSize();
descET.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
categoriesTV_edit = (TextView)v.findViewById(R.id.edit_categories);
categoriesBT = (Button) v.findViewById(R.id.select_categories);
categoriesBT.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
View categoriesListTitle = getActivity().getLayoutInflater().inflate(R.layout.category_list_title, null);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(v.getContext()).setCustomTitle(categoriesListTitle);
categories = db.getAllCategoriesByRate(currentRate);
categoriesList = new ListView(getActivity());
categoriesList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
categoriesList.setClickable(true);
String[] fromColumns = new String[] {
DatabaseHandler.CATEGORY_NAME
};
int[] toViews = new int[]{
R.id.cat_checked
};
//mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_multiple_choice, categories, fromColumns, toViews, 0);
mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.category_item, categories, fromColumns, toViews, 0);
mAdapter.setViewBinder(new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == 1) {
CheckedTextView categRow = (CheckedTextView) view;
String catName = cursor.getString(1);
mAdapter.setViewText((TextView) view, catName);
int catChecked = cursor.getInt(2);
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
categRow.setChecked(catChecked==1);
int catID = cursor.getInt(0);
categRow.setTag(catID);
return true;
}
else {
return false;
}
}
});
categoriesList.setAdapter(mAdapter);
alt_bld.setView(categoriesList);
To have one case or another, all depends on these 2 lines:
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
If they are commented, the checkboxes are not pre-checked, but the toggle on the clicks is working. But if I comment these lines out, the toggle is not working anymore but the categories are prechecked.
What I also don't understand is that this line is not working:
categRow.setChecked(catChecked==1);
But this one is working well (I succeed to retrieve the tag):
categRow.setTag(catID);
So I hope someone will succeed to explain to me what I do wrong, I guess there is something I misunderstood here...
NOTE: I get 3 columns from the cursor "categories", first one is the ID of the category, second one is the name, and third one is the status: checked or not (1 or 0).
Thanks in advance for your time.
Finally I ended up creating my own custom adapter, this way I could at least understand more easily what was happening.
I had to create actually several multiselect lists, some populated with data from the database, others from the shared preferences.
For this one displaying data from the DB, I created the following adapter (I commented out the lines about the icons because I did not set them up yet):
public class CategoriesLVAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private List<Category> categoriesList;
// Constructor
public CategoriesLVAdapter(Context c, List<Category> categories_list){
mContext = c;
mInflater = LayoutInflater.from(c);
categoriesList = categories_list;
}
public List<Category> getCategoriesList(){
return categoriesList;
}
#Override
public int getCount() {
return categoriesList.size();
}
#Override
public Object getItem(int position) {
return categoriesList.get(position);
}
#Override
public long getItemId(int position) {
return categoriesList.get(position).getID();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.categories_list_row, null);
//convertView.setLayoutParams(new ListView.LayoutParams(200, 90));
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.categories_list_row_tv);
//holder.icon = (ImageView) convertView.findViewById(R.id.categories_list_row_iv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//holder.icon.setImageResource(categoriesList.get(position).getDrawableID());
//holder.icon.setAdjustViewBounds(true);
//holder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.title.setText(categoriesList.get(position).getName());
return convertView;
}
static class ViewHolder {
TextView title;
//ImageView icon;
}
}
In my activity, I use this adapter when the AlertDialog is called to populate the ListView, then I pre-select the categories using the last ones saved in the shared preferences:
private void categoriesFilter(){
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(resources.getText(R.string.select_categories).toString());
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categories_list,(ViewGroup) findViewById(R.id.categories_layout_root));
categoriesLV = (ListView) layout.findViewById(R.id.categories_list);
alt_bld.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String selectedCategoriesString = getSelectedValues(categoriesLV);
//Update the shared preferences
prefs.edit().putString(RateDayApplication.PREF_KEY_CATEGORIES, selectedCategoriesString).commit();
updateFilterDisplay(resources.getText(R.string.cat_title).toString(), selectedCategoriesString, searchedCategoriesTV, "Category");
}
});
alt_bld.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
String selectedCategoriesString = prefs.getString(RateDayApplication.PREF_KEY_CATEGORIES, new String());
categoriesLV.setAdapter(new CategoriesLVAdapter(this, categoriesList));
String[] selectedCategoriesArray = selectedCategoriesString.split(",");
int categoriesLVLength = categoriesLV.getCount();
for(int i = 0; i < categoriesLVLength; i++){
int categoryID = ((Category) categoriesLV.getItemAtPosition(i)).getID();
if(Arrays.asList(selectedCategoriesArray).contains(String.valueOf(categoryID))){
categoriesLV.setItemChecked(i, true);
}
}
alt_bld.setView(layout);
AlertDialog alert = alt_bld.create();
alert.show();
}
Finally here is the function I call from my database handler to get the list of catagories:
// Getting All Categories By ID desc
public List<Category> getCategoriesList() {
String selectQuery = "SELECT " + CATEGORY_ID + ", " + CATEGORY_NAME + " FROM " + CATEGORY_TABLE + " ORDER BY " + CATEGORY_ID + " ASC";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
List<Category> categoriesList = new ArrayList<Category>();//String[] categoriesList = {};
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Category category = new Category(cursor.getInt(0), cursor.getString(1), false);
categoriesList.add(category);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return categoriesList;
}
I think my problem before was coming from the fact that the function "setItemChecked" is a little misleading because it does not mean necessarily that anything is checked.
When you use the function "setItemChecked", the item in the list view becomes selected, with or without a checkbox (my rows only contain text views).
The rows selected in my list appear in a different color, and that's enough in my opinion for a simple multi selection list.
The layouts I used are quite simple, "categories_list" contains a ListView in a LinearLayout and "categories_list_row" contains a TextView in a LinearLayout.
Hope it may guide someone!

Android: View doesn't show up again in Listview / Adapter?

I have a listview to populate data with a CustomAdapter as shown below by code.
1.) The listview rows are clickable and onItemClick I show up two buttons retake/review.
2.) When I click on other row the buttons which were visible on the previous row should hide.
3.) When I scroll the list all buttons are again invisible , that should not happen.
I have achieved the point no. 1 by this code , but how could I achieve 2,3. How could I modify getView() method of adapter or onItemClick() so that things work proper.
//Initialized listview with adapter
AttempListView.setAdapter(new AttemptedExcerciseAdapter(mAttempRecord,AttemptedExercise.this));
//A different adapter class to place values
public class AttemptedExcerciseAdapter extends BaseAdapter{
HashMap<Integer, AttemptedRecord> mHashMap;
Context mContext;
LinearLayout mLLButton;
public AttemptedExcerciseAdapter() {
// TODO Auto-generated constructor stub
}
public AttemptedExcerciseAdapter(HashMap<Integer, AttemptedRecord> mAttempRecord,Context mContext) {
this.mHashMap = mAttempRecord;
this.mContext=mContext;
}
#Override
public int getCount() {
return mHashMap.size();
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup arg2) {
if (convertView == null) {
#SuppressWarnings("static-access")
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(AttemptedExercise.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.exerciselistlayout, null);
}
TextView attempChapter_name = (TextView) convertView.findViewById(R.id.TVchapterexercisechapterName);
TextView attemptQues = (TextView) convertView.findViewById(R.id.tvexercisesuccessrate);
TextView attemptSR = (TextView) convertView.findViewById(R.id.tvexerciseperquestiontime);
Button ReviewButton = (Button) convertView.findViewById(R.id.ReviewButton);
Button RetakeButton = (Button) convertView.findViewById(R.id.RetakeButton);
LinearLayout mLLtext = (LinearLayout) convertView.findViewById(R.id.LLText);
mLLButton = (LinearLayout) convertView.findViewById(R.id.LLButton);
mLLButton.setVisibility(View.INVISIBLE);
mLLtext.setVisibility(View.VISIBLE);
System.out.println("data value is..."+position+mHashMap.get(position + 1).getChapter_name());
attempChapter_name.setText(mHashMap.get(position+1).getChapter_name());
attemptQues.setText(" " + mHashMap.get(position+1).getTimePerQues() + " sec/ques");
attemptSR.setText(" " + mHashMap.get(position+1).getSuccess_rate() + " %");
return convertView;
}
}
//Item click listener for listview
public class ExcerciseItemClickListener implements OnItemClickListener {
ArrayList<Integer> rowNo=new ArrayList<Integer>();
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
System.out.println("click working..."+arg2);
arg1.findViewById(R.id.LLButton).setVisibility(View.INVISIBLE);
rowNo.clear();
rowNo.add(arg2);
if(rowNo.size()==1)
{
AttemptedRecord mRecordExcerciseItem = mAttempRecord.get(arg2 + 1);
final int chapter_id = mRecordExcerciseItem.getChapter_id();
final int test_id = mRecordExcerciseItem.getTest_id();
final int subject_id = mRecordExcerciseItem.getSubject_id();
System.out.println("attempted list size is..."+mAttempRecord.size());
arg1.findViewById(R.id.LLText).setVisibility(View.INVISIBLE);
arg1.findViewById(R.id.LLTake).setVisibility(View.INVISIBLE);
arg1.findViewById(R.id.LLButton).setVisibility(View.VISIBLE);
Button review=(Button) arg1.findViewById(R.id.ReviewButton);
Button retake=(Button) arg1.findViewById(R.id.RetakeButton);
review.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DBHelper mDbHelper = new DBHelper(AttemptedExercise.this);
mDbHelper.createOrOpenDatabase("Dashboard");
Cursor chpater_exercise_Cursor = mDbHelper.rawQuery("select current_test_id from practice_test_summary where test_id="+test_id+" order by test_datetime desc limit 1");
chpater_exercise_Cursor.moveToFirst();
Long current_test_id =chpater_exercise_Cursor.getLong(0);
chpater_exercise_Cursor.close();
System.out.println("value of current test id is...."+current_test_id);
Intent reviewIntent = new Intent(AttemptedExercise.this, PracticeReview.class);
reviewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
if (current_test_id > 0) {
reviewIntent.putExtra("current_test_id", current_test_id);
startActivity(reviewIntent);
}
}
});
retake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("test id value when test starts is... "+test_id);
Toast.makeText(AttemptedExercise.this, "chapter_id" + chapter_id + " course_id" + " test_id" + test_id + " subject_id" + subject_id, Toast.LENGTH_LONG).show();
StartTest(4, subject_id, chapter_id, test_id);
}
});
}
}
}
In getView, you hide the button and text,that's why the view dispears when you scrolling。
mLLButton.setVisibility(View.INVISIBLE);
mLLtext.setVisibility(View.VISIBLE);
In your click listener you should record the position of the selected row, and in getView, you need to set view's visilibity status based on the postion of the view.
if you can mange to add ClickListeners of the list in getView like this
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
curruntButtonClickPosition=position;
//Visible you button here
notifyDataSetChanged();
}
});
and in getView
if(curruntButtonClickPosition=position)
//mLLButton visible
else
//mLLButton invisible
add curruntButtonClickPosition globle variable in AttemptedExcerciseAdapter class and init with -1.

getting to another screen from listview row

In the following code, I want to set Onclick Listeners on some "elements" of my row. where should I place the setOnclick listener code? In the activity code or in the adapter? I suppose the first, but in that case how will I identify which row has been selected
(each row is supposed to get me to different views)?
Java code:
List<String[]> info=new ArrayList<String[]>();
String[] names_info=new String[5];
String[] phones_info=new String[5];
String[] map_info=new String[5];
String[] web_info=new String[5];
String[] photos_info=new String[5];
for(int i=0;i<names_info.length;i++)
{
info.add(new String[]{names_info[i],phones_info[i],map_info[i],web_info[i],photos_info[i]});
}
for (int i = 0; i < info.size(); i++) {
Log.d("TAG", "item " + i +
" name:" + info.get(i)[0] +
" info:" + info.get(i)[1]);
}
FacilitiesAdapter adapter = new FacilitiesAdapter(this,info,want_info_display,want_phone_display,want_photos_display);
//System.out.println(info[0]);
setListAdapter(adapter);
EDIT
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// When clicked, show a toast with the TextView text
//Toast.makeText(getApplicationContext(), ((TextView) arg1).getText(),
//Toast.LENGTH_SHORT).show();
Intent i33 = new Intent(HotelsScreen.this,AbousUsScreen.class);
i33.putExtra("position", arg2);
System.out.println(arg2);
System.out.println(info.get(arg2)[0]);
startActivity(i33);
}
});
I see results in Log, so that means that my info is getting its result normally.
This is my adapter.
public class FacilitiesAdapter extends ArrayAdapter<String[]> {
private final Context context;
List <String[]> dataList;
public FacilitiesAdapter(Context context, List<String[]> dataList, int need_phone, int need_info, int need_photos) {
super(context, R.layout.expand_row);
this.context = context;
this.dataList = dataList;
//this.tracks_condition=tracks_condition;
//this.count=count;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.expand_row, parent, false);
System.out.println("I am here");
String[] data = dataList.get(position);
String name=data[0];
TextView textView = (TextView) rowView.findViewById(R.id.name);
System.out.println("I am in the adapter "+name);
textView.setText(name);
return rowView;
}
}
EDIT 1:
am I supposed now to see in every item I click its position and its name? Cause I see nothing?
can be as simple as something alone these lines:
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3)
{
Intent i33 = new Intent(MyScreen.this,OtherScreen.class);
i33.putExtra("position", position);
startActivity(i33);
}
});
I think your biggest problem will be figuring out how to map a row to the appropriate screen. If you can do this, you can set up a Map object with all the mappings.
In your adapter, you can then use setTag() on the view and pass it what you get back from the Map, then creating a new Intent from it.
//In your adapter's getView() method...
Class activityClass = rowToActivityMap.get(someRowAttribute);
view.setTag(activityClass);
//In your click listener...
Class activityClass = (Class)view.getTag();
Intent intent = new Intent(this, activityClass);
startActivity(intent);

Android ViewHolder in CursorAdapter causing listView to get screwed

I've been struggeling in the past few days trying to figure this out, I hope you can help me...
I have an Activity that shows a list of Players by setting a listadapter like this:
PlayerCursorAdapter playerAdapter = new PlayerCursorAdapter(this,
R.layout.players_row, c, columns, to);
setListAdapter(playerAdapter);
When clicking an item in the list, this code will be executed showing a dialog with an "Edit" and "Delete" option for editing and removing players:
private class OnPlayerItemClickListener implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view, int position,
long rowId) {
Toast.makeText(view.getContext(),
"Clicked Item [" + position + "], rowId [" + rowId + "]",
Toast.LENGTH_SHORT).show();
// Prepare Dialog with "Edit" and "Delete" option
final CharSequence[] choices = {
view.getContext().getString(R.string.buttonEdit),
view.getContext().getString(R.string.buttonDelete) };
AlertDialog.Builder builder = new AlertDialog.Builder(
view.getContext());
builder.setTitle(R.string.title_edit_delete_player);
builder.setItems(choices, new EditOrDeleteDialogOnClickListener(
view, rowId));
AlertDialog alert = builder.create();
// Show Dialog
alert.show();
}
Based on your choice (Edit or delete player), the following listener will be executed:
private class EditOrDeleteDialogOnClickListener implements
DialogInterface.OnClickListener {
private View view;
private long rowId;
public EditOrDeleteDialogOnClickListener(View view, long rowId) {
this.view = view;
this.rowId = rowId;
}
public void onClick(DialogInterface dialog, int item) {
if (item == 0) {
// Edit
showDialog(PlayGameActivity.DIALOG_EDIT_PLAYER_ID);
} else if (item == 1) {
// Delete from database
DatabaseHelper databaseHelper = new DatabaseHelper(
view.getContext());
databaseHelper.deletePlayer(rowId);
// Requery to update view.
((PlayerCursorAdapter) getListAdapter()).getCursor().requery();
Toast.makeText(
view.getContext(),
view.getContext().getString(
R.string.message_player_removed)
+ " " + rowId, Toast.LENGTH_SHORT).show();
}
}
}
The code for the adapter is here:
public class PlayerCursorAdapter extends SimpleCursorAdapter {
private LayoutInflater layoutInflater;
private int layout;
public PlayerCursorAdapter(Context context,
int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.layout = layout;
layoutInflater = LayoutInflater.from(context);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Cursor c = getCursor();
View view = layoutInflater.inflate(layout, parent, false);
// Get Data
int nameCol = c.getColumnIndex(Player.COLUMN_PLAYER_NAME);
String name = c.getString(nameCol);
int gamesPlayedCol = c.getColumnIndex(Player.COLUMN_GAMES_PLAYED);
String gamesPlayed = c.getString(gamesPlayedCol);
int gamesWonCol = c.getColumnIndex(Player.COLUMN_GAMES_WON);
String gamesWon = c.getString(gamesWonCol);
// Set data on fields
TextView topText = (TextView) view.findViewById(R.id.topText);
if (name != null)
topText.setText(name);
TextView bottomText = (TextView) view.findViewById(R.id.bottomText);
if (gamesPlayed != null && gamesWon != null)
bottomText.setText(view.getContext().getString(
R.string.info_played_won)
+ gamesPlayed + "/" + gamesWon);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkBox);
// Set up PlayerViewHolder
PlayerViewHolder playerViewHolder = new PlayerViewHolder();
playerViewHolder.playerName = name;
playerViewHolder.gamesPlayed = gamesPlayed;
playerViewHolder.gamesWon = gamesWon;
playerViewHolder.isChecked = checkBox.isChecked();
view.setTag(playerViewHolder);
return view;
}
private class PlayerViewHolder {
String playerName;
String gamesPlayed;
String gamesWon;
boolean isChecked;
}
#Override
public void bindView(View view, Context context, Cursor c) {
PlayerViewHolder playerViewHolder = (PlayerViewHolder) view.getTag();
TextView topText = (TextView) view.findViewById(R.id.topText);
topText.setText(playerViewHolder.playerName);
TextView bottomText = (TextView) view.findViewById(R.id.bottomText);
bottomText.setText(view.getContext()
.getString(R.string.info_played_won)
+ playerViewHolder.gamesPlayed
+ "/"
+ playerViewHolder.gamesWon);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkBox);
checkBox.setChecked(playerViewHolder.isChecked);
}
}
Now, the problem is that after removing a few of the players in the list, the list gets screwed up, eg. it shows something different than what is actually available.
I've experimented a little and if I stop using the PlayerViewHolder in bindView and instead read the text from the cursor and assign it directly to the text fields, then it works.... So question is, why is my ViewHolder screwing up things???
Any help will be greatly appreciated!
Thanks!
Zyb3r
Found a solution...
Basically I reinitialize the Cursor and ListAdapter plus assigns the ListAdapter to the ListView all over again when I change the data in the database.
I'm not entirely sure why this is nessasary, but notifyDataSetChanged(), notifyDataSetInvalidated() and all the other things I tried didn't work, so now I'm using this approach. :o)
Zyb3r

Categories

Resources