转载请注明本文地址:
http://blog.youkuaiyun.com/springcoder/article/details/52296036
本来最近做一个项目想找个不一样点的progressbar,然后看到了一个四点状的progressbar不过需要金币才能下载,算了反正也写的不是那么的适用,干脆直接自己写一个吧。我写东西喜欢封装的过瘾点,多来点set方法给以后用的人自己set去,于是他们只做了点的我就一定做个既可以空心也可以实心的,还可以改变点的数目颜色的,于是花了一个小时左右的时间,写了这个东东
一。废话不多说,先上效果图
二。具体代码
一。首先自定义一个点
这个点可以是空心的,也可以是实心的,其实就是一个圆圈,在这里我们给他的属性有,颜色,半径,是否是空心的还是实心的,还有空心的那么线条的粗细是多少呢,这里我是写的是用半径除以6 ,看起来效果还不错,嗯就用他了
import android.graphics.Canvas;
import android.graphics.Paint;
import android.icu.text.DateFormat;
/**
* Created by sunshine on 2016/8/23.
*/
public class Dot {
/**
* 圆点的坐标
*/
private double x;
private double y;
private float radious;
/**
* 圆圈的中心是不是满的
*/
private boolean isFill;
private Paint paint;
private int color;
/**
* 默认的空虚圆圈的边线宽是三
* @param x
* @param y
* @param radious
* @param color
*/
public Dot(double x, double y, float radious, int color) {
this.x = x;
this.y = y;
this.radious = radious;
this.color = color;
isFill=true;
paint=new Paint();
}
public double getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getRadious() {
return radious;
}
public void setRadious(float radious) {
this.radious = radious;
}
public int getColor() {
return color;
}
public void setColor(int color) {
color = color;
}
public void setLovation(float x,float y){
this.x=x;
this.y=y;
}
public void drawSelf(Canvas canvas){
if(isFill){
paint.setStyle(Paint.Style.FILL);
}else{
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(radious/6);
}
paint.setColor(color);
//设置抗锯齿
paint.setAntiAlias(true);
canvas.drawCircle((float)x,(float)y,radious,paint);
}
public boolean isFill() {
return isFill;
}
public void setFill(boolean fill) {
isFill = fill;
}
解释一下以上代码:
其实实现这个可以在DotProgressBar中直接绘制圆圈,不过因为考虑到每个点的颜色可能不同,那么就会造成我们会多次的 设置画笔,造成一些麻烦,索性直接做成一个类,然后在其中添加一个drawSelf(Canvas canvas)的方法
二。其次就是我们的主角了
首先我们先定义一个DotProgressbar继承自View
public class DotProgressbar extends View {
public DotProgressbar(Context context) {
super(context);
init();
}
public DotProgressbar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DotProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
}
我们 一般前两个构造函数都需要,没有第二个xml文件是不能识别我们的视图的
在这里我们考虑的是怎样画那几个圆圈,那几个圆圈是一直都分布在一个更大的圆上,于是我们便可以动态额改变这个大圆的半径达到的动态的改变点的位置,形成一种动画效果
/**
* 所有圆圈围城的半径
*/
private float radious;
然后我们定义两个点之间的轨迹形成的夹角为theta
/**
* 两个点的轨迹之间的夹角
*/
private float theta;
然后接下来就是对我们需要拿到整个视图的大小,然后将视图切成正方形的,同时计算最大的圆的半径是多少,并且给所有的点一个初始值
在View中view 的绘制顺序为:构造函数->onMeasure()->onLayout()->onDraw()
如果我们在构造函数中getWidth(),getHeight()那么得到的值都是0,因为视图还没有进行测量,所以我这里选择在onLayout中拿到视图的宽高,并且初始化每一个点的位置
/**
* 重写onlayout方法计算控件的高度宽度,以及初始化点的布局
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//得到控件的宽高
width=getWidth();
height=getHeight();
//将视图切成一个方形的
if(height>width){
square=width;
}else {
square=height;
}
//得到中心的坐标方便后续布置点的位置
centerX=width/2;
centerY=height/2;
theta= (float) (2*Math.PI/num);
L=square/2-dotRadious;
radious= (float) (L*Math.sin(t));
dots=new Dot[num];
//初始化开始的时候的点的坐标,以及颜色
for (int i=0;i<num;i++){
dots[i]=new Dot(centerX,centerY,dotRadious,colors[i]);
if (!isFull){
dots[i].setFill(false);
}
}
}
最后将所有的点在onDraw方法中绘制出来就行了
/**
* 通过每个点的位置不断的绘制点
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i=0;i<num;i++){
dots[i].drawSelf(canvas);
}
if(speed>1){
speed=0.9;
}else if (speed<=0){
speed=0;
}
long timeDelay= (long) (100-100*speed);
handler.postDelayed(runnable,timeDelay);
}
在这里我们的点需要 动态的改变位置,也就是大圆需要改变半径,这里我们用handler来动态的 改变并刷新视图
private Handler handler =new Handler();
private Runnable runnable=new Runnable() {
@Override
public void run() {
if(t>Math.PI*2){
t=0;
}
t+=0.1;
double r=L*Math.sin(t);
//重新计算每个点的位置
for (int i=0;i<num;i++){
float x1= (float) (r*Math.sin(i*theta))+centerX;
float y1= (float) (r*Math.cos(i*theta))+centerY;
dots[i].setLovation(x1,y1);
}
invalidate();
}
};
注意:一定要用invalidate刷新视图
很简单的,其他的就不多说了,下面贴出所有的源码:
DotProgressbar.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import com.ccx.dotprogressbar.bean.Dot;
/**
* Created by sunshine on 2016/8/23.
*/
public class DotProgressbar extends View {
/**
* 整个view的属性
*/
private float height;
private float width;
private float square;
/**
* 圆点的半径
*/
private float radious;
/**
* 点的数目以及颜色
*/
private int num=3;
private int colors[]={Color.RED,Color.GREEN,Color.BLUE};
/**
* 点是否是实心的
*/
private boolean isFull=true;
//小圆圈的半径
private float dotRadious=25;
private Dot dots[];
/**
* 时间,其实是控制角度
*/
private float t;
/**
* 通过handler来实现定时器
*/
private float centerX;
private float centerY;
private float L;
/**
* 两个点的轨迹之间的夹角
*/
private float theta;
/**
* 设置转动的速度
*/
private double speed=1;
private Handler handler =new Handler();
private Runnable runnable=new Runnable() {
@Override
public void run() {
if(t>Math.PI*2){
t=0;
}
t+=0.1;
double r=L*Math.sin(t);
//重新计算每个点的位置
for (int i=0;i<num;i++){
float x1= (float) (r*Math.sin(i*theta))+centerX;
float y1= (float) (r*Math.cos(i*theta))+centerY;
dots[i].setLovation(x1,y1);
}
invalidate();
}
};
public DotProgressbar(Context context) {
super(context);
init();
}
public DotProgressbar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DotProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* 重写onlayout方法计算控件的高度宽度,以及初始化点的布局
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//得到控件的宽高
width=getWidth();
height=getHeight();
//将视图切成一个方形的
if(height>width){
square=width;
}else {
square=height;
}
//得到中心的坐标方便后续布置点的位置
centerX=width/2;
centerY=height/2;
theta= (float) (2*Math.PI/num);
L=square/2-dotRadious;
radious= (float) (L*Math.sin(t));
dots=new Dot[num];
//初始化开始的时候的点的坐标,以及颜色
for (int i=0;i<num;i++){
dots[i]=new Dot(centerX,centerY,dotRadious,colors[i]);
if (!isFull){
dots[i].setFill(false);
}
}
}
/**
* 初始化
*/
public void init(){
speed=0.5;
radious=5;
}
/**
* 通过每个点的位置不断的绘制点
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i=0;i<num;i++){
dots[i].drawSelf(canvas);
}
if(speed>1){
speed=0.9;
}else if (speed<=0){
speed=0;
}
long timeDelay= (long) (100-100*speed);
handler.postDelayed(runnable,timeDelay);
}
public void setDotRadious(float dotRadious) {
this.dotRadious = dotRadious;
}
public void setNumAndColor(int colors[]){
this.colors=colors;
this.num=colors.length;
}
public void setDotFilled(boolean isFull){
this.isFull=isFull;
}
public void setSpeed(double speed) {
this.speed = speed;
}
}
布局文件:activity_main.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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".activity.MainActivity">
<LinearLayout
android:background="#aaaaaaaa"
android:layout_centerInParent="true"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.ccx.dotprogressbar.custom.DotProgressbar
android:id="@+id/dot_progress"
android:layout_gravity="center"
android:layout_width="150dp"
android:layout_height="150dp" />
<TextView
android:textColor="@color/colorAccent"
android:layout_marginTop="5dp"
android:layout_gravity="center"
android:text="正在联系陈冰雪..."
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
MainActivity.java
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.ccx.dotprogressbar.R;
import com.ccx.dotprogressbar.custom.DotProgressbar;
public class MainActivity extends AppCompatActivity {
private DotProgressbar progressbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressbar= (DotProgressbar) findViewById(R.id.dot_progress);
int colors[]={Color.BLUE,Color.GREEN,Color.CYAN,Color.YELLOW,Color.BLACK};
progressbar.setNumAndColor(colors);
progressbar.setDotRadious(30);
progressbar.setSpeed(1);
}
}
2088



被折叠的 条评论
为什么被折叠?



