【问题标题】:Updating TextView inside ListView Adapter from a Fragment从片段更新 ListView 适配器内的 TextView
【发布时间】:2018-03-02 01:12:39
【问题描述】:

我的OrderFragment 中有一个价格TextView,我想更新onItemSelected 每件商品的折扣和每件账单的折扣Spinner。一旦我更改了商品的价格,我尝试在我的ArrayList 上使用notifyDataSetChanged,但它没有更新我的ListView。当我在不同的片段中使用notifyDataSetChanged 从我的ArrayList 添加和删除元素时,notifyDataSetChanged 工作正常,但为此更新ArrayList 的价格似乎不起作用。

为了更新我的每张账单折扣,我参考了各种问题,但它似乎无法正常工作:notifyDataSetChange not working from custom adapterAndroid: notifyDataSetChanged(); not workingAndroid ListView not refreshing after notifyDataSetChanged 和其他人。然后我尝试使用ListView.getChildAt()TextView 从我的Fragment 更改为不工作,因为ListView 只加载可见行,因此其他不可见的行不会更新。

至于每件商品的折扣,我可以使用 2 Callback,这似乎效率不高。

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:请先忽略计算以获取折扣价格,因为它确实与我的两个折扣微调器冲突(最初我只是实施每件商品的折扣)。

这是我的应用截图:See here

【问题讨论】:

  • 要在适配器和片段/活动之间进行通信,其中一种方法是使用接口。您可以在这里查看我关于阵列适配器的示例:programandroidlistview.blogspot.com 希望对您有所帮助!
  • 感谢@I_A_Mok 稍后会查看您的示例。

标签: java android listview android-fragments


【解决方案1】:

您在适配器中使用 orderList,但在计算折扣后是否更新了 orderList?

如果你不更新 orderList 中的数据,notifyDataSetChanged确实不会做任何事情。

希望有帮助。

【讨论】:

  • 是的,最初在totalAfterDiscount 函数中,我使用orderList.get(i).setOrderPrice(totalItemPrice); 对其进行了更新,在计算并将所有新数据设置到orderList 后,我​​调用了lvConfirmOrderAdapter.notifyDataSetChanged();,但ListView 没有更新最新数据。我已通过使用System.out.println 确认它已经具有正确的值。
  • 您是否检查过您是否引发了 DiscountSpinnerListener 事件?您需要以某种方式提高 DiscountSpinnerListener.onDiscountChange 以更新您的折扣
  • 是的,我在课堂SpinnerListeneronItemSelected 上调用了它。那部分(每件折扣)正在工作,但似乎没有优化为有点滞后或其他东西。对于每张账单的折扣,TextView 在 OrderFragment 中,所以,我真的不知道如何使用 setText 访问和更新它。这就是为什么我尝试使用 NotifyDataSetChanged() 但不幸的是它不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多