android自定义环形对比图(外环有类似进度条的旋转动画)




1.首先在res/values里创建一个attr.xml的文件。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <declare-styleable name="AnswerChartView">
        <attr name="radius" format="dimension"/>
        <attr name="strokeWidth" format="dimension"/>
        <attr name="circleColor" format="color"/>
        <attr name="innerringColor" format="color"/>
        <attr name="outringColor" format="color"/>
        <attr name="textSize" format="dimension"/>
    </declare-styleable>
    
</resources>


2.然后为自定义对比图View

package com.jsle.ebag.answer.view;


import com.jsle.ebag.answer.R;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.view.View;


/**
 * 弧线对比图
 * @param
 * @return
 * @author LH
 * @data 2016年1月25日 下午6:17:34
 **/
public class AnswerChartView extends View {


	// 圆画笔
	private Paint mCirclePaint;
	// 圆环画笔
	private Paint mRingPaint;
	// 百分数画笔
	private Paint mTextPaint;
	// 文本画笔
	private Paint mTextPaint2;
	// 里面圆颜色
	private int mCircleColor;
	// 里面弧颜色
	private int mInnerRingColor;
	// 外面弧颜色
	private int mOutRingColor;
	// 空白的圆半径
	private float mRadius;
	// 里面的弧半径
	private float mRingRadius;
	// 最外弧半径
	private float mRingRadius2;
	// 圆环的宽度
	private float mStrokeWidth;
	// 文本的中心x轴位置
	private int mXCenter;
	// 文本的中心y轴位置
	private int mYCenter;
	// 百分比文本的宽度
	private float mTxtWidth;
	// 描述文本的宽度
	private float mTxtWidth2;
	// 文本的高度
	private float mTxtHeight;
	// 百分数文本的大小
	private float mTxtSize;
	// 总成绩
	private int mTotalProgress = 100;
	// 个人的正确率
	private double mInnerProgress;
	// 班级的正确率
	private double mOutProgress;
	public AnswerChartView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initAttrs(context, attrs);
		initVariable();
	}


	private void initAttrs(Context context, AttributeSet attrs) {
		TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs,
				R.styleable.AnswerChartView, 0, 0);
		mRadius = typeArray.getDimension(R.styleable.AnswerChartView_radius, 80);
		mTxtSize=typeArray.getDimension(R.styleable.AnswerChartView_textSize, 20);
		mStrokeWidth = typeArray.getDimension(R.styleable.AnswerChartView_strokeWidth, 10);
		mCircleColor = typeArray.getColor(R.styleable.AnswerChartView_circleColor, 0xFFFFFFFF);
		mOutRingColor = typeArray.getColor(R.styleable.AnswerChartView_innerringColor, 0xFFFFFFFF);
		mInnerRingColor = typeArray.getColor(R.styleable.AnswerChartView_outringColor, 0xFFFFFFFF);
		mRingRadius = mRadius + mStrokeWidth / 2;
		mRingRadius2 = mRadius + mStrokeWidth/2*3;
	}


	private void initVariable() {
		mCirclePaint = new Paint();
		mCirclePaint.setAntiAlias(true);
		mCirclePaint.setStyle(Paint.Style.FILL);


		mRingPaint = new Paint();
		mRingPaint.setAntiAlias(true);
		mRingPaint.setColor(mInnerRingColor);
		mRingPaint.setStyle(Paint.Style.STROKE);
		mRingPaint.setStrokeWidth(mStrokeWidth);


		mTextPaint = new Paint();
		mTextPaint.setAntiAlias(true);
		mTextPaint.setStyle(Paint.Style.FILL);
		mTextPaint.setARGB(255, 32, 207, 152);
		mTextPaint.setTextSize(mTxtSize);
		
		mTextPaint2 = new Paint();
		mTextPaint2.setAntiAlias(true);
		mTextPaint2.setStyle(Paint.Style.FILL);
		mTextPaint2.setARGB(255, 0, 0, 0);
		mTextPaint2.setTextSize(20);
		FontMetrics fm = mTextPaint.getFontMetrics();
		mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);


	}


	@Override
	protected void onDraw(Canvas canvas) {


		mXCenter = getWidth() / 2;
		mYCenter = getHeight() / 2;


		mCirclePaint.setColor(getResources().getColor(R.color.gray));
		canvas.drawCircle(mXCenter,mYCenter, mRadius + mStrokeWidth*2, mCirclePaint);
		
		RectF oval1 = new RectF();
		oval1.left = (mXCenter - mRingRadius);
		oval1.top = (mYCenter - mRingRadius);
		oval1.right = mRingRadius * 2 + (mXCenter - mRingRadius);
		oval1.bottom = mRingRadius * 2 + (mYCenter - mRingRadius);
		mRingPaint.setColor(mOutRingColor);
		canvas.drawArc(oval1, -90, ((float)mOutProgress / mTotalProgress) * 360, false, mRingPaint);
		
		mCirclePaint.setColor(mCircleColor);
		canvas.drawCircle(mXCenter, mYCenter, mRadius, mCirclePaint);
		if (mInnerProgress > 0 ) {
			RectF oval = new RectF();
			oval.left = (mXCenter - mRingRadius2);
			oval.top = (mYCenter - mRingRadius2);
			oval.right = mRingRadius2 * 2 + (mXCenter - mRingRadius2);
			oval.bottom = mRingRadius2 * 2 + (mYCenter - mRingRadius2);
			mRingPaint.setColor(mInnerRingColor);
			canvas.drawArc(oval, -90, ((float)mInnerProgress / mTotalProgress) * 360, false, mRingPaint); //
			//			canvas.drawCircle(mXCenter, mYCenter, mRadius + mStrokeWidth / 2, mRingPaint);
			String txt = mInnerProgress + "%";
			String txt2 = "正确率";
			mTxtWidth = mTextPaint.measureText(txt, 0, txt.length());
			mTxtWidth2 = mTextPaint2.measureText(txt2, 0, txt2.length());
			canvas.drawText(txt, mXCenter - mTxtWidth / 2, mYCenter+mTxtWidth / 8, mTextPaint);
			canvas.drawText(txt2 ,mXCenter - mTxtWidth2 / 2, mYCenter + mTxtWidth / 2, mTextPaint2);
		}else if(mInnerProgress==0){
			String txt = mInnerProgress + "%";
			String txt2 = "正确率";
			mTxtWidth = mTextPaint.measureText(txt, 0, txt.length());
			mTxtWidth2 = mTextPaint2.measureText(txt2, 0, txt2.length());
			canvas.drawText(txt, mXCenter - mTxtWidth / 2, mYCenter+mTxtWidth / 8, mTextPaint);
			canvas.drawText(txt2 ,mXCenter - mTxtWidth2 / 2, mYCenter + mTxtWidth / 2, mTextPaint2);
		}
	}
	public void setOutProgress(double progress){
		mOutProgress=progress;
	}
	public void setInnerProgress(double progress) {
		mInnerProgress = progress;
		//		invalidate();
		postInvalidate();
	}


}

3.使用自定义View

<com.jsle.ebag.answer.view.AnswerChartView
            android:id="@+id/tasks_view"
            android:layout_width="160dp"
            android:layout_height="160dp"
            android:layout_centerHorizontal="true"
            tc:circleColor="@color/circle_color"
            tc:innerringColor="@color/dark_yellow"
            tc:outringColor="@color/green"
            tc:radius="60dip"
            tc:strokeWidth="6dip"
            tc:textSize="32sp" />

4.最后可已在AnswerChartActivity中设置内环和外环的百分比和属性

</pre><pre name="code" class="java">package com.jsle.ebag.answer.activity;

import java.text.DecimalFormat;

import com.jsle.ebag.answer.R;
import com.jsle.ebag.answer.R.layout;
import com.jsle.ebag.answer.view.AnswerChartView;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class AnswerChartActivity extends BaseActivity implements OnClickListener {
	private AnswerChartView mTasksView;
	private double mAccuracy;//个人的正确率
	private double cAccuracy;//班级的正确率
	private double mCurrentProgress;
	private LinearLayout btn_black;
	private TextView tv_title,tv_subjectcount,tv_submit,tv_accuracy;
	private String title;
	private double maccuracy,caccuracy;
	private int subjectcount,submit;
	@Override
	protected int getID() {
		// TODO Auto-generated method stub
		return R.id.Activity_ID_AnswerChart;
	}
	@Override
	protected String getTag() {
		// TODO Auto-generated method stub
		return "AnswerChart_Acitivity";
	}
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_answer_chart);
		btn_black=(LinearLayout) findViewById(R.id.btn_black);
		tv_title=(TextView) findViewById(R.id.tv_title);
		tv_subjectcount=(TextView) findViewById(R.id.tv_subjectcount);
		tv_submit=(TextView) findViewById(R.id.tv_submit);
		tv_accuracy=(TextView) findViewById(R.id.tv_accuracy);
		btn_black.setOnClickListener(this);
		getData();
		initVariable();
		initView();
		new Thread(new ProgressRunable()).start();
	}
	private void getData() {
		// TODO Auto-generated method stub
		Intent intent = getIntent();
		title=intent.getStringExtra("title");
		maccuracy = intent.getDoubleExtra("maccuracy", 0);
		caccuracy = intent.getDoubleExtra("caccuracy", 0);
		subjectcount=intent.getIntExtra("subjectcount", 0);
		submit=intent.getIntExtra("submit", 0);
	}
	private void initVariable() {
		tv_title.setText(title);
		tv_subjectcount.setText("共"+subjectcount+"道题");
		tv_submit.setText(submit+"");
		tv_accuracy.setText(caccuracy+"%");
		mAccuracy =maccuracy;
		cAccuracy=caccuracy;
		mCurrentProgress = 0;
	}
	private void initView() {
		mTasksView = (AnswerChartView) findViewById(R.id.tasks_view);
		mTasksView.setOutProgress(cAccuracy);
	}
	/**
	 *进度动画效果
	 * @author LH
	 * @data 2016年1月29日 下午3:43:31
	 **/
	class ProgressRunable implements Runnable {

		@Override
		public void run() {
			while (mCurrentProgress < mAccuracy) {
				mCurrentProgress += 1;
				if(mCurrentProgress>mAccuracy){
					mCurrentProgress=mAccuracy;
				}
				mTasksView.setInnerProgress(mCurrentProgress);
				try {
					Thread.sleep(15);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.btn_black:
			finish();
			break;

		default:
			break;
		}
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值