第一步:先画一个自定义圆。
public class Xiu3 extends View {
private int n;
private Paint paint;
private int r;
public Xiu3(Context context) {
super(context);
init();
}
public int getR() {
return r;
}
public void setR(int r) {
this.r = r;
invalidate();
}
public Xiu3(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public Xiu3(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
//extress = 0;
//设置圆的数目
n = 4;
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(4);
}
public Paint getPaint() {
return paint;
}
public void setPaint(Paint paint) {
this.paint = paint;
}
public final static Property<Xiu3,Integer> R=new Property<Xiu3, Integer>(Integer.class,"r") {
@Override
public Integer get(Xiu3 object) {
return object.getR();
}
@Override
public void set(Xiu3 object, Integer value) {
//super.set(object, value);
object.setR(value);
}
};
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*int r1= getWidth();
int r2= getHeight();
r = Math.min(r1,r2);*/
canvas.drawCircle(getWidth()/2,getHeight()/2, r/2,paint);
}
自定义圆中设置Property<Xiu3,Integer> 属性中设置set,get方法在set方法中调用invalidate重新绘制画布
然后在属性动画中就能使用了
第二步:使用groupview在view中添加上面的view。
然后写属性动画。上面的view涉及到2中属性变化1是alpha透明度变化我设置为1-0.1然后是r的变化是0-你想要的变成的r
List<AnimatorSet> sets=new ArrayList<>();
public void startchildani(Xiu3 xiu){
AnimatorSet set= new AnimatorSet();
ObjectAnimator animator1=ObjectAnimator.ofInt(xiu,"r",0,xiu.getWidth());
animator1.setRepeatCount(ValueAnimator.INFINITE);
ObjectAnimator animator2=ObjectAnimator.ofFloat(xiu,"alpha",1f,0f);
animator2.setRepeatCount(ValueAnimator.INFINITE);
set.setInterpolator(new LinearInterpolator());
set.play(animator1).with(animator2);
set.setDuration(time);
// AnimationSet set1;
set.start();
sets.add(set);
// set.
}
publ
又集合储存方便之后的取消
然后依次画子view我使用了延时的操作实现这个。
public void startani(){
for (int i = 0; i <xiu3s.size() ; i++) {
if (i==0){
startchildani(xiu3s.get(i));
}else{
//delayed to start animation
final int finalI = i;
postDelayed(new Runnable() {
@Override
public void run() {
startchildani(xiu3s.get(finalI));
}
},time/xiu3s.size()*i);
}
}
}
public void stopani(){
// set.end();
removeCallbacks(null);
for (int i = 0; i < sets.size(); i++) {
// ((Xiu3) getChildAt(i)).clearAnimation();
//stopanimation
sets.get(i).end();
}
}
真是开始和停止的方法。为了防止在view关闭以后postdelay任然调用
最好在view关闭动画的时候移除postdelay不然你调用end动画任然会继续跑搞不好还会报空指针异常在activty关闭后。
即这个方法:
removeCallbacks(null)
可以移除全部
然后是自定义属性的方法:我把代码一粘一看就明白了
TypedArray array=getContext().obtainStyledAttributes(attrs,R.styleable.GroupXiu);
time= array.getInteger(R.styleable.GroupXiu_animationtime,3000);
//set circle color
color = array.getColor(R.styleable.GroupXiu_circlecolor, Color.RED);
circlenums = array.getInteger(R.styleable.GroupXiu_circlenums,3);
这是代码获取自定义属性的方法
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="GroupXiu">
<attr name="circlenums" format="integer"></attr>
<attr name="animationtime" format="integer"></attr>
<attr name="circlecolor" format="color"></attr>
</declare-styleable>
</resources>
这是在attrs中设置自定属性然后就能在布局文件中的view中使用该属性
<com.cheerchip.xiuyixiu.GroupXiu
android:id="@+id/xiu"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:circlenums="6"
app:circlecolor="#33f74141"
app:animationtime="3000"
/>
这是布局文件中调用属性的方法然后在view中就可以使用了
最后我把整个groupview放上来:
public class GroupXiu extends RelativeLayout {
//scroller also can change the value to do thia animation but i don't like
//private Scroller scroller;
/*private Xiu3 xiu1;
private Xiu3 xiu2;
private Xiu3 xiu3;*/
private List<Xiu3> xiu3s=new ArrayList<>();
private int time;
private int color;
private int circlenums;
public GroupXiu(Context context) {
super(context);
// init();
}
public GroupXiu(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public GroupXiu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
public void init(AttributeSet attrs){
// LayoutInflater.from(getContext()).inflate(R.layout.xiu,this,false);
// scroller = new Scroller(getContext());
//init the data
TypedArray array=getContext().obtainStyledAttributes(attrs,R.styleable.GroupXiu);
time= array.getInteger(R.styleable.GroupXiu_animationtime,3000);
//set circle color
color = array.getColor(R.styleable.GroupXiu_circlecolor, Color.RED);
circlenums = array.getInteger(R.styleable.GroupXiu_circlenums,3);
// time = 3000;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//add view to group
LayoutParams params=new LayoutParams(getWidth(),getHeight());
for (int i = 0; i < circlenums; i++) {
Xiu3 xiu=new Xiu3(getContext());
//set params
addView(xiu,params);
xiu3s.add(xiu);
//set paint color you can also set the paint you like
xiu.getPaint().setColor(color);
//
}
//this is the test
// xiu1 = new Xiu3(getContext());
// xiu2 = new Xiu3(getContext());
// xiu3 = new Xiu3(getContext());
// addView(xiu2,params);
// addView(xiu3,params);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
LayoutParams params=new LayoutParams(getWidth(),getHeight());
for (int i = 0; i <xiu3s.size() ; i++) {
xiu3s.get(i).setLayoutParams(params);
}
/* xiu1.setLayoutParams(params);
xiu2.setLayoutParams(params);
xiu3.setLayoutParams(params);*/
}
public void startani(){
for (int i = 0; i <xiu3s.size() ; i++) {
if (i==0){
startchildani(xiu3s.get(i));
}else{
//delayed to start animation
final int finalI = i;
postDelayed(new Runnable() {
@Override
public void run() {
startchildani(xiu3s.get(finalI));
}
},time/xiu3s.size()*i);
}
}
}
List<AnimatorSet> sets=new ArrayList<>();
public void startchildani(Xiu3 xiu){
AnimatorSet set= new AnimatorSet();
ObjectAnimator animator1=ObjectAnimator.ofInt(xiu,"r",0,xiu.getWidth());
animator1.setRepeatCount(ValueAnimator.INFINITE);
ObjectAnimator animator2=ObjectAnimator.ofFloat(xiu,"alpha",1f,0f);
animator2.setRepeatCount(ValueAnimator.INFINITE);
set.setInterpolator(new LinearInterpolator());
set.play(animator1).with(animator2);
set.setDuration(time);
// AnimationSet set1;
set.start();
sets.add(set);
// set.
}
public void stopani(){
// set.end();
removeCallbacks(null);
for (int i = 0; i < sets.size(); i++) {
// ((Xiu3) getChildAt(i)).clearAnimation();
//stopanimation
sets.get(i).end();
}
}
}
在activity中开启和关闭动画:
xiu = ((GroupXiu) findViewById(R.id.xiu));
// startanimation( xiu);
}
public void startanimation(View view) {
//Xiu3 xiu=((Xiu3) findViewById(R.id.xiu));
if (scan){
xiu.startani();
scan=false;
}else {
xiu.stopani();
}
就是这些了。
网上有很多在我看来都是复杂的数学公式看起来头昏眼花就自己想了一个写。
还有一个较为简单的是线条的扩散的代码单独一个view就完成了;
因为这个不需要颜色的渐变只要单一属性我使用valueanimotion完成的是几个圆圈线不停向外扩散
public class Xiu extends View {
private Paint paint;
private int n;
private int excess;
private int r;
public Xiu(Context context) {
super(context);
init();
}
public int getExcess() {
return excess;
}
public void setExcess(int excess) {
this.excess = excess;
}
private void init() {
//初始化圆的数目
n = 4;
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
}
public Xiu(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Xiu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int r1= getWidth();
int r2= getHeight();
r = Math.min(r1,r2);
if (r ==r1){
for (int i = 0; i <n ; i++) {
canvas.drawCircle(r /2,getHeight()/2, r /2/n*4+excess,paint);
canvas.drawCircle(r /2,getHeight()/2, r /2/n*3+excess,paint);
canvas.drawCircle(r /2,getHeight()/2, r /2/n*2+excess,paint);
canvas.drawCircle(r /2,getHeight()/2, r /2/n+excess,paint);
}
}
}
public void sartanimotion(){
ValueAnimator animator=ValueAnimator.ofInt(0,r/4);
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
excess= ((int) animation.getAnimatedValue());
invalidate();
}
});
animator.start();
}
就这些了。
项目地址
https://github.com/hfc123/XiuYiXiu1/