okHttp网络请求2——MVP

6 篇文章 0 订阅
6 篇文章 0 订阅

adapter包

package adapter;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.sax.StartElementListener;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.example.dell.zhoukao3.Main2Activity;
import com.example.dell.zhoukao3.Main3Activity;
import com.example.dell.zhoukao3.R;

import java.util.List;

import bean.Shop;

/**
 * Created by DELL on 2017/10/21.
 */

public class MyAdapter extends RecyclerView.Adapter {

    private Activity context;
    private List<Shop.DataBean> data;
    private final int atype=0;
    private final int btype=1;
    private final int ctype=2;

    public MyAdapter(Activity context, List<Shop.DataBean> data) {
        this.context = context;
        this.data = data;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //View view = View.inflate(context, R.layout.rv_item, null);
        View view=null;
        RecyclerView.ViewHolder holder=null;
        switch (viewType)
        {
            case atype:

                view = View.inflate(context, R.layout.rv_item1, null);
                holder=new ViewHolder1(view);

                break;


            case btype:
                view = View.inflate(context, R.layout.rv_item2, null);
                holder=new ViewHolder2(view);
                break;


            case ctype:
                view = View.inflate(context, R.layout.rv_item3, null);
                holder=new ViewHolder3(view);
                break;
        }
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

        switch (getItemViewType(position))
        {
            case atype:
                ViewHolder1 holder1= (ViewHolder1) holder;
                holder1.tv_name.setText(data.get(position).title);
                holder1.tv_price.setText(data.get(position).price+"");
                String images = data.get(position).images;
                String[] img = images.split("\\|");
                Glide.with(context).load(img[0]).into(holder1.iv);
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                        Intent intent=new Intent(context, Main3Activity.class);
                        intent.putExtra("title",data.get(position).title);
                        context.startActivity(intent);
                    }
                });
                break;
            case btype:
                ViewHolder2 holder2= (ViewHolder2) holder;
                holder2.tv_name.setText(data.get(position).title);
                holder2.tv_price.setText(data.get(position).price+"");
                String images1 = data.get(position).images;
                String[] img1 = images1.split("\\|");
                Glide.with(context).load(img1[0]).into(holder2.iv);
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent=new Intent(context, Main3Activity.class);
                        intent.putExtra("title",data.get(position).title);
                        context.startActivity(intent);
                    }
                });

                break;
            case ctype:
                ViewHolder3 holder3= (ViewHolder3) holder;
                holder3.tv_name.setText(data.get(position).title);
                holder3.tv_price.setText(data.get(position).price+"");
                String images2 = data.get(position).images;
                String[] img2 = images2.split("\\|");
                Glide.with(context).load(img2[0]).into(holder3.iv);
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent=new Intent(context, Main3Activity.class);
                        intent.putExtra("title",data.get(position).title);
                        context.startActivity(intent);
                    }
                });
                break;
        }




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

    public class ViewHolder1 extends RecyclerView.ViewHolder{

        private final TextView tv_name;
        private final TextView tv_price;
        private final ImageView iv;

        public ViewHolder1(View itemView) {
            super(itemView);
            tv_name = itemView.findViewById(R.id.tv_name);
            tv_price = itemView.findViewById(R.id.tv_price);
            iv = itemView.findViewById(R.id.iv);
        }
    }
    public class ViewHolder2 extends RecyclerView.ViewHolder{

        private final TextView tv_name;
        private final TextView tv_price;
        private final ImageView iv;

        public ViewHolder2(View itemView) {
            super(itemView);
            tv_name = itemView.findViewById(R.id.tv_name);
            tv_price = itemView.findViewById(R.id.tv_price);
            iv = itemView.findViewById(R.id.iv);
        }
    }

    public class ViewHolder3 extends RecyclerView.ViewHolder{

        private final TextView tv_name;
        private final TextView tv_price;
        private final ImageView iv;

        public ViewHolder3(View itemView) {
            super(itemView);
            tv_name = itemView.findViewById(R.id.tv_name);
            tv_price = itemView.findViewById(R.id.tv_price);
            iv = itemView.findViewById(R.id.iv);
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(data.get(position).itemtype==0)
        {
            return atype;
        }
        else if(data.get(position).itemtype==1)
        {
            return btype;
        }
        else
        {
            return ctype;
        }
    }
}


Bean类

bean

package bean;

import java.util.List;

/**
 * Created by DELL on 2017/10/21.
 */

public class Shop {
 
    public String msg;
    public String code;
    public String page;
    public List<DataBean> data;

    public static class DataBean {
        
        public double bargainPrice;
        public String createtime;
        public String detailUrl;
        public String images;
        public int itemtype;
        public int pid;
        public double price;
        public int pscid;
        public int salenum;
        public int sellerid;
        public String subhead;
        public String title;
    }
}

Main包

MainActivity

package com.example.dell.zhoukao3;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AnimationSet;
import android.widget.ImageView;
import android.widget.Toast;

import view.CountDownProgress;

public class MainActivity extends AppCompatActivity {

    private ImageView iv;
    private CountDownProgress countDownProgress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
    }

    private void initData() {
        ObjectAnimator animator=ObjectAnimator.ofFloat(iv,"translationY",0f,250f);
        ObjectAnimator animator1=ObjectAnimator.ofFloat(iv,"scaleX",1,2);
        ObjectAnimator animator2=ObjectAnimator.ofFloat(iv,"scaleX",2,1);
        AnimatorSet set=new AnimatorSet();
        set.play(animator1).before(animator2).after(animator);
        set.setDuration(3000);
        set.start();
    }

    private void initView() {
        iv = (ImageView) findViewById(R.id.iv);
        countDownProgress = (CountDownProgress) findViewById(R.id.countdownProgress);
        countDownProgress.setCountdownTime(10*1000);

        countDownProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                countDownProgress.startCountDownTime(new CountDownProgress.OnCountdownFinishListener() {
                    @Override
                    public void countdownFinished() {
                        //Toast.makeText(MainActivity.this, "倒计时结束了--->该UI处理界面逻辑了", Toast.LENGTH_LONG).show();
                        Intent intent=new Intent(MainActivity.this,Main2Activity.class);
                        startActivity(intent);
                    }
                });
                /*Message message = Message.obtain();
                message.what = HANDLER_MESSAGE;
                handler.sendMessage(message);*/
            }
        });
    }
}

Main2Activity

package com.example.dell.zhoukao3;

import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.jcodecraeer.xrecyclerview.XRecyclerView;

import java.io.IOException;
import java.util.List;

import adapter.MyAdapter;
import bean.Shop;
import okhttp3.Call;
import presenter.ShopPresenter;
import view.ShopView;

public class Main2Activity extends AppCompatActivity implements ShopView {
    private String s;
    private SwipeRefreshLayout swiperefreshlayout;
    private XRecyclerView recycler;
    private ShopPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
       // System.out.println(s.equals("any string"));
        initView();
        initData();

    }

    private void initData() {
        presenter = new ShopPresenter(this);


    }

    private void initView() {
        recycler = (XRecyclerView) findViewById(R.id.rv);
        recycler.setLoadingMoreEnabled(true);
        recycler.setPullRefreshEnabled(true);

    }

    @Override
    public void onShopSuccess(final List<Shop.DataBean> data) {
        System.out.println(data.size()+"^^^^^^^^^^^^");
        if(this!=null)
        {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    LinearLayoutManager linearLayoutManager=new LinearLayoutManager(Main2Activity.this);
                    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

                    recycler.setLayoutManager(linearLayoutManager);
                    MyAdapter adapter=new MyAdapter(Main2Activity.this,data);
                    recycler.setAdapter(adapter);

                    recycler.setLoadingListener(new XRecyclerView.LoadingListener() {
                        @Override
                        public void onRefresh() {
                            presenter.requestShop(1);
                            recycler.refreshComplete();
                        }

                        @Override
                        public void onLoadMore() {
                            presenter.requestShop(2);
                            recycler.loadMoreComplete();

                        }
                    });


                }
            });
        }
    }

    @Override
    public void onShopFailure(String msg) {

    }

    @Override
    public void onFailure(Call call, IOException e) {

    }

    @Override
    protected void onResume() {
        super.onResume();
        presenter.requestShop(1);
    }
}

MyApp

package com.example.dell.zhoukao3;

import android.app.Application;

import utils.CrashHandler;

/**
 * Created by DELL on 2017/10/21.
 */

public class MyApp extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        /*CrashHandler crashHandler = CrashHandler.getInstance();
        crashHandler.init(getApplicationContext());*/
    }
}


api类

API

package common;

/**
 * Created by DELL on 2017/10/21.
 */

public class Api {

    public static  final String URL="http://120.27.23.105/product/getProducts?pscid=1";
}


拦截器

Interceptor

package lanjieqi;

import java.io.IOException;

import okhttp3.Connection;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by DELL on 2017/10/21.
 */

public interface Interceptor {
    Response intercept(Chain chain) throws IOException;
    interface Chain{
        Request request();
        Response proceed(Request request)throws IOException;
        Connection connection();

    }

}

LoggingInterceptor

package lanjieqi;

import android.util.Log;

import java.io.IOException;

import okhttp3.*;
import okhttp3.internal.platform.Platform;

/**
 * Created by DELL on 2017/10/21.
 */

public class LoggingInterceptor implements okhttp3.Interceptor {



    public static String TAG = "LogInterceptor";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        long startTime = System.currentTimeMillis();
        Response response = chain.proceed(chain.request());
        long endTime = System.currentTimeMillis();
        long duration=endTime-startTime;
        MediaType mediaType = response.body().contentType();
        String content = response.body().string();
        Log.d(TAG,"\n");
        Log.d(TAG,"----------Start----------------");
        Log.d(TAG, "| "+request.toString());
        String method=request.method();
        if("POST".equals(method)){
            StringBuilder sb = new StringBuilder();
            if (request.body() instanceof FormBody) {
                FormBody body = (FormBody) request.body();
                for (int i = 0; i < body.size(); i++) {
                    sb.append(body.encodedName(i) + "=" + body.encodedValue(i) + ",");
                }
                sb.delete(sb.length() - 1, sb.length());
                Log.d(TAG, "| RequestParams:{"+sb.toString()+"}");
            }
        }
        Log.d(TAG, "| Response:" + content);
        Log.d(TAG,"----------End:"+duration+"毫秒----------");
        return response.newBuilder()
                .body(ResponseBody.create(mediaType, content))
                .build();
    }
}

Model包

ShopModel


package model;

import com.google.gson.Gson;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import bean.Shop;
import common.Api;
import okhttp3.Call;
import okhttp3.Response;
import utils.Callbak;
import utils.NetRequestData;

/**
 * Created by DELL on 2017/10/21.
 */

public class ShopModel {


    private onShop onShop;
    public void getShop(int page){
        Map<String,String> params=new HashMap<>();
        params.put("page",page+"");
        NetRequestData.call(Api.URL, params, new Callbak() {
            @Override
            public void RequestSuccess(Call call, Response response) {
                try {
                    String result = response.body().string();
                    Gson gson=new Gson();
                    Shop shop = gson.fromJson(result, Shop.class);
                    List<Shop.DataBean> data = shop.data;
                    System.out.println("==============="+data.size());
                    String code = shop.code;
                    String msg = shop.msg;
                    if("0".equals(code))
                    {
                        onShop.onShopSuccess(data);
                    }
                    else
                    {
                        onShop.onShopFailure(msg);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void RequestFaliure(Call call, IOException e) {
                onShop.onFailure(call,e);
            }
        });

    }


    public void setOnShop(ShopModel.onShop onShop) {
        this.onShop = onShop;
    }

    public interface onShop{
        void onShopSuccess(List<Shop.DataBean> data);
        void onShopFailure(String msg);
        void onFailure(Call call,IOException e);
    }



}


presenter包

ShopPresenter

package presenter;

import java.io.IOException;
import java.util.List;

import bean.Shop;
import model.ShopModel;
import okhttp3.Call;
import view.ShopView;

/**
 * Created by DELL on 2017/10/21.
 */

public class ShopPresenter implements ShopModel.onShop {

    private ShopModel shopModel;
    private ShopView shopView;

    public ShopPresenter(ShopView shopView) {
        this.shopView = shopView;
        shopModel=new ShopModel();
        shopModel.setOnShop(this);
    }


    public void requestShop(int page){
        shopModel.getShop(page);

    }
    @Override
    public void onShopSuccess(List<Shop.DataBean> data) {
        shopView.onShopSuccess(data);

    }

    @Override
    public void onShopFailure(String msg) {
        shopView.onShopFailure(msg);

    }

    @Override
    public void onFailure(Call call, IOException e) {
        shopView.onFailure(call,e);

    }
}



View

ShopView

package view;

import java.io.IOException;
import java.util.List;

import bean.Shop;
import okhttp3.Call;

/**
 * Created by DELL on 2017/10/21.
 */

public interface ShopView {
    void onShopSuccess(List<Shop.DataBean> data);
    void onShopFailure(String msg);
    void onFailure(Call call, IOException e);
}


Utils包

Callbak类

package utils;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Response;

/**
 * Created by DELL on 2017/10/21.
 */

public interface Callbak {
    void RequestSuccess(Call call, Response response);
    void RequestFaliure(Call call, IOException e);
}



CrashHandler

package utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
/**
 * Created by DELL on 2017/10/21.
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    public static final String TAG = "CrashHandler";

    //系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //CrashHandler实例
    private static CrashHandler INSTANCE = new CrashHandler();
    //程序的Context对象
    private Context mContext;
    //用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();

    //用于格式化日期,作为日志文件名的一部分
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

    /** 保证只有一个CrashHandler实例 */
    private CrashHandler() {
    }

    /** 获取CrashHandler实例 ,单例模式 */
    public static CrashHandler getInstance() {
        return INSTANCE;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context;
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当UncaughtException发生时会转入该函数来处理
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }
            //退出程序
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();
        //收集设备参数信息
        collectDeviceInfo(mContext);
        //保存日志文件
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * 收集设备参数信息
     * @param ctx
     */
    public void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return  返回文件名称,便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {

        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = "crash-" + time + "-" + timestamp + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = "/mnt/sdcard/";
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(sb.toString().getBytes());
                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }
}


NetRequestDate类

package utils;

import java.io.IOException;
import java.util.Map;

import lanjieqi.LoggingInterceptor;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by DELL on 2017/10/21.
 */

public class NetRequestData {

    public static void call(String url, Map<String,String> params, final Callbak callbak){


        OkHttpClient client=new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())
                .build();

        FormBody.Builder body= new FormBody.Builder();
        for (Map.Entry<String, String> stringStringEntry : params.entrySet()) {

            body.add(stringStringEntry.getKey(),stringStringEntry.getValue());
        }

        RequestBody build = body.build();

        Request request=new Request.Builder().url(url).header("User-Agent", "OkHttp Example").post(build).build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

                callbak.RequestFaliure(call,e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                callbak.RequestSuccess(call,response);
            }
        });


    }




}


CountDownProgress 属性动画

package view;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;

import com.example.dell.zhoukao3.R;

/**
 * Created by DELL on 2017/10/21.
 */

public class CountDownProgress extends View {

    private static int defaultCircleSolideColor = Color.BLUE;
    private static int defaultCircleStrokeColor = Color.WHITE;
    private static int defaultCircleStrokeWidth = 8;
    private static int defaultCircleRadius = 200;
    private static int progressColor = Color.RED;
    private static int progressWidth = 4;
    private static int smallCircleSolideColor = Color.BLACK;
    private static int smallCircleStrokeColor = Color.WHITE;
    private static float smallCircleStrokeWidth = 8;
    private static float smallCircleRadius = 30;
    private static int textColor = Color.BLACK;
    private static float textSize = 30;
    private static Paint defaultCriclePaint;
    private static Paint progressPaint;
    private static Paint smallCirclePaint;
    private static Paint smallCircleSolidePaint;
    private static Paint textPaint;
    private static float currentAngle;
    private static String textDesc;
    private static long countdownTime;
    private static int mStartSweepValue = -90;


    public CountDownProgress(Context context) {
        super(context);
    }

    public CountDownProgress(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CountDownProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义属性
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CountDownProgress);
        int indexCount = typedArray.getIndexCount();
        for(int i=0;i<indexCount;i++){
            int attr = typedArray.getIndex(i);
            switch (attr){
                case R.styleable.CountDownProgress_default_circle_solide_color:
                    defaultCircleSolideColor = typedArray.getColor(attr, defaultCircleSolideColor);
                    break;
                case R.styleable.CountDownProgress_default_circle_stroke_color:
                    defaultCircleStrokeColor = typedArray.getColor(attr, defaultCircleStrokeColor);
                    break;
                case R.styleable.CountDownProgress_default_circle_stroke_width:
                    defaultCircleStrokeWidth = (int) typedArray.getDimension(attr, defaultCircleStrokeWidth);
                    break;
                case R.styleable.CountDownProgress_default_circle_radius:
                    defaultCircleRadius = (int) typedArray.getDimension(attr, defaultCircleRadius);
                    break;
                case R.styleable.CountDownProgress_progress_color:
                    progressColor = typedArray.getColor(attr, progressColor);
                    break;
                case R.styleable.CountDownProgress_progress_width:
                    progressWidth = (int) typedArray.getDimension(attr, progressWidth);
                    break;
                case R.styleable.CountDownProgress_small_circle_solide_color:
                    smallCircleSolideColor = typedArray.getColor(attr, smallCircleSolideColor);
                    break;
                case R.styleable.CountDownProgress_small_circle_stroke_color:
                    smallCircleStrokeColor = typedArray.getColor(attr, smallCircleStrokeColor);
                    break;
                case R.styleable.CountDownProgress_small_circle_stroke_width:
                    smallCircleStrokeWidth = (int) typedArray.getDimension(attr, smallCircleStrokeWidth);
                    break;
                case R.styleable.CountDownProgress_small_circle_radius:
                    smallCircleRadius = (int) typedArray.getDimension(attr, smallCircleRadius);
                    break;
                case R.styleable.CountDownProgress_text_color:
                    textColor = typedArray.getColor(attr, textColor);
                    break;
                case R.styleable.CountDownProgress_text_size:
                    textSize = (int) typedArray.getDimension(attr, textSize);
                    break;
            }
        }
        typedArray.recycle();
    }

    private void setPaint() {
        //默认圆
        defaultCriclePaint = new Paint();
        defaultCriclePaint.setAntiAlias(true);//抗锯齿
        defaultCriclePaint.setDither(true);//防抖动
        defaultCriclePaint.setStyle(Paint.Style.STROKE);
        defaultCriclePaint.setStrokeWidth(defaultCircleStrokeWidth);
        defaultCriclePaint.setColor(defaultCircleStrokeColor);//这里先画边框的颜色,后续再添加画笔画实心的颜色
        //默认圆上面的进度弧度
        progressPaint = new Paint();
        progressPaint.setAntiAlias(true);
        progressPaint.setDither(true);
        progressPaint.setStyle(Paint.Style.STROKE);
        progressPaint.setStrokeWidth(progressWidth);
        progressPaint.setColor(progressColor);
        progressPaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔笔刷样式
        //进度上面的小圆
        smallCirclePaint = new Paint();
        smallCirclePaint.setAntiAlias(true);
        smallCirclePaint.setDither(true);
        smallCirclePaint.setStyle(Paint.Style.STROKE);
        smallCirclePaint.setStrokeWidth(smallCircleStrokeWidth);
        smallCirclePaint.setColor(smallCircleStrokeColor);
        //画进度上面的小圆的实心画笔(主要是将小圆的实心颜色设置成白色)
        smallCircleSolidePaint = new Paint();
        smallCircleSolidePaint.setAntiAlias(true);
        smallCircleSolidePaint.setDither(true);
        smallCircleSolidePaint.setStyle(Paint.Style.FILL);
        smallCircleSolidePaint.setColor(smallCircleSolideColor);

        //文字画笔
        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setPaint();
        canvas.save();
        canvas.translate(getPaddingLeft(), getPaddingTop());
        //画默认圆
        canvas.drawCircle(defaultCircleRadius, defaultCircleRadius, defaultCircleRadius, defaultCriclePaint);

        //画进度圆弧
        //currentAngle = getProgress()*1.0f/getMax()*360;
        canvas.drawArc(new RectF(0, 0, defaultCircleRadius*2, defaultCircleRadius*2),mStartSweepValue, 360*currentAngle,false,progressPaint);
        //画中间文字
        // String text = getProgress()+"%";
        //获取文字的长度的方法
        /* float textWidth = textPaint.measureText(textDesc);
         float textHeight = (textPaint.descent() + textPaint.ascent()) / 2;
         canvas.drawText(textDesc, defaultCircleRadius - textWidth/2, defaultCircleRadius - textHeight, textPaint);*/

        //画小圆
        float currentDegreeFlag = 360*currentAngle;
        float smallCircleX = 0,smallCircleY = 0;
        float hudu = (float) Math.abs(Math.PI * currentDegreeFlag / 180);//Math.abs:绝对值 ,Math.PI:表示π , 弧度 = 度*π / 180
        smallCircleX = (float) Math.abs(Math.sin(hudu) * defaultCircleRadius + defaultCircleRadius);
        smallCircleY = (float) Math.abs(defaultCircleRadius -Math.cos(hudu) * defaultCircleRadius);
        canvas.drawCircle(smallCircleX, smallCircleY, smallCircleRadius, smallCirclePaint);
        canvas.drawCircle(smallCircleX, smallCircleY, smallCircleRadius - smallCircleStrokeWidth, smallCircleSolidePaint);//画小圆的实心

        canvas.restore();

    }

    /**
     * 如果该View布局的宽高开发者没有精确的告诉,则需要进行测量,如果给出了精确的宽高则我们就不管了
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize;
        int heightSize;
        int strokeWidth = Math.max(defaultCircleStrokeWidth, progressWidth);
        if(widthMode != MeasureSpec.EXACTLY){
            widthSize = getPaddingLeft() + defaultCircleRadius*2 + strokeWidth + getPaddingRight();
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
        }
        if(heightMode != MeasureSpec.EXACTLY){
            heightSize = getPaddingTop() + defaultCircleRadius*2 + strokeWidth + getPaddingBottom();
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    //属性动画
    public void startCountDownTime(final OnCountdownFinishListener countdownFinishListener){
        setClickable(false);
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1.0f);
        //动画时长,让进度条在CountDown时间内正好从0-360走完,这里由于用的是CountDownTimer定时器,倒计时要想减到0则总时长需要多加1000毫秒,所以这里时间也跟着+1000ms
        animator.setDuration(3000);
        animator.setInterpolator(new LinearInterpolator());//匀速
        animator.setRepeatCount(0);//表示不循环,-1表示无限循环
        //值从0-1.0F 的动画,动画时长为countdownTime,ValueAnimator没有跟任何的控件相关联,那也正好说明ValueAnimator只是对值做动画运算,而不是针对控件的,我们需要监听ValueAnimator的动画过程来自己对控件做操作
        //添加监听器,监听动画过程中值的实时变化(animation.getAnimatedValue()得到的值就是0-1.0)
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                /**
                 * 这里我们已经知道ValueAnimator只是对值做动画运算,而不是针对控件的,因为我们设置的区间值为0-1.0f
                 * 所以animation.getAnimatedValue()得到的值也是在[0.0-1.0]区间,而我们在画进度条弧度时,设置的当前角度为360*currentAngle,
                 * 因此,当我们的区间值变为1.0的时候弧度刚好转了360度
                 */
                currentAngle = (float) animation.getAnimatedValue();
                //       Log.e("currentAngle",currentAngle+"");
                invalidate();//实时刷新view,这样我们的进度条弧度就动起来了
            }
        });
        //开启动画
        animator.start();
        //还需要另一个监听,监听动画状态的监听器
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //倒计时结束的时候,需要通过自定义接口通知UI去处理其他业务逻辑
                if(countdownFinishListener != null){
                    countdownFinishListener.countdownFinished();
                }
                if(countdownTime > 0){
                    setClickable(true);
                }else{
                    setClickable(false);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        //调用倒计时操作
        countdownMethod();
    }

    //倒计时的方法
    private void countdownMethod(){
        new CountDownTimer(countdownTime+1000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                //         Log.e("time",countdownTime+"");
                countdownTime = countdownTime-1000;
                textDesc = countdownTime/1000 + "″";
                //countdownTime = countdownTime-1000;
                Log.e("time",countdownTime+"");
                //刷新view
                invalidate();
            }
            @Override
            public void onFinish() {
                //textDesc = 0 + "″";
                textDesc = "时间到";
                //同时隐藏小球
                smallCirclePaint.setColor(getResources().getColor(android.R.color.transparent));
                smallCircleSolidePaint.setColor(getResources().getColor(android.R.color.transparent));
                //刷新view
                invalidate();
            }
        }.start();
    }
    public void setCountdownTime(long countdownTime){
        this.countdownTime = countdownTime;
        textDesc = countdownTime / 1000 + "″";
    }

    public interface OnCountdownFinishListener {
        void countdownFinished();
    }
}



attr

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundProgressBar">
        <attr name="radius" format="dimension"></attr>
        <attr name="roundColor" format="color" />
        <attr name="roundProgressOneColor" format="color" />
        <attr name="roundProgressTwoColor" format="color" />
        <attr name="roundProgressThreeColor" format="color" />
        <attr name="roundWidth" format="dimension"></attr>
        <attr name="roundProgressOneWidth" format="dimension" />
        <attr name="roundProgressTwoWidth" format="dimension" />
        <attr name="roundProgressThreeWidth" format="dimension" />
        <attr name="smallRoundWidth" format="dimension" />
        <attr name="topTextColor" format="color" />
        <attr name="bottomTextColor" format="color" />
        <attr name="topTextSize" format="dimension" />
        <attr name="bottomTextSize" format="dimension" />
        <attr name="lineColor" format="color" />
        <attr name="lineWidth" format="dimension" />
        <attr name="max" format="integer"></attr>
        <attr name="textIsDisplayable" format="boolean"></attr>
    </declare-styleable>

    <declare-styleable name="CountDownProgress">

        <!-- 默认圆实心的颜色 -->
        <attr name="default_circle_solide_color" format="color"/>
        <!-- 默认圆边框的颜色 -->
        <attr name="default_circle_stroke_color" format="color"/>
        <!-- 默认圆边框的宽度 -->
        <attr name="default_circle_stroke_width" format="dimension"/>
        <!-- 默认圆的半径 -->
        <attr name="default_circle_radius" format="dimension"/>
        <!-- 进度条的颜色 -->
        <attr name="progress_color" format="color"/>
        <!-- 进度条的宽度 -->
        <attr name="progress_width" format="dimension"/>
        <!-- 小圆的实心颜色 -->
        <attr name="small_circle_solide_color" format="color"/>
        <!-- 小圆的边框颜色 -->
        <attr name="small_circle_stroke_color" format="color"/>
        <!-- 小圆的边框宽度 -->
        <attr name="small_circle_stroke_width" format="dimension"/>
        <!-- 小圆的半径 -->
        <attr name="small_circle_radius" format="dimension"/>
        <!-- 文字的颜色 -->
        <attr name="text_color" format="color"/>
        <!-- 文字的字体大小 -->
        <attr name="text_size" format="dimension"/>
    </declare-styleable>
</resources>


权限

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


依赖


compile 'com.squareup.okhttp3:okhttp:3.9.0'
    compile 'org.kie.modules:com-google-code-gson:6.5.0.Final'
    compile 'com.google.code.gson:gson:2.8.2'
    compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.jcodecraeer:xrecyclerview:1.3.2'


Main布局

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.example.dell.zhoukao3.MainActivity"
    android:orientation="vertical"
    android:weightSum="1">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

   <!-- <view.CountDownProgress
        android:id="@+id/countdownprogress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />-->


    <view.CountDownProgress
        android:id="@+id/countdownProgress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        />


</LinearLayout>


Main2布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="com.example.dell.zhoukao3.Main2Activity">


  <!-- <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swiperefreshlayout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="vertical"
        >
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            ></android.support.v7.widget.RecyclerView>
    </android.support.v4.widget.SwipeRefreshLayout>-->

    <com.jcodecraeer.xrecyclerview.XRecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></com.jcodecraeer.xrecyclerview.XRecyclerView>
</RelativeLayout>


Main3布局

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.example.dell.zhoukao3.Main3Activity">

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


</LinearLayout>

rv_item布局

<?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="match_parent">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="84dp"
        android:src="@mipmap/ic_launcher"
        android:padding="10dp"/>

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

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="title"
        android:padding="5dp"/>

        <TextView
            android:id="@+id/tv_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="price"
            android:padding="5dp"/>
</LinearLayout>
</LinearLayout>


rv_item1布局

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

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="84dp"
        android:src="@mipmap/ic_launcher"
        android:padding="10dp"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="title"
            android:padding="5dp"/>

        <TextView
            android:id="@+id/tv_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="price"
            android:padding="5dp"/>
    </LinearLayout>

</LinearLayout>


rv_item2

<?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="match_parent">

    <ImageView
    android:id="@+id/iv"
    android:layout_width="wrap_content"
    android:layout_height="84dp"
    android:src="@mipmap/ic_launcher"
    android:padding="10dp"/>

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

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="title"
            android:padding="5dp"/>

        <TextView
            android:id="@+id/tv_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="price"
            android:padding="5dp"/>
    </LinearLayout>

</LinearLayout>


rv_item3

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

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

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>
</LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="title"
            android:padding="5dp"/>

        <TextView
            android:id="@+id/tv_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="price"
            android:padding="5dp"/>
    </LinearLayout>



</LinearLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值