//适配器
public class ExpandableAdapter extends BaseExpandableListAdapter{ private Context context; private List<GroupBean> groupBeen; private List<List<ChildBean>> childBean; public ExpandableAdapter(Context context, List<GroupBean> groupBeen, List<List<ChildBean>> childBean) { this.context = context; this.groupBeen = groupBeen; this.childBean = childBean; } @Override public int getGroupCount() { return groupBeen.size(); } @Override public int getChildrenCount(int i) { return childBean.get(i).size(); } @Override public Object getGroup(int i) { return groupBeen.get(i).getSellerName(); } @Override public Object getChild(int i, int i1) { return childBean.get(i).get(i1).getTitle(); } @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 View getGroupView(final int i, boolean b, View view, ViewGroup viewGroup) { view=View.inflate(context,R.layout.group_view,null); final CheckBox groupCb = view.findViewById(R.id.group_checkbox); TextView shopName = view.findViewById(R.id.shop_name); groupCb.setChecked(groupBeen.get(i).isGropuCb()); shopName.setText(groupBeen.get(i).getSellerName()); groupCb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { boolean checked = groupCb.isChecked(); groupBeen.get(i).setGropuCb(checked); MainActivity main = (MainActivity) ExpandableAdapter.this.context; for (GroupBean group:groupBeen) { boolean gropuCB = group.isGropuCb(); if(!gropuCB){ main.allChekbox.setChecked(false); break; }else{ main.allChekbox.setChecked(true); } } int size = childBean.get(i).size(); if(checked){ for (int j = 0; j < size; j++) { childBean.get(i).get(j).setChildCb(true); } }else{ for (int j = 0; j < size; j++) { childBean.get(i).get(j).setChildCb(false); } } notifyDataSetChanged(); main.changesum(childBean); } }); return view; } @Override public View getChildView(final int i, final int i1, boolean b, View view, ViewGroup viewGroup) { view=View.inflate(context,R.layout.child_view,null); final CheckBox childCb = view.findViewById(R.id.child_checkbox); TextView shopTitle= view.findViewById(R.id.shop_title); TextView shopPrice= view.findViewById(R.id.shop_price); ImageView shopImg=view.findViewById(R.id.shop_img1); final AddDeleteView adv = view.findViewById(R.id.adv); final boolean childCb1 = childBean.get(i).get(i1).isChildCb(); childCb.setChecked(childCb1); String images = childBean.get(i).get(i1).getImages(); Log.d("ooo", "getChildView: "+images); // shopImg.setBackgroundResource(R.drawable.timg); Glide.with(context).load(childBean.get(i).get(i1).getImages()).into(shopImg); shopTitle.setText(childBean.get(i).get(i1).getTitle()); shopPrice.setText(childBean.get(i).get(i1).getPrice()+""); adv.setNumber(childBean.get(i).get(i1).getNum()); final MainActivity main = (MainActivity) this.context; adv.setOnAddDelClickListener(new AddDeleteView.OnAddDelClickListener() { @Override public void onAddClick(View v) { int number = adv.getNumber(); number++; adv.setNumber(number); childBean.get(i).get(i1).setNum(number); main.changesum(childBean); } @Override public void onDelClick(View v) { int number = adv.getNumber(); number--; adv.setNumber(number); childBean.get(i).get(i1).setNum(number); main.changesum(childBean); } }); childCb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { boolean flag=false; boolean checked = childCb.isChecked(); childBean.get(i).get(i1).setChildCb(checked); for(List<ChildBean> child:childBean){ for (int j = 0; j < child.size(); j++) { boolean childCb2 = child.get(j).isChildCb(); if(!childCb2){ main.allChekbox.setChecked(false); groupBeen.get(i).setGropuCb(false); flag=true; break; }else{ main.allChekbox.setChecked(true); groupBeen.get(i).setGropuCb(true); } } if(flag){ flag=true; break; } } int size = childBean.get(i).size(); for (int j = 0; j < size; j++) { boolean childCb2 = childBean.get(i).get(j).isChildCb(); if(!childCb2){ groupBeen.get(i).setGropuCb(false); break; }else{ groupBeen.get(i).setGropuCb(true); } } notifyDataSetChanged(); main.changesum(childBean); } }); return view; } @Override public boolean isChildSelectable(int i, int i1) { return false; } }//app
public class App extends Application { @Override public void onCreate() { super.onCreate(); Fresco.initialize(this); } }//Bean类
子分类
public class ChildBean { private String title; private String images; private double price; private int num; private boolean childCb; public ChildBean(String title, String images, double price, int num, boolean childCb) { this.title = title; this.images = images; this.price = price; this.num = num; this.childCb = childCb; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getImages() { return images; } public void setImages(String images) { this.images = images; } 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; } public boolean isChildCb() { return childCb; } public void setChildCb(boolean childCb) { this.childCb = childCb; } @Override public String toString() { return "ChildBean{" + "title='" + title + '\'' + ", images='" + images + '\'' + ", price=" + price + ", num=" + num + ", childCb=" + childCb + '}'; } }//总分类
public class GroupBean { private String sellerName; private boolean gropuCb; public GroupBean(String sellerName, boolean gropuCb) { this.sellerName = sellerName; this.gropuCb = gropuCb; } public String getSellerName() { return sellerName; } public void setSellerName(String sellerName) { this.sellerName = sellerName; } public boolean isGropuCb() { return gropuCb; } public void setGropuCb(boolean gropuCb) { this.gropuCb = gropuCb; } @Override public String toString() { return "GroupBean{" + "sellerName='" + sellerName + '\'' + ", gropuCb=" + gropuCb + '}'; } }//shopBean
public class ShopCarBean { private String code; private String msg; private List<DataBean> data; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } public static class DataBean { /** * list : [{"bargainPrice":22.9,"createtime":"2017-10-14T21:48:08","detailUrl":"https://item.m.jd.com/product/2542855.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends","images":"https://m.360buyimg.com/n0/jfs/t1930/284/2865629620/390243/e3ade9c4/56f0a08fNbd3a1235.jpg!q70.jpg|https://m.360buyimg.com/n0/jfs/t2137/336/2802996626/155915/e5e90d7a/56f0a09cN33e01bd0.jpg!q70.jpg|https://m.360buyimg.com/n0/jfs/t1882/31/2772215910/389956/c8dbf370/56f0a0a2Na0c86ea6.jpg!q70.jpg|https://m.360buyimg.com/n0/jfs/t2620/166/2703833710/312660/531aa913/57709035N33857877.jpg!q70.jpg","num":2,"pid":24,"price":288,"pscid":2,"selected":0,"sellerid":1,"subhead":"三只松鼠零食特惠,专区满99减50,满199减100,火速抢购》","title":"三只松鼠 坚果炒货 零食奶油味 碧根果225g/袋"}] * sellerName : 商家1 * sellerid : 1 */ 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 { /** * bargainPrice : 22.9 * createtime : 2017-10-14T21:48:08 * detailUrl : https://item.m.jd.com/product/2542855.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends * images : https://m.360buyimg.com/n0/jfs/t1930/284/2865629620/390243/e3ade9c4/56f0a08fNbd3a1235.jpg!q70.jpg|https://m.360buyimg.com/n0/jfs/t2137/336/2802996626/155915/e5e90d7a/56f0a09cN33e01bd0.jpg!q70.jpg|https://m.360buyimg.com/n0/jfs/t1882/31/2772215910/389956/c8dbf370/56f0a0a2Na0c86ea6.jpg!q70.jpg|https://m.360buyimg.com/n0/jfs/t2620/166/2703833710/312660/531aa913/57709035N33857877.jpg!q70.jpg * num : 2 * pid : 24 * price : 288.0 * pscid : 2 * selected : 0 * sellerid : 1 * subhead : 三只松鼠零食特惠,专区满99减50,满199减100,火速抢购》 * title : 三只松鼠 坚果炒货 零食奶油味 碧根果225g/袋 */ 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; } } } } //网络请求类
public interface ApiService { @POST("getCarts") Flowable<ShopCarBean> getShop(@Query("uid") String uid,@Query("source") String source); }
public class RetrofitUtil { private static volatile RetrofitUtil instance; private final Retrofit retrofit; private final ApiService apiService; private RetrofitUtil (){ retrofit = new Retrofit.Builder() .baseUrl("http://120.27.23.105/product/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); apiService = retrofit.create(ApiService.class); } public static RetrofitUtil getInstance(){ if(null==instance){ synchronized(RetrofitUtil.class){ if(instance==null){ instance=new RetrofitUtil(); } } } return instance; } public ApiService getApiService(){ return apiService; } }//model层
public interfaceIModel {
void getData(String uid);
}
//类
public class ShopCarModel implements IModel{ private ShopCarPersenter shopCarPersenter; public ShopCarModel(ShopCarPersenter shopCarPersenter){ this.shopCarPersenter=shopCarPersenter; } @Override public void getData(String uid) { Flowable<ShopCarBean> flowable = RetrofitUtil.getInstance().getApiService().getShop(uid,"android"); shopCarPersenter.getShopData(flowable); } }//MyView层
public class AddDeleteView extends LinearLayout { private OnAddDelClickListener listener; private EditText etNumber; //对外提供一个点击的回调接口 public interface OnAddDelClickListener { void onAddClick(View v); void onDelClick(View v); } public void setOnAddDelClickListener(OnAddDelClickListener listener) { if (listener != null) { this.listener = listener; } } public AddDeleteView(Context context) { this(context, null); } public AddDeleteView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AddDeleteView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context, attrs, defStyleAttr); } private void initView(Context context, AttributeSet attrs, int defStyleAttr) { View.inflate(context, R.layout.layout_add_delete, this); //获取控件 TextView txtDelete = findViewById(R.id.txt_delete); TextView txtAdd = findViewById(R.id.txt_add); etNumber = findViewById(R.id.et_number); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AddDeleteViewStyle); String leftText = typedArray.getString(R.styleable.AddDeleteViewStyle_left_text); String rightText = typedArray.getString(R.styleable.AddDeleteViewStyle_right_text); String middleText = typedArray.getString(R.styleable.AddDeleteViewStyle_middle_text); int color = typedArray.getColor(R.styleable.AddDeleteViewStyle_left_text_color, Color.BLACK); txtDelete.setText(leftText); txtAdd.setText(rightText); etNumber.setText(middleText); txtDelete.setTextColor(color); //回收 typedArray.recycle(); txtDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { listener.onDelClick(view); } }); txtAdd.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { listener.onAddClick(view); } }); } //对外提供一个修改数字的方法 public void setNumber(int number) { if (number > 0) { etNumber.setText(number + ""); } } //对外提供一个获取当前数字的方法 public int getNumber() { String string = etNumber.getText().toString(); int i = Integer.parseInt(string); return i; } }Presenter层接口
public interface BasePersenter { void getData(String uid); }//实现presenter层
public class ShopCarPersenter implements BasePersenter{ private IView iView; private DisposableSubscriber<ShopCarBean> disposableSubscriber; public void attchView( IView iView){ this.iView=iView; } @Override public void getData(String uid) { IModel model = new ShopCarModel(this); model.getData(uid); } public void detachView(){ if(iView!=null){ iView=null; } if(disposableSubscriber!=null){ if(!disposableSubscriber.isDisposed()){ disposableSubscriber.dispose(); } } } public void getShopData(Flowable<ShopCarBean> flowable){ disposableSubscriber = flowable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSubscriber<ShopCarBean>() { @Override public void onNext(ShopCarBean shopCarBean) { if(shopCarBean!=null){ iView.onSuccess(shopCarBean); } } @Override public void onError(Throwable t) { iView.onFailed(t.getMessage()); } @Override public void onComplete() { } }); } }//View接口
public interface IView { void onSuccess(Object o); void onFailed(String msg); }//MainActivity
public class MainActivity extends AppCompatActivity implements IView { List<GroupBean> groupBeen = new ArrayList<>(); List<List<ChildBean>> childBeen = new ArrayList<>(); @BindView(R.id.edit) TextView edit; @BindView(R.id.exListView) ExpandableListView exListView; @BindView(R.id.all_chekbox) public CheckBox allChekbox; @BindView(R.id.total_price) TextView totalPrice; @BindView(R.id.total_number) TextView totalNumber; private ShopCarPersenter persenter; private ExpandableAdapter expandableAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); persenter = new ShopCarPersenter(); persenter.attchView(this); persenter.getData("1290"); expandableAdapter = new ExpandableAdapter(this, groupBeen, childBeen); exListView.setAdapter(expandableAdapter); for(int i = 0; i < expandableAdapter.getGroupCount(); i++){ exListView.expandGroup(i); } exListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) { return true; } }); allChekbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { boolean checked = allChekbox.isChecked(); //改变一级item复选框 for (GroupBean i:groupBeen){ i.setGropuCb(checked); } //改变二级item复选框 for (List<ChildBean> i1:childBeen){ for(int r=0;r<i1.size();r++) { i1.get(r).setChildCb(checked); } } expandableAdapter.notifyDataSetChanged(); changesum(childBeen); } }); } @Override public void onSuccess(Object o) { if (o!=null) { ShopCarBean shopCarBean = (ShopCarBean) o; List<ShopCarBean.DataBean> groupData = shopCarBean.getData(); for (ShopCarBean.DataBean group : groupData) { groupBeen.add(new GroupBean(group.getSellerName(), false)); List<ChildBean> childOne = new ArrayList<>(); for (ShopCarBean.DataBean.ListBean child : group.getList()) { String[] split = child.getImages().split("\\|"); childOne.add(new ChildBean(child.getTitle(), split[0], child.getPrice(), child.getNum(), false)); } childBeen.add(childOne); } for(int i = 0; i < expandableAdapter.getGroupCount(); i++){ exListView.expandGroup(i); } expandableAdapter.notifyDataSetChanged(); } } @Override public void onFailed(String msg) { } //计算和数量总价 public void changesum(List<List<ChildBean>> childBeen){ int count=0; double sum=0; for (List<ChildBean> i1:childBeen){ for(int r=0;r<i1.size();r++) { boolean childCb1 = i1.get(r).isChildCb(); if(childCb1){ double price = i1.get(r).getPrice(); int num = i1.get(r).getNum(); sum+=price*num; count++; } } } totalPrice.setText("¥"+sum); totalNumber.setText("共有商品:"+count+"件"); } @Override protected void onDestroy() { super.onDestroy(); if(persenter!=null){ persenter.detachView(); } } }//一下是视图
main_activity
<!--头布局--> <LinearLayout android:id="@+id/top_bar" android:layout_width="match_parent" android:layout_height="48dp" android:background="#f7f7f7" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="48dp" android:background="@android:color/transparent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:minHeight="48dp" android:text="购物车" android:textColor="#1a1a1a" android:textSize="16sp" /> <TextView android:id="@+id/edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginRight="40dp" android:gravity="center" android:minHeight="48dp" android:text="编辑" android:textColor="#1a1a1a" android:textSize="14sp" android:visibility="visible" /> </RelativeLayout> </LinearLayout> <ExpandableListView android:id="@+id/exListView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:childIndicator="@null" android:groupIndicator="@null" > </ExpandableListView> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center_vertical" android:orientation="horizontal" > <CheckBox android:id="@+id/all_chekbox" android:layout_marginLeft="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全选"/> <LinearLayout android:id="@+id/ll_info" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="4" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginRight="20dp" android:layout_weight="1" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="right" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="合计:" android:textSize="18sp" android:textStyle="bold" /> <TextView android:id="@+id/total_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥0.00" android:textColor="#f23232" android:textSize="16sp" android:textStyle="bold" /> </LinearLayout> <TextView android:id="@+id/total_number" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="共有商品:0件" android:gravity="right" android:textSize="16sp" android:textStyle="bold" /> </LinearLayout> <TextView android:id="@+id/tv_go_to_pay" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="3" android:background="#fd7a05" android:clickable="true" android:gravity="center" android:text="结算" android:textColor="#FAFAFA" /> </LinearLayout> </LinearLayout>//child_view子视图
<CheckBox android:id="@+id/child_checkbox" android:layout_marginTop="50dp" android:layout_marginLeft="20dp" android:layout_marginBottom="50dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/shop_img1" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="30dp" /> </LinearLayout> <LinearLayout android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/shop_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> <TextView android:id="@+id/shop_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:text="¥20" android:textColor="#f23232"/> <com.example.shopcar.MyView.AddDeleteView android:id="@+id/adv" android:layout_width="160dp" android:layout_height="30dp" android:layout_marginTop="30dp" app:left_text="-" app:right_text="+" app:middle_text="1" android:focusable="false" > </com.example.shopcar.MyView.AddDeleteView> </LinearLayout> <Button android:id="@+id/shop_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:visibility="invisible" android:text="删除" />//group_view
<CheckBox android:id="@+id/group_checkbox" android:layout_marginLeft="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false"/> <TextView android:id="@+id/shop_name" android:layout_marginLeft="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16dp" />//layout_add_delete
<TextView android:id="@+id/txt_delete" android:layout_width="30dp" android:layout_height="30dp" android:text="-" android:gravity="center" android:background="#ff0000"/> <EditText android:id="@+id/et_number" android:layout_marginTop="2dp" android:layout_width="50dp" android:layout_height="30dp" android:background="#fff" android:layout_weight="0.00" android:gravity="center" android:text="1"/> <TextView android:id="@+id/txt_add" android:layout_width="30dp" android:layout_height="30dp" android:text="+" android:gravity="center" android:background="#ff0000"/>//values底下创建一个attrs
<declare-styleable name="AddDeleteViewStyle"> <attr name="left_text" format="string"></attr> <attr name="right_text" format="string"></attr> <attr name="middle_text" format="string"></attr> <attr name="left_text_color" format="color"></attr> </declare-styleable> <declare-styleable name="CheckBox_Sample"> <attr name="size" format="dimension" /> <attr name="color_border" format="color" /> <attr name="color_background" format="color" /> </declare-styleable>/需要配置的权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>///需要配置的依赖
compile 'com.android.support.constraint:constraint-layout:1.0.2' compile 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.facebook.fresco:fresco:0.12.0' compile 'io.reactivex.rxjava2:rxjava:2.1.1' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.squareup.retrofit2:retrofit:2.0.0' compile 'com.squareup.retrofit2:converter-gson:2.0.2'//解析使用 compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//与RxJava结合时使用