组合属性动画:缩放、渐变 平移和旋转+ImageLoader加载图片+MVP+OKhttp+拦截器+请求网络数据二级列表购物车

效果图:

图一                                            图二                                             图三

 

 

 

1.导入依赖

 

 
compile 'com.jakewharton:butterknife:7.0.1' compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.google.code.gson:gson:2.8.2' compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.2' compile 'com.squareup.okio:okio:1.5.0' compile 'com.squareup.okhttp3:okhttp:3.9.0' compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'


2. 清单文件

 

(1)加权限:

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

 

(2)配置application的name属性,ImageLoader初始化

 

 
<application
	android:name=".util.BaseApplication"
</application>

 

 

 

一. 首页  组合实现属性动画页面

1.SplashActivity类

 

 

 

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;

//创建启动页SplashActivity类,运用属性动画,实现应用图标动画效果;
public class SplashActivity extends AppCompatActivity {
    private ProgressBarView pbv;
    private int progress = 120;
    private int time = 3;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //动画运行时间为3秒钟,动画结束后跳转到商品详情页面。
            time--;
            if (time == 0) {
                startActivity(new Intent(SplashActivity.this, SecondActivity.class));
                finish();
            } else {
                //设置动画播放进程
                progress += 120;
                pbv.setProgress(progress);
                handler.sendEmptyMessageDelayed(0, 1000);
            }
        }
    };

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

        //查找控件
        ImageView imageView = (ImageView) findViewById(R.id.logo_img);
        pbv = (ProgressBarView) findViewById(R.id.my_progess);
        setAnimation(imageView);
        handler.sendEmptyMessage(0);
        pbv.setProgress(progress);
    }

    //执行动画的方法
    private void setAnimation(ImageView imageView) {
        //应用图标从屏幕最上方平移到屏幕中间
        ObjectAnimator trans = ObjectAnimator.ofFloat(imageView, "translationY", 0f, 500f).setDuration(1000);
        //缩放由2倍到1倍
        ObjectAnimator scalX = ObjectAnimator.ofFloat(imageView, "scaleX",  2f, 1f).setDuration(1000);
        ObjectAnimator scalY = ObjectAnimator.ofFloat(imageView, "scaleY",  2f, 1f).setDuration(1000);
        //渐变从完全透明到完全不透明
        ObjectAnimator alpha = ObjectAnimator.ofFloat(imageView, "alpha", 0.0f, 1f).setDuration(1000);
        // 旋转为旋转一圈
        ObjectAnimator rotate = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f).setDuration(1000);

        //动画组合开始执行
        AnimatorSet setAnimatior = new AnimatorSet();
        setAnimatior.play(trans).before(scalX).before(scalY).before(alpha).before(rotate);
        setAnimatior.start();
    }
}

 

 

 

2. 需要调用的自定义view类

 

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

//自定义ProgressBarView类
public class ProgressBarView extends View {
    private Paint paint;
    private int currentX = 100;
    private int  currentY = 100;
    private int count;
    private PointF pointF = new PointF(currentX,currentY);
    private  int mProgress;


    public ProgressBarView(Context context) {
        super(context);
        initpaint(context);
    }

    private void initpaint(Context context) {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
    }

    public ProgressBarView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initpaint(context);
    }

    public ProgressBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initpaint(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setStrokeWidth(0);
        paint.setColor(Color.BLACK);
        canvas.drawCircle(pointF.x,pointF.y,20,paint);
        canvas.drawCircle(pointF.x,pointF.y,30,paint);

        paint.setStrokeWidth(10);
        paint.setColor(Color.RED);
        RectF recyF = new RectF(75,75,125,125);
        canvas.drawArc(recyF,-90,mProgress,false,paint);

        paint.setStrokeWidth(1);
        paint.setColor(Color.BLUE);
        canvas.drawText(count+"",98,102,paint);
    }

    public void setProgress(int progress){
        this.mProgress = progress;
        if (mProgress == 120){
            count = 2;
        }
        if (mProgress == 240){
            count = 1;
        }
        if (mProgress == 360){
            count = 0;
        }
        invalidate();
    }
}

3. 实现的布局:

 

activity_splash.xml

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/logo_img"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@mipmap/ic_launcher"
        android:layout_centerHorizontal="true" />

    <com.bwie.duhongwang.customview.ProgressBarView
        android:visibility="gone"
        android:id="@+id/my_progess"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

 

 

 

二. 商品详情页   

1. SecondActivity

 

import android.content.Intent;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.io.IOException;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

//商品详情页面
public class SecondActivity extends AppCompatActivity implements SecondViewListener.PresenterSecondInterface {
    @Bind(R.id.title)
    TextView title;
    @Bind(R.id.yuanJia)
    TextView yuanJia;
    @Bind(R.id.youHui)
    TextView youHui;
    @Bind(R.id.backImage)
    ImageView backImage;
    @Bind(R.id.ProductImage)
    ImageView ProductImage;
    private SecondPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        ButterKnife.bind(this);

        //关联p层,获取数据
        presenter = new SecondPresenter(this);
        presenter.getData();
    }

    @OnClick({R.id.backImage, R.id.goToCart, R.id.addCart})
    public void onViewClicked(View view) {
        switch (view.getId()) {
                case R.id.backImage:        //点击左上角返回按钮跳转至属性动画页面
                    Intent intent = new Intent(SecondActivity.this, SplashActivity.class);
                    startActivity(intent);
                    break;

                case R.id.addCart:      //点击加入购物车的方法
                    //路径
                    String path = "https://www.zhaoapi.cn/product/addCart?uid=71&pid=1";
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url(path)
                            .build();
                    Call call = client.newCall(request);
                    call.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            final String body = response.body().string();
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    //吐司加入购物车成功
                                    Toast.makeText(SecondActivity.this, "购物车加入商品成功"+body, Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    });
                break;

            case R.id.goToCart:     //点击  购物车  按钮跳转至购物车列表页面
                Intent intent1 = new Intent(SecondActivity.this, ThirdActivity.class);
                startActivity(intent1);
                break;
        }
    }

    @Override
    public void success(SecondBean bean) {
        //设置图片 下标为0的图片数据
        String images = bean.getData().getImages();
        String[] split = images.split("\\|");
        //ImageLoader加载图片数组中的图片
        ImageLoader.getInstance().displayImage(split[0],ProductImage);

        //设置商品信息显示
        title.setText(bean.getData().getTitle());
        yuanJia.setText("原价:¥" + bean.getData().getPrice());
        //设置原价中间横线(删除线)
        yuanJia.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
        youHui.setText("优惠价:" + bean.getData().getBargainPrice());
    }

    @Override
    public void failed(Exception e) {
        Toast.makeText(SecondActivity.this,"数据出错",Toast.LENGTH_SHORT).show();
    }

    //为防止内存泄漏,在view层销毁p层
    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.detach();
    }
}

2. 详情页面需要的数据封装的bean类 SecondBean(自己实现)

 

请求接口是:https://www.zhaoapi.cn/product/getProductDetail?pid=1

3.本页面需要用到的mvp 3层

(1)model层

 

//购物车详情页面model层
public class SecondModel {
    public void getDataModel(final SecondViewListener.ModelSecondInterface modelSecondInterface){
        OkhttpUtils.getInstance().asy(null, "https://www.zhaoapi.cn/product/getProductDetail?pid=1", new AbstractUiCallBack<SecondBean>() {
            @Override
            public void success(SecondBean bean) {
                modelSecondInterface.success(bean);
            }

            @Override
            public void failure(Exception e) {
                modelSecondInterface.failed(e);
            }
        });
    }
}

 

 

 

(2)view层

 

//购物车详情页面View层
public interface SecondViewListener {
    public interface ModelSecondInterface{
        public void success(SecondBean bean);
        public void failed(Exception e);
    }
    public interface PresenterSecondInterface{
        public void success(SecondBean bean);
        public void failed(Exception e);
    }
}

 

 

 

(3)presenter层

 

//购物车详情页面presenter层
public class SecondPresenter {
    SecondViewListener.PresenterSecondInterface  presenterSecondInterface;
    SecondModel secondModel;

    public SecondPresenter(SecondViewListener.PresenterSecondInterface  presenterSecondInterface) {
        this.presenterSecondInterface = presenterSecondInterface;
        this.secondModel = new SecondModel();
    }

    public void getData(){
        secondModel.getDataModel(new SecondViewListener.ModelSecondInterface() {
            @Override
            public void success(SecondBean bean) {
                presenterSecondInterface.success(bean);
            }

            @Override
            public void failed(Exception e) {
                presenterSecondInterface.failed(e);
            }
        });
    }

    //防止内存泄露
    public void detach(){
        presenterSecondInterface = null;
    }
}

4. 设置布局

 

activity_second.xml

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="58dp"
        android:id="@+id/relative01">

        <ImageView
            android:padding="5dp"
            android:id="@+id/backImage"
            android:layout_width="38dp"
            android:layout_height="38dp"
            android:src="@drawable/icon_back"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"/>

        <TextView
            android:padding="10dp"
            android:text="商品详情"
            android:textSize="26sp"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"    />
    </RelativeLayout>
    <View
        android:id="@+id/view"
        android:background="#000"
        android:layout_height="1dp"
        android:visibility="visible"
        android:layout_width="match_parent"
        android:layout_below="@+id/relative01"></View>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_below="@+id/view"
        android:layout_height="288dp"
        android:id="@+id/relative">

        <ImageView
            android:id="@+id/ProductImage"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </RelativeLayout>
    <View
        android:id="@+id/view01"
        android:background="#000"
        android:layout_height="1dp"
        android:visibility="visible"
        android:layout_width="match_parent"
        android:layout_below="@+id/relative"></View>
    <LinearLayout
        android:id="@+id/line1"
        android:orientation="vertical"
        android:layout_above="@+id/line2"
        android:layout_width="match_parent"
        android:layout_below="@+id/relative"
        android:layout_height="wrap_content"  >
        <TextView
            android:textSize="18sp"
            android:id="@+id/title"
            android:layout_weight="1"
            android:layout_height="0dp"
            android:layout_marginLeft="18dp"
            android:layout_width="wrap_content"    />
        <TextView
            android:textSize="18sp"
            android:id="@+id/yuanJia"
            android:layout_weight="1"
            android:layout_height="0dp"
            android:layout_marginLeft="18dp"
            android:layout_width="wrap_content"     />
        <TextView
            android:textSize="18sp"
            android:id="@+id/youHui"
            android:layout_weight="1"
            android:layout_height="0dp"
            android:textColor="#f14d07"
            android:layout_marginLeft="18dp"
            android:layout_width="wrap_content"    />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_above="@+id/line2"
        android:visibility="visible"
        android:background="#000"
        android:layout_height="1dp"></View>

    <LinearLayout
        android:id="@+id/line2"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        <Button
            android:text="购物车"
            android:gravity="center"
            android:id="@+id/goToCart"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/buttonstyle" ></Button>
        <Button
            android:gravity="center"
            android:text="加入购物车"
            android:id="@+id/addCart"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:background="@drawable/buttonstyle"
            android:layout_height="wrap_content"></Button>
    </LinearLayout>

</RelativeLayout>
需在drawable文件夹下添加布局文件 buttonstyle.xml
 
<?xml version="1.0" encoding="UTF-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 连框颜色值 -->  <item> <shape> <solid android:color="#8b8686" /> </shape> </item> <!-- 主体背景颜色值 -->  <item android:bottom="2dp" android:right="2dp"> <shape> <solid android:color="#ffffff" /> <padding android:bottom="10dp"  android:left="10dp"  android:right="10dp"  android:top="10dp" /> </shape> </item> </layer-list>

 

三. 购物车列表页   

 

 

1.ThirdActivity

 

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

//购物车列表页面,全选、反选、单选、多选等等功能
public class ThirdActivity extends AppCompatActivity implements MainViewListener {
    @Bind(R.id.third_recyclerview)
    RecyclerView thirdRecyclerview;
    @Bind(R.id.third_allselect)
    CheckBox checkBoxAll;
    @Bind(R.id.third_totalprice)
    TextView thirdTotalprice;
    private MainPresenter presenter;
    private ShopAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        ButterKnife.bind(this);

        //关联p层
        presenter = new MainPresenter(this);
        presenter.getData();

        //设置布局管理器以及适配器
        adapter = new ShopAdapter(this);
        LinearLayoutManager manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        thirdRecyclerview.setLayoutManager(manager);
        thirdRecyclerview.setAdapter(adapter);

        adapter.setListener(new ShopAdapter.UpdateUiListener() {
            @Override
            public void setTotal(String total, String num, boolean allCheck) {
                checkBoxAll.setChecked(allCheck);
                thirdTotalprice.setText("总价:¥" + total);
            }
        });
    }

    @Override
    public void success(ShopBean bean) {
        adapter.add(bean);
    }

    @Override
    public void failure(Exception e) {
        Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
    }

    //避免内存泄漏
    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.detach();
    }


    @OnClick({R.id.thirdBackImage, R.id.third_allselect})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.thirdBackImage:       //点击左上角返回按钮跳转至购物车详情页面
                Intent intent = new Intent(ThirdActivity.this, SecondActivity.class);
                startActivity(intent);
                break;
            case R.id.third_allselect:     //全选/反选按钮
                adapter.selectAll(checkBoxAll.isChecked());
                break;
        }
    }
}

 

 

 

2. 适配器 ShopAdapter 

 

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.Bind;
import butterknife.ButterKnife;

//页面适配器
public class ShopAdapter extends RecyclerView.Adapter<ShopAdapter.IViewHolder> {
    private Context context;
    private List<ShopBean.DataBean.ListBean> list;

    // 存放 商家的id 和 商家名称
    private Map<String, String> map = new HashMap<>();

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

    /**
     * 添加数据 并更新显示
     * @param bean
     */
    public void add(ShopBean bean) {
        if (this.list == null) {
            this.list = new ArrayList<>();
        }

        // 遍历商家
        for (ShopBean.DataBean shop : bean.getData()) {
            map.put(shop.getSellerid(), shop.getSellerName());
            // 遍历商品
            for (int i = 0; i < shop.getList().size(); i++) {
                this.list.add(shop.getList().get(i));
            }
        }

        setFirst(this.list);
        notifyDataSetChanged();
    }

    /**
     * 设置数据源, 控制显示商家
     * @param list
     */
    private void setFirst(List<ShopBean.DataBean.ListBean> list) {
        if (list.size() > 0) {
            list.get(0).setIsFirst(1);
            for (int i = 1; i < list.size(); i++) {
                if (list.get(i).getSellerid() == list.get(i - 1).getSellerid()) {
                    list.get(i).setIsFirst(2);
                } else {
                    list.get(i).setIsFirst(1);
                }
            }
        }
    }

    @Override
    public IViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(context, R.layout.adapter_layout, null);
        return new IViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final IViewHolder holder, final int position) {
        // 显示商品图片
        if (list.get(position).getIsFirst() == 1) {
            //显示商家
            holder.shop_checkbox.setVisibility(View.VISIBLE);
            holder.tvItemShopcartShopname.setVisibility(View.VISIBLE);
            holder.shop_checkbox.setChecked(list.get(position).isShopSelected());

            //显示商家的名称
            holder.tvItemShopcartShopname.setText("我是"+map.get(String.valueOf(list.get(position).getSellerid())));
        } else {
            holder.shop_checkbox.setVisibility(View.GONE);
            holder.tvItemShopcartShopname.setVisibility(View.GONE);
        }

        //控制 商品的  checkbox
        holder.item_checkbox.setChecked(list.get(position).isItemSelected());

        String[] url = list.get(position).getImages().split("\\|");
        ImageLoader.getInstance().displayImage(url[0], holder.item_pic, ImageLoaderUtil.getDefaultOption());

        holder.item_name.setText(list.get(position).getTitle());
        holder.item_price.setText("优惠价:¥"+list.get(position).getPrice() + "");

        // 商家的checkbox
        holder.shop_checkbox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                list.get(position).setShopSelected(holder.shop_checkbox.isChecked());
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(position).getSellerid() == list.get(i).getSellerid()) {
                        list.get(i).setItemSelected(holder.shop_checkbox.isChecked());
                    }
                }
                notifyDataSetChanged();
                sum(list);
            }
        });

        // 商品的checkbox
        holder.item_checkbox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                list.get(position).setItemSelected(holder.item_checkbox.isChecked());
                for (int i = 0; i < list.size(); i++) {
                    for (int j = 0; j < list.size(); j++) {
                        if (list.get(i).getSellerid() == list.get(j).getSellerid() && !list.get(j).isItemSelected()) {
                            list.get(i).setShopSelected(false);
                            break;
                        } else {
                            list.get(i).setShopSelected(true);
                        }
                    }
                }
                notifyDataSetChanged();
                sum(list);
            }
        });
    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    /**
     * 计算总价
     * @param list
     */
    private void sum(List<ShopBean.DataBean.ListBean> list) {
        int totalNum = 0;
        float totalMoney = 0.0f;

        boolean allCheck = true;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).isItemSelected()) {
                totalNum += list.get(i).getNum();
                totalMoney += list.get(i).getNum() * list.get(i).getPrice();
            } else {
                allCheck = false;
            }
        }

        listener.setTotal(totalMoney + "", totalNum + "", allCheck);
    }

    public void selectAll(boolean check) {

        for (int i = 0; i < list.size(); i++) {
            list.get(i).setShopSelected(check);
            list.get(i).setItemSelected(check);
        }
        notifyDataSetChanged();

        sum(list);
    }

    static class IViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.shop_checkbox)
        CheckBox shop_checkbox;
        @Bind(R.id.tv_item_shopcart_shopname)
        TextView tvItemShopcartShopname;
        @Bind(R.id.item_checkbox)
        CheckBox item_checkbox;
        @Bind(R.id.item_pic)
        ImageView item_pic;
        @Bind(R.id.item_price)
        TextView item_price;
        @Bind(R.id.item_name)
        TextView item_name;
        IViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }

    public UpdateUiListener listener;

    public void setListener(UpdateUiListener listener) {
        this.listener = listener;
    }

    interface UpdateUiListener {
         public void setTotal(String total, String num, boolean allCheck);
    }

 

3. 本页面需要的数据封装的bean类 ShopBean(自己实现)

请求接口是:https://www.zhaoapi.cn/product/getCarts?uid=71

(关键加上下面3个属性变量,设置setter和getter)

 

 

 

// 1 显示商家  2 隐藏商家
private int isFirst;

// true 表示商家选中 false 相反
private boolean shopSelected;

// true 表示 当前商品是选中的 false 相反
private boolean itemSelected;

 

 

 

 

 

4.本页面需要用到的mvp 3层

(1)model层

//model层
public class MainModel {
    //获取购物车数据请求接口
    public void getData(final MainModelCallBack callBack){
        OkhttpUtils.getInstance().asy(null, "https://www.zhaoapi.cn/product/getCarts?uid=71", new AbstractUiCallBack<ShopBean>() {
            @Override
            public void success(ShopBean bean) {
                callBack.success(bean);
            }
            @Override
            public void failure(Exception e) {
                callBack.failure(e);
            }
        });
    }
}
需实现的接口类 MainModelCallBack:

 

public interface MainModelCallBack {
    public void success(ShopBean bean);
    public void failure(Exception e);

}

(2)view层

 

 

 

 

//view层
public interface MainViewListener {
    public void success(ShopBean bean);
    public void failure(Exception e);

}

(3)presenter层

 

 

//Presenter层
public class MainPresenter {
    private MainViewListener listener;
    private MainModel mainModel;
    public MainPresenter(MainViewListener listener){
        this.listener = listener ;
        this.mainModel = new MainModel();
    }


    public void getData(){


        mainModel.getData(new MainModelCallBack() {

            @Override
            public void success(ShopBean bean) {

                if(listener != null){
                    listener.success(bean);
                }

            }

            @Override
            public void failure(Exception e) {

                if(listener != null){
                    listener.failure(e);
                }
            }
        });
    }


    /**
     * 防止内存泄漏
     */
    public void detach(){
        listener = null;
    }

}

5. 设置本页面布局:

 

activity_third.xml

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="58dp"
        android:id="@+id/relative01">

        <ImageView
            android:padding="5dp"
            android:id="@+id/thirdBackImage"
            android:layout_width="38dp"
            android:layout_height="38dp"
            android:src="@drawable/icon_back"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"/>

        <TextView
            android:padding="10dp"
            android:text="购物车"
            android:textSize="26sp"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"    />
    </RelativeLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/third_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/third_pay_linear"
        android:layout_below="@+id/relative01" />

    <RelativeLayout
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFFFFF"
        android:gravity="center_vertical"
        android:id="@+id/third_pay_linear"
        >

        <CheckBox
            android:drawablePadding="@dimen/padding_5dp"
            android:id="@+id/third_allselect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="全选/反选"
            />

            <TextView
                android:layout_alignParentRight="true"
                android:id="@+id/third_totalprice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:paddingRight="18dp"
                android:text="总价:¥ 0"
                android:textColor="@color/main_red_text"
                android:textSize="@dimen/common_font_size_16"
                />
        </RelativeLayout>

</RelativeLayout>
适配器 adapter_layout.xml(页面布局出错时,参考 http://blog.csdn.net/IT666DHW/article/details/78622821 的购物车布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/ll_shopcart_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"  >

        <View
            android:background="@color/background_color"
            android:layout_height="@dimen/margin_10dp"
            android:layout_width="match_parent"
            android:id="@+id/view"/>

        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:gravity="center_vertical" >

            <!-- 商店checkbox -->
            <CheckBox
                android:id="@+id/shop_checkbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/margin_15dp"
                android:paddingRight="@dimen/margin_15dp"
                android:paddingTop="@dimen/margin_10dp"
                android:paddingBottom="@dimen/margin_10dp"
                />

            <!-- 商店信息 -->
            <TextView
                android:id="@+id/tv_item_shopcart_shopname"
                android:textColor="@color/cblack"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawablePadding="@dimen/padding_5dp"
                android:text="宝儿家服装"
                android:padding="@dimen/padding_10dp" />

        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"  >

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

            <View
                android:layout_width="match_parent"
                android:layout_height="@dimen/margin_1dp"
                android:background="@color/background_color"  />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal" >

                <!-- 商品 checkbox -->
                <CheckBox
                    android:id="@+id/item_checkbox"
                    android:layout_marginLeft="18dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/margin_15dp"  />

                <!-- 商品图片 -->
                <ImageView
                    android:id="@+id/item_pic"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_margin="@dimen/margin_10dp"
                    />

                <LinearLayout
                    android:layout_weight="1"
                    android:layout_width="0dp"
                    android:orientation="vertical"
                    android:layout_height="wrap_content">

                    <TextView
                        android:text="颜色:黑色"
                        android:id="@+id/item_name"
                        android:textColor="@color/cblack"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textSize="@dimen/common_font_size_12" />

                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="@dimen/margin_5dp"
                        android:layout_marginBottom="@dimen/margin_5dp"  >


                        <TextView
                            android:text="¥185"
                            android:id="@+id/item_price"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:textColor="@color/main_red_text"
                            android:textSize="@dimen/common_font_size_14" />
                    </LinearLayout>

                </LinearLayout>

            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/margin_1dp"
        android:background="@color/background_color" />
</LinearLayout>

 

 

至此,页面写完。下面是公具类:

三. okhttp的单例封装以及拦截器:

1. OkhttpUtils

 

 
import java.io.File; import java.util.Map; import java.util.concurrent.TimeUnit; import okhttp3.FormBody; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; /**  * Okhttp 单例模式进行二次封装  */ public class OkhttpUtils { private static OkhttpUtils okhttpUtils = null ; private OkhttpUtils(){ } public static OkhttpUtils getInstance(){ if(okhttpUtils == null){ okhttpUtils = new OkhttpUtils(); client = new OkHttpClient.Builder() .readTimeout(20, TimeUnit.SECONDS) .writeTimeout(20,TimeUnit.SECONDS) .connectTimeout(20,TimeUnit.SECONDS) //添加拦截器  .addInterceptor(new LoggingInterceptor()) .build(); } return okhttpUtils ; } private static OkHttpClient client ; /**  * 发起异步请求  * @param params  * @param url  * @param callBack  */  public void asy(Map<String,String> params,String url,AbstractUiCallBack callBack){ Request request = null ; if(params != null){ // post 请求  FormBody.Builder builder = new FormBody.Builder() ; for(Map.Entry<String,String> entry : params.entrySet()){ builder.add(entry.getKey(),entry.getValue()); } FormBody body = builder.build(); request = new Request.Builder() .url(url) .post(body) .build(); } else { // get 请求  request = new Request.Builder() .url(url) .build(); } client.newCall(request).enqueue(callBack); } private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); public static void postFile(Map<String,String> map, String url, File file,AbstractUiCallBack callBack){ String [] array = file.getAbsolutePath().split("\\/"); MultipartBody.Builder builder = new MultipartBody.Builder(); builder.setType(MultipartBody.FORM); for(Map.Entry<String,String> entry : map.entrySet()){ builder.addFormDataPart(entry.getKey(),entry.getValue()); } builder.addFormDataPart("imageFileName",array[array.length-1]); if(file.exists() && file.length() > 0){ builder.addFormDataPart("image",array[array.length-1], RequestBody.create(MEDIA_TYPE_PNG,file)); } MultipartBody body = builder.build() ; Request request = new Request.Builder() .url(url) .post(body) .build(); client.newCall(request).enqueue(callBack); } }

2. AbstractUiCallBack

 
import android.os.Handler; import android.os.Looper; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; /**  * Created by muhanxi on 17/11/10.  *  * * Okhttp 单例 范型的封装  */  public abstract class AbstractUiCallBack<T> implements Callback { /**  * 成功回调  * @param t  */  public abstract void success(T t); /**  * 失败回调  * @param e  */  public abstract void failure(Exception e); private Handler handler = null ; private Class clazz ; public AbstractUiCallBack(){ handler = new Handler(Looper.getMainLooper()); // 得到的是一个 AbstractUiCallBack<T> 的Type  Type type = getClass().getGenericSuperclass() ; // 得到的是T的实际Type  Type [] arr = ((ParameterizedType)type).getActualTypeArguments() ; clazz = (Class) arr[0] ; } @Override  public void onFailure(Call call, IOException e) { failure(e); } @Override  public void onResponse(Call call, Response response) throws IOException { try { String result = response.body().string(); System.out.println("result = " + result); Gson gson = new Gson(); final T t = (T) gson.fromJson(result,clazz); handler.post(new Runnable() { @Override  public void run() { success(t); } }); } catch (IOException e) { e.printStackTrace(); failure(e); } catch (JsonSyntaxException e) { e.printStackTrace(); failure(e); } } } 

3. 自定义拦截器,封装公共请求参数

 
import java.io.IOException; import okhttp3.FormBody; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /**  * 自定义拦截器,封装公共请求参数  */ public class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { //首先取到Request  Request request = chain.request(); Response response = null; Request requestProcess = null ; if("GET".equals(request.method())){ String url = request.url().toString() + "&source=android"; Request.Builder builder = request.newBuilder() ; builder.get().url(url); requestProcess = builder.build(); response = chain.proceed(requestProcess); } else { FormBody.Builder builder = new FormBody.Builder() ; RequestBody requestBody = request.body() ; if(requestBody instanceof FormBody){ FormBody formBody = (FormBody)requestBody ; for (int i=0;i<formBody.size();i++){ builder.add(formBody.encodedName(i),formBody.encodedValue(i)); } builder.add("source","android"); } requestProcess = request.newBuilder().url(request.url().toString()).post(builder.build()).build() ; response = chain.proceed(requestProcess); } return response; } 

 

 

 

 

四. ImageLoader类的全局化配置初始化

1. BaseApplication.java

 

import android.app.Application;
//全局初始化Application类
public class BaseApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        //配置imageLoader
        ImageLoaderUtil.init(this);
    }
}

 

 

 

2. ImageLoaderUtil.java

 

import android.content.Context;
import android.graphics.Bitmap;
import com.dhw.lastmonthexam.R;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;
import java.io.File;
public class ImageLoaderUtil {
    /**
     * 初始化imageLoader
     * @param context
     */
    public static void init(Context context) {
        //1.获取配置config对象
        File cacheDir = StorageUtils.getCacheDirectory(context);  //缓存文件夹路径

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)

                .threadPoolSize(3) // default  线程池内加载的数量
                .threadPriority(Thread.NORM_PRIORITY - 2) // default 设置当前线程的优先级
                .tasksProcessingOrder(QueueProcessingType.FIFO) // default
                .denyCacheImageMultipleSizesInMemory()
                .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通过自己的内存缓存实现
                .memoryCacheSize(2 * 1024 * 1024)  // 内存缓存的最大值
                .memoryCacheSizePercentage(13) // default
                .diskCache(new UnlimitedDiscCache(cacheDir)) // default 可以自定义缓存路径
                .diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)缓存的最大值
                .diskCacheFileCount(100)  // 可以缓存的文件数量
                // default为使用HASHCODE对UIL进行加密命名, 还可以用MD5(new Md5FileNameGenerator())加密
                .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
                .imageDownloader(new BaseImageDownloader(context)) // default
                .imageDecoder(new BaseImageDecoder(true)) // default
                .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
                .writeDebugLogs() // 打印debug log
                .build(); //开始构建


        //2.初始化配置...ImageLoader.getInstance()图片加载器的对象,单例模式
        ImageLoader.getInstance().init(config);
    }

    /**
     * imageLoader加载图片的默认选项
     * @return
     */
    public static DisplayImageOptions getDefaultOption(){

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的默认图片
                .showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
                .resetViewBeforeLoading(true)  // default 设置图片在加载前是否重置、复位
                .delayBeforeLoading(1000)  // 下载前的延迟时间
                .cacheInMemory(true) // default  设置下载的图片是否缓存在内存中
                .cacheOnDisk(true) // default  设置下载的图片是否缓存在SD卡中

                .considerExifParams(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示
                .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型

                .displayer(new SimpleBitmapDisplayer()) // default  还可以设置圆角图片new RoundedBitmapDisplayer(20)

                .build();

        return options;
    }

    /**
     * imageLoader加载圆角图片....指定圆角的大小
     * @return
     */
    public static DisplayImageOptions getRoundedOption(int corner){

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的图片
                .showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
                .resetViewBeforeLoading(true)  // default 设置图片在加载前是否重置、复位
                .delayBeforeLoading(1000)  // 下载前的延迟时间
                .cacheInMemory(true) // default  设置下载的图片是否缓存在内存中
                .cacheOnDisk(true) // default  设置下载的图片是否缓存在SD卡中

                .considerExifParams(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示
                .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型

                .displayer(new RoundedBitmapDisplayer(corner)) // default  还可以设置圆角图片new RoundedBitmapDisplayer(20)

                .build();

        return options;
    }

}

到此,全部代码实现完毕。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值