EditText Values getting cleared on scrolling listview android - java

public class Custom_Student_marks_list_faculty_adapter extends ArrayAdapter<MarksStudentListFacultyObject> {
private Activity context;
private List<MarksStudentListFacultyObject> studentlist;
public Custom_Student_marks_list_faculty_adapter(Activity context,List<MarksStudentListFacultyObject> studentlist) {
super(context,R.layout.custom_listview_marks_faculty,studentlist);
this.context=context;
this.studentlist=studentlist;
}
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
final ViewHolder holder;
if(convertView==null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.custom_listview_marks_faculty, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_name_id);
holder.marks = (EditText) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_marks_id);
String mark = holder.marks.getText().toString();
MarksStudentListFacultyObject student_list = studentlist.get(position);
holder.name.setText(student_list.getName());
holder.marks.setText(mark);
holder.marks.setTag(position);
convertView.setTag(holder);
} else {
holder =(ViewHolder)convertView.getTag();
}
holder.name.setText(studentlist.get(position).getName());
holder.marks.setText(studentlist.get(position).getMakrs());
return convertView;
}
}
class ViewHolder {
protected TextView name;
protected EditText marks;
}
I have seen many solution for it but it is not working out for me. Every time on scrolling, ListView values are getting cleared.

Hope this will work...
public Custom_Student_marks_list_faculty_adapter(Activity context,List<MarksStudentListFacultyObject> studentlist) {
super(context,R.layout.custom_listview_marks_faculty,studentlist);
this.context=context;
this.studentlist=studentlist;
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
final ViewHolder holder;
if(convertView==null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.custom_listview_marks_faculty, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_name_id);
holder.marks = (EditText) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_marks_id);
convertView.setTag(holder);
} else {
holder =(ViewHolder)convertView.getTag();
}
MarksStudentListFacultyObject student_list = studentlist.get(position);
holder.name.setText(student_list.getName());
//holder.marks.setText(student_list.getMarks());
return convertView;
}

You will need to update the edittext values again in your student list because of the recycling nature of list view and also set the value on each time getview method is called.
Something like:
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
final ViewHolder holder;
if(convertView==null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.custom_listview_marks_faculty, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_name_id);
holder.marks = (EditText) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_marks_id);
convertView.setTag(holder);
} else {
holder =(ViewHolder)convertView.getTag();
}
MarksStudentListFacultyObject student_list = studentlist.get(position);
holder.name.setText(student_list.getName());
holder.marks.setText(student_list.getMarks());
holder.marks.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
//set data to array when changed
student_list.setMarks(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
return convertView;
}

Try:
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
final ViewHolder holder;
if(convertView==null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.custom_listview_marks_faculty, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_name_id);
holder.marks = (EditText) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_marks_id);
convertView.setTag(holder);
} else {
holder =(ViewHolder)convertView.getTag();
}
String mark = holder.marks.getText().toString();
MarksStudentListFacultyObject student_list = studentlist.get(position);
holder.name.setText(student_list.getName());
holder.marks.setText(mark);
return convertView;
}
}

Try this:
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if(convertView==null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.custom_listview_marks_faculty, null);
}
TextView name = (TextView) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_name_id);
EditText marks = (EditText) convertView.findViewById(R.id.custom_listview_marks_faculty_stu_marks_id);
name.setText(studentlist.get(position).getName());
marks.setText(studentlist.get(position).getMakrs());
return convertView;
}
Edit :
Override getCount() method in ArrayAdaptor:
#Override public int getCount(){ return studentlist.size(); }

Related

Refresh ListView when item in adapter is removed

I have created a ListView of items that each one of them looks as follows:
In simplified code, It looks like this:
public class MyBAdapter extends ArrayAdapter {
private static class ViewHolder {
public ImageButton ib_Delete;
public ToggleButton tb_Status;
}
public MyBAdapter(Context context, ArrayList<MyB> aB) {
super(context, 0, aB);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final MyB b = getItem(position);
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate( R.layout.item_b_myb, parent, false);
viewHolder.ib_DeleteB = convertView.findViewById( R.id.ib_DeleteB );
viewHolder.tb_Status = convertView.findViewById( R.id.tb_Status );
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
Now, I had like that once a user clicks on the ToggleButton of on the x button, that it will remove this item from the list and that the view will be updated on this screen.
How can I do it?
I saw that for this case notifyDataSetChanged() won't work.
Basically what I'm trying to do is to refresh the list without calling again the activity.
Thank you
You can try like this:
public static class MyBAdapter extends ArrayAdapter {
private ArrayList<String> aB;
private class ViewHolder {
public ImageButton ib_Delete;
public ToggleButton tb_Status;
public TextView text;
}
public MyBAdapter(Context context, ArrayList<String> aB) {
super(context,0, aB);
this.aB = aB;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate( R.layout.item_b_myb, parent, false);
viewHolder.ib_Delete = convertView.findViewById( R.id.ib_DeleteB );
viewHolder.tb_Status = convertView.findViewById( R.id.tb_Status );
viewHolder.text = convertView.findViewById( R.id.text );
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.tb_Status.setChecked(false);
}
viewHolder.text.setText(aB.get(position));
viewHolder.ib_Delete.setTag(position);
viewHolder.ib_Delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(viewHolder.tb_Status.isChecked()){
delete((Integer)view.getTag());
}
}
});
return convertView;
}
private void delete(int position) {
aB.remove(position);
notifyDataSetChanged();
}
#Override
public int getCount() {
return aB.size();
}
}

ArrayAdapter for country flag and image spinner slowing view down

I have the following class:
private class CountryAdapter extends ArrayAdapter<String> {
private LayoutInflater inflater;
CountryAdapter(Context context, int textViewResourceId, ArrayList objects) {
super(context, textViewResourceId, objects);
inflater = getLayoutInflater();
}
#Override
public View getDropDownView(int position, View convertView, #NonNull ViewGroup parent) {
return getCustomDropdown(position, convertView, parent);
}
#NonNull
#Override
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
View getCustomDropdown(int position, View convertView, ViewGroup parent) {
DropViewHolder dropViewHolder;
if (convertView == null) {
dropViewHolder = new DropViewHolder();
convertView = inflater.inflate(R.layout.country_spinner_row, parent, false);
convertView.setTag(dropViewHolder);
dropViewHolder.label = convertView.findViewById(R.id.spinner_countryNameRow);
dropViewHolder.icon = convertView.findViewById(R.id.spinner_countryFlagRow);
} else {
dropViewHolder = (DropViewHolder) convertView.getTag();
}
dropViewHolder.label.setText(String.format("%s (+%s)", countryNameList.get(position), countryList.optJSONObject(position).optString("phoneCountryCode")));
String flagPath = "flag_" + countryList.optJSONObject(position).optString("countryCode").toLowerCase();
dropViewHolder.icon.setImageResource(getResources().getIdentifier(flagPath, "drawable", getPackageName()));
return convertView;
}
View getCustomView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.country_spinner_row_dropdown, parent, false);
convertView.setTag(viewHolder);
viewHolder.icon = convertView.findViewById(R.id.spinner_countryFlagRow);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
String flagPath = "flag_" + countryList.optJSONObject(position).optString("countryCode").toLowerCase(); viewHolder.icon.setImageResource(getResources().getIdentifier(flagPath, "drawable", getPackageName()));
return convertView;
}
private class DropViewHolder {
TextView label;
AdapterImageView icon;
}
private class ViewHolder {
AdapterImageView icon;
}
}
I think it complies with all the standards for an ArrayAdapter, reusing views etc. However when opening the keyboard, the view redraws and there is significant lag on button positioning updating.
Is there anything glaringly obvious I'm missing?
Thanks in advance :)
EDIT: for extra clarity, AdapterImageView is just a class that extends ImageView and overrides requestLayout without calling super to prevent expensive redraws.
EDIT2: By contrast, this piece of code, which is older and in theory worse performing, does not lag the UI.
public class CountryAdapter extends ArrayAdapter<String> {
public CountryAdapter(Context context, int textViewResourceId, ArrayList objects) {
super(context, textViewResourceId, objects);
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.country_spinner_row, parent, false);
TextView label = (TextView) row.findViewById(R.id.spinner_countryNameRow);
label.setText(countryNameList.get(position).toString());
ImageView icon = (ImageView) row.findViewById(R.id.spinner_countryFlagRow);
String flagPath = "flag_" + countryList.optJSONObject(position).optString("countryCode").toLowerCase();
icon.setImageResource(getResources().getIdentifier(flagPath, "drawable", getPackageName()));
return row;
}
}

Listview lag when scrolling, and crash when add item

I have a custom listview with a button to add more elements
but when I add and element the app crash, but when I restart I find that the element is added, (rarely it doesn't crash)
And i
I use custom adapter
class CustomAdapter extends BaseAdapter {
ArrayList<ListItem> listItems = new ArrayList<ListItem>();
CustomAdapter(ArrayList<ListItem> list){
this.listItems = list;
}
#Override
public int getCount() {
return listItems.size();
}
#Override
public Object getItem(int position) {
return listItems.get(position).name;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int i, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.list_item,null);
TextView name = (TextView) view.findViewById(R.id.name);
TextView lastm = (TextView) view.findViewById(R.id.last);
TextView time = (TextView) view.findViewById(R.id.time);
CircleImageView pic= (CircleImageView) view.findViewById(R.id.pic);
name.setText(listItems.get(i).name);
lastm.setText(listItems.get(i).lastm);
time.setText(listItems.get(i).time);
Bitmap bmp = BitmapFactory.decodeByteArray(listItems.get(i).pic,0,listItems.get(i).pic.length);
pic.setImageBitmap(bmp);
return view;
}
}
and when I add an element the app crashs
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText editText=(EditText) mView.findViewById(R.id.name);
String name=editText.getText().toString();
boolean result=myDataBase.insertData(imageViewToByte(img),name,"no messages yet","");
if (result) {
Toast.makeText(Main2Activity.this, "Saved in DATABASE", Toast.LENGTH_SHORT).show();
viewLastData();
dialog.dismiss();
}
If your ListView lags it's because you used wrap_content for the listView's layout_height. It forces your ListView to count all the items inside and it has a huge performance impact.
So replace wrap_content by match_parent to avoid those lags.
EDIT: Use a ViewHolder pattern too in your Adapter, see this link.
Here is an example:
// ViewHolder Pattern
private static class ViewHolder {
TextView name, status;
}
#Override #NonNull
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater vi = LayoutInflater.from(getContext());
convertView = vi.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.text_name);
holder.status = (TextView) convertView.findViewById(R.id.another_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Then do the other stuff with your item
// to populate your listView
// ...
return convertView
}

How to pass the information on adapter inside a listener.

The int "pos" is not passing correctly.
How I can the to correct value when the ImageView is OnClick().
It seems when the listener activate the information is not accurate anymore.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vHolder;
if (convertView != null)
vHolder = (ViewHolder) convertView.getTag();
else {
convertView = mInflater.inflate(R.layout.car_list, null);
vHolder = new ViewHolder();
vHolder.textView = ((TextView) convertView.findViewById(R.id.tvCarListText));
vHolder.textView2 = ((TextView) convertView.findViewById(R.id.tvCarDescriptionListText));
vHolder.imageView = ((ImageView) convertView.findViewById(R.id.ivCarListMenuIcon));
vHolder.relativeLayout = ((RelativeLayout) convertView.findViewById(R.id.relativeLayout));
convertView.setTag(vHolder);
CarItem c = mItems.get(position);
final int pos = (int)c.getCarID();
vHolder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showCarEditDialog(pos); //THIS IS PASSING WRONG <--------------
}
});
}
return convertView;
}
Use ImageView.setTag() to get position of clicked row on ImageVIew click as:
vHolder.imageView.setTag(pos); // set current pos
vHolder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showCarEditDialog(Integer.parseInt(v.getTag().toString()));
}
});
you can easily do it like this :
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder vHolder;
if (convertView != null)
vHolder = (ViewHolder) convertView.getTag();
else {
convertView = mInflater.inflate(R.layout.car_list, null);
vHolder = new ViewHolder();
vHolder.textView = ((TextView) convertView.findViewById(R.id.tvCarListText));
vHolder.textView2 = ((TextView) convertView.findViewById(R.id.tvCarDescriptionListText));
vHolder.imageView = ((ImageView) convertView.findViewById(R.id.ivCarListMenuIcon));
vHolder.relativeLayout = ((RelativeLayout) convertView.findViewById(R.id.relativeLayout));
convertView.setTag(vHolder);
}
vHolder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showCarEditDialog((int)((CarItem)mItems.get(position)).getCarId);
}
});
return convertView;
}

Changing the background color of a listview row conditionally

I'm trying to change the background row color of a list view based on a parameter and on the line View v = super.getView(position, convertView, parent) its giving me the error "Cannot directly invoke the abstract method getView(int, View, ViewGroup) for the type Adapter". Here is the all of the code.
public class CustomListViewAdapter extends BaseAdapter
{
LayoutInflater inflater;
List<ListViewItem> items;
public CustomListViewAdapter(Activity context, List<ListViewItem> items) {
super();
this.items = items;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
ListViewItem item = items.get(position);
if(convertView==null)
v = inflater.inflate(R.layout.my_hospitals, null);
TextView status = (TextView) v.findViewById(R.id.status);
TextView name = (TextView) v.findViewById(R.id.name);
TextView table = (TextView) v.findViewById(R.id.id);
TextView info = (TextView) v.findViewById(R.id.info);
status.setText(item.status);
name.setText(item.name);
table.setText(item.table);
info.setText(item.info);
if (item.status == "green"){
v.setBackgroundColor(Color.GREEN);
}
return v;
}
}
Change getView()
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v=convertView;
ListViewItem item = items.get(position);
if(v==null){
v = inflater.inflate(R.layout.my_hospitals, null);
}
TextView status = (TextView) v.findViewById(R.id.status);
TextView name = (TextView) v.findViewById(R.id.name);
TextView table = (TextView) v.findViewById(R.id.id);
TextView info = (TextView) v.findViewById(R.id.info);
status.setText(item.status);
name.setText(item.name);
table.setText(item.table);
info.setText(item.info);
String state=tem.status;
if (state.equals("green"){
v.setBackgroundColor(Color.GREEN);
}
return v;
}
well like the error says you cannot do this
View v = super.getView(position, convertView, parent);
instead you should be doing
View v = convertView;
then check if v is null
if(v == null){
//get the view
}
Maybe i didn't understand well your question but instead of this
item.status == "green"
Use this
item.status.equals("green")

Categories