首页 > 系统 > Android > 正文

Android自定义控件实现支付宝记账饼图

2019-10-22 18:13:10
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android实现支付宝记账饼图,点击旋转到最下面,供大家参考,具体内容如下

Android,支付宝,记账

代码:

package com.example.a_102.myapplication7.ui;  import java.util.ArrayList; import java.util.List;   import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.AccelerateInterpolator;  import com.example.a_102.myapplication7.util.Util;  /**  *  */ public class SelectPieView extends View {   private static final String TAG = "CustomPie_tag";  private int width;  private SelectPieCallBack mCallBack;  private boolean initPostion = false;  /**   * 当前选中的区域   */  private int currentDownPostion;   public SelectPieView(Context context) {   super(context);  }   public SelectPieView(Context context, AttributeSet attrs) {   super(context, attrs);  }   public SelectPieView(Context context, AttributeSet attrs, int defStyleAttr) {   super(context, attrs, defStyleAttr);  }   @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   super.onMeasure(widthMeasureSpec, heightMeasureSpec);   int width;   int hight;    int widthmode = MeasureSpec.getMode(widthMeasureSpec);   int widthsize = MeasureSpec.getSize(widthMeasureSpec);    int hightmode = MeasureSpec.getMode(heightMeasureSpec);   int hightsize = MeasureSpec.getSize(heightMeasureSpec);    if (MeasureSpec.EXACTLY == widthmode) {    width = widthsize;   } else {    width = 200;    if (MeasureSpec.AT_MOST == widthmode) {     width = Math.min(widthsize, 200);    }   }    if (MeasureSpec.EXACTLY == hightmode) {    hight = hightsize;   } else {    hight = 200;    if (MeasureSpec.AT_MOST == hightmode) {     hight = Math.min(hightsize, 200);    }   }    setMeasuredDimension(Math.min(width, hight), Math.min(width, hight));  }   /**   * 笔宽   */  private int mPaintWid;  /**   * 外边圆半径   */  private int mOutRoot;  /**   * 内边圆半径   */  private int mIntRoot;  /**   * 空白处宽度   */  private int emptysize = -1;  /**   * 点击前的圆和点击后的圆半径差距   */  private float betweenSize = 10;  /**   * 向限   */  private int XIANGXAIN;  /**   * 开始的角度   */  private float start = 360;  /**   * 旋转过的角度   */  private List<startAndRoatData> haveRoats = new ArrayList<>();  /**   *   */  private String mTitle = "总消费";  /**   *   */  private String mSubTitle = "00";  /**   *   */  private String mSubTitleDot = "00";  /**   * 是否在运行   */  private boolean isRun = true;   private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);   private Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  /**   * 整数部分   */  private Paint textPaintSubTitle= new Paint(Paint.ANTI_ALIAS_FLAG);  /**   * 小数部分   */  private Paint textPaintSubTitleDot= new Paint(Paint.ANTI_ALIAS_FLAG);   @Override  protected void onDraw(Canvas canvas) {   // reSetData();   if (null == datas || datas.size() == 0)    return;   width = getWidth();   mOutRoot = width / 2;   mPaintWid = Util.dip2px(getContext(), 40);   mIntRoot = mOutRoot - mPaintWid;    paint.setStyle(Paint.Style.STROKE);   paint.setColor(Color.RED);   paint.setStrokeWidth(mPaintWid);   RectF rt = new RectF(mPaintWid / 2 + betweenSize, mPaintWid / 2 + betweenSize,     width - mPaintWid / 2 - betweenSize, width - mPaintWid / 2 - betweenSize);   RectF rt2 = new RectF(mPaintWid / 2, mPaintWid / 2, width - mPaintWid / 2, width - mPaintWid / 2);    int size = datas.size();   float allValues = 0;   for (int i = 0; i < datas.size(); i++) {    allValues += datas.get(i).getValuse();   }   // allValues = allValues + emptysize * size;   float sigleSize = (360 - emptysize * datas.size()) / (allValues * 1f);    float end = 0;   haveRoats.clear();   for (int i = 0; i < size; i++) {    paint.setColor(getResources().getColor(datas.get(i).getColor()));    end = datas.get(i).getValuse() * sigleSize;     if (!isRun && datas.get(i).getPostion() == currentDownPostion && datas.size()>1) {     canvas.drawArc(rt2, start + 3, end - 6, false, paint);     canvas.drawArc(rt, start + 3, end - 6, false, paint);    } else {     canvas.drawArc(rt, start, end, false, paint);    }    Log.i(TAG, "first=" + start % 360 + "==" + end + "postion=" + datas.get(i).getPostion());     haveRoats.add(new startAndRoatData(datas.get(i).getPostion(), start % 360, end));     start = start + end + emptysize;    }    textPaint.setStrokeWidth(Util.dip2px(getContext(), 1));   /** 画图片 */   for (int i = 0; i < haveRoats.size(); i++) {    startAndRoatData startAndRoatData = haveRoats.get(i);     float x = 0;    float y = 0;     if (!isRun && currentDownPostion == haveRoats.get(i).getPostion() && datas.size()>1) {      x = (float) (Math       .cos(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))       * (mIntRoot + mPaintWid / 2) + mOutRoot);     y = (float) (Math       .sin(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))       * (mIntRoot + mPaintWid / 2) + mOutRoot);    } else {     x = (float) (Math       .cos(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))       * (mIntRoot + mPaintWid / 2 - betweenSize) + mOutRoot);     y = (float) (Math       .sin(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))       * (mIntRoot + mPaintWid / 2 - betweenSize) + mOutRoot);    }     Rect rect = new Rect((int) (x - mPaintWid / 3), (int) (y - mPaintWid / 3), (int) (x + mPaintWid / 3),      (int) (y + mPaintWid / 3));     int width = BitmapFactory.decodeResource(getResources(), datas.get(i).getIcon()).getWidth();    // L=n(圆心角度数)× π(圆周率)× r(半径)/180(角度制)    if (startAndRoatData.getRoatAng() * Math.PI * (mIntRoot + mPaintWid / 2) / 180 > width) {     canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), datas.get(i).getIcon()), null, rect,       null);    }   }    textPaint.setStyle(Paint.Style.FILL);   textPaint.setTextSize(Util.dip2px(getContext(), 14));   /** 写文字 */   canvas.drawText(mTitle, width / 2 - (textPaint.measureText(mTitle)) / 2,     width / 2 - Util.dip2px(getContext(), 8), textPaint);    textPaintSubTitle.setTextSize(Util.dip2px(getContext(), 20));   canvas.drawText(mSubTitle,     width / 2 - (textPaintSubTitle.measureText(mSubTitle)) / 2 - (textPaintSubTitleDot.measureText("."+mSubTitleDot) / 2),     width / 2 + Util.dip2px(getContext(), 15), textPaintSubTitle);    textPaintSubTitleDot.setTextSize(Util.dip2px(getContext(), 15));   canvas.drawText("." + mSubTitleDot,     width / 2 + textPaintSubTitle.measureText(mSubTitle) /2 - (textPaintSubTitleDot.measureText("." + mSubTitleDot))/2,     width / 2 + Util.dip2px(getContext(), 15), textPaintSubTitleDot);   //Toast.makeText(getContext(), "=="+textPaint.measureText(mSubTitle), Toast.LENGTH_SHORT).show();   /** 测试基线 */   /*    * paint.setColor(Color.BLACK);    * paint.setStrokeWidth(Util.dip2px(getContext(), 1));    *    * canvas.drawLine(0, width / 2, width, width / 2, paint);    * canvas.drawLine(width / 2, 0, width / 2, width, paint);    */   /**    * 初始化位置    * */   if (!initPostion) {    initPostion = true;     startAndRoatData roatData = haveRoats.get(0);    float currentCenterAng = roatData.getStartAng() + roatData.getRoatAng() / 2;    if (currentCenterAng < 90) {     starRoat(start, start + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), false);    } else if (currentCenterAng > 90 && currentCenterAng < 270) {     starRoat(start, start - (currentCenterAng - 90), false);    } else {     starRoat(start, start + 360 + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), false);    }    currentDownPostion = roatData.getPostion();    isRun = false;    invalidate();   }   }   /**   * 设置显示金额   *   * @param number   */  public void setNumber(String number) {   if (TextUtils.isEmpty(number)) {    number = "0.00";   }   if (number.contains(".")) {    String[] split = number.split("//.");    mSubTitle = split[0];    mSubTitleDot = split[1];   } else {    mSubTitle = number;    mSubTitleDot = "00";   }   if (mSubTitleDot.length() > 2) {    mSubTitleDot = mSubTitleDot.substring(0, 2);   }  }   private int Lxy2;   @Override  public boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {   case MotionEvent.ACTION_DOWN:    float x = event.getX();    float y = event.getY();    double atan = Math.atan((x - mOutRoot) / (mOutRoot - y));    double currntAngle = (atan / Math.PI * 180);    double clickAngle = 0;    Lxy2 = (int) Math.pow(x - mOutRoot, 2) + (int) Math.pow(mOutRoot - y, 2);    if (Math.pow(mIntRoot, 2) < Lxy2 && Lxy2 < Math.pow(mOutRoot, 2)) {      if (x > width / 2 && y > width / 2) {      /** currntAngle第四象限是负数 */      // starRoat(start, (float) (start - currntAngle), true);      clickAngle = currntAngle +90;      } else if (x > width / 2 && y < width / 2) {      /** currntAngle第一象限是负数 */      //starRoat(start, (float) (start + 180 - currntAngle), true);      clickAngle = currntAngle +270;     } else if (x < width / 2 && y < width / 2) {      /** currntAngle第二象限是正数 */      //starRoat(start, (float) (start - (180 - Math.abs(currntAngle))), true);      clickAngle = currntAngle +270;     } else {      /** currntAngle第三象限是正数 */      //starRoat(start, (float) (start - Math.abs(currntAngle)), true);      clickAngle = currntAngle +90;     }      int i = clickDownPostion(clickAngle);     startAndRoatData roatData = haveRoats.get(i);     currentDownPostion = roatData.getPostion();     float currentCenterAng = roatData.getStartAng() + roatData.getRoatAng() / 2;     if (currentCenterAng < 90) {      starRoat(start, start + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), true);     } else if (currentCenterAng > 90 && currentCenterAng < 270) {      starRoat(start, start - (currentCenterAng - 90), true);     } else {      starRoat(start, start + 360 + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), true);     }     }     return true;   }    return super.onTouchEvent(event);  }   private int clickDownPostion(double clickAngle) {   for (int i = 0; i < haveRoats.size(); i++) {    startAndRoatData data = haveRoats.get(i);    if ((data.getStartAng() < clickAngle && data.getStartAng() + data.getRoatAng() > clickAngle)      || (data.getStartAng() + data.getRoatAng() > 360        && ((data.getStartAng() + data.getRoatAng()) % 360) > clickAngle)) {     return i;    }   }   return 0;  }   @TargetApi(Build.VERSION_CODES.HONEYCOMB)  public void starRoat(final float star, final float end, boolean isSmooth) {   ValueAnimator valueAnimator = ValueAnimator.ofFloat(star, end);   valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator animation) {     float animatedValue = (float) animation.getAnimatedValue();     start = animatedValue;     isRun = true;     invalidate();    }   });   valueAnimator.setDuration(isSmooth ? (long) (700) : 10);   valueAnimator.setInterpolator(new AccelerateInterpolator());   valueAnimator.start();   valueAnimator.addListener(new Animator.AnimatorListener() {    @Override    public void onAnimationStart(Animator animation) {     }     @Override    public void onAnimationEnd(Animator animation) {      if (currentDownPostion == -1) {      start++;      starRoat(start, start++, false);     } else {      isRun = false;      invalidate();//画突出部分      mCallBack.currentPostion(currentDownPostion);     }    }     @Override    public void onAnimationCancel(Animator animation) {     }     @Override    public void onAnimationRepeat(Animator animation) {     }   });  }   private List<PieData> datas = new ArrayList<>();   public void reSetData(List<PieData> data) {   datas.clear();   datas.addAll(data);   float all =0;   for (PieData da : datas) {    all += da.getValuse();   }   if (all < 360) {    for (PieData da : datas) {     da.setValuse(da.getValuse() * 200);    }   }   for (PieData da : datas) {    all += da.getValuse();   }   /**强制设置最低值*/   for (PieData da : datas) {    if (da.getValuse() / all < 0.03) {     da.setValuse((float) (all * 0.03));    }   }    invalidate();   }   /**   * 判断当前选择的所在区间   *   * @return   */  private int findCurrentDownPostion() {   if (haveRoats == null || haveRoats.size() <= 0) {    return 1;   }    for (int i = 0; i < haveRoats.size(); i++) {     float startAng = haveRoats.get(i).getStartAng();    float roatAng = haveRoats.get(i).getRoatAng();    //Utility.Logi(TAG, "currentpostion=sstar=" + startAng + "===rroat=" + roatAng);    if (startAng < 90 && (startAng <= 90 && startAng + roatAng > 90)) {     // Utility.Logi(TAG, "currentpostion=" + haveRoats.get(i).getPostion());     return haveRoats.get(i).getPostion();    } else if (startAng > 90 && startAng - 360 + roatAng > 90) {     //Utility.Logi(TAG, "currentpostion=" + haveRoats.get(i).getPostion());     return haveRoats.get(i).getPostion();    }   }   return -1;  }   public void setCallBack(SelectPieCallBack callBack) {   this.mCallBack = callBack;  }   public interface SelectPieCallBack {   void currentPostion(int postion);  }   public static class PieData {    public PieData(int postion, float valuse, int color, int icon) {    this.postion = postion;    this.valuse = valuse;    this.color = color;    this.icon = icon;   }    private int postion;    private float valuse;    private int color;    private int icon;    public int getPostion() {    return postion;   }    public void setPostion(int postion) {    this.postion = postion;   }    public float getValuse() {    return valuse;   }    public void setValuse(float valuse) {    this.valuse = valuse;   }    public int getColor() {    return color;   }    public void setColor(int color) {    this.color = color;   }    public int getIcon() {    return icon;   }    public void setIcon(int icon) {    this.icon = icon;   }  }   class startAndRoatData {    private int postion;    private float startAng;    private float roatAng;    public startAndRoatData(int postion, float startAng, float roatAng) {    this.postion = postion;    this.startAng = startAng;    this.roatAng = roatAng;   }    public int getPostion() {    return postion;   }    public void setPostion(int postion) {    this.postion = postion;   }    public float getStartAng() {    return startAng;   }    public void setStartAng(float startAng) {    this.startAng = startAng;   }    public float getRoatAng() {    return roatAng;   }    public void setRoatAng(float roatAng) {    this.roatAng = roatAng;   }    @Override   public String toString() {    return "startAndRoatData{" + "postion=" + postion + ", startAng=" + startAng + ", roatAng=" + roatAng + '}';   }  } } 

用法如下:

SelectPieView mPie = (SelectPieView) findViewById(R.id.pie); mPie.setCallBack(new SelectPieView.SelectPieCallBack() {  @Override  public void currentPostion(int postion) {   Toast.makeText(CustomViewActivity.this, "postion="+postion, Toast.LENGTH_SHORT).show();  } }); ArrayList<SelectPieView.PieData> datas = new ArrayList<>(); datas.add(new SelectPieView.PieData(1, 200.3f, R.color.read_color, R.drawable.arrow)); datas.add(new SelectPieView.PieData(2, 200.3f, R.color.hx_red, R.drawable.arrow)); datas.add(new SelectPieView.PieData(3, 200.3f, R.color.text_blue, R.drawable.arrow)); mPie.reSetData(datas); mPie.setNumber("333.33"); 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表