华域联盟 Andriod Android自定义控件实现支付宝记账饼图

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"); 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持华域联盟。

本文由 华域联盟 原创撰写:华域联盟 » Android自定义控件实现支付宝记账饼图

转载请保留出处和原文链接:https://www.cnhackhy.com/106361.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

Android Studio彻底删除项目 Android Studio彻底删除Module

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们