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);
Related
I have a RecyclerView with swiping feature to reveal a delete and edit button.
I added: adapter.notifyItemRemoved(position) and this:
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
when the revealed delete button is clicked, the animation for removing the item works and
The item is deleted from my database
BUT then the deleted item re-appears in my recyclerview. When I change activity and go back, to the activity with the recyclerview, the list that I should be seeing is good.
If I remove the "notifyItemRangeChanged" code, the list updates with the last item repeated.
I think it is my Adapter's getItemCount not properly updating. so what I tried differently was to call my method that generates the list in the first place. This did the trick BUT my remove item animation is gone now because I guess it just skips to re-generate the list....
Any ideas?
Thank you in advanced for your feedback!
****************** UPDATE - ADDING ADAPTER CLASS CODE ****************
public class RVCategoryAdapter extends RecyclerView.Adapter {
Context context;
List categoryItemList;
public RVCategoryAdapter(Context context, List<CategoryItem> categoryItemList) {
this.context = context;
this.categoryItemList = categoryItemList;
}
#NonNull
#Override
public CategoryViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).inflate(R.layout.category_item_layout, parent, false);
return new CategoryViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull CategoryViewHolder holder, final int position) {
final int categoryID;
final String categoryTitle;
Glide.with(context).load(categoryItemList.get(position).getImage()).into(holder.ivCategoryIcon);
holder.txtCatID.setText(""+categoryItemList.get(position).getCategoryID());
holder.txtCategoryTitle.setText(categoryItemList.get(position).getTitle());
holder.txtCategoryDesc.setText(categoryItemList.get(position).getDescription());
categoryID = Integer.parseInt(holder.txtCatID.getText().toString());
categoryTitle = holder.txtCategoryTitle.getText().toString();
holder.cardViewItemLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, NotesListActivity.class);
intent.putExtra("CategoryID", categoryID);
intent.putExtra("CategoryTitle", categoryTitle);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return categoryItemList.size();
}
}
In your swipe delete button click listener remove your item from the list, too.
I would suggest you to add delete function in your adapter. Then in that method delete your item from list and call notifyItemRemoved.
public void delete(int position){
categoryItemList.remove(position);
notifyItemRemoved(position);
}
I have implemented a custom adapter and listItemView. The adapter sets an onlclick listener to a button that is on the listItemView. The onclick listener simply calls a private method I have in the adapter and passes it the position of the item to be removed. I know the position is correct because the database removes the proper item. I have found similar questions but have not been able to adapt the answers to work for me. Ideas and thoughts are greatly appreciated. Thanks.
Here is the full adapter class
public class FoodListAdapter extends ArrayAdapter<FoodListItem> {
//private
private int type;
public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects) {
super(context, 0, _objects);
type = 0;
}
public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects, int _type) {
super(context, 0, _objects);
type = _type;
}
#Override
public View getView(int position, View reusableView, ViewGroup parent)
{
//Cast the reusable view to a listAdpaterItemView
FoodListItemView listItemView = (FoodListItemView) reusableView;
//Check if the listAdapterItem is null
if(listItemView == null)
{
//If it is null, then create a view.
listItemView = FoodListItemView.inflate(parent, this, type);
}
if (type == 2)
{
Button deleteButton = (Button) listItemView.findViewById(R.id.listItemViewDeleteBTN);
deleteButton.setTag(new Integer(position));
}
//Now we need to set the view to display the data.
listItemView.setData(getItem(position));
return listItemView;
}
}
Here is a portion of my code used in fragment. Note that I have a private variable decalred in the class for listAdapter, though I don't think I need that.
private void displayListForDate(Calendar _date)
{
//get the list view
ListView listView = (ListView) getView().findViewById(1);
//Clear the listview by removing the listadapter and setting it to null.
//listView.setAdapter(null);
//First we must get the items.
Global global = (Global) getActivity().getApplicationContext();
DietSQLiteHelper database = global.getDatabase();
//Create a list to hold the items we ate. This list will then be added to the listView.
final ArrayList<FoodListItem> consumedList;
//Add the items to the array.
consumedList = database.getConsumed(_date.getTimeInMillis());
//Create an adapter to be used by the listView
listAdapter = new FoodListAdapter(getActivity().getBaseContext(), consumedList, 2);
//Add the adapter to the listView.
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
consumedList.remove(position);
listAdapter.notifyDataSetChanged();
}
});
}
If you didn't implement "equals" method of FoodListItem, try to implements it.
I would suggest,
that you just update the underlying data, in your case its ArrayList<FoodItems>.
In your Adapter make this simple method and change :
private List<FoodListItem> myList = new ArrayList<FoodListItem>();
public FoodListAdapter(Context context, List<FoodListItem> myList) {
super(context, 0, myList);
type = 0;
this.myList = myList;
}
public FoodListAdapter(Context context, List<FoodListItem> myList, int _type) {
super(context, 0, myList);
type = _type;
this.myList = myList;
}
// Also update your getView() method to use myList!
#Override
public View getView(int position, View reusableView, ViewGroup parent)
{
...
listItemView.setData(myList.get(position));
public void removeItem(int positio){
if(myList != null){
myList.remove(position);
}
}
And then in class, you are creating the adapter (Activity/Fragment), just call the method.
// Update the underlying ArrayAdapter
adapter.removeItem(position);
// Notify the adapter, the data has changed
adapter.notifyDataSetChanged();
Also, you shouldnt open connection to your SQLiteDatabase on UI thread, because you are blocking it. You never know, how fast is the reading from disk going to be. If it takes too long, user can think, that your application froze and therefore, he leaves, which you dont want. I would suggest to use AsyncTask, you will find a lot of examples.
I went through and cleaned up my code and it now works, here is the working code. I really don't know exactly the difference other than I updated the IDs that I was using to assign and get views. If anyone can explain the cause for the issue I was having I would appreciate it.
Here is the snippet from my fragment where I create the list view and assign an adapter.
private void displayListForDate(Calendar _date)
{
//get the list view
ListView listView = (ListView) getView().findViewById(R.id.listView);
//Clear the listview by removing the listadapter and setting it to null.
//listView.setAdapter(null);
//First we must get the items.
Global global = (Global) getActivity().getApplicationContext();
DietSQLiteHelper database = global.getDatabase();
//Create a list to hold the items we ate. This list will then be added to the listView.
ArrayList<FoodListItem> consumedList;
//Add the items to the array.
consumedList = database.getConsumed(_date.getTimeInMillis());
//Create an adapter to be used by the listView
listAdapter = new FoodListAdapter(getActivity().getBaseContext(), consumedList, 2);
//Add the adapter to the listView.
listView.setAdapter(listAdapter);
}
and here is my adapter class.
public class FoodListAdapter extends ArrayAdapter<FoodListItem>
{
//private
private int type;
public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects) {
super(context, 0, _objects);
type = 0;
}
public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects, int _type) {
super(context, 0, _objects);
type = _type;
}
#Override
public View getView(int position, View reusableView, ViewGroup parent)
{
//Cast the reusable view to a listAdpaterItemView
FoodListItemView listItemView = (FoodListItemView) reusableView;
//Check if the listAdapterItem is null
if(listItemView == null)
{
//If it is null, then create a view.
listItemView = FoodListItemView.inflate(parent, type);
}
if (type == 2)
{
Button deleteButton = (Button) listItemView.findViewById(R.id.listItemViewDeleteBTN);
deleteButton.setTag(new Integer(position));
deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Integer tag = (Integer) view.getTag();
deleteItem(tag.intValue());
}
});
}
//Now we need to set the view to display the data.
listItemView.setData(getItem(position));
return listItemView;
}
private void deleteItem(int position)
{
FoodListItem item = getItem(position);
Global global = (Global) getContext().getApplicationContext();
DietSQLiteHelper database = global.getDatabase();
database.removeConsumed(item.getID());
remove(getItem(position));
}
}
So I have a listview that I want to add checkboxes to.
lv = (ListView)findViewById(R.id.list);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, listItems);
lv.setAdapter(adapter);
lv.setItemsCanFocus(true);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
This works and the checkboxes show up. Then I have my setOnItemClickListener() for my listview because the user needs to select an item, then the next acitivty will be launched
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id)
{
Intent components = new Intent();
components.setClass(context, ComponentsActivity.class);
components.putExtra("studyID", studyID);
components.putExtra("studyName", studyName);
startActivity(components);
}
});
However, I want to add a checkbox so that the user can tick that item in the listview to perform other actions. The problem is I can't differentiate the events. When I click on the checkbox, it gets checked but then the list item also gets selected and the new activity starts. I only want the checkbox to be affected when they click on it, not have it launch the new acitivty. I know you can also just create your own adapter but why bother if I can make a checkbox in 2 lines of code. Any suggestions? I just want to be able to check the textbox and get the id of the checked items.
I never managed to find anything for what I was looking for so I bit the bullet and decided to learn how to make my own custom adapter class. Here is my code if anybody ever runs into this problem. This adapter class is for a listview with text(TextView) and a checkbox.
public class CustomAdapter extends BaseAdapter
{
ArrayList<String> studies;
Context context;
LayoutInflater myInflater;
ArrayList<Boolean> positionArray;
public CustomAdapter(ArrayList<String> arr, Context c)
{
studies = arr;
context = c;
myInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
positionArray = new ArrayList<Boolean>();
for(int i = 0; i < studies.size(); ++i)
{
positionArray.add(false);
}
}
#Override
public int getCount() {
return studies.size();
}
#Override
public Object getItem(int i) {
return studies.get(i);
}
#Override
public long getItemId(int i) {
return 0;
}
public void remove(int i)
{
this.studies.remove(i);
this.positionArray.remove(i);
}
#Override
public View getView(int position, View view, ViewGroup viewGroup)
{
final int pos = position;
Holder holder = null;
//Create the views and populate it with an element from teh array
if(view == null)
view = myInflater.inflate(R.layout.custom_list_layout, viewGroup, false);//made my own layout for each listview 'cell'
holder = new Holder();
TextView study = (TextView)view.findViewById(R.id.adapterTextView);
holder.ckbox = (CheckBox)view.findViewById(R.id.adapterCheckBox);
holder.ckbox.setOnCheckedChangeListener(null);
study.setText(studies.get(position));
holder.ckbox.setFocusable(false);
//Since this method gets called whenever we scroll(view recycling), we have to re-check the checkboxes
holder.ckbox.setChecked(positionArray.get(position));
holder.ckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
//checkBoxArray[pos].setChecked(isChecked);
positionArray.set(pos, isChecked);
}
});
return view;
}
static class Holder
{
CheckBox ckbox;
}
}
Summary: I need a way to trigger my calculate() function within my main activity when an item is added or removed from my ListView
Background:
My android application fills a listview with list items. A list item contains a textview and an imagebutton (delete) that removes the item from the list on click. I use a custom adapter to keep track of changes in the list. This all works fine.
In my main acticity, some calculations take place based on the values in the list in a function called calulate(). I want to call this function whenever an item is added or deleted from the list. However, I don't know if this is possible and how to implement such a function.
I noticed that it is possible to add an observer using registerDataSetObserver() that will be notified when notifyDataSetChanged() is called. However, I'm not sure if this is what I need and how to implement this. Any help or suggestions are more than welcome.
Here is my CustomListAdapter:
public class CustomListAdapter extends BaseAdapter {
static final String TAG = "CustomListAdapter";
private Context context;
ArrayList <String> listArray;
LayoutInflater inflater;
public CustomListAdapter(Context context, List <String> inputArray) {
super();
this.context = context;
this.listArray = (ArrayList<String>) inputArray;
}
#Override
public int getCount() {
return listArray.size(); // total number of elements in the list
}
#Override
public String getItem(int i) {
return listArray.get(i); // single item in the list
}
#Override
public long getItemId(int i) {
return i; // index number
}
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
View V = convertView;
if(V == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
V = vi.inflate(R.layout.selected_drug_list_item, null);
}
//place text in textview
String listItem = listArray.get(position);
TextView textView = (TextView) V.findViewById(R.id.selectedDrugName);
textView.setText(listItem);
ImageButton deleteSelectedDrugButton = (ImageButton) V.findViewById(R.id.deleteSelectedDrugButton);
deleteSelectedDrugButton.setTag(position);
//Listener for the delete button. Deletes item from list.
deleteSelectedDrugButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//re
Integer index = (Integer) view.getTag();
listArray.remove(index.intValue());
notifyDataSetChanged();
}
});
return V;
}
public void add(String input) {
listArray.add(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
}
public void remove(String input){
listArray.remove(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
}
}
Here is how my ListView is initialized in my onCreate() method.
selectionListView = (ListView) findViewById(R.id.selectionListView);
selectionAdapter = new CustomListAdapter(this,myListItems);
selectionListView.setAdapter(selectionAdapter);
If any other code fragment is required, I'll happily provide it.
You may create Interfece that will be implemented by Your Main Activity and passed to Adapter (eg. in constructor)
public interface SomeInterface
{
public void foo();
}
Add SomeInterface object in Your Adapter
SomeInterface responder=null;
public CustomListAdapter(Context context, List <String> inputArray, SomeInterface responder) {
super();
this.context = context;
this.listArray = (ArrayList<String>) inputArray;
this.responder=responder;
}
public void add(String input) {
listArray.add(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
responder.foo();
}
public void remove(String input){
listArray.remove(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
responder.foo();
}
and implements SomeInterface in Your MainActivity
public class MainActivity extends Activity implements SomeInterface
{
...
public void foo()
{
//do whatever
}
private initializeAdapter()
{
CustomListAdapter adapter=new Adapter(this, someArray, this);
}
}
You can create a callback interface with a simple method, like stuffHappened(). Then, let your activity implement that interface. Now you can add a constructor argument which has as type the callback interface, pass the activity in, keep it as a member variable on the adapter and call the stuffHappened() method whenever you need to send feedback to your activity.
I am creating a contact list view, diplaying user name,user email and user id. Now while clicking on particular item i want to post some event to server based on the user id. How to get the user id inside the onClickItem listener, as user id is long value. i am able to get the user name that means the text but not the user id.
listView has onCLicklistener that has parameter position.If you are using arrayList to inflate ListView then you can use this positon to get corresponding object.
You can try to set the user id to tag using View.setTag and View.getTag. There are two version available choose the one you need. This way you can attach the user id as tag and then get it back.
http://developer.android.com/reference/android/view/View.html#setTag(int, java.lang.Object)
You code should look like:
view.setTag(Long.valueOf(id));
.....
onClickListener(..) {
Long id = (Long)view.getTag();
}
You should make your own bean class which contains your userid and put it in List (or ArrayList)
then create an adapter by creating a class extending ArrayAdapter (for instance) to bind your list of this bean class
register a listener either using onItemClickListener or View listener in your row if you inflate your custom layout.
get the position and use it to retrieve your userid on your bean list.
Here's my snippet
public class ListActivity extends Activity implements OnItemClickListener {
private Context context;
private RowAdapter adapter;
private ArrayList<Row> rowList = new ArrayList<Row>();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = ListActivity.this;
initRows();
adapter = new RowAdapter(context, rowList);
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
private void initRows() {
Row row = new Row(1);
rowList.add(row);
row = new Row(2);
rowList.add(row);
}
public class Row {
long userid = 0;
public Row(long userid) {
this.userid = userid;
}
public long getUserid() {
return userid;
}
public void setUserid(long userid) {
this.userid = userid;
}
}
public class RowAdapter extends ArrayAdapter<Row> {
private Context context;
public RowAdapter(Context context, ArrayList<Row> bindList) {
super(context, R.layout.row_layout, bindList);
this.context = context;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.row_layout, null);
}
//if you use some additional View you can retrieve your position using this
Button button = view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateSelected(position);
}
});
return view;
}
}
//or if you rather just listen on row click then you can retrieve your position using this
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
updateSelected(position);
}
private void updateSelected(int position) {
rowList.get(position).getUserid();
//have it your way
}
}