先来无事研究了一下Android 自定义view的开发,简单写了一个雪花飘飘的效果:
效果如图:
废话不多说直接上代码:
public class SnowViewextends View {
private PaintmyPaint;
private int snowNum=100;
private ListsnowBeans;
private boolean isPlaying;
public SnowView(Context context) {
super(context);
init();
}
public SnowView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public SnowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
myPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
snowBeans=new ArrayList<>();
isPlaying=true;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
snowBeans.clear();
for (int i=0;i
snowBeans.add(SnowBean.getBuildSnowBean(w,h));
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i=0;i
snowBeans.get(i).onDraw(canvas,myPaint);
snowBeans.get(i).step();
}
if(isPlaying){
postInvalidateDelayed(10);
}
}
public void start(){
invalidate();
isPlaying=true;
}
public void stop(){
isPlaying=false;
}
/**
* 雪花对象
*/
static class SnowBean {
private int x;
private int y;
private int color;
private int radius;
private int rotation;
private int speed;
private int viewWdith;
private int viewheight;
private int stokeWidth;
private PointstartPoint;
private PointmiddlePoint;
private PointendPoint;
public int getStokeWidth() {
return stokeWidth;
}
public void setStokeWidth(int stokeWidth) {
this.stokeWidth = stokeWidth;
}
public PointgetStartPoint() {
return startPoint;
}
public void setStartPoint(Point startPoint) {
this.startPoint = startPoint;
}
public PointgetMiddlePoint() {
return middlePoint;
}
public void setMiddlePoint(Point middlePoint) {
this.middlePoint = middlePoint;
}
public PointgetEndPoint() {
return endPoint;
}
public void setEndPoint(Point endPoint) {
this.endPoint = endPoint;
}
public int getViewWdith() {
return viewWdith;
}
public void setViewWdith(int viewWdith) {
this.viewWdith = viewWdith;
}
public int getViewheight() {
return viewheight;
}
public void setViewheight(int viewheight) {
this.viewheight = viewheight;
}
public int getX() {
float t = getY() *1.0f / (getEndPoint().y - getStartPoint().y);
return BezierUtil.calutePoint(t, getStartPoint(), getMiddlePoint(), getEndPoint()).x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public int getRotation() {
return rotation;
}
public void setRotation(int rotation) {
this.rotation = rotation;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public static SnowBeangetBuildSnowBean(int width, int height) {
SnowBean snowBean =new SnowBean();
Random random =new Random();
snowBean.setY(-random.nextInt(height));
snowBean.setX(random.nextInt(width));
snowBean.setColor(Color.WHITE);
snowBean.setRadius(2+random.nextInt(20));
snowBean.setRotation(random.nextInt(60));
snowBean.setSpeed(2 +Math.abs(snowBean.getRadius()-20));
snowBean.setViewheight(height);
snowBean.setViewWdith(width);
snowBean.setStartPoint(new Point(random.nextInt(width), -random.nextInt(height)));
snowBean.setMiddlePoint(new Point(random.nextInt(width), random.nextInt(height)));
snowBean.setEndPoint(new Point(random.nextInt(width), height + random.nextInt(height)));
snowBean.setStokeWidth((int)(snowBean.getRadius()*0.2));
snowBean.setRotation(random.nextInt(60));
return snowBean;
}
public void step() {
y +=speed;
if (y >viewheight) {
y = -50;
}
setRotation(getRotation()+1);
}
public void onDraw(Canvas canvas, Paint paint) {
canvas.save();
paint.setColor(getColor());
// canvas.drawRect(getX() - getRadius(), getY() - getRadius(), getX() + getRadius(), getY() + getRadius(), paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(getStokeWidth());
canvas.rotate(getRotation(),getX(),getY());
for(int i=0;i<6;i++){
int lineStartX=getX();
int lineEndX=getX()+radius;
canvas.drawLine(lineStartX,getY(),lineEndX,getY(),paint);
int line1Startx=(int)(getX()+getRadius()*0.5);
int lint1Starty=getY();
double degree60=Math.toRadians(60);
int lint1Endx=(int)(line1Startx+radius*0.5*Math.cos(degree60));
int lint1Endy=(int)(lint1Starty-radius*0.5*Math.cos(degree60));
canvas.drawLine(line1Startx,lint1Starty,lint1Endx,lint1Endy,paint);
int line2Startx = (int) (getX() + getRadius() *0.5);
int lint2Starty = getY();
int lint2Endx = (int) (line1Startx +radius *0.5 * Math.cos(degree60));
int lint2Endy = (int) (lint1Starty +radius *0.5 * Math.cos(degree60));
canvas.drawLine(line2Startx, lint2Starty, lint2Endx, lint2Endy, paint);
canvas.rotate(60,getX(),getY());
}
canvas.restore();
}
}
}
其中用到了贝塞尔曲线算法,工具类公式:
public class BezierUtil {
public static PointcalutePoint(float t,Point p0,Point p1,Point p2){
Point point=new Point();
float temp=1-t;
point.x=(int)(temp*temp*p0.x+2*t*temp*p1.x+t*t*p2.x);
point.y=(int)(temp*temp*p0.y+2*t*temp*p1.y+t*t*p2.y);
return point;
}
}
好了就是这些了,嘿嘿,还是挺好玩的,希望能够帮到有需要的同学;