I call my specific ArrayAdapter from an Activity which shows a list of datasets from my database. If the user tap on an item of the ArrayAdapter it will open an extension of an AlertDialog. If the user taps on a button in this AlertDialog a dataset in the database will be deleted among others and the AlertDialog is dismiss(). Now I want to refresh the view of the ArrayAdapter.
I found solutions like
remove(position);
notifyDataSetChanged();
But where could I call this? Can I pass a boolean from the AlertDialog backwards to the ArrayAdapter if the user clicked on the specific button to say "hey adapter, please remove the current item in your list"?
here's some code:
Activity:
final ListView list = (ListView) findViewById(R.id.myList);
DBhandler db = new DBhandler (context);
list.setAdapter(new MyAdapter(context, db.getMyItems()))
MyAdapter:
public View getView(int position, View row, ViewGroup parent) {
if(row != null) {
row.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final MyDialog myDialog = new MyDialog(context, currentItem);
myDialog.show();
}
});
}
}
MyDialog:
protected void onCreate(Bundle savedInstanceState) {
Button btn_delete = (Button) findViewById(R.id.btn_delete);
btn_delete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
DBhandler db = new DBhandler (context);
db.delete(currentItem);
Toast.makeText(context, "item is deleted", Toast.LENGTH_SHORT).show();
dismiss();
}
});
}
I found also Passing Events Back to the Dialog's Host, but I don't know how I can use that for my AlertDialog...
You may call function of your custom adapter before dismissing alert dialog as
if(adapter.remove(postion)){
adapter.refreshdata();
}
and the function like
public boolean removedata(int position){
boolean isremoved = false;
// loop array data and remove specific item
// and return isRemoved value.
}
public void refreshdata(){
notifyDataSetChanged();
}
Related
Some Context: I have a Custom ArrayAdapter for a ListView that has 3 parameters Name, Edit Button, Delete Button. I have setup onClicks in the ArrayAdapter to be able to detect which profile is being clicked with the specific edit/delete button press. When the user deletes a profile I remove the profile from SQLite DB however now I've ran into the problem of trying to update the ArrayList with the removed item and notifyDataSetChanged for my ListView.
Question 1: I can't figure out if I should be doing this in the Class that is containing the ListView and ArrayList or if I should be trying to update this from the ArrayAdapter in the onClicks.
Question 2: Whatever method might be right how can I correctly update the deleted item from the ListView when the user confirms the delete in the Dialog.
Current ArrayAdapter Class
public class ListViewItemAdapter extends ArrayAdapter<ListViewItem>
{
private Context mContext;
private List<ListViewItem> list = new ArrayList<>();
private DatabaseHelper databaseHelper;
private String profileName;
public ListViewItemAdapter(#NonNull Context context, ArrayList<ListViewItem> listItem) {
super(context, 0 , listItem);
mContext = context;
list = listItem;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
if(listItem == null)
listItem = LayoutInflater.from(mContext).inflate(R.layout.custom_listview,parent,false);
final ListViewItem listViewItem = list.get(position);
//Text View Profile
final TextView name = (TextView) listItem.findViewById(R.id.textView_name);
name.setText(listViewItem.getmName());
profileName = listViewItem.getmName();
//Edit Button Profile
ImageButton image = listItem.findViewById(R.id.imageView_poster);
image.setImageResource(listViewItem.getmImageDrawable());
image.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(mContext,
"Edit Profile:" + listViewItem.getmProfile() + " Name:" + listViewItem.getmName(),
Toast.LENGTH_SHORT).show();
}
});
//Delete Button Profile **Currently Testing**
ImageButton image2 = listItem.findViewById(R.id.imageView_poster2);
image2.setImageResource(listViewItem.getmImageDrawable2());
image2.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
databaseHelper = new DatabaseHelper(getContext());
Toast.makeText(mContext,
"Delete Profile:" + listViewItem.getmProfile() + " Name:" + listViewItem.getmName(),
Toast.LENGTH_SHORT).show();
AlertDialog.Builder builder = new AlertDialog.Builder(getContext(),R.style.AlertDialogTheme);
builder.setTitle("Delete Profile?")
.setMessage("Are you sure you want to delete\n" + listViewItem.getmName())
.setPositiveButton("yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
databaseHelper.deleteRowProfile(listViewItem.getmName());
//
//This is where I'm try to update the ListView
//
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
});
return listItem;
}
}
Function in Fragment Class that Populates the ListView onViewCreated
public void getProfileList()
{
arrayList = new ArrayList<ListViewItemAdapter>();
listViewItemAdapter = new ListViewItemAdapter(getContext(),arrayList);
Cursor result = databaseHelper.getAllDataCarProfile();
if(listViewItemAdapter != null){
listViewItemAdapter.clear();
listViewItemAdapter.notifyDataSetChanged();
}
if (result.getCount() != 0)
{
while (result.moveToNext())
{
arrayList.add(new ListViewItem("CarProfile",
result.getString(0),
R.drawable.ic_edit_gray_24dp,
R.drawable.ic_delete_grey_24dp));
}
listViewItemAdapter.notifyDataSetChanged();
}
listViewCarProfile.setAdapter(listViewItemAdapter);
}
You can do this in either way . You can create a function in your adapter class and perform the clickListener on it .
deleteItem.setOnClickListener(v -> {
potsList.remove(getAdapterPosition());
notifyDataSetChanged();
}
Or in your class , when remove the item from list , don't forget to notify the adapter . One the adapter get notified , it will reflect the change on screen.
I made my own dialog box class. This class has a button to delete an item from a listview(which is the main acctivity_main.xml). When I push the delete button the item does not get deleted.
I have seen this topic Android: how to remove an item from a listView and arrayAdapter. It just appears the user does not know how to get the item index correctly, which I believe I have done correctly.
Remove ListView items in Android This one is pretty close. But in my code I created my own dialog, this one is using a positive and negative button. I am passing variables between my dialog class and to the mainActivity.
my onClickListener in OnCreate withing the MainActivity
mFoodDataAdapter = new FoodDataAdapter();
final ListView listFoodData = (ListView) findViewById(R.id.listView);
listFoodData.setAdapter(mFoodDataAdapter);
//Handle clicks on the ListView
listFoodData.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view, int whichItem, long id) {
FoodData tempFoodData = mFoodDataAdapter.getItem(whichItem);
//create a new dialog window
DialogShowFood dialog = new DialogShowFood();
// send in a reference to the note to be shown
dialog.sendFoodDataSelected(tempFoodData);
FoodDataAdapter adapter1 = new FoodDataAdapter();
/*this is where i send the data to the DialogShowFood.java*/
dialog.sendFoodDataAdapter(adapter1, whichItem);
// show the dialog window with the note in it
dialog.show(getFragmentManager(),"");
}
});
Here is my class for the dialog "DialogShowFood.java"
public class DialogShowFood extends DialogFragment {
FoodData mFood;
MainActivity.FoodDataAdapter mAdapter;
int mitemToDelete;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View dialogView = inflater.inflate(R.layout.dialog_show_food, null);
Button btnDelete = (Button) dialogView.findViewById(R.id.btnDelete);
builder.setView(dialogView).setMessage("Your food");
/*this sends the item to delete to the adapter*/
btnDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mAdapter.deleteFoodData(mitemToDelete);
dismiss();
}
});
return builder.create();
}
/*this gets the data to delete from the MainActivity*/
public void sendFoodDataAdapter(MainActivity.FoodDataAdapter adapter1, int whichItem) {
mAdapter = adapter1;
mitemToDelete = whichItem;
}
}
The function inside the adapter
/*this is the function in the base adapter to delete the item*/
public void deleteFoodData(int n){
Toast.makeText(MainActivity.this,Integer.toString(n), Toast.LENGTH_SHORT).show();
foodDataList.remove(n);
notifyDataSetChanged();
}
The Toast outputs the proper indexes of the item to delete, it just does not delete the item for some reason.
I have a delete all button and everytime it delete all item in a listview, the listview won't road but stay the same, they will reload only when I create a new item or restart this activity. I have print a log on my code and it seems that the list view reload before the delete method called. my code is this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBHelper db = new DBHelper(this);
final ListView listView = (ListView) findViewById(R.id.listView);
TextView empty = (TextView) findViewById(R.id.empty);
ArrayList<Inventory> listArray = new ArrayList<>();
listArray.clear();
listArray = db.read();
if (listArray.size() == 0) {
empty.setText("No Items");
} else {
empty.setText("");
}
ListViewAdapter customAdapter = new ListViewAdapter(listArray);
customAdapter.notifyDataSetChanged();
listView.setAdapter(customAdapter);
Button add_button = (Button) findViewById(R.id.button);
add_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addNewItem(view);
}
});
Button button_deleteAll = (Button) findViewById(R.id.button_deleteAll);
button_deleteAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
deteleAll();
DBHelper db = new DBHelper(MainActivity.this);
final ListView listView = (ListView) findViewById(R.id.listView);
TextView empty = (TextView) findViewById(R.id.empty);
ArrayList<Inventory> listArray = new ArrayList<>();
listArray.clear();
listArray = db.read();
Log.v("arraysize:", String.valueOf(listArray.size()));
if (listArray.size() == 0) {
empty.setText("No Items");
} else {
empty.setText("");
}
ListViewAdapter customAdapter = new ListViewAdapter(listArray);
customAdapter.notifyDataSetChanged();
listView.setAdapter(customAdapter);
}
});
}
The method deleteAll() deletes all the data in SQLite.
I wish to know how to reload listview after this method called, rather than reload before this method.
add the delete all method in your adapter. call the deleteAll method of your adapter whenever button was clicked. the deleteAll method would be like below:
public void setListArray(ArrayList arrayList)
{
//assuming your adapter list is named "listArray"
this.listArray = arrayList;
notifyDataSetChanged();
}
and in your button click simply write this code:
button_deleteAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//assuming your list of itames here is named "mListArray"
mListArray.clear();
adapter.setListArray(mListArray);
}
}
I guess there is no need to initialize the customAdapter again in the button OnClick method. Also no need to setAdapter again.
Try to remove these lines in the onClick method.
Hope this fixes you issue.
Just add notifyDataSetChanged(); to your Adapter, inside a Listener. For example:
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
myArrayList.remove(position);
myArrayAdapter.notifyDataSetChanged();
}
});
In here I am trying to make OnItemLongClick, I tried doing it in ListActivity before and that's working.
Now I am trying to make one inside a Fragment, but I get an error here and there, I need some advice/suggestion/answer to solve the error, or the correct way to implement the method.
In the ListActivity (working):
public class ViewData extends ListActivity implements OnItemLongClickListener {
//init controller
private DBDataSource dataSource;
//init arraylist
private ArrayList<Barang> values;
private Button delButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewdata);
dataSource = new DBDataSource(this);
// open controller
dataSource.open();
// get values
values = dataSource.getAllBarang();
// insert data to array adapter
ArrayAdapter<Barang> adapter = new ArrayAdapter<Barang>(this,
android.R.layout.simple_list_item_1, values);
// set adapter in list
setListAdapter(adapter);
// listview for set onItemLongClickListener
ListView lv = (ListView) findViewById(android.R.id.list);
lv.setOnItemLongClickListener(this);
}
//if user longclick
#Override
public boolean onItemLongClick(final AdapterView<?> adapter, View v, int pos,
final long id) {
//tampilkan alert dialog
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog_view);
dialog.setTitle("Pilih Aksi");
dialog.show();
final Barang b = (Barang) getListAdapter().getItem(pos);
delButton = (Button) dialog.findViewById(R.id.button_delete_data);
//apabila tombol delete di klik
delButton.setOnClickListener(
new OnClickListener()
{
#Override
public void onClick(View v) {
// Delete barang
dataSource.deleteBarang(b.getId());
dialog.dismiss();
finish();
startActivity(getIntent());
}
}
);
return true;
}
}
The Fragment version (still giving an error) :
public class Menu_Riwayat extends Fragment {
//init controller
private DBDataSource dataSource;
//init arraylist
private ArrayList<Investasi_DB> values;
static ListView lv;
private Button button_hapus;
static LinearLayout mLinear;
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
mLinear = (LinearLayout) inflater.inflate(R.layout.viewdata, container, false);
lv = (ListView) mLinear.findViewById(R.id.list);
dataSource = new DBDataSource(getActivity());
// open controller
dataSource.open();
// get values
values = dataSource.getAllInvestasi_DB();
// insert data to array adapter
ArrayAdapter<Investasi_DB> adapter = new ArrayAdapter<Investasi_DB>(getActivity(),
android.R.layout.simple_list_item_1, values);
// set adapter in list
lv.setAdapter(adapter);
return mLinear;
// ERROR IN THIS PART BELOW, not sure what to change "this" with
lv.setOnItemClickListener(this);
}
public boolean onItemLongClick(final AdapterView<?> adapter, View v, int pos,
final long id) {
//tampilkan alert dialog
final Dialog dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.dialog_view);
dialog.setTitle("Pilihan");
dialog.show();
// ERROR IN THIS PART BELOW, not sure how to implement "getListAdapter()" inside fragment
final Investasi_DB b = (Investasi_DB) getListAdapter().getItem(pos);
button_hapus = (Button) dialog.findViewById(R.id.button_hapus);
button_hapus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dataSource.deleteInvestasi_DB(b.getId());
dialog.dismiss();
getActivity().finish();
// ERROR IN THIS PART BELOW, the "getIntent()" part
startActivity(getIntent());
}
});
return true;
}
}
I need help to solve the error (correct way to implement it):
getListAdapter(), getIntent(), and this in lv.setOnItemClickListener(this);
EDITED PART AFTER SOME SUGGESTION :
so now i make it like this
public class Menu_Riwayat extends Fragment {
//inisialisasi kontroller
private DBDataSource dataSource;
//inisialisasi arraylist
private ArrayList<Investasi_DB> values;
static ListView lv;
private Button button_hapus;
static LinearLayout mLinear;
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
mLinear = (LinearLayout) inflater.inflate(R.layout.viewdata, container, false);
lv = (ListView) mLinear.findViewById(R.id.list);
dataSource = new DBDataSource(getActivity());
// buka kontroller
dataSource.open();
// ambil semua data barang
values = dataSource.getAllInvestasi_DB();
// masukkan data barang ke array adapter
ArrayAdapter<Investasi_DB> adapter = new ArrayAdapter<Investasi_DB>(getActivity(),
android.R.layout.simple_list_item_1, values);
// set adapter pada list
lv.setAdapter(adapter);
//lv.setOnItemLongClickListener(this);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Dialog dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.dialog_view);
dialog.setTitle("Pilihan");
dialog.show();
final Investasi_DB b = (Investasi_DB) lv.getItemAtPosition(position);
button_hapus = (Button) dialog.findViewById(R.id.button_hapus);
button_hapus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dataSource.deleteInvestasi_DB(b.getId());
dialog.dismiss();
getActivity().finish();
}
});
}
});
return mLinear;
}
its working, but the apps close itself after i click the button (i think because of getActivity().finish();), any idea about that ?
I need help to solve the error (correct way to implement it):
getListAdapter(), getIntent(), and this in
lv.setOnItemClickListener(this);
if with this you want to access a Context, you can use getActivity(). Fragment is not a Context
In setOnItemClickListener(this);, this refers to the current instance. With that line you are implying that this is also implementing the OnItemClickListener interface. Which is not true. You need yo add implement OnItemClickListener to your Fragment class.
getListAdapter():
instead of getListAdapter() you can use the ListView to retrieve the item at position, since you are already keeping a reference as member. Change
final Investasi_DB b = (Investasi_DB) getListAdapter().getItem(pos);
with
final Investasi_DB b = (Investasi_DB) lv.getItemAtPosition(pos);
why do you need this line startActivity(getIntent());?
I hope my title makes sense, basically I have a button inside a listview a layout as an adapter in a listview inside a fragment.
My problem is that my onClick method deleteQuote(View v) is not recognized when I declare it in the fragment class. It errors out something about not found in the main activity. So I transferred it to the main activity, but the problem is that I needed the view tag to get a primary key in the entry via the getTag to delete that entry in the database and in the adapter of the listview. Where should I put my onClick method where in i can still get the view tag or What is the best way to do this implementing setonclicklisteners?
Fragment class
public class QuotationList extends Fragment{
ListView lvQuotationsMotorcar;
ArrayList<Quotation> menuList_motorcar;
CustomMotorcarQuoteAdapter cmqa;
ListView lvQuotationsFire;
ArrayList<Quotation> menuList_fire;
CustomFireQuoteAdapter cfqa;
Button btnDeleteQuote_motorcar;
Spinner spQuotationType;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_online_quotation_list, container, false);
lvQuotationsMotorcar = (ListView) rootView.findViewById(R.id.lvQuotationsMotorcar);
menuList_motorcar = new ArrayList<Quotation>();
cmqa = new CustomMotorcarQuoteAdapter(getActivity(), R.layout.motorcarquotationlayout, menuList_motorcar);
lvQuotationsMotorcar.setAdapter(cmqa);
lvQuotationsFire = (ListView) rootView.findViewById(R.id.lvQuotationsFire);
menuList_fire = new ArrayList<Quotation>();
cfqa = new CustomFireQuoteAdapter(getActivity(), R.layout.firequotationlayout, menuList_fire);
lvQuotationsFire.setAdapter(cfqa);
final SQLiteDatabase mydatabase = getActivity().openOrCreateDatabase("INLIS", Context.MODE_PRIVATE, null);
spQuotationType = (Spinner) rootView.findViewById(R.id.spQuotationType);
btnDeleteQuote_motorcar = (Button) getActivity().findViewById(R.id.btnDeleteMotorcarQuote);
Cursor resultSet = mydatabase.rawQuery("Select * from QuotationMotorcar", null);
if (resultSet != null){
if (resultSet .moveToFirst()) {
while (!resultSet.isAfterLast()) {
//stuff
cmqa.add(q);
resultSet.moveToNext();
}
}
}else{
Toast.makeText(getActivity(), "No Pending Motorcar Quotations", Toast.LENGTH_LONG).show();
}
Cursor resultSet1 = mydatabase.rawQuery("Select * from QuotationFire", null);
if (resultSet1 != null){
if (resultSet1 .moveToFirst()) {
while (!resultSet1.isAfterLast()) {
//stuff
cfqa.add(q);
resultSet1.moveToNext();
}
}
}else{
Toast.makeText(getActivity(), "No Pending Fire Quotations", Toast.LENGTH_LONG).show();
}
mydatabase.close();
//more code
return rootView;
}
onClick method deleteQuote
public void deleteQuote_motorcar(final View v){
final SQLiteDatabase mydatabase = getActivity().openOrCreateDatabase("INLIS", Context.MODE_PRIVATE, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle("Warning!");
alertDialogBuilder
.setMessage("Are you sure you want to delete this quote?")
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Quotation itemToRemove = (Quotation)v.getTag();
cmqa.remove(itemToRemove);
mydatabase.execSQL("DELETE FROM QoutationMotorcar WHERE QuoteNumber =" + itemToRemove.getQuoteNumber() + "; ");
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
This works perfectly fine if it just extends an activity class. Hope someone can help. I'm really annoyed on how this onClick is not working on Fragments.
How and where can I declare my method where in it can be called properly with the view tag?
Use this declaration of OnClickListener in your custom Adapter getView method
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.your_lv_item_layout, parent, false);
view.findViewById(R.id.your_bt).setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View arg0) {
//do what ever you want
}
});
return view;
}
Instead of public void deleteQuote_motorcar(final View v)