I have a price TextView
in my OrderFragment
which I would like to update onItemSelected
of discount per item and discount per bill Spinner
. I tried using notifyDataSetChanged
on my ArrayList
once I had change the price of my items but it did not update my ListView
. The notifyDataSetChanged
is working fine when I use it in different fragment for add and removing element from my ArrayList
but updating price on the ArrayList
for this doesn't seems to be working.
For update my discount per bill, I refer to various question but it doesn't seems to get it working : notifyDataSetChange not working from custom adapter, Android: notifyDataSetChanged(); not working, Android ListView not refreshing after notifyDataSetChanged and others also. Then I tried changing the TextView
from my Fragment
using ListView.getChildAt()
but it is not working due to the ListView
only loads the visible rows so, other rows that are not visible are not updated.
As for discount per item, I had it working but by using 2 Callback
which seems to be not efficient.
OrderFragment
public class OrderFragment extends Fragment {
private ArrayList<Product> orderList = new ArrayList<Product>();
private ListView lvConfirmOrder;
private ListViewOrderAdapter lvConfirmOrderAdapter;
private TextView tvTotalOrderPrice;
private int totalOrderPrice;
private Spinner sBillDiscount;
private int billDiscount = 0;
private ItemClickListener itemClickListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_order, container, false);
activity = getActivity();
db = DatabaseHelper.getInstance(activity);
Bundle bundle = new Bundle();
orderList = getArguments().getParcelableArrayList("orderList");
tvTotalOrderPrice = (TextView) view.findViewById(R.id.tvShowTotalPrice);
sBillDiscount = (Spinner) view.findViewById(R.id.sBillDiscount);
lvConfirmOrder = (ListView) view.findViewById(R.id.lvConfirmOrder);
lvConfirmOrderAdapter = new ListViewOrderAdapter(activity, orderList, new ItemClickListener() {
@Override
public void onItemClick(Product product) {
}
@Override
public void onItemClick(ProductCategory productCategory) {
}
@Override
public void onItemClick(ArrayList<Product> productList) {
tvTotalOrderPrice.setText(String.format("%d",setTotalPrice()));
}
});
lvConfirmOrder.setAdapter(lvConfirmOrderAdapter);
// Get the total price of all items
totalOrderPrice = setTotalPrice();
// Set the total price into TextView
tvTotalOrderPrice.setText(String.format("%d",totalOrderPrice));
addItemsOnSBillDiscountAndPreselect(billDiscount);
sBillDiscount.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
float spinnerValue = Float.parseFloat(adapterView.getItemAtPosition(i).toString());
float discount = 1.0f - (spinnerValue/100.0f);
totalAfterDiscount(discount);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
return view;
}
private int setTotalPrice() {
int totalPrice = 0;
for (int index = 0; index < orderList.size(); index++) {
totalPrice += orderList.get(index).getOrderPrice();
}
return totalPrice;
}
// add items into spinner
public void addItemsOnSBillDiscountAndPreselect(int discount) {
List<Integer> list = new ArrayList<Integer>();
for(int index = 0; index <= 100; index++) {
list.add(index);
}
ArrayAdapter<Integer> dataAdapter = new ArrayAdapter<Integer>(activity,
android.R.layout.simple_spinner_item, list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sBillDiscount.setAdapter(dataAdapter);
int spinnerPosition = dataAdapter.getPosition(discount);
sBillDiscount.setSelection(spinnerPosition);
}
public void totalAfterDiscount(float discount) {
float totalItemPrice[] = new float[orderList.size()];
for (int i = 0; i < orderList.size(); i++) {
totalItemPrice[i] = orderList.get(i).getOrderPrice() * discount;
}
TextView tvPrice;
for ( int i = 0 ; i < lvConfirmOrder.getCount() ; i++){
View v = getViewByPosition(i,lvConfirmOrder);
tvPrice = (TextView) v.findViewById(R.id.tvQtyPrice);
tvPrice.setText(String.valueOf(totalItemPrice[i]));
}
tvTotalOrderPrice.setText(String.format("%d",setTotalPrice()));
lvConfirmOrderAdapter.notifyDataSetChanged();
}
public View getViewByPosition(int position, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition =firstListItemPosition + listView.getChildCount() - 1;
if (position < firstListItemPosition || position > lastListItemPosition ) {
return listView.getAdapter().getView(position, listView.getChildAt(position), listView);
} else {
final int childIndex = position - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
}
ListViewOrderAdapter
public class ListViewOrderAdapter extends ArrayAdapter {
//to store the list of products
private ArrayList<Product> productList = new ArrayList<Product>();
private ItemClickListener itemClickListener;
private ViewHolder viewHolder;
private DiscountSpinnerListener discountSpinnerListener;
private static class ViewHolder {
TextView tvProductName;
TextView tvProductSku;
TextView tvPrice;
TextView tvProductNum;
TextView iAddQuantity;
TextView tvQuantity;
TextView tvQtyPrice;
TextView iMinusQuantity;
Spinner sDiscount;
TextView iDelete;
}
public ListViewOrderAdapter(Activity context, ArrayList<Product> listProduct, ItemClickListener itemClickListener){
super(context,R.layout.row_order , listProduct);
this.context = context;
this.productList = listProduct;
this.itemClickListener = itemClickListener;
}
public View getView(final int position, View view, ViewGroup parent) {
final Product product = productList.get(position);
if (view == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.row_order, null, false);
viewHolder.tvProductName = (TextView) view.findViewById(R.id.tvOrderProduct);
viewHolder.tvProductSku = (TextView) view.findViewById(R.id.tvOrderSKU);
viewHolder.tvPrice = (TextView) view.findViewById(R.id.tvProductPrice);
viewHolder.tvProductNum = (TextView) view.findViewById(R.id.tvOrderNum);
viewHolder.iAddQuantity = (TextView) view.findViewById(R.id.iAddQuantity);
viewHolder.tvQuantity = (TextView) view.findViewById(R.id.tvQuantity);
viewHolder.tvQtyPrice = (TextView) view.findViewById(R.id.tvQtyPrice);
viewHolder.iMinusQuantity = (TextView) view.findViewById(R.id.iMinusQuantity);
viewHolder.sDiscount = (Spinner) view.findViewById(R.id.sDiscount);
viewHolder.iDelete = (TextView) view.findViewById(R.id.iDelete);
// Cache the viewHolder object inside the fresh view
view.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) view.getTag();
}
//this code sets the values of the objects to values from the arrays
viewHolder.tvProductName.setText(product.getProduct_name());
viewHolder.tvProductSku.setText(product.getProduct_sku());
viewHolder.tvPrice.setText(String.valueOf(product.getPrice_max()));
String num = Integer.toString(position + 1);
viewHolder.tvProductNum.setText(num);
viewHolder.tvQuantity.setText(String.valueOf(product.getOrderQuantity()));
addItemsOnSDiscountAndPreselect(viewHolder,product.getDiscount_per_item());
viewHolder.sDiscount.setOnItemSelectedListener(new SpinnerListener(viewHolder, position, new DiscountSpinnerListener() {
@Override
public void onDiscountChange(TextView tvPrice, int pos, float price) {
if (position == pos) {
tvPrice.setText(String.valueOf(price));
itemClickListener.onItemClick(productList);
}
}
}));
font = Typeface.createFromAsset(context.getAssets(), "fonts/fontawesome-webfont.ttf" );
viewHolder.iAddQuantity.setTypeface(font);
viewHolder.iMinusQuantity.setTypeface(font);
viewHolder.iDelete.setTypeface(font);
viewHolder.iAddQuantity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
product.setOrderQuantity(product.getOrderQuantity() + 1);
product.setOrderPrice(product.getOrderQuantity() * product.getPrice_max());
itemClickListener.onItemClick(productList);
notifyDataSetChanged();
}
});
viewHolder.iMinusQuantity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
product.setOrderQuantity(product.getOrderQuantity() - 1);
product.setOrderPrice(product.getOrderQuantity() * product.getPrice_max());
if (product.getOrderQuantity() == 0) {
createAndShowAlertDialog(position, productList);
} else {
itemClickListener.onItemClick(productList);
notifyDataSetChanged();
}
}
});
viewHolder.iDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createAndShowAlertDialog(position, productList);
notifyDataSetChanged();
}
});
return view;
}
private void createAndShowAlertDialog(final int position, final ArrayList<Product> productList) {
AlertDialog.Builder builder = new AlertDialog.Builder(context,R.style.MyDialogTheme);
builder.setTitle("Are you sure you want to delete " + productList.get(position).getProduct_name());
builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
productList.remove(position);
itemClickListener.onItemClick(productList);
notifyDataSetChanged();
dialog.dismiss();
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
productList.get(position).setOrderQuantity(1);
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
// add items into spinner
public void addItemsOnSDiscountAndPreselect(ViewHolder viewHolder, int discount) {
List<Integer> list = new ArrayList<Integer>();
for(int index = 0; index <= 100; index++) {
list.add(index);
}
ArrayAdapter<Integer> dataAdapter = new ArrayAdapter<Integer>(context,
android.R.layout.simple_spinner_item, list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
viewHolder.sDiscount.setAdapter(dataAdapter);
int spinnerPosition = dataAdapter.getPosition(discount);
viewHolder.sDiscount.setSelection(spinnerPosition);
}
private class SpinnerListener implements AdapterView.OnItemSelectedListener {
private int mSpinnerPosition;
private DiscountSpinnerListener discountSpinnerListener;
private ViewHolder viewHolder;
public SpinnerListener(ViewHolder viewHolder, int spinnerPosition, DiscountSpinnerListener discountSpinnerListener) {
mSpinnerPosition = spinnerPosition;
this.discountSpinnerListener = discountSpinnerListener;
this.viewHolder = viewHolder;
}
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
float spinnerValue = Float.parseFloat(arg0.getItemAtPosition(arg2).toString());
float discount = 1.0f - (spinnerValue/100.0f);
float totalItemPrice = productList.get(mSpinnerPosition).getPrice_max() * productList.get(mSpinnerPosition).getOrderQuantity() * discount;
productList.get(mSpinnerPosition).setOrderPrice(totalItemPrice);
productList.get(mSpinnerPosition).setDiscount_per_item(Integer.parseInt(arg0.getItemAtPosition(arg2).toString()));
// Listener to set total price of an item after discount
discountSpinnerListener.onDiscountChange(viewHolder.tvQtyPrice, mSpinnerPosition, totalItemPrice);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
}
P/S: Please ignore the calculation to get the discount price first, as it does conflict against my both discount spinner(initially I was only implementing the discount per item).
This is screenshot of my app: See here