仿京東——購物車
阿新 • • 發佈:2018-12-11
介面佈局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="9" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="40dp" android:gravity="center" android:text="購物車" android:textColor="@color/black" /> <LinearLayout android:id="@+id/cart_unlogin" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/cart_gologin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="登入" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="35dp" android:text="登入後可檢視購物車中的商品" /> </LinearLayout> <ExpandableListView android:id="@+id/cart_ex" android:layout_width="match_parent" android:layout_height="match_parent" android:groupIndicator="@null"></ExpandableListView> </LinearLayout> <LinearLayout android:id="@+id/cart_foot" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="7"> <CheckBox android:text="全選" android:id="@+id/cart_quanxuan" android:layout_width="wrap_content" android:layout_height="match_parent" /> <TextView android:layout_marginLeft="20dp" android:gravity="center_vertical" android:text="合計:¥" android:id="@+id/cart_total" android:layout_width="wrap_content" android:layout_height="match_parent" /> </LinearLayout> <TextView android:id="@+id/cart_sum" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:background="@color/cheng" android:gravity="center" android:text="去結算()" android:textColor="@color/white" /> </LinearLayout> </LinearLayout>
程式碼
public class CartFragment extends Fragment implements CartView { @BindView(R.id.cart_ex) ExpandableListView cartEx; Unbinder unbinder; @BindView(R.id.cart_unlogin) LinearLayout cartUnlogin; @BindView(R.id.cart_quanxuan) CheckBox cartQuanxuan; @BindView(R.id.cart_total) TextView cartTotal; @BindView(R.id.cart_foot) LinearLayout cartFoot; @BindView(R.id.cart_gologin) TextView cartGologin; @BindView(R.id.cart_sum) TextView cartSum; private SharedPreferences preferences; private CartPresenter presenter = new CartPresenter(this); private CartAdapter cartAdapter; private int uid; private int islogin; private List<Cart.DataBean> list = new ArrayList<>(); private int sum; private float totalPrice; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = View.inflate(getActivity(), R.layout.cart_fg, null); unbinder = ButterKnife.bind(this, view); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // presenter=new CartPresenter(this); Log.d("aaa", "重新載入了onActivityCreated"); initDialog(); } private void initDialog() { } @Override public void onGetCartSuccess(Cart cart) { final List<Cart.DataBean> data = cart.getData(); //***京東未解之謎2.使用請求資料得到的集合不行,會造成頁面資料不更新 list.clear(); list.addAll(data); if (cartAdapter == null) { cartAdapter = new CartAdapter(list); cartEx.setAdapter(cartAdapter); } else { cartAdapter.notifyDataSetChanged(); } //購物車介面的實現 //*************************************************************** cartAdapter.setOnCartListener(new CartAdapter.OnCartListener() { @Override public void onGroupChecked(int groupPosition) { boolean allCheckedOnGroup = cartAdapter.isAllCheckedOnGroup(groupPosition); cartAdapter.setGoodsCheckedOnGroup(groupPosition, !allCheckedOnGroup); cartAdapter.notifyDataSetChanged(); refreshBottom(); } @Override public void onGoodsChecked(int groupPosition, int childPosition) { cartAdapter.setGoodsChecked(groupPosition, childPosition); cartAdapter.notifyDataSetChanged(); refreshBottom(); } @Override public void onGoodsNumChang(int sellerid, int pid, int num, String selected, int groupPosition, int childPosition) { cartAdapter.setGoodsNum(groupPosition, childPosition, num); cartAdapter.notifyDataSetChanged(); refreshBottom(); //聯網更新資料 presenter.getUpdateCart(uid + "", sellerid + "", pid + "", selected, num + ""); } @Override public void onRemoveGoods(final int groupPosition, final int childPosition, final String pid) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage("刪除當前商品?"); builder.setPositiveButton("確認", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { cartAdapter.removeGoods(groupPosition, childPosition); //判斷group的長度是否為0 cartAdapter.setGroup(groupPosition); cartAdapter.notifyDataSetChanged(); refreshBottom(); //聯網刪除 presenter.deleteCart(uid, Integer.parseInt(pid)); } }); builder.setNegativeButton("取消", null); AlertDialog alertDialog = builder.create(); alertDialog.show(); } }); //************************************************************ //展開所有一級條目 for (int i = 0; i < data.size(); i++) { cartEx.expandGroup(i); } //重新整理底部 refreshBottom(); //全選反選,不能使用setOnCheckedChangeListener監聽,而要用點選監聽 cartQuanxuan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { boolean allGoodsSelected = cartAdapter.isAllGoodsSelected(); cartAdapter.setAllGoodsChecked(!allGoodsSelected); cartAdapter.notifyDataSetChanged(); //更新ui refreshBottom(); } }); } @Override public void onGetUpdateCart(UpdateCart updateCart) { String code = updateCart.getCode(); if (code.equals("0")) { Toast.makeText(getActivity(), "更新商品數量成功", Toast.LENGTH_SHORT).show(); } } @Override public void onDeleteSuccess(DeleteCart deleteCart) { String code = deleteCart.getCode(); if (code.equals("0")) { Toast.makeText(getActivity(), "刪除商品成功", Toast.LENGTH_SHORT).show(); } } @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); presenter.onDestroy(); presenter = null; } @Override public void onResume() { super.onResume(); Log.d("aaa", "onResume"); preferences = getActivity().getSharedPreferences("user", 0); presenter = new CartPresenter(this); //判斷是否已經登入 islogin = preferences.getInt("islogin", 0); uid = preferences.getInt("uid", 0); if (islogin == 1) { cartUnlogin.setVisibility(View.GONE); cartEx.setVisibility(View.VISIBLE); cartFoot.setVisibility(View.VISIBLE); //請求資料,設定二級列表介面卡 presenter.getCart(uid + ""); } else { cartUnlogin.setVisibility(View.VISIBLE); cartEx.setVisibility(View.GONE); cartFoot.setVisibility(View.GONE); } } // @OnClick({R.id.cart_gologin, R.id.cart_sum}) // public void onViewClicked() { // startActivity(new Intent(getActivity(), LoginActivity.class)); // } //當fragment隱藏狀態發生改變時回撥 @Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); //判斷是否已經登入 if (!hidden) { Log.d("aaa", "被show出來了onHiddenChanged"); } islogin = preferences.getInt("islogin", 0); uid = preferences.getInt("uid", 0); if (islogin == 1 && !hidden) { cartUnlogin.setVisibility(View.GONE); cartEx.setVisibility(View.VISIBLE); cartFoot.setVisibility(View.VISIBLE); //請求資料,設定二級列表介面卡 presenter.getCart(uid + ""); } else { cartUnlogin.setVisibility(View.VISIBLE); cartEx.setVisibility(View.GONE); cartFoot.setVisibility(View.GONE); } } // @Override // public void setUserVisibleHint(boolean isVisibleToUser) { // super.setUserVisibleHint(isVisibleToUser); // Log.d("aaa", "setUserVisibleHint"); // if (isVisibleToUser) { // Log.d("aaa", "對使用者可見了isVisibleToUser"); // presenter.getCart(uid + ""); // } // } public void refreshBottom() { //所有商品都選中,將全選按鈕選中 boolean allGoodsSelected = cartAdapter.isAllGoodsSelected(); cartQuanxuan.setChecked(allGoodsSelected); //設定所有選中商品數量 sum = cartAdapter.getSum(); cartSum.setText("去結算(" + cartAdapter.getSum() + ")"); //設定所有選中商品的總價 totalPrice = cartAdapter.getTotalPrice(); cartTotal.setText("合計:¥" + cartAdapter.getTotalPrice()); } @OnClick({R.id.cart_gologin, R.id.cart_sum}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.cart_gologin: startActivity(new Intent(getActivity(), LoginActivity.class)); break; case R.id.cart_sum: //商品數量大於0才建立訂單 int sum = cartAdapter.getSum(); if (sum > 0) { //使用rxjava過濾資料,選中的資料取出來 EventBus.getDefault().postSticky(new OrderEvent(list, totalPrice)); //使用者登入,獲得userid,sessionid userLogin(); // getActivity().startActivity(new Intent(getActivity(), CreateOrderActivity.class)); } Toast.makeText(getActivity(), "所選商品數量:" + this.sum, Toast.LENGTH_SHORT).show(); break; } } private void userLogin() { OkHttpClient client = genericClient(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(Api.url) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(client) .build(); ApiService apiService = retrofit.create(ApiService.class); String phone = "13522219872"; String pwd = "123456"; //對稱加密 String pssword = AESEncryptUtil.encrypt(pwd); Log.i("aaa", "對稱加密pssword:" + pssword); Flowable<LoginInfo> flowable = apiService.login(phone, pssword); flowable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSubscriber<LoginInfo>() { @Override public void onNext(LoginInfo loginInfo) { LoginInfo.ResultBean result = loginInfo.getResult(); int userId = result.getUserId(); String sessionId = result.getSessionId(); // getActivity().startActivity(new Intent(getActivity(), CreateOrderActivity.class)); Intent intent = new Intent(getActivity(), CreateOrderActivity.class); //正常是把登入成功後的使用者資訊儲存在SharedPreferences需要的時候取 intent.putExtra("userId", userId); intent.putExtra("sessionId", sessionId); getActivity().startActivity(intent); Log.i("aaa", "登入成功 userId:" + userId + ",登入成功sessionId:" + sessionId); // Toast.makeText(UserActivity.this, loginInfo.getMessage(), Toast.LENGTH_SHORT).show(); //放在這裡純粹為了拿到 userId,sessionId // push(token, userId, sessionId); } @Override public void onError(Throwable t) { } @Override public void onComplete() { } }); } //把請求頭新增給OkHttpClient的攔截器 public OkHttpClient genericClient() { OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { //把Request給Chain Request request = chain.request() .newBuilder() .addHeader("Content-Type", "application/x-www-form-urlencoded") .addHeader("ak", "0110010010001") .build(); return chain.proceed(request); } }) .build(); return httpClient; } }
mvp-model-CarModel
public class CartModel { public Observable<Cart> getCart(String uid){ return RetrofitUtil.getDefault().create(MyRetrofit.class).getCart(uid); } public Observable<UpdateCart> getUpdateCart(String uid,String sellerid,String pid,String selected,String num){ return RetrofitUtil.getDefault().create(MyRetrofit.class).getUpdateCart(uid,sellerid,pid,selected,num); } public Observable<DeleteCart> deleteCart(int uid,int pid){ return RetrofitUtil.getDefault().create(MyRetrofit.class).deleteCart(uid,pid); } }
mvp-presenter-CarPresenter
public class CartPresenter extends BasePresenter<CartView> {
private CartModel cartModel;
public CartPresenter(CartView view) {
super(view);
}
@Override
public void initModel() {
cartModel = new CartModel();
}
public void getCart(String uid) {
cartModel.getCart(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Cart>() {
@Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
@Override
public void onNext(Cart cart) {
view.onGetCartSuccess(cart);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
public void getUpdateCart(String uid,String sellerid,String pid,String selected,String num) {
cartModel.getUpdateCart(uid,sellerid,pid,selected,num)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<UpdateCart>() {
@Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
@Override
public void onNext(UpdateCart updateCart) {
view.onGetUpdateCart(updateCart);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
public void deleteCart(int uid,int pid) {
cartModel.deleteCart(uid,pid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<DeleteCart>() {
@Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
@Override
public void onNext(DeleteCart deleteCart) {
view.onDeleteSuccess(deleteCart);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
}
mvp-view-CarView
public interface CartView extends IView {
void onGetCartSuccess(Cart cart);
void onGetUpdateCart(UpdateCart updateCart);
void onDeleteSuccess(DeleteCart deleteCart);
}
CarAdapter
public class CartAdapter extends BaseExpandableListAdapter {
private List<Cart.DataBean> list;
private CheckBox seller_check;
private CheckBox goods_check;
private Cart.DataBean.ListBean bean;
private Context context;
public CartAdapter(List<Cart.DataBean> list) {
this.list = list;
}
@Override
public int getGroupCount() {
return list.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return list.get(groupPosition).getList().size();
}
@Override
public Object getGroup(int groupPosition) {
return list.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return list.get(groupPosition).getList().get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
context = parent.getContext();
if (convertView == null) {
convertView = View.inflate(parent.getContext(), R.layout.seller_item, null);
}
TextView seller_name = convertView.findViewById(R.id.seller_name);
seller_check = convertView.findViewById(R.id.seller_check);
//************************************group點選監聽
seller_check.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onCartListener != null) {
onCartListener.onGroupChecked(groupPosition);
}
}
});
//如果當前group中的所有商品都被選中,那就把group選中
boolean selectedOnGroup = isSelectedOnGroup(groupPosition);
seller_check.setChecked(selectedOnGroup);
seller_name.setText(list.get(groupPosition).getSellerName());
return convertView;
}
private boolean isSelectedOnGroup(int groupPosition) {
List<Cart.DataBean.ListBean> list = this.list.get(groupPosition).getList();
for (Cart.DataBean.ListBean bean : list) {
if (bean.getSelected() == 0) {
return false;
}
}
return true;
}
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(parent.getContext(), R.layout.goods_item, null);
}
bean = list.get(groupPosition).getList().get(childPosition);
SimpleDraweeView goods_img = convertView.findViewById(R.id.goods_img);
TextView goods_title = convertView.findViewById(R.id.goods_title);
TextView goods_price = convertView.findViewById(R.id.goods_price);
goods_check = convertView.findViewById(R.id.goods_check);
//處理imgurl
String imgUrl = getImgUrl(bean.getImages());
goods_img.setImageURI(Uri.parse(imgUrl));
goods_title.setText(bean.getTitle());
goods_price.setText("¥"+bean.getBargainPrice());
//根據集合資料設定複選框選中狀態
goods_check.setChecked(bean.getSelected() == 1);
//************************************
goods_check.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onCartListener != null) {
onCartListener.onGoodsChecked(groupPosition, childPosition);
}
}
});
//設定加減器監聽
AddDeleteView goods_ad = convertView.findViewById(R.id.goods_ad);
goods_ad.setOnAddDeleteViewClick(new AddDeleteView.OnAddDeleteViewClick() {
@Override
public void onNumChange(int num) {
if (onCartListener != null) {
Cart.DataBean.ListBean bean = list.get(groupPosition).getList().get(childPosition);
onCartListener.onGoodsNumChang(bean.getSellerid(), bean.getPid(), num,bean.getSelected()+"", groupPosition, childPosition);
}
}
});
//長按刪除當前條目
convertView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Cart.DataBean.ListBean bean = CartAdapter.this.list.get(groupPosition).getList().get(childPosition);
if (onCartListener!=null){
onCartListener.onRemoveGoods(groupPosition,childPosition,bean.getPid()+"");
}
return true;
}
});
goods_ad.setSum(bean.getNum());
return convertView;
}
private String getImgUrl(String images) {
int i = images.indexOf("!");
return images.substring(0, i);
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
//計算總數
public int getSum() {
int sum = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list.get(i).getList().size(); j++) {
if (list.get(i).getList().get(j).getSelected() == 1) {
int num = list.get(i).getList().get(j).getNum();
sum += num;
}
}
}
return sum;
}
//結算總價
public float getTotalPrice() {
int sum = 0;
float price = 0f;
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list.get(i).getList().size(); j++) {
if (list.get(i).getList().get(j).getSelected() == 1) {
int num = list.get(i).getList().get(j).getNum();
double bargainPrice = list.get(i).getList().get(j).getBargainPrice();
price += (float) (num * bargainPrice);
}
}
}
return price;
}
//判斷所有商品是都都被選中
public boolean isAllGoodsSelected() {
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list.get(i).getList().size(); j++) {
if (list.get(i).getList().get(j).getSelected() == 0) {
//如果有一個沒選中返回false
return false;
}
}
}
return true;
}
//改變單個group中所有商品的選中狀態
public void setGoodsCheckedOnGroup(int groupPosition, boolean groupChecked) {
List<Cart.DataBean.ListBean> list = this.list.get(groupPosition).getList();
for (Cart.DataBean.ListBean listBean : list) {
listBean.setSelected(groupChecked ? 1 : 0);
}
}
//判斷單個group中所有商品是否都被選中
public boolean isAllCheckedOnGroup(int groupPosition) {
List<Cart.DataBean.ListBean> list = this.list.get(groupPosition).getList();
for (Cart.DataBean.ListBean listBean : list) {
if (listBean.getSelected() == 0) {
return false;
}
}
return true;
}
//改變集合中所有商品的狀態
public void setAllGoodsChecked(boolean check) {
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list.get(i).getList().size(); j++) {
list.get(i).getList().get(j).setSelected(check ? 1 : 0);
}
}
}
//改變某個商品的狀態
public void setGoodsChecked(int groupPosition, int childPosition) {
//***京東未解之謎1.複用bean會造成複選框取消不了
// list.get(groupPosition).getList().get(childPosition).setSelected(bean.getSelected() == 0 ? 1 : 0);
Cart.DataBean.ListBean bean = list.get(groupPosition).getList().get(childPosition);
bean.setSelected(bean.getSelected() == 0 ? 1 : 0);
}
//修改某個商品的數量
public void setGoodsNum(int groupPosition, int childPosition, int num) {
list.get(groupPosition).getList().get(childPosition).setNum(num);
}
//從集合刪除某個商品
public void removeGoods( int groupPosition, int childPosition){
list.get(groupPosition).getList().remove(childPosition);
}
//判斷某個group長度是否為0
public void setGroup(int groupPosition){
List<Cart.DataBean.ListBean> listBeans =list.get(groupPosition).getList();
if(listBeans.size()==0){
list.remove(groupPosition);
}
}
public interface OnCartListener {
void onGroupChecked(int groupPosition);
void onGoodsChecked(int groupPosition, int childPosition);
void onGoodsNumChang(int sellerid, int pid, int num,String selected, int groupPosition, int childPosition);
void onRemoveGoods(int groupPosition, int childPosition,String pid);
}
private OnCartListener onCartListener;
public void setOnCartListener(OnCartListener onCartListener) {
this.onCartListener = onCartListener;
}
}
自定義加減器的佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:gravity="center"
android:textSize="30dp"
android:text="-"
android:id="@+id/delete"
android:layout_width="40dp"
android:layout_height="wrap_content" />
<TextView
android:gravity="center"
android:textSize="30dp"
android:text="0"
android:id="@+id/num"
android:layout_width="60dp"
android:layout_height="wrap_content" />
<TextView
android:gravity="center"
android:textSize="30dp"
android:text="+"
android:id="@+id/add"
android:layout_width="40dp"
android:layout_height="wrap_content" />
</LinearLayout>
自定義加減器
public class AddDeleteView extends LinearLayout {
private int sum = 0;
private TextView delete;
private TextView num;
private TextView add;
public AddDeleteView(Context context) {
this(context, null, 0);
}
public AddDeleteView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public AddDeleteView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(context).inflate(R.layout.adddeleteview, this);
add = findViewById(R.id.add);
delete = findViewById(R.id.delete);
num = findViewById(R.id.num);
add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sum++;
num.setText(sum + "");
if (onAddDeleteViewClick != null) {
onAddDeleteViewClick.onNumChange(sum);
}
}
});
delete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (sum > 1) {
sum--;
num.setText(sum + "");
if (onAddDeleteViewClick != null) {
onAddDeleteViewClick.onNumChange(sum);
}
}
}
});
}
public void setSum(int sum) {
this.sum = sum;
num.setText(sum + "");
}
public interface OnAddDeleteViewClick {
void onNumChange(int num);
}
private OnAddDeleteViewClick onAddDeleteViewClick;
public void setOnAddDeleteViewClick(OnAddDeleteViewClick onAddDeleteViewClick) {
this.onAddDeleteViewClick = onAddDeleteViewClick;
}
}