購物車頁面【仿】淘寶App
阿新 • • 發佈:2019-01-10
首先是效果圖
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 =