0

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

Mike
  • 697
  • 1
  • 9
  • 21
  • To communicate between adapter and fragment/activity, one of the ways is using Interface. You may take a look on my sample about array adapter here: http://programandroidlistview.blogspot.com/ Hope that helps! – i_A_mok Mar 08 '18 at 02:40
  • Thanks @I_A_Mok will take a look at your sample later. – Mike Mar 09 '18 at 03:20

1 Answers1

0

You are using orderList in your adapter but have you update your orderList after calculating the discount?

if you dont update the data in orderList , notifyDataSetChangeddoesnt really do anything.

hope that helps.

user456
  • 262
  • 2
  • 9
  • Yes, initially at the `totalAfterDiscount` function I has updated it by using `orderList.get(i).setOrderPrice(totalItemPrice);` After calculating and set all the new data into orderList, I called the `lvConfirmOrderAdapter.notifyDataSetChanged();` but the ListView was not updated with the latest data. I has confirmed that it already has the correct value by using `System.out.println`. – Mike Mar 02 '18 at 01:56
  • have you check if you have raised DiscountSpinnerListener event ? You need to raise DiscountSpinnerListener.onDiscountChange somehow to update your discount – user456 Mar 02 '18 at 03:21
  • Yes, I called it in class `SpinnerListener` at `onItemSelected`. That part(discount per item) is working but seems not optimised as kinda lag or something. For the discount per bill, the `TextView` is in OrderFragment, so, I don't really know how to access and update it by using setText. That's why I tried using NotifyDataSetChanged() but unfortunately it was not working. – Mike Mar 02 '18 at 03:43