1. 程式人生 > >購物車頁面【仿】淘寶App

購物車頁面【仿】淘寶App

首先是效果圖
這裡寫圖片描述

xml佈局檔案

activity_shopping.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/re"
        android:layout_width="match_parent"
        android:layout_height="50dp"
android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true"> <TextView android:id="@+id/back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true"
android:text="〈" android:textSize="20dp" /> <TextView android:id="@+id/shop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true"
android:text="購物車(0)" android:textSize="20dp" /> </RelativeLayout> <TextView android:id="@+id/bj" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginTop="14dp" android:text="編輯" android:textSize="20dp" /> <RelativeLayout android:id="@+id/re2" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true"> <CheckBox android:id="@+id/all" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全選" /> <TextView android:id="@+id/price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/all" android:layout_centerHorizontal="true" android:text="總價:0.00" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="去支付(0)" /> </RelativeLayout> <ExpandableListView android:id="@+id/expandablelistview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/re2" android:layout_below="@id/re"> </ExpandableListView> </RelativeLayout>

add_delete.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="-"
        android:textSize="20dp" />

    <TextView
        android:id="@+id/count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="0"
        android:textSize="20dp" />

    <TextView
        android:id="@+id/add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="+"
        android:textSize="20dp" />
</LinearLayout>

child_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <CheckBox
        android:id="@+id/main_check_all"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textView4" />

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/imageView3"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_alignParentTop="true"
        android:layout_toEndOf="@+id/main_check_all"
        android:layout_toRightOf="@+id/main_check_all" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toEndOf="@+id/imageView3"
        android:layout_toRightOf="@+id/imageView3"
        android:text="TextView"
        android:textSize="15dp" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/main_check_all"
        android:layout_toEndOf="@+id/imageView3"
        android:layout_toRightOf="@+id/imageView3"
        android:text="TextView"
        android:textColor="#c91622"
        android:textSize="10dp" />

    <com.bwei.view.ShopAddDelete
        android:id="@+id/ad"
        android:layout_width="80dp"
        android:layout_height="30dp"
        android:layout_alignBottom="@+id/imageView3"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/ad"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:text="刪除"
        android:visibility="gone" />
</RelativeLayout>

group_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:paddingLeft="20sp"
    android:layout_height="match_parent">

    <CheckBox
        android:id="@+id/main_check_all"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/main_check_all"
        android:layout_alignBottom="@+id/main_check_all"
        android:layout_toEndOf="@+id/main_check_all"
        android:layout_toRightOf="@+id/main_check_all"
        android:text="TextView" />
</RelativeLayout>

java檔案

adapter資料夾:介面卡

ExpandAdapter.java

public class ExpandAdapter extends BaseExpandableListAdapter implements IView {

    private Context context;
    private List<Group> data1;
    private List<List<Child>> data2;
    public static int q = 0;

    public ExpandAdapter(Context context, List<Group> data1, List<List<Child>> data2) {
        this.context = context;
        this.data1 = data1;
        this.data2 = data2;
    }

    @Override
    public int getGroupCount() {
        return data1.size();
    }

    @Override
    public int getChildrenCount(int i) {
        return data2.get(i).size();
    }

    @Override
    public Object getGroup(int i) {
        return data1.get(i);
    }

    @Override
    public Object getChild(int i, int i1) {
        return data2.get(i).get(i1);
    }

    @Override
    public long getGroupId(int i) {
        return i;
    }

    @Override
    public long getChildId(int i, int i1) {
        return i1;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public void onSuccess(Object o) {
        DeBean d = (DeBean) o;
        Toast.makeText(context, d.getMsg(), Toast.LENGTH_SHORT).show();
        data1.clear();
        data2.clear();
        ShoppingActivity s = (ShoppingActivity) context;
        s.se();
    }

    @Override
    public void onFailed(Exception e) {

    }

    class ViewHolder {
        CheckBox check;
        TextView tv;
    }

    class ViewHolder2 {
        CheckBox check;
        ImageView image;
        TextView tv1, tv2;
        ShopAddDelete ad;
        Button b;
    }


    @Override
    public View getGroupView(final int i, final boolean b, View view, ViewGroup viewGroup) {
        final ViewHolder holder;
        if (view == null) {
            holder = new ViewHolder();
            view = View.inflate(context, R.layout.group_item, null);
            holder.check = view.findViewById(R.id.main_check_all);
            holder.tv = view.findViewById(R.id.textView3);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
        holder.tv.setText(data1.get(i).getName());
        holder.check.setChecked(data1.get(i).isFlag());

        holder.check.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                ShoppingActivity s = (ShoppingActivity) context;
                //Group布林值變成選中狀態
                data1.get(i).setFlag(holder.check.isChecked());
                //遍歷Group集合
                for (int i = 0; i < data1.size(); i++) {
                    //如果有一個未選中   全選變成false並跳出
                    if (!data1.get(i).isFlag()) {
                        s.all.setChecked(false);
                        break;
                    } else {//全部選中 全選變成true
                        s.all.setChecked(true);
                    }
                }
                //Child集合布林值為選中的狀態
                for (int j = 0; j < data2.get(i).size(); j++) {
                    data2.get(i).get(j).setFlag(holder.check.isChecked());
                }
                //重新整理介面卡
                notifyDataSetChanged();
                //呼叫計算的方法
                s.js();
            }
        });
        return view;
    }

    @Override
    public View getChildView(final int i, final int i1, final boolean b, View view, ViewGroup viewGroup) {
        final ViewHolder2 holder2;
        if (view == null) {
            holder2 = new ViewHolder2();
            view = View.inflate(context, R.layout.child_item, null);
            holder2.check = view.findViewById(R.id.main_check_all);
            holder2.image = view.findViewById(R.id.imageView3);
            holder2.tv1 = view.findViewById(R.id.textView4);
            holder2.tv2 = view.findViewById(R.id.textView5);
            holder2.ad = view.findViewById(R.id.ad);
            holder2.b = view.findViewById(R.id.button2);
            view.setTag(holder2);
        } else {
            holder2 = (ViewHolder2) view.getTag();
        }
        String images = data2.get(i).get(i1).getImage();
        String[] split = images.split("!");
        holder2.image.setImageURI(Uri.parse(split[0]));
        holder2.tv1.setText(data2.get(i).get(i1).getTitle());
        holder2.tv2.setText(data2.get(i).get(i1).getPrice() + "");
        holder2.ad.count.setText(data2.get(i).get(i1).getNum() + "");
        holder2.check.setChecked(data2.get(i).get(i1).isFlag());
        if (q == 0) {
            holder2.b.setVisibility(View.GONE);
        } else {
            holder2.b.setVisibility(View.VISIBLE);
        }
        holder2.b.setOnClickListener(new View.OnClickListener() {

            private DePresenter dePresenter;

            @Override
            public void onClick(View view) {
                //http://120.27.23.105/product/deleteCart?source=android&uid=1653&pid=2
                dePresenter = new DePresenter(ExpandAdapter.this);
                Map<String, String> map = new HashMap<>();
                map.put("source", "android");
                map.put("uid", "1653");
                map.put("pid", data2.get(i).get(i1).getPid() + "");
                dePresenter.get("http://120.27.23.105/", map);
            }
        });
        holder2.check.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                ShoppingActivity s = (ShoppingActivity) context;
                //Child布林值變成選中狀態
                data2.get(i).get(i1).setFlag(holder2.check.isChecked());
                //遍歷Ghild集合
                for (int i = 0; i < data2.size(); i++) {
                    for (int j = 0; j < data2.get(i).size(); j++) {
                        //如果有一個未選中     全選與商家按鈕變成false並跳出
                        if (!data2.get(i).get(j).isFlag()) {
                            data1.get(i).setFlag(false);
                            s.all.setChecked(false);
                            break;
                        } else {//全部選中  全選與商家按鈕變成true
                            data1.get(i).setFlag(true);
                            s.all.setChecked(true);
                        }
                    }
                }
                //二次遍歷
                for (int i = 0; i < data1.size(); i++) {
                    boolean flag = data1.get(i).isFlag();
                    if (flag) {
                        s.all.setChecked(true);
                    } else {
                        s.all.setChecked(false);
                        break;
                    }
                }
                notifyDataSetChanged();
                //呼叫計算的方法
                s.js();
            }
        });
        holder2.ad.setOnAddDeleteClick(new ShopAddDelete.OnAddDeleteClickListener() {
            @Override
            public void onAddClick(View v) {
                ShoppingActivity s = (ShoppingActivity) context;
                int number = holder2.ad.getNumber();
                number++;
                holder2.ad.setNumber(number);
                Log.i("TAG", number + "");
                data2.get(i).get(i1).setNum(number);
                notifyDataSetChanged();
                //呼叫計算的方法
                s.js();
            }

            @Override
            public void onDelClick(View v) {
                ShoppingActivity s = (ShoppingActivity) context;
                int number = holder2.ad.getNumber();
                number--;
                if (number > 0) {
                    holder2.ad.setNumber(number);
                    data2.get(i).get(i1).setNum(number);
                } else {
                    Toast.makeText(context, "最小數量為1", Toast.LENGTH_SHORT).show();
                }
                notifyDataSetChanged();
                //呼叫計算的方法
                s.js();
            }
        });
        return view;
    }

    @Override
    public boolean isChildSelectable(int i, int i1) {
        return false;
    }

app資料夾:圖片載入

App.java

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Fresco.initialize(this);
    }
}

bean資料夾:資料解析

Child.java

private boolean flag;
    private String image;
    private String title;
    private double price;
    private int num;
    private int pid;

    public Child(boolean flag, String image, String title, double price, int num, int pid) {
        this.flag = flag;
        this.image = image;
        this.title = title;
        this.price = price;
        this.num = num;
        this.pid = pid;
    }

    public int getPid() {
        return pid;
    }

    public void setPid(int pid) {
        this.pid = pid;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

DeBean.java

private String msg;
    private String code;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

Group.java

private boolean flag;
    private String name;

    public Group(boolean flag, String name) {
        this.flag = flag;
        this.name = name;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

SeBean.java

private String msg;
    private String code;
    private List<DataBean> data;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public List<DataBean> getData() {
        return data;
    }

    public void setData(List<DataBean> data) {
        this.data = data;
    }

    public static class DataBean {
    private String sellerName;
        private String sellerid;
        private List<ListBean> list;

        public String getSellerName() {
            return sellerName;
        }

        public void setSellerName(String sellerName) {
            this.sellerName = sellerName;
        }

        public String getSellerid() {
            return sellerid;
        }

        public void setSellerid(String sellerid) {
            this.sellerid = sellerid;
        }

        public List<ListBean> getList() {
            return list;
        }

        public void setList(List<ListBean> list) {
            this.list = list;
        }

        public static class ListBean {
        private double bargainPrice;
            private String createtime;
            private String detailUrl;
            private String images;
            private int num;
            private int pid;
            private double price;
            private int pscid;
            private int selected;
            private int sellerid;
            private String subhead;
            private String title;

            public double getBargainPrice() {
                return bargainPrice;
            }

            public void setBargainPrice(double bargainPrice) {
                this.bargainPrice = bargainPrice;
            }

            public String getCreatetime() {
                return createtime;
            }

            public void setCreatetime(String createtime) {
                this.createtime = createtime;
            }

            public String getDetailUrl() {
                return detailUrl;
            }

            public void setDetailUrl(String detailUrl) {
                this.detailUrl = detailUrl;
            }

            public String getImages() {
                return images;
            }

            public void setImages(String images) {
                this.images = images;
            }

            public int getNum() {
                return num;
            }

            public void setNum(int num) {
                this.num = num;
            }

            public int getPid() {
                return pid;
            }

            public void setPid(int pid) {
                this.pid = pid;
            }

            public double getPrice() {
                return price;
            }

            public void setPrice(double price) {
                this.price = price;
            }

            public int getPscid() {
                return pscid;
            }

            public void setPscid(int pscid) {
                this.pscid = pscid;
            }

            public int getSelected() {
                return selected;
            }

            public void setSelected(int selected) {
                this.selected = selected;
            }

            public int getSellerid() {
                return sellerid;
            }

            public void setSellerid(int sellerid) {
                this.sellerid = sellerid;
            }

            public String getSubhead() {
                return subhead;
            }

            public void setSubhead(String subhead) {
                this.subhead = subhead;
            }

            public String getTitle() {
                return title;
            }

            public void setTitle(String title) {
                this.title = title;
            }
        }
    }
}

model資料夾:資料層

DeModel.java

public class DeModel implements IModel {
    private DePresenter presenter;

    public DeModel(DePresenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public void get(String baseurl, Map<String, String> map) {
        Flowable<DeBean> flowable = RetrofitUtils.getInstance(baseurl).getretrofit().create(ApiService.class).deget(map);
        presenter.getData(flowable);
    }
}

IModel.java

public interface IModel {
    void get(String baseurl, Map<String, String> map);
}

SeModel。java

public class SeModel implements IModel {
    private SePresenter presenter;

    public SeModel(SePresenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public void get(String baseurl, Map<String, String> map) {
        Flowable<SeBean> flowable = RetrofitUtils.getInstance(baseurl).getretrofit().create(ApiService.class).seget(map);
        presenter.getData(flowable);
    }
}

net資料夾:網路請求

ApiService.java

//http://120.27.23.105/product/getCarts?source=android&uid=1653
    @GET("product/getCarts")
    Flowable<SeBean> seget(@QueryMap Map<String, String> map);

    //http://120.27.23.105/product/deleteCart?source=android&uid=1653&pid=2
    @GET("product/deleteCart")
    Flowable<DeBean> deget(@QueryMap Map<String, String> map);

RetrofitUtils.java

public class RetrofitUtils {
    private static volatile RetrofitUtils instance;
    private final Retrofit retrofit;

    private RetrofitUtils(String baseurl) {
        retrofit = new Retrofit.Builder()
                .baseUrl(baseurl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    public static RetrofitUtils getInstance(String baseurl) {
        if (instance == null) {
            synchronized (RetrofitUtils.class) {
                if (instance == null) {
                    instance = new RetrofitUtils(baseurl);
                }
            }
        }
        return instance;
    }

    public Retrofit getretrofit() {
        return retrofit;
    }
}

presenter資料夾:邏輯層
BasePresenter.java

public interface BasePresenter {
    void get(String baseurl, Map<String, String> map);

    void get2(String baseurl, Map<String, String> map);
}

DePresenter.java

public class DePresenter implements BasePresenter {
    private IView iv;
    private DisposableSubscriber<DeBean> disposableSubscriber;

    public DePresenter(IView iv) {
        this.iv = iv;
    }

    @Override
    public void get(String baseurl, Map<String, String> map) {
        DeModel model = new DeModel(this);
        model.get(baseurl, map);
    }

    @Override
    public void get2(String baseurl, Map<String, String> map) {

    }

    public void getData(Flowable<DeBean> flowable) {
        disposableSubscriber = flowable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableSubscriber<DeBean>() {
                    @Override
                    public void onNext(DeBean deBean) {
                        iv.onSuccess(deBean);
                    }

                    @Override
                    public void onError(Throwable t) {
                        iv.onFailed((Exception) t);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    //防止記憶體洩漏
    public void detatch() {
        if (iv != null) {
            iv = null;
        }
        if (disposableSubscriber != null) {
            if (!disposableSubscriber.isDisposed()) {
                disposableSubscriber.dispose();
            }
        }
    }
}

SePresenter.java

public class SePresenter implements BasePresenter {
    private IView iv;
    private DisposableSubscriber<SeBean> disposableSubscriber;

    public SePresenter(IView iv) {
        this.iv = iv;
    }

    @Override
    public void get(String baseurl, Map<String, String> map) {
        SeModel model = new SeModel(this);
        model.get(baseurl, map);
    }

    @Override
    public void get2(String baseurl, Map<String, String> map) {

    }

    public void getData(Flowable<SeBean> flowable) {
        disposableSubscriber = flowable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableSubscriber<SeBean>() {
                    @Override
                    public void onNext(SeBean seBean) {
                        iv.onSuccess(seBean);
                    }

                    @Override
                    public void onError(Throwable t) {
                        iv.onFailed((Exception) t);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    //防止記憶體洩漏
    public void detatch() {
        if (iv != null) {
            iv = null;
        }
        if (disposableSubscriber != null) {
            if (!disposableSubscriber.isDisposed()) {
                disposableSubscriber.dispose();
            }
        }
    }

view資料夾:檢視層

IView.java

public interface IView {
    void onSuccess(Object o);
    void onFailed(Exception e);
}

ShopAddDelete.java

public class ShopAddDelete extends RelativeLayout {

    public TextView count;

    public ShopAddDelete(Context context) {
        this(context, null);
    }

    public ShopAddDelete(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ShopAddDelete(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs, defStyleAttr);
    }

    private OnAddDeleteClickListener listener;

    //對外提供一個點選的回撥介面
    public interface OnAddDeleteClickListener {
        void onAddClick(View v);

        void onDelClick(View v);
    }

    public void setOnAddDeleteClick(OnAddDeleteClickListener listener) {
        this.listener = listener;
    }

    private void initView(final Context context, AttributeSet attrs, int defStyleAttr) {
        View view = View.inflate(context, R.layout.add_delete, this);
        TextView delete = (TextView) view.findViewById(R.id.delete);
        count = (TextView) view.findViewById(R.id.count);
        TextView add = (TextView) view.findViewById(R.id.add);
        delete.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onDelClick(view);
            }
        });
        add.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onAddClick(view);
            }
        });
    }

    //對外提供設定EditText值的方法
    public void setNumber(int number) {
        count.setText(number + "");
    }

    //得到控制元件原來的值,並轉成int型別
    public int getNumber() {
        int number = Integer.parseInt(count.getText().toString().trim());
        return number;
    }

ShoppingActivity.java

public class ShoppingActivity extends AppCompatActivity implements IView {

    @BindView(R.id.back)
    TextView back;
    @BindView(R.id.shop)
    TextView shop;
    @BindView(R.id.re)
    RelativeLayout re;
    @BindView(R.id.bj)
    TextView bj;
    @BindView(R.id.price)
    TextView price;
    @BindView(R.id.button)
    Button button;
    @BindView(R.id.re2)
    RelativeLayout re2;
    @BindView(R.id.expandablelistview)
    ExpandableListView expandablelistview;
    private SePresenter sePresenter;
    private List<Group> grouplist = new ArrayList<>();
    private List<List<Child>> childlist = new ArrayList<>();
    public static CheckBox all;
    private ExpandAdapter expandAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shopping);
        all = (CheckBox) findViewById(R.id.all);
        ButterKnife.bind(this);
        all.setChecked(true);
        expandAdapter =