本文共 7387 字,大约阅读时间需要 24 分钟。
要实现以下两个重要模块:
1.在中间大部分处展示所有食物的列表(需要一个RecyclerView) 2.需要一个购物车按钮,点击后从底部弹出购物车,显示选择的餐品列表,和总金额(需要一个实现从底部出现窗口的BottomSheetDiaLog和一个展示已选餐品列表的RecyclerView)1.所有食物列表
(1)select_food_layout.xml注意点: 1.刚上手android的可以使用constraintlayout布局,很方便‘; 2.如果是新手一定要记得起id并且要起的详细精炼,因为后面同一个activity中可能要引入多个相似的部件,很可能搞混。
(2)food_item.xml
*注意点:
1.通过在顶层标签中设置背景颜色为透明(@null)和padding建个属性,可以实现列表Item之间有间隔.(3)SelectFoodActivity.java中该列表的代码
a.首先声明它private RecyclerView foodsListView;
b.创建对应的Adapter和ViewHolder
private class MyFoodsViewHolder extends RecyclerView.ViewHolder{ private TextView foodName; ... public MyFoodsViewHolder(final View itemView){ super(itemView); //获取行中显示各种数据的控件 foodName = itemView.findViewById(R.id.foodName); ... } } private class MyFoodsAdapter extends RecyclerView.Adapter{ private List items; public MyFoodsAdapter(List items) { this.items = items; } @NonNull @Override public MyFoodsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_item_view, parent, false); MyFoodsViewHolder viewHolder = new MyFoodsViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(@NonNull final MyFoodsViewHolder holder, final int position) { //获取要绑定数据的行的控件 Food food = items.get(position); holder.foodName.setText(food.getFood_name()); byte[] image = food.getFood_image(); Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length); } @Override public int getItemCount() { return items.size(); } }
注意点: 1.ViewHolder的onCreateViewHolder中引入item布局文件; 2.Adapter只负责生成一行的item,通过回调方法来重复生成item,每个item的数据不同是通过position参数来从集合中拿取对应的对象信息,再绑定到该Item上; 3.接收到由byte数组存储的图片后用bitmap来显示到前端。
c.声明并绑定RecyclerView
foodsListView = findViewById(R.id.foods);foodsListView.setLayoutManager(new LinearLayoutManager(getBaseContext()));foodsListView.setAdapter(new MyFoodsAdapter(foods));
2.点击购物车底部弹出购物车页面
(1)弹出界面需要使用到BottomSheetDialog: a.声明:private BottomSheetDialog bottomSheetDialog;
b.实现:其中check是购物车按钮(这里使用的是悬浮按钮)
bottomSheetDialog = new BottomSheetDialog(SelectFoodActivity.this); View view = LayoutInflater.from(this).inflate(R.layout.layout_bottom_sheet, null); bottomSheetDialog.setContentView(view); bottomSheetDialog.setCancelable(true); bottomSheetDialog.setCanceledOnTouchOutside(true); check = findViewById(R.id.check); check.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { bottomSheetDialog.show();//点击后显示该bottomSheetDialog } });
注意点: 1.很大的一个坑,不要用BottomSheetLayOut来代替BottomSheetDialog,会导致其中的列表无法显示(救命我搞了一天这个bug); 2.因为弹出的也是个页面,所以要新建个layout文件,布置这个页面,而已选择食物列表就在这个layout上面。
(2)已选择食物列表:
和全部食物列表的实现大同小异,不写了3.点击食物Item的加减按钮同步更新金额和已选择食物列表
(1)点击加减更新已选食物列表和全部食物列表的数量://点击加号,食物数量++ holder.increase.setOnClickListener(new View.OnClickListener() { @RequiresApi(api = Build.VERSION_CODES.Q) @Override public void onClick(View v) { int count = Integer.parseInt(holder.foodCount.getText().toString()); holder.foodCount.setText(String.valueOf(count + 1)); Food food = foods.get(position); if(count == 0){ //该行食物数量为1 food.setCount(1); //增加一行已选择食物 selectedFoods.add(food); selectedFoodsListView.getAdapter().notifyDataSetChanged(); Log.e(THIS, "增加了:" + food.getFood_name()); print(selectedFoods); }else { //不新增,覆盖该位置的原数量值 selectedFoods.remove(food); food.setCount(count + 1); selectedFoods.add(food); selectedFoodsListView.getAdapter().notifyItemChanged(position); Log.e(THIS, "增加了:" + food.getFood_name()); print(selectedFoods); } total = BigDecimal.valueOf(Double.parseDouble(total.toString())).add(food.getFood_price()); refresh(total); } });
//点击减号,食物数量-- holder.decrease.setOnClickListener(new View.OnClickListener() { @RequiresApi(api = Build.VERSION_CODES.Q) @Override public void onClick(View v) { int count = Integer.parseInt(holder.foodCount.getText().toString()); Food food = foods.get(position); //不让0有可乘之机,别把重复的抽出放外面! if(count == 1){ Log.e(THIS, "减少了:" + food.getFood_name()); selectedFoods.remove(food); selectedFoodsListView.getAdapter().notifyDataSetChanged(); food.setCount(count - 1); holder.foodCount.setText(String.valueOf(count - 1)); total = BigDecimal.valueOf(Double.parseDouble(total.toString())).subtract(food.getFood_price()); refresh(total); }else if(count > 1){ Log.e(THIS, "减少了:" + food.getFood_name()); selectedFoods.remove(food); food.setCount(count - 1); selectedFoods.add(food); selectedFoodsListView.getAdapter().notifyItemChanged(position); print(selectedFoods); holder.foodCount.setText(String.valueOf(count - 1)); total = BigDecimal.valueOf(Double.parseDouble(total.toString())).subtract(food.getFood_price()); refresh(total); } } });
(2)点击加减同步总金额:通知已选餐品列表的时候通知该列表即可,但是总金额怎么整呢?实时setText?事实证明就算你set了页面是不刷新的等于白set,所以用Handler实现,在onCreate中声明实现该handler:
refreshHandler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 0) { totalPrice.setText(String.valueOf(total)); //View.ininvalidate() sendEmptyMessageDelayed(0, 1000); } } };
在每次需要更新总金额的时候调用:
refreshHandler.sendEmptyMessageDelayed(0, 1000);
1.试图将值放到一个空部件上:大部分是获取该部件的时候没获取对,要么id没写对,要么view.findViewById的view不是存在这个部件的view。
2.使用了通知RecylcerView更新的方法但是不更新:首先检测数据集是否更新,没问题了再检查其他原因。大部分是因为你把对象列表的引用指向了别处,原本和列表绑定的内存块在角落看着你不敢说话,例如list = newData;不可以这样,需要removeAll(list),addAll(newData)。再不然可能是特殊情况,比如我遇到的bottomSheetLayout遇到RecyclerView打架问题。如果你和我一样是初学者的话,最好自己多看博客和书自己改编实现各种功能,粘代码的话永远学不到自己肚子里,过程虽然痛苦但是结果开心呀,一步一步来,一点点改bug,慢慢滴用的多了就懂了,页面就不放了,是毕设内容~
转载地址:http://pwcl.baihongyu.com/