1. 程式人生 > >mvp實現Xrecyclerview的上下拉和購物車功能(仿淘寶)

mvp實現Xrecyclerview的上下拉和購物車功能(仿淘寶)

首先先匯入我們要使用的依賴

 implementation 'com.android.support:design:28.0.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'cn.bingoogolapple:bga-qrcode-zxing:1.2.5'
    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
    implementation 'com.jcodecraeer:xrecyclerview:1.5.9'
    implementation 'com.github.bumptech.glide:glide:4.8.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation 'com.youth.banner:banner:1.4.10'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0'

其次還要匯入許可權注意最終沒寫許可權是無法執行出效果的

<uses-permission android:name="com.dingtao.week3.permission.JPUSH_MESSAGE"/>

    <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT"/>

    <uses-permission android:name="android.permission.INTERNET"/>

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>

    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
//謹記如果配置application的話要在清單檔案中配置

現在開始寫佈局檔案

首先的佈局肯定是我們的主頁面的佈局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:src="@drawable/b"
            android:layout_width="50dp"
            android:layout_height="50dp" />
        <ImageView
            android:id="@+id/ss"
            android:src="@drawable/c"
            android:layout_width="50dp"
            android:layout_height="50dp" />
        <EditText
            android:textFontWeight="1"
            android:id="@+id/edit"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <ImageView
            android:id="@+id/qh"
            android:src="@drawable/d"
            android:layout_width="50dp"
            android:layout_height="50dp" />
    </LinearLayout>
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="排序▲"
            android:gravity="center"/>
        <TextView
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="排序▲"
            android:gravity="center"/>
        <TextView
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="排序▲"
            android:gravity="center"/>
        <TextView
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="排序▲"
            android:gravity="center"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/shop_car_image"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/a" />
    <com.jcodecraeer.xrecyclerview.XRecyclerView
        android:id="@+id/xrecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></com.jcodecraeer.xrecyclerview.XRecyclerView>
    </LinearLayout>
</LinearLayout>

記得要注意自己的佈局購物車的image是要跳入購物車的如果你寫成相對佈局的話會被XRecyclerView覆蓋掉(這個要注意)

寫介面的bean類


public class Result<T> {
    int code;
    String msg;
    T data;

    public int getCode() {
        return code;
    }

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

    public String getMsg() {
        return msg;
    }

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

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

泛型的bean類

public class Shop {
    List<Goods> list;
    String sellerName;
    String sellerid;
    int textColor = 0xffffffff;
    int background = R.color.grayblack;

    boolean check;


    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setBackground(int background) {
        this.background = background;
    }

    public int getBackground() {
        return background;
    }

    public void setCheck(boolean check) {
        this.check = check;
    }

    public boolean isCheck() {
        return check;
    }

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

    public void setList(List<Goods> list) {
        this.list = 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 class Goods implements Serializable {


//        "bargainPrice": 111.99,
//            "createtime": "2017-10-14T21:39:05",
//            "detailUrl": "https:\/\/item.m.jd.com\/product\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends",
//            "images": "https:\/\/m.360buyimg.com\/n0\/jfs\/t9004\/210\/1160833155\/647627\/ad6be059\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\/\/m.360buyimg.com\/n0\/jfs\/t7504\/338\/63721388\/491286\/f5957f53\/598e95f1N7f2adb87.jpg!q70.jpg|https:\/\/m.360buyimg.com\/n0\/jfs\/t7441\/10\/64242474\/419246\/adb30a7d\/598e95fbNd989ba0a.jpg!q70.jpg",
//            "itemtype": 1,
//            "pid": 1,
//            "price": 118.0,
//            "pscid": 1,
//            "salenum": 0,
//            "sellerid": 17,
//            "subhead": "每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下",
//            "title": "北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g"

    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;
    private int count=1;

    public void setCount(int count) {
        this.count = count;
    }

    public int getCount() {
        return count;
    }

    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;
    }
}

寫好 bean類就該寫mvp了

我們的core層

首先先寫成功和失敗的藉口

public interface DataCall<T> {

    void success(T data);

    void fail(Result result);

}

用hander來判斷失敗成功


public abstract class BasePresenter {

    DataCall dataCall;

    public BasePresenter(DataCall dataCall){
        this.dataCall = dataCall;
    }


    Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {

            Result result = (Result) msg.obj;
            if (result.getCode()==0){
                dataCall.success(result.getData());
            }else{
                dataCall.fail(result);
            }
        }
    };



    public void requestData(final Object...args){
        new Thread(new Runnable() {
            @Override
            public void run() {


                Message message = mHandler.obtainMessage();
                message.obj = getData(args);
                mHandler.sendMessage(message);

            }
        }).start();
    }

    protected abstract Result getData(Object...args);

    public void unBindCall(){
        this.dataCall = null;
    }

}
SharedPreferences的類

public class DTApplication extends Application {

    private static DTApplication instance;
    private SharedPreferences mSharedPreferences;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        mSharedPreferences = getSharedPreferences("application",
                Context.MODE_PRIVATE);
    }

    public static DTApplication getInstance() {
        return instance;
    }

    public SharedPreferences getShare() {
        return mSharedPreferences;
    }

}

首先mvp框架的

model層(這個要注意的是介面的毛病,如果介面有問題的話是出不來資料的,我們可以直接傳入從介面拿到的資料不通過okhttp直接解析資料顯示到列表)

首先寫列表的model


public class GoodsListModel {

    public static Result goodsList(String keywords, final String page) {
        String resultString = HttpUtils.postForm("http://www.zhaoapi.cn/product/searchProducts",
                new String[]{"keywords", "page"}, new String[]{keywords, page});

        try {
            Gson gson = new Gson();

            Type type = new TypeToken<Result<List<Goods>>>() {
            }.getType();

            Result result = gson.fromJson(resultString, type);
//        Result<List<Goods>> result = new Result<>();
//        result.setCode(0);
//        List<Goods> list = new ArrayList<>();
//        for (int i = 0; i < 30; i++) {
//            Goods goods = new Goods();
//            goods.setImages("");
//            goods.setTitle("手機"+i);
//            list.add(goods);
//        }
//        result.setData(list);

            return result;
        } catch (Exception e) {

        }
        Result result = new Result();
        result.setCode(-1);
        result.setMsg("資料解析異常");
        return result;
    }

}

presenter層

首先寫列表的presenter層


public class GoodsListPresenter extends BasePresenter {

    private int page=1;
    private boolean isRefresh=true;

    public GoodsListPresenter(DataCall dataCall) {
        super(dataCall);
    }

    @Override
    protected Result getData(Object... args) {
        isRefresh = (boolean) args[0];//是否需要重新整理
        if (isRefresh){//重新整理
            page = 1;
        }else{
            page++;
        }
        Result result = GoodsListModel.goodsList((String)args[1],page+"");//呼叫網路請求獲取資料
        return result;
    }

    public boolean isResresh(){
        return isRefresh;
    }
}

忘記一個非常重要的東西

okhttp的封裝類

我們model中用到的HttpUtils就是okhttp 的封裝類


public class HttpUtils {
    public static String get(String urlString){

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())//日誌攔截器
                .connectTimeout(10, TimeUnit.SECONDS)//連線超時
                .readTimeout(10,TimeUnit.SECONDS)//讀取超時
                .writeTimeout(10,TimeUnit.SECONDS)//寫入超時
                .build();

        Request request = new Request.Builder().url(urlString).get().build();

        try {
            Response response = okHttpClient.newCall(request).execute();
            String result = response.body().string();
            Log.i("dt","請求結果:"+result);
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String postForm(String url,String[] name,String[] value){

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())//日誌攔截器
                .connectTimeout(10, TimeUnit.SECONDS)//連線超時
                .readTimeout(10,TimeUnit.SECONDS)//讀取超時
                .writeTimeout(10,TimeUnit.SECONDS)//寫入超時
                .build();

        FormBody.Builder formBuild = new FormBody.Builder();
        for (int i = 0; i < name.length; i++) {
            formBuild.add(name[i],value[i]);
        }

        Request request = new Request.Builder().url(url).post(formBuild.build()).build();

        try {
            Response response = okHttpClient.newCall(request).execute();

            String result = response.body().string();
            Log.i("dt",result);
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String postFile(String url,String[] name,String[] value,String fileParamName,File file){

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())//日誌攔截器
                .connectTimeout(10, TimeUnit.SECONDS)//連線超時
                .readTimeout(10,TimeUnit.SECONDS)//讀取超時
                .writeTimeout(10,TimeUnit.SECONDS)//寫入超時
                .build();

        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
        if(file != null){
            // MediaType.parse() 裡面是上傳的檔案型別。
            RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);
            String filename = file.getName();
            // 引數分別為: 檔案引數名 ,檔名稱 , RequestBody
            requestBody.addFormDataPart(fileParamName, "jpg", body);
        }
        if (name!=null) {
            for (int i = 0; i < name.length; i++) {
                requestBody.addFormDataPart(name[i], value[i]);
            }
        }

        Request request = new Request.Builder().url(url).post(requestBody.build()).build();

        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.code()==200) {
                return response.body().string();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String postJson(String url,String jsonString){

        OkHttpClient okHttpClient = new OkHttpClient();

        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"),jsonString);

        Request request = new Request.Builder().url(url).post(requestBody).build();

        try {
            Response response = okHttpClient.newCall(request).execute();

            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
}

接著我們的思路

完成presenter我們的下一步就是

主頁面的效果實現


public class MainActivity extends AppCompatActivity  implements XRecyclerView.LoadingListener,
        DataCall<List<Goods>>, View.OnClickListener,GoodsListAdapter.OnItemClickListener,
        GoodsListAdapter.OnItemLongClickListener {

    private XRecyclerView mRecyclerView;
    private GoodsListAdapter mAdapter;
    private LinearLayoutManager mLinearManager;
    private GridLayoutManager mGridManager;

    private static final int GRID_LAYOUT_MANAGER = 1;
    private static final int LINEAR_LAYOUT_MANAGER = 2;


    private ImageView mBtnLayout;
    private EditText mKeywordsEdit;

    //新建商品列表Presenter
    private GoodsListPresenter mPresenter = new GoodsListPresenter(this);
    private ImageView shop;

    /**
     * 在onCreate方法裡面查詢Recylerview,並且設定上介面卡。
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ActivityCompat.checkSelfPermission(this,android.Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION,
                    android.Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
        }
        mKeywordsEdit = findViewById(R.id.edit);
        mBtnLayout = findViewById(R.id.qh);

        findViewById(R.id.ss).setOnClickListener(this);
        findViewById(R.id.shop_car_image).setOnClickListener(this);
        mBtnLayout.setOnClickListener(this);

        mRecyclerView = findViewById(R.id.xrecyclerView);//查詢mRecyclerView
        mRecyclerView.setLoadingListener(this);//新增下拉和重新整理的監聽器

//        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        mGridManager = new GridLayoutManager(this, 2,
                GridLayoutManager.VERTICAL, false);//網格佈局


        mLinearManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);//線性佈局
        mRecyclerView.setLayoutManager(mLinearManager);

        mAdapter = new GoodsListAdapter(this);//新建介面卡
        mAdapter.setOnItemClickListener(this);
        mAdapter.setOnItemLongClickListener(this);
        mRecyclerView.setAdapter(mAdapter);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ss:

                mRecyclerView.refresh();
                break;
            case R.id.qh:
                if (mRecyclerView.getLayoutManager().equals(mLinearManager)) {
//            if (mAdapter.getItemViewType(0) == GoodsListAdapter.LINEAR_TYPE) {
                    isGrid = true;
                    mAdapter.setViewType(GoodsListAdapter.GRID_TYPE);
                    mRecyclerView.setLayoutManager(mGridManager);
                } else {
                    isGrid = false;
                    mAdapter.setViewType(GoodsListAdapter.LINEAR_TYPE);
                    mRecyclerView.setLayoutManager(mLinearManager);
                }
                mAdapter.notifyDataSetChanged();
                break;
            case R.id.shop_car_image:
                Intent intent=new Intent(this,Cart2Activity.class);
                startActivity(intent);
                break;
        }
//        if (v.getId() == R.id.ss) {//搜尋
//            mRecyclerView.refresh();
//            //呼叫列表重新整理,重新整理方法中獲取輸入框的值進行自動請求;
//        } else if (v.getId() == R.id.qh) {//切換佈局
//
////            if (!isGrid) {
//            if (mRecyclerView.getLayoutManager().equals(mLinearManager)) {
////            if (mAdapter.getItemViewType(0) == GoodsListAdapter.LINEAR_TYPE) {
//                isGrid = true;
//                mAdapter.setViewType(GoodsListAdapter.GRID_TYPE);
//                mRecyclerView.setLayoutManager(mGridManager);
//            } else {
//                isGrid = false;
//                mAdapter.setViewType(GoodsListAdapter.LINEAR_TYPE);
//                mRecyclerView.setLayoutManager(mLinearManager);
//            }
//            mAdapter.notifyDataSetChanged();
//        }else if (v.getId() == R.id.shop){//進入購物車
////            Intent intent = new Intent(this,ShopCartActivity1.class);
//            Intent intent=new Intent(this,Cart2Activity.class);
//            startActivity(intent);
//        }
    }

    @Override
    public void onItemClick(Goods goods) {
        Intent intent = new Intent(this,WebActivity.class);
        intent.putExtra("url",goods.getDetailUrl());
        startActivity(intent);
    }

    @Override
    public void onItemLongClick(int position) {
        mAdapter.remove(position);
        mAdapter.notifyItemRemoved(position+1);//xRecyclerView如果增加了header,childView的序號就需要增加headerview的數量
        if (position < mAdapter.getItemCount()+1) {
            mAdapter.notifyItemRangeChanged(position+1,mAdapter.getItemCount()-position);
        }
    }

    @Override
    public void success(List<Goods> data) {
        mRecyclerView.refreshComplete();//結束重新整理
        mRecyclerView.loadMoreComplete();//結束載入更多
        if (mPresenter.isResresh()) {//只有重新整理需要清空資料
            mAdapter.clearList();
        }
        mAdapter.addAll(data);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void fail(Result result) {
        mRecyclerView.refreshComplete();//重新整理完成,隱藏重新整理view
        mRecyclerView.loadMoreComplete();//載入完成,隱藏載入view
        Toast.makeText(this, result.getCode() + "  " + result.getMsg(),
                Toast.LENGTH_LONG).show();
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        mPresenter.unBindCall();//釋放引用,防止記憶體溢位
    }

    private boolean isGrid = false;
    @Override
    public void onRefresh() {
        String keywords = mKeywordsEdit.getText().toString();
        mPresenter.requestData(true, keywords);
    }

    @Override
    public void onLoadMore() {
        String keywords = mKeywordsEdit.getText().toString();
        mPresenter.requestData(false, keywords);
    }
}

首先先寫列表的adapter介面卡

public class GoodsListAdapter extends RecyclerView.Adapter<GoodsListAdapter.GoodsHodler> {

    private List<Goods> mList = new ArrayList<>();//資料集合
    private Context context;


    public final static int LINEAR_TYPE = 0;//線性
    public final static int GRID_TYPE = 1;//網格

    private int viewType = LINEAR_TYPE;

    private OnItemClickListener onItemClickListener;

    private OnItemLongClickListener onItemLongClickListener;

    public GoodsListAdapter(Context context) {
        this.context = context;
    }

    @Override
    public int getItemViewType(int position) {
        return viewType;
    }

    //設定item的檢視型別
    public void setViewType(int viewType) {
        this.viewType = viewType;
    }


    @NonNull
    @Override
    public GoodsHodler onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        View view = null;
        if (viewType == LINEAR_TYPE) {//通過第二個引數viewType判斷選用的檢視
            view = View.inflate(viewGroup.getContext(), R.layout.goods_linear_item, null);//載入item佈局
        } else {
            view = View.inflate(viewGroup.getContext(), R.layout.goods_grid_item, null);//載入item佈局
        }
        GoodsHodler goodsHodler = new GoodsHodler(view);

        return goodsHodler;
    }

    @Override
    public void onBindViewHolder(@NonNull final GoodsHodler goodsHodler, final int position) {
        final Goods goods = mList.get(position);//拿到商品,開始賦值

        goodsHodler.itemView.setTag(mList.get(position));

        //增加點選事件
        goodsHodler.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //*******跳轉webActivity進行網頁訪問
//                Intent intent = new Intent(context,WebActivity.class);
//                intent.putExtra("url",goods.getDetailUrl());
//                context.startActivity(intent);

                //————————跳轉自定義的詳情頁面
                Intent intent = new Intent(context,GoodsDetailActivity.class);
                Bundle bundle = new Bundle();//使用bundle傳遞引用資料型別的物件
                bundle.putSerializable("goods",goods);
                intent.putExtras(bundle);//一定要把值放入了。
                context.startActivity(intent);

//                if (onItemClickListener!=null) {
//                onItemClickListener.onItemClick(goods);
//                }
            }
        });
        goodsHodler.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                //*****************方案1*************
//                ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(
//                        goodsHodler.itemView,"alpha",1,0
//                );
//                objectAnimator.setDuration(1000);
//                objectAnimator.setInterpolator(new LinearInterpolator());
//                objectAnimator.addListener(new Animator.AnimatorListener() {
//                    @Override
//                    public void onAnimationStart(Animator animation) {
//
//                    }
//
//                    @Override
//                    public void onAnimationEnd(Animator animation) {
//                        mList.remove(position);//動畫執行結束,移除
//                        notifyDataSetChanged();//重新整理列表
//                        goodsHodler.itemView.setAlpha(1);//由於複用機制,需要重新改成不透明
//                    }
//
//                    @Override
//                    public void onAnimationCancel(Animator animation) {
//                        mList.remove(position);//動畫執行結束,移除
//                        notifyDataSetChanged();//重新整理列表
//                        goodsHodler.itemView.setAlpha(1);//由於複用機制,需要重新改成不透明
//                    }
//
//                    @Override
//                    public void onAnimationRepeat(Animator animation) {
//
//                    }
//                });
//                objectAnimator.start();

                //***********方案二**************
                if (onItemLongClickListener!=null) {
                    onItemLongClickListener.onItemLongClick(position);
                }
                return true;
            }
        });

        goodsHodler.text.setText(goods.getTitle());
        //由於我們的資料圖片提供的不標準,所以我們需要切割得到圖片
        String imageurl = "https" + goods.getImages().split("https")[1];
        Log.i("dt", "imageUrl: " + imageurl);
        imageurl = imageurl.substring(0, imageurl.lastIndexOf(".jpg") + ".jpg".length());
        Glide.with(context).load(imageurl).into(goodsHodler.imageView);//載入圖片
    }

    public static void main(String[] args) {
        String aa = "a111a222a333a";
        String[] b = aa.split("a");
        System.out.println(b[0]);
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    /**
     * 新增集合資料
     */
    public void addAll(List<Goods> data) {
        if (data != null) {
            mList.addAll(data);
        }
    }

    /**
     * 清空資料
     */
    public void clearList() {
        mList.clear();
    }

    /**
     * 設定點選方法
     */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public void remove(int position) {
        mList.remove(position);
    }

    public class GoodsHodler extends RecyclerView.ViewHolder {
        TextView text;
        ImageView imageView;

        public GoodsHodler(@NonNull View itemView) {
            super(itemView);
            text = itemView.findViewById(R.id.text);
            imageView = itemView.findViewById(R.id.image);
        }
    }

    /**
     * @author dingtao
     * @date 2018/12/15 10:28 AM
     * 點選介面
     */
    public interface OnItemClickListener {
        void onItemClick(Goods goods);
    }

    /**
     * @author dingtao
     * @date 2018/12/15 10:28 AM
     * 點選介面
     */
    public interface OnItemLongClickListener {
        void onItemLongClick(int position);
    }

    public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
        this.onItemLongClickListener = onItemLongClickListener;
    }
}

我們要實現切換檢視的效果

所以我們要寫兩個item佈局

一個網格一個縱向

先是網格

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

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:minHeight="50dp"
        android:src="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="aa"
        android:padding="10dp"/>

</LinearLayout>

後是縱向

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

    <ImageView
        android:id="@+id/image"
        android:layout_margin="10dp"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:minHeight="50dp"
        android:src="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="aa"
        android:padding="10dp"/>

</LinearLayout>

介面回撥點選事件

我們所要跳轉的兩個頁面

其中一個就是點選條目跳轉

跳轉到使用者詳情頁

實現輪播圖功能和加入購物車點選吐司

使用者詳情頁佈局

一個是網頁webview一個是banner輪播圖

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

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <com.youth.banner.Banner
                android:id="@+id/goods_banner"
                android:layout_width="match_parent"
                android:layout_height="200dp" />
        </LinearLayout>

    </ScrollView>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">
        <Button
            android:id="@+id/goods_add_cart_btn"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="@color/mark_red"
            android:textColor="@color/white"
            android:layout_alignParentRight="true"
            android:text="加入購物車"/>
    </RelativeLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

詳情頁功能程式碼實現

public class GoodsDetailActivity extends AppCompatActivity implements View.OnClickListener {
    private Goods mGoods;//商品詳情

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_goods_detail);

        Bundle bundle = getIntent().getExtras();
        mGoods = (Goods) bundle.getSerializable("goods");//讀取列表傳遞過來的商品資料

        initBanner();

        findViewById(R.id.goods_add_cart_btn).setOnClickListener(this);

    }

    /**
     * 初始化banner
     */
    private void initBanner() {

        List<String> imageList = new ArrayList<>();//圖片url集合
        String[] imageurls = mGoods.getImages().split("https");//對圖片進行切割
        for (int i = 0; i < imageurls.length; i++) {
            if (!TextUtils.isEmpty(imageurls[i])) {
                String url = "https" + imageurls[i];

                url = url.substring(0, url.lastIndexOf(".jpg") + ".jpg".length());
                imageList.add(url);//圖片路徑拼接完成,重新賦值給陣列
            }
        }

        Banner banner = findViewById(R.id.goods_banner);
        //設定圖片載入器
        banner.setImageLoader(new GlideImageLoader());
        //設定banner樣式
        banner.setBannerStyle(BannerConfig.NUM_INDICATOR);

        //設定圖片集合
        banner.setImages(imageList);
        //設定標題集合(當banner樣式有顯示title時)
//        banner.setBannerTitles(titleList);
        //設定banner動畫效果
        banner.setBannerAnimation(Transformer.DepthPage);
        //設定自動輪播,預設為true
        banner.isAutoPlay(false);
        //設定輪播時間
//        banner.setDelayTime(1500);
        //設定指示器位置(當banner模式中有指示器時)
        banner.setIndicatorGravity(BannerConfig.RIGHT);
        //banner設定方法全部呼叫完畢時最後呼叫
        banner.start();
    }

    @Override
    public void onClick(View v) {
        if (v.getId()==R.id.goods_add_cart_btn){
            Toast.makeText(this,"加入購物車",Toast.LENGTH_LONG).show();
        }
    }
}
public class WebActivity extends AppCompatActivity {
    WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);

        mWebView = (WebView) findViewById(R.id.webview);

        WebSettings webSettings = mWebView.getSettings();

        // 設定與Js互動的許可權
        webSettings.setJavaScriptEnabled(true);
        // 設定允許JS彈窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

        String url = getIntent().getStringExtra("url");

        //如果不設定WebViewClient,請求會跳轉系統瀏覽器
        mWebView.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //該方法在Build.VERSION_CODES.LOLLIPOP以前有效,從Build.VERSION_CODES.LOLLIPOP起,建議使用shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead
                //返回false,意味著請求過程裡,不管有多少次的跳轉請求(即新的請求地址),均交給webView自己處理,這也是此方法的預設處理
                //返回true,說明你自己想根據url,做新的跳轉,比如在判斷url符合條件的情況下
                return false;
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                //返回false,意味著請求過程裡,不管有多少次的跳轉請求(即新的請求地址),均交給webView自己處理,這也是此方法的預設處理
                //返回true,說明你自己想根據url,做新的跳轉,比如在判斷url符合條件的情況下
                return false;
            }
        });

        // 先載入JS程式碼
        // 格式規定為:file:///android_asset/檔名.html
        mWebView.loadUrl(url);

        // webview只是載體,內容的渲染需要使用webviewChromClient類去實現
        // 通過設定WebChromeClient物件處理JavaScript的對話方塊
        //設定響應js 的Alert()函式
        mWebView.setWebChromeClient(new WebChromeClient());

    }

}

第二個跳轉就是跳轉頁面到

購物車頁面佈局

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

    <ExpandableListView
        android:id="@+id/list_cart"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

    </ExpandableListView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <CheckBox
            android:id="@+id/check_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:text="全選" />
        <TextView
            android:id="@+id/goods_sum_price"
            android:layout_toRightOf="@+id/check_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="價格:"
            android:layout_marginLeft="20dp"
            android:layout_centerVertical="true"/>
    </RelativeLayout>
</LinearLayout>

購物車的model層

public class CartModel {

    public static Result goodsList() {
//        String resultString = HttpUtils.get("http://www.zhaoapi.cn/product/getCarts?uid=71");
        String resultString = "{\"msg\":\"請求成功\",\"code\":\"0\",\"data\":[{\"list\":[],\"sellerName\":\"\",\"sellerid\":\"0\"},{\"list\":[{\"bargainPrice\":111.99,\"createtime\":\"2017-10-14T21:48:08\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":11,\"pid\":11,\"price\":8989.0,\"pscid\":1,\"selected\":0,\"sellerid\":4,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家4\",\"sellerid\":\"4\"},{\"list\":[{\"bargainPrice\":111.99,\"createtime\":\"2017-10-03T23:43:53\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":1,\"pid\":13,\"price\":465.0,\"pscid\":1,\"selected\":0,\"sellerid\":6,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家6\",\"sellerid\":\"6\"},{\"list\":[{\"bargainPrice\":11800.0,\"createtime\":\"2017-10-14T21:38:26\",\"detailUrl\":\"https:\\/\\/mitem.jd.hk\\/ware\\/view.action?wareId=1988853309&cachekey=1acb07a701ece8d2434a6ae7fa6870a1\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t6130\\/97\\/1370670410\\/180682\\/1109582a\\/593276b1Nd81fe723.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5698\\/110\\/2617517836\\/202970\\/c9388feb\\/593276b7Nbd94ef1f.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5698\\/110\\/2617517836\\/202970\\/c9388feb\\/593276b7Nbd94ef1f.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5815\\/178\\/2614671118\\/51656\\/7f52d137\\/593276c7N107b725a.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5878\\/60\\/2557817477\\/30873\\/4502b606\\/593276caN5a7d6357.jpg!q70.jpg\",\"num\":3,\"pid\":63,\"price\":10000.0,\"pscid\":40,\"selected\":0,\"sellerid\":7,\"subhead\":\"購買電腦辦公部分商品滿1元返火車票5元優惠券(返完即止)\",\"title\":\"全球購 新款Apple MacBook Pro 蘋果膝上型電腦 銀色VP2新13英寸Bar i5\\/8G\\/256G\"}],\"sellerName\":\"商家7\",\"sellerid\":\"7\"},{\"list\":[{\"bargainPrice\":399.0,\"createtime\":\"2017-10-03T23:53:28\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/1439822107.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5887\\/201\\/859509257\\/69994\\/6bde9bf6\\/59224c24Ne854e14c.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5641\\/233\\/853609022\\/57374\\/5c73d281\\/59224c24N3324d5f4.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5641\\/233\\/853609022\\/57374\\/5c73d281\\/59224c24N3324d5f4.jpg!q70.jpg\",\"num\":1,\"pid\":87,\"price\":888.0,\"pscid\":85,\"selected\":0,\"sellerid\":8,\"subhead\":\"滿2件,總價打6.50折\",\"title\":\"Gap男裝 休閒舒適簡約水洗五袋直筒長褲緊身牛仔褲941825 深灰色 33\\/32(175\\/84A)\"},{\"bargainPrice\":3455.0,\"createtime\":\"2017-10-03T23:53:28\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/12224420750.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9106\\/106\\/1785172479\\/537280\\/253bc0ab\\/59bf78a7N057e5ff7.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9106\\/106\\/1785172479\\/537280\\/253bc0ab\\/59bf78a7N057e5ff7.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8461\\/5\\/1492479653\\/68388\\/7255e013\\/59ba5e84N91091843.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8461\\/5\\/1492479653\\/68388\\/7255e013\\/59ba5e84N91091843.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8803\\/356\\/1478945529\\/489755\\/2a163ace\\/59ba5e84N7bb9a666.jpg!q70.jpg\",\"num\":2,\"pid\":52,\"price\":666.0,\"pscid\":39,\"selected\":0,\"sellerid\":8,\"subhead\":\"【現貨新品搶購】全面屏2.0震撼來襲,驍龍835處理器,四曲面陶瓷機\",\"title\":\"小米(MI) 小米MIX2 手機 黑色 全網通 (6GB+64GB)【標配版】\"}],\"sellerName\":\"商家8\",\"sellerid\":\"8\"},{\"list\":[{\"bargainPrice\":11800.0,\"createtime\":\"2017-10-14T21:48:08\",\"detailUrl\":\"https:\\/\\/mitem.jd.hk\\/ware\\/view.action?wareId=1988853309&cachekey=1acb07a701ece8d2434a6ae7fa6870a1\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t6130\\/97\\/1370670410\\/180682\\/1109582a\\/593276b1Nd81fe723.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5698\\/110\\/2617517836\\/202970\\/c9388feb\\/593276b7Nbd94ef1f.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5698\\/110\\/2617517836\\/202970\\/c9388feb\\/593276b7Nbd94ef1f.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5815\\/178\\/2614671118\\/51656\\/7f52d137\\/593276c7N107b725a.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5878\\/60\\/2557817477\\/30873\\/4502b606\\/593276caN5a7d6357.jpg!q70.jpg\",\"num\":3,\"pid\":65,\"price\":12000.0,\"pscid\":40,\"selected\":0,\"sellerid\":9,\"subhead\":\"購買電腦辦公部分商品滿1元返火車票5元優惠券(返完即止)\",\"title\":\"全球購 新款Apple MacBook Pro 蘋果膝上型電腦 銀色VP2新13英寸Bar i5\\/8G\\/256G\"},{\"bargainPrice\":2999.0,\"createtime\":\"2017-10-14T21:48:08\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/2385655.html?utm#_source=androidapp&utm#_medium=appshare&utm#_campaign=t#_335139774&utm#_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t2068\\/298\\/2448145915\\/157953\\/7be197df\\/56d51a42Nd86f1c8e.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t2437\\/128\\/1687178395\\/117431\\/bcc190c1\\/56d3fcbaNb2963d21.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t2467\\/222\\/2263160610\\/95597\\/927b8a2f\\/56d3eafeNdecebeb6.jpg!q70.jpg\",\"num\":2,\"pid\":53,\"price\":777.0,\"pscid\":39,\"selected\":0,\"sellerid\":9,\"subhead\":\"Super AMOLED三星雙曲面2K 屏,支援無線充電!\",\"title\":\"三星 Galaxy S7 edge(G9350)4GB+32GB 鉑光金 移動聯通電信4G手機 雙卡雙待\"},{\"bargainPrice\":111.99,\"createtime\":\"2017-10-14T21:39:05\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":1,\"pid\":16,\"price\":199.0,\"pscid\":1,\"selected\":0,\"sellerid\":9,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家9\",\"sellerid\":\"9\"},{\"list\":[{\"bargainPrice\":11800.0,\"createtime\":\"2017-10-14T21:38:26\",\"detailUrl\":\"https:\\/\\/mitem.jd.hk\\/ware\\/view.action?wareId=1988853309&cachekey=1acb07a701ece8d2434a6ae7fa6870a1\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t6130\\/97\\/1370670410\\/180682\\/1109582a\\/593276b1Nd81fe723.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5698\\/110\\/2617517836\\/202970\\/c9388feb\\/593276b7Nbd94ef1f.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5698\\/110\\/2617517836\\/202970\\/c9388feb\\/593276b7Nbd94ef1f.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5815\\/178\\/2614671118\\/51656\\/7f52d137\\/593276c7N107b725a.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t5878\\/60\\/2557817477\\/30873\\/4502b606\\/593276caN5a7d6357.jpg!q70.jpg\",\"num\":3,\"pid\":66,\"price\":13000.0,\"pscid\":40,\"selected\":0,\"sellerid\":10,\"subhead\":\"購買電腦辦公部分商品滿1元返火車票5元優惠券(返完即止)\",\"title\":\"全球購 新款Apple MacBook Pro 蘋果膝上型電腦 銀色VP2新13英寸Bar i5\\/8G\\/256G\"},{\"bargainPrice\":159.0,\"createtime\":\"2017-10-14T21:49:15\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/5061723.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8716\\/197\\/1271594444\\/173291\\/2f40bb4f\\/59b743bcN8509428e.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8347\\/264\\/1286771527\\/92188\\/5cf5ec04\\/59b7420fN65378e9e.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7363\\/165\\/3000956253\\/190883\\/179a372\\/59b743bfNd0c79d93.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7399\\/112\\/2935531768\\/183594\\/b77c7d4a\\/59b7441aNc3d40133.jpg!q70.jpg\",\"num\":5,\"pid\":99,\"price\":2100.0,\"pscid\":112,\"selected\":0,\"sellerid\":10,\"subhead\":\"針織針織閃閃閃亮你的眼\",\"title\":\"維邇旎 2017秋冬新款長袖針織連衣裙韓版氣質中長款名媛包臀A字裙 zx179709 黑色 XL\"},{\"bargainPrice\":111.99,\"createtime\":\"2017-10-03T23:53:28\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":2,\"pid\":17,\"price\":299.0,\"pscid\":1,\"selected\":0,\"sellerid\":10,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家10\",\"sellerid\":\"10\"},{\"list\":[{\"bargainPrice\":159.0,\"createtime\":\"2017-10-14T21:49:15\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/5061723.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8716\\/197\\/1271594444\\/173291\\/2f40bb4f\\/59b743bcN8509428e.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t8347\\/264\\/1286771527\\/92188\\/5cf5ec04\\/59b7420fN65378e9e.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7363\\/165\\/3000956253\\/190883\\/179a372\\/59b743bfNd0c79d93.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7399\\/112\\/2935531768\\/183594\\/b77c7d4a\\/59b7441aNc3d40133.jpg!q70.jpg\",\"num\":1,\"pid\":100,\"price\":2200.0,\"pscid\":112,\"selected\":0,\"sellerid\":11,\"subhead\":\"針織針織閃閃閃亮你的眼\",\"title\":\"維邇旎 2017秋冬新款長袖針織連衣裙韓版氣質中長款名媛包臀A字裙 zx179709 黑色 XL\"},{\"bargainPrice\":22.9,\"createtime\":\"2017-10-14T21:38:26\",\"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\":5,\"pid\":34,\"price\":9.0,\"pscid\":2,\"selected\":0,\"sellerid\":11,\"subhead\":\"三隻松鼠零食特惠,專區滿99減50,滿199減100,火速搶購》\",\"title\":\"三隻松鼠 堅果炒貨 零食奶油味 碧根果225g\\/袋\"},{\"bargainPrice\":111.99,\"createtime\":\"2017-10-14T21:48:08\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":2,\"pid\":18,\"price\":399.0,\"pscid\":1,\"selected\":0,\"sellerid\":11,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家11\",\"sellerid\":\"11\"},{\"list\":[{\"bargainPrice\":111.99,\"createtime\":\"2017-10-14T21:39:05\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":3,\"pid\":19,\"price\":499.0,\"pscid\":1,\"selected\":0,\"sellerid\":12,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家12\",\"sellerid\":\"12\"},{\"list\":[{\"bargainPrice\":111.99,\"createtime\":\"2017-10-14T21:39:05\",\"detailUrl\":\"https:\\/\\/item.m.jd.com\\/product\\/4719303.html?utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=QQfriends\",\"images\":\"https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t9004\\/210\\/1160833155\\/647627\\/ad6be059\\/59b4f4e1N9a2b1532.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7504\\/338\\/63721388\\/491286\\/f5957f53\\/598e95f1N7f2adb87.jpg!q70.jpg|https:\\/\\/m.360buyimg.com\\/n0\\/jfs\\/t7441\\/10\\/64242474\\/419246\\/adb30a7d\\/598e95fbNd989ba0a.jpg!q70.jpg\",\"num\":3,\"pid\":1,\"price\":118.0,\"pscid\":1,\"selected\":0,\"sellerid\":17,\"subhead\":\"每個中秋都不能簡單,無論身在何處,你總需要一塊餅讓生活更圓滿,京東月餅讓愛更圓滿京東自營,閃電配送,更多驚喜,快用手指戳一下\",\"title\":\"北京稻香村 稻香村中秋節月餅 老北京月餅禮盒655g\"}],\"sellerName\":\"商家17\",\"sellerid\":\"17\"}]}";
        try {
            Gson gson = new Gson();

            Type type = new TypeToken<Result<List<Shop>>>() {
            }.getType();

            Result result = gson.fromJson(resultString, type);
//        Result<List<Goods>> result = new Result<>();
//        result.setCode(0);
//        List<Goods> list = new ArrayList<>();
//        for (int i = 0; i < 30; i++) {
//            Goods goods = new Goods();
//            goods.setImages("");
//            goods.setTitle("手機"+i);
//            list.add(goods);
//        }
//        result.setData(list);

            return result;
        } catch (Exception e) {

        }
        Result result = new Result();
        result.setCode(-1);
        result.setMsg("資料解析異常");
        return result;
    }

}

購物車的presenter層

public class CartPresenter extends BasePresenter {


    public CartPresenter(DataCall dataCall) {
        super(dataCall);
    }

    @Override
    protected Result getData(Object... args) {
        Result result = CartModel.goodsList();//呼叫網路請求獲取資料
        return result;
    }

}

方法實現

public class Cart2Activity extends AppCompatActivity implements
        DataCall<List<Shop>>,CartAdapter2.TotalPriceListener{
    private TextView mSumPrice;
    private CheckBox mCheckAll;

    private ExpandableListView mGoodsList;
    private CartAdapter2 mCartAdapter;

    private CartPresenter cartPresenter = new CartPresenter(this);

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cart2);

        mSumPrice = findViewById(R.id.goods_sum_price);
        mCheckAll = findViewById(R.id.check_all);
        mCheckAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mCartAdapter.checkAll(isChecked);
            }
        });
        mGoodsList = findViewById(R.id.list_cart);
        mCartAdapter = new CartAdapter2();
        mGoodsList.setAdapter(mCartAdapter);
        mCartAdapter.setTotalPriceListener(this);//設定總價回撥器
        mGoodsList.setGroupIndicator(null);
        //讓其group不能被點選
        mGoodsList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {

                return true;
            }
        });
        cartPresenter.requestData();
    }

    @Override
    public void success(List<Shop> data) {
        mCartAdapter.addAll(data);
        //遍歷所有group,將所有項設定成預設展開
        int groupCount = data.size();
        for (int i = 0; i < groupCount; i++) {
            mGoodsList.expandGroup(i);
        }

        mCartAdapter.notifyDataSetChanged();
    }

    @Override
    public void fail(Result result) {
        Toast.makeText(this, result.getCode() + "   " + result.getMsg(), Toast.LENGTH_LONG).show();
    }

    @Override
    public void totalPrice(double totalPrice) {
        mSumPrice.setText(String.valueOf(totalPrice));
    }
}

購物車資料的介面卡

public class CartAdapter2 extends BaseExpandableListAdapter {

    private List<Shop> mList = new ArrayList<>();

    private TotalPriceListener totalPriceListener;

    public CartAdapter2(){
    }

    public void setTotalPriceListener(TotalPriceListener totalPriceListener) {
        this.totalPriceListener = totalPriceListener;
    }

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

    @Override
    public int getChildrenCount(int groupPosition) {
        return mList.get(groupPosition).getList().size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return mList.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return mList.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 false;
    }

    @Override
    public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

        GroupHodler holder;

        if (convertView == null) {
            convertView = View.inflate(parent.getContext(), R.layout.cart2_group_item, null);
            holder = new GroupHodler();
            holder.checkBox = convertView.findViewById(R.id.checkBox);
            convertView.setTag(holder);
        } else {
            holder = (GroupHodler) convertView.getTag();
        }
        final Shop shop = mList.get(groupPosition);

        holder.checkBox.setText(shop.getSellerName());
        holder.checkBox.setChecked(shop.isCheck());//設定商鋪選中狀態
        holder.checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CheckBox checkBox = (CheckBox) v;
                shop.setCheck(checkBox.isChecked());//資料更新
                List<Goods> goodsList = mList.get(groupPosition).getList();//得到商品資訊
                for (int i = 0; i < goodsList.size(); i++) {//商品資訊迴圈賦值
                    goodsList.get(i).setSelected(checkBox.isChecked()?1:0);//商鋪選中則商品必須選中
                }
                notifyDataSetChanged();

                //計算價格
                calculatePrice();
            }
        } );

        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        MyHolder holder;

        if (convertView == null) {
            convertView = View.inflate(parent.getContext(), R.layout.cart_item, null);
            holder = new MyHolder();
            holder.text = convertView.findViewById(R.id.text);
            holder.price = convertView.findViewById(R.id.text_price);
            holder.image = convertView.findViewById(R.id.image);
            holder.addSub = convertView.findViewById(R.id.add_sub_layout);
            holder.check = convertView.findViewById(R.id.cart_goods_check);
            convertView.setTag(holder);
        } else {
            holder = (MyHolder) convertView.getTag();
        }
        final Goods goods = mList.get(groupPosition).getList().get(childPosition);
        holder.text.setText(goods.getTitle());
        holder.price.setText("單價:"+goods.getPrice());//單價
        //點選選中,計算價格
        holder.check.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CheckBox checkBox = (CheckBox) v;
                goods.setSelected(checkBox.isChecked()?1:0);
                calculatePrice();//計算價格
            }
        });

        if (goods.getSelected()==0){
            holder.check.setChecked(false);
        }else{
            holder.check.setChecked(true);
        }

        String imageurl = "https" + goods.getImages().split("https")[1];
        Log.i("dt", "imageUrl: " + imageurl);
        imageurl = imageurl.substring(0, imageurl.lastIndexOf(".jpg") + ".jpg".length());
        Glide.with(DTApplication.getInstance()).load(