Update specific Items in ListView - android

I want to update (and delete) specific rows in my ListView knowing the attributes (id and name) of the object contained in the ListView. I don't know the position, therefore I can't use
View v = mListView.getChildAt()
I'm using an adapter for the List View, which is extending an ArrayAdapter of my model class.
How can I override the method getPosition ?
Here my ListViewAdapter
public class ListViewAdapter extends ArrayAdapter<ModelTimer> {
public List<ModelTimer> mListOfTimers;
private Context mContext;
public ListViewAdapter(Context context, List<ModelTimer> modelTimerList) {
super(context, R.layout.item_active_timer, modelTimerList);
this.mListOfTimers = modelTimerList;
this.mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
ModelTimer modelTimer = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder holder;// view lookup cache stored in tag
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.item_active_timer, parent, false);
holder.tvTime = (TextView) convertView.findViewById(R.id.active_timer_timeLeft);
holder.tvTitle = (TextView) convertView.findViewById(R.id.active_timer_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Populate the data into the template view using the data object
holder.tvTime.setText(modelTimer.expirationTime);
holder.tvTitle.setText(modelTimer.name);
// Return the completed view to render on screen
return convertView;
}
#Override
public int getPosition(ModelTimer item) {
return super.getPosition(item);
}
// View lookup cache
public class ViewHolder {
TextView tvTitle;
TextView tvTime;
}
}

Not the best way to do it, but look this code:
#Override
public int getPosition(ModelTimer item) {
int pos = -1;
for(int i = 0; i < mListOfTimers.size(); i++ )
if(mListOfTimers.name.equals(item.name) // and check id
pos = i;
return pos;
}

Related

Using holder for textview in listview

I'm implementing a ListView with 2 TextViews in it. The first TextView is the name of the product that I'm populating from a query. When I touch any item in the ListView a Dialog appears. When I confirm the Dialog I would like to change the second TextView text to string but whenever I do so every second Textview text changes. For example, if I have 3 items in list view and I click the first one only that item's text view should change instead of all three.
This is my base adapter code:
public class StrengthAdapter extends BaseAdapter {
private ArrayList<Strengths> list;
private LayoutInflater layoutInflater;
private static HashMap<Integer, String> selectedStrengthsMap = new HashMap<Integer, String>();
private String testing;
public StrengthAdapter(Context context, ArrayList<Strengths> list, String test) {
this.list = list;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.testing = test;
//HashMap<Integer, String> issuesStrengthsbrandNameIDMap = context
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null){
viewHolder = new ViewHolder();
//viewHolder.position = position;
convertView = layoutInflater.inflate(R.layout.strengthslistview, null);
viewHolder.strengthCheckBox = (TextView) convertView.findViewById(R.id.strengthsCheckBox);
viewHolder.chip = convertView.findViewById(R.id.chip);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.strengthCheckBox.setText(((Strengths) list.get(position)).getStrength_title());
viewHolder.chip.setText(testing);
//viewHolder.position = position;
return convertView;
}
public static HashMap<Integer, String> sendSelectedStrengthMap(){
return selectedStrengthsMap;
}
static class ViewHolder {
TextView strengthCheckBox;
TextView chip;
//int position;
}
}
This is how my I set my adapter initially:
strengthListView.setAdapter(new StrengthAdapter(StrengthOfDemandsView.this, strengthsList, "TEST"));
and this is how I set my adapter after closing the dialog:
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
strengthListView.setAdapter(new StrengthAdapter(StrengthOfDemandsView.this, strengthsList, "TEST123"));
}
});
You need to handle clicks inside of your adapter and not setting adapter every time click happens. It have to look like this:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null){
viewHolder = new ViewHolder();
//viewHolder.position = position;
convertView = layoutInflater.inflate(R.layout.strengthslistview, null);
viewHolder.strengthCheckBox = (TextView) convertView.findViewById(R.id.strengthsCheckBox);
viewHolder.chip = convertView.findViewById(R.id.chip);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.strengthCheckBox.setText(((Strengths) list.get(position)).getStrength_title());
convertView.setOnClickListener(
// show dialog here and then in positiveButton callback call
//viewHolder.chip.setText(testing);
);
return convertView;
}
First of all inflate your layout before creation of holder.
Then you need to define onclick behavior by implementing onclicklistener. I updated your getView method please implement this as follows:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null){
convertView = layoutInflater.inflate(R.layout.strengthslistview, null);
viewHolder = new ViewHolder();
//viewHolder.position = position;
viewHolder.strengthCheckBox = (TextView) convertView.findViewById(R.id.strengthsCheckBox);
viewHolder.chip = convertView.findViewById(R.id.chip);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.strengthCheckBox.setText(((Strengths) list.get(position)).getStrength_title());
viewHolder.chip.setText(testing);
//viewHolder.position = position;
convertView.setOnClickListener(
//you can do your job here what u want to do by clicking specific row
);
return convertView;
}
Also write your functionalities in the block I mentioned above in comments.

ListView Custom Adapter repeat items

Whats wrong with this adapter, when i scroll down i see repeated rows at the bottom and then when scroll up again i see also repeated rows at the top that were not exist before, and the rest of Data items does not appear
the adapter:
public class ClassesListViewAdapter extends BaseAdapter {
private Context mContext;
ArrayList<String> Data = new ArrayList<>();
public ClassesListViewAdapter(Context context, ArrayList<String> data) {
Data = data;
mContext = context;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return Data.size();
}
private class ViewHolder{
TextView ClassDataTV;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
holder.ClassDataTV.setText(Data.get(position));
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
return convertView;
}
}
and here how i use it:
ArrayList<String> v = new ArrayList<>();
v.add("AAAAAAA");
v.add("WWWWWwW");
v.add("VVVVVVV");
v.add("SSSSSSSSS");
v.add("QQQQQQQQQ");
v.add("YYYYYYYY");
v.add("TTTTTTT");
v.add("UUUUUUUUUU");
v.add("zzzzzzzzzzzz");
v.add("CCCCCCCCCC");
v.add("HHHHHHHHHHH");
v.add("IIIIIIIIII");
v.add("PPPPPPPPP");
mListView.setAdapter(new ClassesListViewAdapter(getActivity(), v));
Put following part of your code outside if-block and it will be fixed :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
// initialize your view here
holder.ClassDataTV.setText(Data.get(position));
return convertView;
}
The logic behind ViewHolder pattern tells that you should do it in this way. when you scroll some of reference will not created again and else block called so this cause your list not updated as you expected.

Not able to remove item at particular index from array adapter

i am not able to remove item from arraylist at particular index.
When i am trying to remove item then it is remove from bottom only.
private ArrayList<myproduct> values;
public View getView(final int position, final View convertView,
ViewGroup parent) {
final ViewHolder holder;
View v = convertView;
if (v == null) {
final LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row_favourite, parent, false);
holder = new ViewHolder();
holder.btnaddcollection = (Button) v
.findViewById(R.id.btnaddcollection);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
homeproduct mhomeproduct = values.get(position);
holder.btnaddcollection.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
values.remove(position);
}
});
return v;
}
static class ViewHolder {
public Button btnaddcollection;
}
From above code when i am trying to remove then it is start from bottom to remove .
How can i start to remove item from top with particular position.?
Call notifyDataSetChanged() after you remove the item.
This 'will say' to adapter: "Eh!! data was changed!"

Listview: Only one list item with multiple textviews

I need to show multiple text views in only one list item and the rest of the list view items will have just one textview.
How do I achieve this? Any samples or tutorials you can point me at?
Thank you.
Make your own adapter:
BaseAdapter already provieds methods for working with different View types (different layout for list item cells) and to effektivly recycle views:
getViewTypeCount(): The count of how many different Views (layouts) are present.
getItemViewType(): Returns a integer to identify the view type of the item in the cell. Note the internally BaseAdapter implementation uses an array. Therefore your values returned here must be from 0 to n. You are not allowed to skip indexes.
public class MyAdapter extends BaseAdapter {
private final int VIEW_TYPE_NORMAL = 0;
private final int VIEW_TYPE_4_TEXTS = 1;
/**
* The inflater for
*/
protected LayoutInflater inflater;
protected Context context;
public MyAdapter(Context context) {
this.context = context;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getViewTypeCount() {
// There are two view types
return 2;
}
#Override
public int getItemViewType(int position) {
if (position == 0)
return VIEW_TYPE_4_TEXTS;
else
return VIEW_TYPE_NORMAL;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
if (convertView == null) {
convertView = newView(type, parent);
}
bindView(position, type, convertView);
return convertView;
}
#Override
public long getItemId(int position) {
return 0; // replace it with your id, if you have stable ids in your
// adapter
}
/** Inflates the correct view accorind the view type **/
public View newView(int type, ViewGroup parent) {
if (VIEW_TYPE_4_TEXTS == type) {
View view = inflater.inflate(R.layout.your_layout_with_4_textviews,
parent, false);
view.setTag(new ViewHolder4TextViews(view)); // ViewHolder pattern
return view;
}
// Otherwise its a normal item with VIEW_TYPE_NORMAL
View view = inflater
.inflate(R.layout.your_normal_layout, parent, false);
view.setTag(new NormalViewHolder(view)); // ViewHolder pattern
return view;
}
/** Bind the data for the specified {#code position} to the {#code view}. */
public void bindView(int position, int type, View view) {
if (VIEW_TYPE_4_TEXTS == type) {
// set the 4 text view values
ViewHolder4TextViews holder = (ViewHolder4TextViews) view.getTag();
holder.textview1.setText("...");
holder.textview2.setText("...");
holder.textview3.setText("...");
holder.textview4.setText("...");
} else {
// VIEW_TYPE_NORMAL
NormalViewHolder holder = (NormalViewHolder) view.getTag();
holder.textview.setText("...");
}
}
}
Use a custom adapter for you list and edit the getView function:
public class MyListAdapter extends BaseAdapter {
[...]
#Override
public View getView(int position, View view, ViewGroup parentView) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(position < 1) {
/* Inflate a layout with 4 textview */
view = inflater.inflate(R.layout.your_4_textview_layout, parentView, false);
} else {
/* Inflate a layout with 1 textview */
view = inflater.inflate(R.layout.your_1_textview_layout, parentView, false);
}
return view;
}
[...]
}
Take care about pass Context context to MyListAdapter in constructor like this answer
You can make changes in your adapter...some thing like this.
#position 1: "blank" view will be diplayed
#rest positions: "triplistrow" will bw displayed
#Override
public View getView(final int position, View convertView, final ViewGroup parent)
{
View rowView = convertView;
if(position !=1)
{
if (rowView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.triplistrow, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.no = (TextView) rowView.findViewById(R.id.TVTripNo);
viewHolder.name = (TextView) rowView.findViewById(R.id.TVTripName);
viewHolder.date = (TextView) rowView.findViewById(R.id.TVTripDate);
rowView.setTag(viewHolder);
}
}
else
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.triplistrow, null);
ViewHolder viewHolder = new ViewHolder();
rowView.setTag(viewHolder);
}
if(position!=1)
{
final ViewHolder holder = (ViewHolder) rowView.getTag();
holder.no.setText(String.valueOf(position+1));
holder.name.setText(values.get(position).name);
holder.date.setText(values.get(position).fromdate + " to " + values.get(position).tilldate);
}else
{
}
return rowView;
}

Custom ListView doesn't save it's state

I was using standart android ListView with simle_list_item_multiple_choice item layout and custom adapter. It saved it's stated on pause and restored on resume. But after few days of working on I've implemented SectionIndexer, StickyListHeadersAdapter interface within my adapter and changed ListView to StickyListHeadersListView from this library. Also there were other changes in application but these are only attached to ListView. However now when my application resumes working listview is coming scrolled to begining and with all items unchecked. I've tryed to remove SectionIndexer interface and sticky headers support but it had no effect. Maybe there is some hidden options of listview which I need to enable?
(tried saveState property - no effect)
public class WordAdapter extends ArrayAdapter<Word> implements SectionIndexer, StickyListHeadersAdapter{
// -----------------------------------------------------------------------
//
// Fields
//
// -----------------------------------------------------------------------
private int mResID;
private List<Word> mList;
private String[] mSectionNames;
private StickyListHeadersListView mListView;
private int[] mSectionIndexes;
private boolean mHeadersEnabled;
// -----------------------------------------------------------------------
//
// Constructor
//
// -----------------------------------------------------------------------
public WordAdapter(Context context, StickyListHeadersListView listView, int resID, List<Word> list, String[] sectionNames, int[] sectionIndexes, boolean enableHeaders) {
super(context, resID, list);
mResID = resID;
mList = list;
mListView = listView;
mSectionIndexes = sectionIndexes;
mSectionNames = sectionNames;
mHeadersEnabled = enableHeaders;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(mResID, parent, false);
holder = new ViewHolder();
holder.root = convertView;
holder.textView = (TextView) convertView.findViewById(android.R.id.text1);
holder.checkBox = (CheckBox) convertView.findViewById(android.R.id.checkbox);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
holder.textView.setText(getItem(position).getValue());
if(mListView.isItemChecked(position))
holder.root.setBackgroundColor(getContext().getResources().getColor(R.color.highlight));
else
holder.root.setBackgroundColor(getContext().getResources().getColor(android.R.color.transparent));
return convertView;
}
#Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
if(!mHeadersEnabled)
return new View(getContext());
HeaderViewHolder holder;
if (convertView == null) {
holder = new HeaderViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_header, parent, false);
holder.labelView = (TextView) convertView.findViewById(R.id.list_item_header_label);
convertView.setTag(holder);
} else {
holder = (HeaderViewHolder) convertView.getTag();
}
String label;
if(mSectionNames != null){
label = mSectionNames[getSectionForPosition(position)];
holder.labelView.setText(label);
}
return convertView;
}
#Override
public long getHeaderId(int position) {
long result = getSectionForPosition(position);
return result;
}
#Override
public int getPositionForSection(int section) {
return (mSectionIndexes == null || section < 0 ) ? 0 : (section == mSectionIndexes.length ? mList.size():mSectionIndexes[section]);
}
#Override
public int getSectionForPosition(int position) {
if(mSectionIndexes != null && position >= mSectionIndexes[0]) {
for(int i = 0; i < mSectionIndexes.length; ++i)
if(position < mSectionIndexes[i])
return i-1;
return (mSectionIndexes.length - 1);
}
return 0;
}
#Override
public Object[] getSections() {
return mSectionNames == null ? new Object[0] : mSectionNames;
}
// -------------------------------------------------------------------------------
//
// Internal classes
//
// -------------------------------------------------------------------------------
private static class ViewHolder {
public View root;
public TextView textView;
public CheckBox checkBox;
}
private static class HeaderViewHolder {
public TextView labelView;
}
Here is adapter code.

Categories

Resources