Android ListView items displayed in wrong order - android

I am having an issue updating the ListView in my Android application. I have searched for the solution and read multiple answers but none solved my issue:
android-listview-repeating-old-data-after-refresh
android-requestlayout-improperly-called
android-listview-not-refreshing-after-notifydatasetchanged
android-listview-getview-being-called-multiple-times-on-unobservable-views
Issue
I have a listview with 2 items displayed like this:
Item 1 (position 0)
Item 2 (position 1)
After reloading the data from the source I get the same 2 items, but in the listview it is displayed like this:
Item 2 (position 0)
Item 2 (position 1)
However, when I click on the position 0 in new list it shows correct data of Item 1 (click on position 1 it also shows correct data of Item 2).
The problem is that it displays Item 2 on position 0 and on position 1 (twice).
Here is the code where list is updated and adapter is setup:
public class FishTankFragment extends DeviceFragment {
...
private final List<FishTankStatus.Schedule> schedulesList = new ArrayList<>();
private ScheduleAdapter scheduleAdapter;
...
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
scheduleAdapter = new ScheduleAdapter(view.getContext(), schedulesList);
screenBinding.lvSchedules.setAdapter(scheduleAdapter);
screenBinding.lvSchedules.setOnItemClickListener((parent, view1, position, id) -> {
new ScheduleItemClickListener(this.getContext(), schedulesList.get(position), position);
});
...
}
#Override
public <T> void onResponse(T responseObject) {
...
schedulesList.clear();
schedulesList.addAll(data.getSchedules());
scheduleAdapter.notifyDataSetChanged();
...
}
Here is Adapter code:
public class ScheduleAdapter extends BaseAdapter {
private ScheduleItemBinding itemBinding;
private final List<FishTankStatus.Schedule> schedules;
private final Context context;
public ScheduleAdapter(#NonNull Context context, #NonNull List<FishTankStatus.Schedule> objects) {
this.context = context;
schedules = objects;
}
#Override
public int getCount() {
return schedules.size();
}
#Override
public FishTankStatus.Schedule getItem(int position) {
return schedules.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
itemBinding = ScheduleItemBinding.inflate(LayoutInflater.from(context));
view = itemBinding.getRoot();
}
if (!schedules.isEmpty()) {
String start = StringUtils.printTime(schedules.get(position).getStart());
String end = StringUtils.printTime(schedules.get(position).getEnd());
itemBinding.tvScheduleStart.setText(start);
itemBinding.tvScheduleEnd.setText(end);
FishTankStatus.Schedule schedule = schedules.get(position);
for (String device : schedule.getDevices()) {
switch (device) {
case "something":
itemBinding.ivYellowlightIcon.setVisibility(View.VISIBLE);
break;
case "something 1":
itemBinding.ivBluelightIcon.setVisibility(View.VISIBLE);
break;
case "something 2":
itemBinding.ivAirIcon.setVisibility(View.VISIBLE);
}
}
if (schedules.get(position).getActive()) {
ColorStateList white = ColorStateList.valueOf(
view.getResources().getColor(R.color.white, view.getContext().getTheme()));
itemBinding.lySchedule.setBackground(ResourcesCompat.getDrawable(view.getResources(),
R.drawable.rectangle_p_light_8,
view.getContext().getTheme()));
...
}
}
return view;
}
}
ListView has width and height set to match_parent in parent ConstraintLayout where width=0dp (has parent) and height=match_parent
See the video:
screen recording
Thank you for all the help.
I debugged the app. After clearing schedulesList.clear() it contained 0 items in Fragment and also in BaseAdapter. After addAll items from the source it contained correct items in schedulesList both in Fragment and BaseAdapter.
I tried to fill the data in Adapter as separate List object using clear and addAll.

I will answer my own question for the future visitors...
Just use RecyclerView
It solved all my issues. But I still do not know why the above problem happened.

Related

Multiply recycler view and adapters

Actually I am going to ask more than one question here. Don't ban me, please, just read a full story. Let's begin. So I need to create an activity or fragment (it doesn't matter) with to parts (views) inside (top and bottom). Inside the bottom part dynamically loads buttons (sometimes 2, sometimes 30), there is a click listener on them. When a user clicks on a button, the button appears on the top part (view) and disappears on the bottom view. The buttons on the top view also have click listener and if a user clicks on a button it appears on the bottom view and disappears on a top. So this is a task. I thought how to implement it. The simplest solution that I created is: two views are recycler views with two adapters. Mm, probably it is not the best solution, I am pretty sure of it. I could implement two adapters, but I can't implement the click listener for my second adapter. It doesn't work!? I don't like this way for two reasons: 1. both adapters are the same; 2. I can't use click adapter for second adapter. Below you can find my code.
My adapter - standard adapter:
public class KeyboardAdapter extends RecyclerView.Adapter<KeyboardAdapter.KeyboardAdapterViewHolder> {
private List<String> values;
/*
* An on-click handler that we've defined to make it easy for an Activity to interface with
* our RecyclerView
*/
private final KeyboardAdapterOnClickHandler mClickHandler;
/**
* The interface that receives onClick messages.
*/
public interface KeyboardAdapterOnClickHandler {
void onClick(int position, String nameClicked);
}
/**
* Creates a SourceAdapter.
*
* #param clickHandler The on-click handler for this adapter. This single handler is called
* when an item is clicked.
*/
public KeyboardAdapter(List<String> myDataset, KeyboardAdapterOnClickHandler clickHandler) {
values = myDataset;
mClickHandler = clickHandler;
}
/**
* Cache of the children views for a forecast list item.
*/
public class KeyboardAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
// each data item is just a string in this case
private Button btnValue;
private String mName;
public View layout;
private int parentId;
private KeyboardAdapterViewHolder(View view) {
super(view);
//layout = view;
btnValue = view.findViewById(R.id.btn);
//parentId = ((View) btnValue.getParent()).getId();
// Call setOnClickListener on the view passed into the constructor (use 'this' as the OnClickListener)
view.setOnClickListener(this);
}
public void setData(String name) {
mName = name;
btnValue.setText(mName);
}
#Override
public void onClick(View view) {
int adapterPosition = getAdapterPosition();
mClickHandler.onClick(adapterPosition, mName);
}
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
#NonNull
public KeyboardAdapterViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, parent, false);
return new KeyboardAdapterViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull KeyboardAdapterViewHolder viewHolder, final int position) {
viewHolder.setData(values.get(position));
}
#Override
public int getItemCount() {
return values.size();
}
#Override
public int getItemViewType(int position) {
return 0;
}
public void remove(int position) {
values.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, values.size());
}
}
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
...
String s = "test it";
mAdapter = new KeyboardAdapter(virtualKeyboardInit(s), MainActivity.this);
recyclerView1.setAdapter(mAdapter);
// empty list just to init rv
answerList = new ArrayList<>();
mAdapter1 = new KeyboardAdapter1(answerList, MainActivity.this); // doesn't work, error message "KeyboardAdapter1.KeyboardAdapterOnClickHandler cannot be applied to MainActivity"
recyclerView2.setAdapter(mAdapter1);
}
private List<String> virtualKeyboardInit(String s) {
boolean checkBool = true;
// convert string to array and then to list
String [] strArray = s.split("(?!^)");
stringList = new ArrayList<>(Arrays.asList(strArray));
// shuffle letters in the list
long seed = System.nanoTime();
Collections.shuffle(stringList, new Random(seed));
// API 24
// /String[] strArray = Stream.of(cArray).toArray(String[]::new);
return stringList;
}
#Override
public void onClick(int position, String nameClicked) {
mAdapter.remove(position);
}
These are just a fragment of code. So, what can I do in this case? Thank you for attention and help.

Android:getting number of views in recyclerview

I am implementing recyclerview with multiple layouts.Usually we have multiple viewholders for different layouts and override other methods as per the required layout.I have successfully implemented this.But now i have a different scenario like: A recyclerview that shows some videos (say 3) then another layout(say layout x), again 3 videos and then again layout x and so on.Suppose i have 10 videos then in this case the itemcount would be 10 + 3 as 3 layout x would be displayed.But the videos are loaded while scrolling.So how can i determine the number of views to return in getItemCount();
I mean
#Override
public int getItemCount() {
return ListofVideos.size() + "WHAT??"
}
layout is like this
If all the videos are loaded at at once then it is easy to calculate the number of views like if i have 21 videos i would have total 27 views(i.e 21 videos and 6 layout X views). But when the list is loaded on scroll how can i determine the number of views?
Your Adapter is responsible to populate view so it has all views of your RecyclerView while your ListofVideos (may) have only video links.
Whenever you scroll your RecyclerView, Adapter is responsible to inflate views.
What you should do?
Create an interface
public interface BaseItem {
int ITEM_TYPE_HEADER = 0;
int ITEM_TYPE_SUB_HEADER = 1;
int ITEM_TYPE_ROW_NORMAL = 2;
int getItemType();
}
And implement this interface with your adapter's video item like
public class YourAdapterVideoItem implements BaseItem {
// rest of your code
#Override
public int getItemType() {
return ITEM_TYPE_ROW_NORMAL;
}
}
Create your adapter's header item
public class YourAdapterHeaderItem implements BaseItem {
// rest of your code
#Override
public int getItemType() {
return ITEM_TYPE_HEADER;
}
}
Update your adapter with
public class YourAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<BaseItem> items = new ArrayList<BaseItem>();
#Override
public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
BaseRecyclerViewHolder holder;
switch (viewType) {
case BaseItem.ITEM_TYPE_ROW_NORMAL:
default:
// inflate your default items
break;
case BaseItem.ITEM_TYPE_HEADER:
// inflate your default items
break;
}
return holder;
}
#Override
public void onBindViewHolder(BaseRecyclerViewHolder viewHolder, int position) {
BaseItem base = getItemAt(position);
switch (base.getItemType()) {
case BaseItem.ITEM_TYPE_HEADER:
// populate your header view
break;
case BaseItem.ITEM_TYPE_ROW_NORMAL:
// populate your actual view
break;
}
}
#Override
public int getItemCount() {
return items == null ? 0 : items.size();
}
#Override
public int getItemViewType(int position) {
return getItemAt(position).getItemType();
}
public BaseItem getItemAt(int position) {
return items == null ? null : items.get(position);
}
}
When you want to add header use YourAdapterHeaderItem for your videos use YourAdapterVideoItem.
Hope this helps
Edit
For adding headers in GridLayoutManager have a look at RecyclerView GridLayoutManager with full width header

Nested ArrayList while creating RecyclerView

I am developing an android application where i am using a RecyclerView to display a list of items.I am getting the list from server as json.So my problem is within this list i am getting another list as item.That is if my main arraylist contain title and materials, the material is another arraylist.So can you please suggest a solution to display a list within recyclerview.
The code below is my adapter
public class CurriculumAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private ArrayList<Curriculum> mArrayListCurriculum;
public CurriculumAdapter(Context mContext, ArrayList<Curriculum> mArrayListCurriculum) {
this.mContext = mContext;
this.mArrayListCurriculum = mArrayListCurriculum;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_key_features, parent,false);
return new KeyFeatureViewHolder(v);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof KeyFeatureViewHolder) {
((KeyFeatureViewHolder) holder).mTextViewFeatureTitle.setText(mArrayListCurriculum.get(position).getTitle());
}
}
#Override
public int getItemCount() {
return mArrayListCurriculum == null ? 0 : mArrayListCurriculum.size();
}
public static class KeyFeatureViewHolder extends RecyclerView.ViewHolder {
public TextView mTextViewFeatureTitle;
public KeyFeatureViewHolder(View itemView) {
super(itemView);
mTextViewFeatureTitle = (TextView) itemView.findViewById(R.id.txtFeature);
}
}
}
The code below is my fragment with dummy arraylist data
public class CourseCurriculumFragment extends Fragment {
private FragmentInterface mFragmentInterface;
private ArrayList<Curriculum> mArrayListCurriculum;
private ArrayList<Material> mArrayListMaterial;
private RecyclerView mRecyclerViewCurriculum;
private LinearLayoutManager mLinearLayoutManager;
private CurriculumAdapter mCurriculumAdapter;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_course_curriculum, container, false);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initView(view);
}
private void initView(View view) {
mArrayListMaterial = new ArrayList<>();
mArrayListCurriculum = new ArrayList<>();
populateMaterials();
populateKeyFeatures();
mRecyclerViewCurriculum = (RecyclerView) view.findViewById(R.id.recyclerViewCurriculum);
mCurriculumAdapter = new CurriculumAdapter(getActivity(), mArrayListCurriculum);
mLinearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerViewCurriculum.setLayoutManager(mLinearLayoutManager);
mRecyclerViewCurriculum.setAdapter(mCurriculumAdapter);
mRecyclerViewCurriculum.setItemAnimator(new DefaultItemAnimator());
}
private void populateMaterials() {
mArrayListMaterial.add(new Material("12:00","pdf","","Sample Text","0"));
mArrayListMaterial.add(new Material("12:00","pdf","","Sample Text","0"));
}
private void populateKeyFeatures() {
mArrayListCurriculum.add(new Curriculum("UNIT 1",mArrayListMaterial));
mArrayListCurriculum.add(new Curriculum("UNIT 2",mArrayListMaterial));
mArrayListCurriculum.add(new Curriculum("UNIT 3",mArrayListMaterial));
}
}
A bind method in a holder is a good way to pass data to it.
In your case this bind method should take in a Curriculum and a Material object as parameters.
Inside the onBindViewHolder method of the adapter, instead of reaching into the variables of the holder, you should call this bind method.
In the implementation of the method inside the you KeyFeatureViewHolder class you should use these passed parameters and display them in the appropriate UI elements.
Lastly, to get the Material object data into adapter, add ArrayList<Material> as a constructor parameter just like you did with Curriculum.
Use RecyclerView with header, title as header and materials as items of that header. Look at this example.
You need to design a custom list for yourself. For example take an object like this.
public class ListItem {
public curriculumName = null;
public materialName = null;
}
Now populate this list after you parse the JSON string. Get your first Curriculum and populate the object like this
private ArrayList<ListItem> mListItemArray = new ArrayList<ListItem> ();
for(curriculum : mArrayListCurriculum) {
ListItem mListItemHead = new ListItem();
mListItemHead.curriculumName = curriculum.getName();
// Set the header here
mListItemArray.add(mListItemHead);
for(material : curriculum.getMaterials()){
ListItem mListItem = new ListItem();
mListItem.materialName = material.getName();
// Add materials here
mListItemArray.add(mListItem);
}
}
Now, you've a list with headers and materials. When the materialName in your mListItemArray is null, it identifies that this is a header and vice versa.
Now the trick is to modify your adapter of your RecyclerView so that you can bind proper view to your items in your list.
You can find an indication from this answer on how you can achieve this desired behaviour.
Basically, the idea is to modify your getItemViewType to pass the proper view in your onBindViewHolder. Your getItemViewType might look like this.
#Override
public int getItemViewType(int position) {
if (mListItemArray.get(position).curriculumName != null) {
// This is where we'll add header.
return HEADER_VIEW;
}
return super.getItemViewType(position);
}

Android: Select ListView Item in onResume

I have an Activity that hosts multiple fragments using the actionbar's tab functionality. One of those fragments contains a ListView. Upon this tab being selected, I'd like to select a certain item.
To do this programmatically, I use the following code (where calls is the ListView)
private void selectItem(int position)
{
long itemId = calls.GetItemIdAtPosition(position);
calls.PerformItemClick(calls, position, itemId);
}
If this ListView has been rendered, and I'm calling this, no problem. However, if I call it from onResume, then the code executes but nothing is selected in the end. I figure this is because at the point where I'm calling selectItem, not all items of the ListView have been rendered yet. If however I start off a background thread, sleep for a couple hundred milliseconds, then run the same code (in the ui thread of course), everything is fine, but this is an ugly hack.
Now you might be wondering, "why isn't he using calls.setSelection"? The thing is, I'm using a custom layout that performs expansion - so I need to actually click on the item I want selected (which in turn triggers the layout expansion for the item selected). However, I can call the code that is performed on PerformItemClick directly, the results will be the same (the layout expansion isn't performed).
Isn't there any way for me to catch the "Listview has finished rendering all viewable items" point in time, and then execute my selectItem call at that point? In ASP.NET, I have an event on every UI item telling me when it is done rendering, so I do item selection at that point but I haven't found anything.
Regards
Stephan
Here's the Adapter I'm using
public class ActiveCallsAdapter: ObservableAdapter<Call>
{
public ActiveCallsAdapter(Activity activity, ObservableCollection<Call> calls)
: base(activity, calls)
{
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
var view = (convertView ?? context.LayoutInflater.Inflate(Resource.Layout.Call, parent, false)) as LinearLayout;
//View view = convertView;
//if (view == null) // no view to re-use, create new
// view = context.LayoutInflater.Inflate(Resource.Layout.Call, null);
SetTextView(view, Resource.Id.CallerName, item.CallerName);
SetTextView(view, Resource.Id.CallerNumber, item.CallerNumber);
SetTextView(view, Resource.Id.CallStatus, item.State.ToString());
SetTextView(view, Resource.Id.CallDuration, item.Duration);
return view;
}
public void Update(LinearLayout view, Call item)
{
SetTextView(view, Resource.Id.CallerName, item.CallerName);
SetTextView(view, Resource.Id.CallerNumber, item.CallerNumber);
string identifier = "callState_" + item.State.ToString();
int resourceId = Application.Context.Resources.GetIdentifier(identifier, "string", Application.Context.PackageName);
string callStateString = item.State.ToString();
if (resourceId != 0)
{
try
{
callStateString = Application.Context.Resources.GetString(resourceId);
}
catch (Exception e)
{
AndroidLogModel.Model.AddLogMessage("ActiveCallsAdapter", "Unable to find call state string with resource id " + resourceId + " state string: " + identifier, 3);
}
}
SetTextView(view, Resource.Id.CallStatus, callStateString);
//SetTextView(view, Resource.Id.CallDuration, item.Duration);
}
public void UpdateDuration(LinearLayout view, Call item)
{
SetTextView(view, Resource.Id.CallDuration, item.Duration);
}
}
And the base class of that adapter
public class ObservableAdapter<T>: BaseAdapter<T>
{
protected readonly Activity context;
protected readonly ObservableCollection<T> items;
public ObservableAdapter(Activity context, ObservableCollection<T> collection)
{
this.context = context;
this.items = collection;
//this.collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(collection_CollectionChanged);
this.items.CollectionChanged += (sender, e) => NotifyDataSetChanged();
}
void collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
NotifyDataSetChanged();
}
public override T this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
var view = (convertView ?? context.LayoutInflater.Inflate(Resource.Layout.Call, parent, false)) as LinearLayout;
// configure view here
return view;
}
protected void SetTextView(LinearLayout view, int id, string text)
{
var textView = view.FindViewById<TextView>(id);
if (textView != null)
textView.SetText(text, TextView.BufferType.Normal);
}
}
My Mono skills are limited so I don't know if I fully understood your adapter, anyway I've adapted some old code and made an adapter that expands a single item when click, also it will move the ListView in onResume to a desired position:
private static class CustomAdapter extends BaseAdapter {
// the data
private ArrayList<String> mData;
// an int pointing to a position that has an expanded layout,
// for simplicity I assume that you expand only one item(otherwise use
// an array or list)
private int mExpandedPosition = -1; // -1 meaning no expanded item
private LayoutInflater mInflater;
public CustomAdapter(Context context, ArrayList<String> items) {
mInflater = LayoutInflater.from(context);
mData = items;
}
public void setExpandedPosition(int position) {
// if the position equals mExpandedPosition then we have a click on
// the same row so simply toggle the row to be gone again
if (position == mExpandedPosition) {
mExpandedPosition = -1;
} else {
// else change position of the row that was expanded
mExpandedPosition = position;
}
// notify the adapter
notifyDataSetChanged();
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.ad_expandedelement,
parent, false);
}
((TextView) convertView.findViewById(R.id.textView1))
.setText(getItem(position));
// see if there is an expanded position and if we are at that
// position
if (mExpandedPosition != -1 && mExpandedPosition == position) {
// if yes simply expand the layout
convertView.findViewById(R.id.button1).setVisibility(
View.VISIBLE);
} else {
// this is required, we must revert any possible changes
// otherwise the recycling mechanism will hurt us
convertView.findViewById(R.id.button1).setVisibility(View.GONE);
}
return convertView;
}
}
The onListItemClick will simply be:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// set the expanded(or collapsed if it's a click on the same row that
// was previously expanded) row in the adapter
((CustomAdapter) getListView().getAdapter())
.setExpandedPosition(position);
}
and in onResume will have:
#Override
protected void onResume() {
super.onResume();
// set the position to the desired element
((CustomAdapter) getListView().getAdapter()).setExpandedPosition(15);
// set the selection to that element so we can actually see it
// this isn't required but has the advantage that it will move the
// ListView to the desired
// position if not visible
getListView().setSelection(15);
}
The R.layout.ad_expandedelement is a simple vertical LinearLayout with a TextView and an initially hidden(visibility set to gone) Button. For this Button I change the visibility to simulate expanding/collapsing a row in the ListView. You should be able to understand my code, if you want I can post on github the full sample.
While I'm not sure of the exact equivalent in C#/Mono, the Android framework provides a callback on Activity called onWindowFocusChanged() that indicates the period when the Window associated with a given Activity is visible to the user. You may have better luck waiting to call your selection method until that time, as the ListView should be measured and laid out by that point. In Java, it would be something like this:
#Override
public void onWindowFocusChanged (boolean hasFocus) {
if (hasFocus) {
selectItem(position);
}
}
You may need to have a bit more logic in there, this callback is directly associated with window focus and isn't a true lifecycle method. I can get called multiple times if you are displaying Dialogs or doing other similar operations.

How to delete a custom listview item in android?

I have a listview and a button in my layout file. I'am adding items to listview on click of that button. The listview should be empty when the activity is started but it should grow by adding the items to it.
This is my code inside onCreate() :
list = (ListView)findViewById(R.id.inverterListView);
adapter = new ArrayAdapter<String>(InverterList.this, R.layout.inverters_list_row, R.id.inverterNumberTextViewInPanelListRow);
list.setAdapter(adapter);
And here iam adding the items to listview onclick of a button.
adapter.add(inverterNo);
adapter.notifyDataSetChanged();
This works fine. Can anyone guide me to delete custom listview item ? Thanks in advance.
If you know the position of the item you can do this:
Object item = adapter.getItem(position);
adapter.remove(item);
adapter.notifyDataSetChanged();
You may write your own adapter extends BaseAdapter and implement all you need methods.
It is example of my adapter:
public class PeopleUserAdapter extends BaseAdapter
{
private List<User> users;
private int viewResourceId;
private Context context;
public PeopleUserAdapter(Context context, int viewResourceId)
{
this.context = context;
this.viewResourceId = viewResourceId;
this.users = new ArrayList<User>();
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
UserItemHolder holder;
if (convertView == null)
{
convertView = LayoutInflater.from(context).inflate(viewResourceId, parent, false);
holder = new UserItemHolder(convertView);
}
else holder = (UserItemHolder) convertView.getTag();
User user = getItem(position);
holder.name.setText("#" + user.getLogin());
return convertView;
}
#Override
public int getCount()
{
return users.size();
}
#Override
public User getItem(int position)
{
return users.get(position);
}
#Override
public long getItemId(int position)
{
return getItem(position).hashCode();
}
public void clear()
{
users.clear();
}
public void addAll(Collection<User> users)
{
this.users.addAll(users);
notifyDataSetChanged();
}
public void replace(Collection<User> users)
{
clear();
addAll(users);
}
public static PeopleUserAdapter init(Context context)
{
return new PeopleUserAdapter(context, R.layout.item_user);
}
}
adapter.remove(item) .. and then call adapter.notifyDataSetChanged();
In case you are using a custom adapter (for a custom layout listview), you will want to do this:
When your Adapter is something like:
public class YourAdapterName extends ArrayAdapter<yourObject>
then the code for deleting the selected ListView Item will be:
ListView yourListView = (ListView) findViewById(R.id.listviewid);
YourAdapterName adapter;
adapter = (YourAdapterName) yourListView.getAdapter();
yourObject theitem = adapter.getItem(position);
adapter.remove(theitem);
adapte.notifyDataSetChanged();
This is assuming you are inside an event that gives you access to the current position inside the listview. like:
public boolean onItemLongClick(AdapterView<?> parent, View strings,int position, long id)
or
public void onItemClick(AdapterView<?> arg0, View v, int position, long id)
Otherwise you will need to obtain that position some other way, like storing it (onItemClick or onItemLongClick) in a textView with Visibility.GONE, and retrieve it when clicking the button (this is silly, you can use all kinds of storage options, like global variables, database and such).
Make sure you have overridden the remove method on your custom adapter
For example if this is your add method:
#Override
public void add(String[] object) {
scoreList.add(object);
super.add(object);
}
then your remove method would look something like this:
#Override
public void remove(String[] object) {
scoreList.remove(object);
super.remove(object);
}
call the below two lines::
adapter.remove(inverterNo);
adapter.notifyDataSetChanged();
where inverterNo is your item
It easy; you only to need is: add a method public in your personalize adapter some this:
public void remove(int position) {
itemsMovieModelFiltered.remove(position);
notifyDataSetChanged();
}
Remenber, this method you must add in your personalize adapter.
Then, call this method from other
adapte=new PersonalizeListAdapter(getActivity().getApplicationContext(),
movieModelList);
adapte.remove(position);

Categories

Resources