美文网首页
自定义View之酷炫的波浪泡沫

自定义View之酷炫的波浪泡沫

作者: 二运_3694 | 来源:发表于2017-08-15 16:26 被阅读0次
    海浪

            这个效果我其实是用两个自定义View实现的 -_-  , 波浪是用两个不断改变的float值加画布裁剪实现的 , 泡泡是用float数组随机生成不同大小的shape画的圆,使用三阶Bezier曲线和属性动画实现。

    MainActivity:

    public classMainActivityextendsAppCompatActivity {

    LoveBezierViewlover;

    HandlermHandler=newHandler(){

    @Override

    public voidhandleMessage(Message msg) {

    super.handleMessage(msg);

    switch(msg.what){

    case20:

    lover.addImg();

    break;

    }

    }

    };

    @Override

    protected voidonCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    lover= (LoveBezierView) findViewById(R.id.mylove);

    addPaopao();

    }

    public voidaddPaopao(){

    newThread(newRunnable() {

    @Override

    public voidrun() {

    while(true){

    SystemClock.sleep(100);

    mHandler.sendEmptyMessageDelayed(20,1500);

    }

    }

    }).start();

    }

    }

    WaveView波浪自定义View:

    public classWaveViewextendsView{

    private intmHeight;

    private intmWidth;

    private float[]mContentOneYs=null;

    private float[]mContentTwoys=null;

    private float[]mRestoreOnes=null;

    private float[]mRestoreTwos=null;

    private static final intSWINGONE=35;

    private static final intSWINGTWO=60;//波动幅度

    private static final intOFFSETONE=10;

    private static final intOFFSETTWO=50;

    private final intINIT_BASE_HEIGHT1=200;//距离View顶部的高度

    private final intINIT_BASE_HEIGHT2=200;

    private intmPosition1=0;//偏移坐标

    private intmPosition2=0;

    private static final intSTEP1=5;

    private static final intSTEP2=8;

    privatePaintmPaint1,mPaint2;//画笔

    publicWaveView(Context context) {

    this(context,null);

    }

    publicWaveView(Context context, AttributeSet attrs) {

    this(context, attrs,0);

    }

    publicWaveView(Context context, AttributeSet attrs,intdefStyleAttr) {

    super(context, attrs, defStyleAttr);

    init();

    }

    private voidinit() {//初始化画笔

    mPaint1=newPaint(Paint.ANTI_ALIAS_FLAG);

    mPaint1.setColor(Color.parseColor("#33CCFF"));

    mPaint1.setStrokeWidth(4);

    mPaint1.setAlpha(85);

    mPaint2=newPaint(Paint.ANTI_ALIAS_FLAG);

    mPaint2.setColor(Color.parseColor("#99FFFF"));//代码设置颜色

    mPaint2.setStrokeWidth(4);

    mPaint2.setAlpha(155);

    }

    @Override

    protected voidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) {

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override

    protected voidonSizeChanged(intw,inth,intoldw,intoldh) {

    super.onSizeChanged(w, h, oldw, oldh);

    if(w !=0|| h !=0|| w != oldw || h != oldh) {

    mWidth= w;

    mHeight= h;

    calculatePoints();

    }

    }

    @Override

    protected voidonDraw(Canvas canvas) {

    super.onDraw(canvas);

    canvas.save();

    Path path =newPath();

    path.addArc(0,(mHeight/2)-350,mWidth,(mHeight/2)+350,0,360);

    canvas.clipPath(path);

    changeRestorePosition();

    for(inti =0; i

    final intx = i;

    final floaty1 =mRestoreOnes[i];

    final floaty2 =mRestoreTwos[i];

    canvas.drawLine(x, y2, x,mHeight,mPaint2);

    canvas.drawLine(x, y1, x,mHeight,mPaint1);

    }

    invalidate();

    }

    private voidcalculatePoints() {

    mContentOneYs=new float[mWidth];

    mContentTwoys=new float[mWidth];

    mRestoreOnes=new float[mWidth];

    mRestoreTwos=new float[mWidth];

    for(inti =0; i

    mContentOneYs[i] = getYPosition(i,SWINGONE,OFFSETONE,INIT_BASE_HEIGHT1);

    mContentTwoys[i] = getYPosition(i,SWINGTWO,OFFSETTWO,INIT_BASE_HEIGHT2);

    }

    }

    private voidchangeRestorePosition() {

    //偏移坐标的方法,根据响应的步长设置每次的偏移起始点

    if(mWidth!=0) {

    mPosition1= (mPosition1+STEP1) %mWidth;

    System.arraycopy(mContentOneYs,mPosition1,mRestoreOnes,0,mWidth-mPosition1);

    System.arraycopy(mContentOneYs,0,mRestoreOnes,mWidth-mPosition1,mPosition1);

    mPosition2= (mPosition2+STEP2) %mWidth;

    System.arraycopy(mContentTwoys,mPosition2,mRestoreTwos,0,mWidth-mPosition2);

    System.arraycopy(mContentTwoys,0,mRestoreTwos,mWidth-mPosition2,mPosition2);

    }

    }

    private floatgetYPosition(intx,intswing,intoffset,intbaseHeight) {

    floatcycle = (float) (2* Math.PI) /mWidth;

    return(float) Math.sin(cycle * x + offset) * swing + baseHeight;

    }

    }

    LoveBezierView泡沫上升效果:

    public classLoveBezierViewextendsRelativeLayout{

    privateDrawable[]drawables;//图片集合

    private intdWidth,dHeight;//泡泡宽高

    privateLayoutParamslayoutParams;//泡泡宽高及位置

    private intmWidth,mHeight;

    privateRandomrandom=newRandom();

    intwhats=1;

    publicLoveBezierView(Context context) {

    super(context);

    init();

    }

    publicLoveBezierView(Context context, AttributeSet attrs) {

    super(context, attrs);

    init();

    }

    publicLoveBezierView(Context context, AttributeSet attrs,intdefStyleAttr) {

    super(context, attrs, defStyleAttr);

    init();

    }

    private voidinit() {

    drawables=newDrawable[3];//泡泡的数组

    drawables[0] = ContextCompat.getDrawable(getContext(), R.drawable.yuan);

    drawables[1] = ContextCompat.getDrawable(getContext(), R.drawable.yuan2);

    drawables[2] = ContextCompat.getDrawable(getContext(), R.drawable.yuan3);

    }

    @Override

    protected voidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) {

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    mWidth= getMeasuredWidth();

    mHeight= getMeasuredHeight();

    }

    /*@Override    两种测量方法

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

    super.onSizeChanged(w, h, oldw, oldh);

    mWidth = w;

    mHeight = h;

    }*/

    public voidaddImg(){

    ImageView imageView =newImageView(getContext());

    intwhat =random.nextInt(3);

    imageView.setBackground(drawables[what]);

    dWidth=drawables[what].getIntrinsicWidth();

    dHeight=drawables[what].getIntrinsicHeight();

    layoutParams=newLayoutParams(dWidth,dHeight);//泡泡宽高

    /* layoutParams.addRule(ALIGN_PARENT_LEFT , TRUE);    //水平居中

    layoutParams.addRule(ALIGN_PARENT_BOTTOM, TRUE);  //在父控件底部*/

    imageView.setLayoutParams(layoutParams);

    addView(imageView);

    AnimatorSet animator = getBezierAnimator(imageView);

    animator.addListener(newAnimatorLinstener(imageView));

    animator.start();

    }

    privateAnimatorSet getBezierAnimator(ImageView imageView) {

    Estimator evaluator =newEstimator(getPoint(2), getPoint(1));//随机两个拐点

    ValueAnimator valueAnimator = ValueAnimator.ofObject(evaluator, getPointF(1), getPointF(2));

    valueAnimator.setDuration(5000);

    valueAnimator.addUpdateListener(newValueUpdateLinstener(imageView));

    valueAnimator.setTarget(imageView);

    ObjectAnimator ob = ObjectAnimator.ofFloat(imageView,"alpha",0.1f,1.0f);

    ob.setDuration(2000);

    AnimatorSet a =newAnimatorSet();

    a.playTogether(valueAnimator,ob);

    returna;

    }

    privatePointF getPoint(intscale) {

    PointF pointF =newPointF();//选择Y轴的两个拐点

    pointF.x=random.nextInt((mWidth));

    pointF.y=random.nextInt((mHeight-100)) / scale;

    returnpointF;

    }

    private classAnimatorLinstenerextendsAnimatorListenerAdapter {

    privateImageViewimageView;

    publicAnimatorLinstener(ImageView imageView) {

    this.imageView= imageView;

    }

    @Override

    public voidonAnimationEnd(Animator animation) {

    removeView(imageView);

    }

    }

    privatePointF getPointF(inti) {

    PointF pointF =newPointF();

    if(i ==1){

    pointF.set(random.nextInt(mWidth-18),mHeight-dHeight-30);//在底部X轴随机出现

    }else{

    pointF.set(random.nextInt(getWidth()),0);

    }

    returnpointF;

    }

    private classValueUpdateLinstenerimplementsValueAnimator.AnimatorUpdateListener {

    privateImageViewimageView;

    publicValueUpdateLinstener(ImageView imageView) {

    this.imageView= imageView;

    }

    @Override

    public voidonAnimationUpdate(ValueAnimator valueAnimator) {

    PointF pointF = (PointF) valueAnimator.getAnimatedValue();

    imageView.setX(pointF.x);

    imageView.setY(pointF.y);

    //            Log.e("TAG", valueAnimator.getAnimatedFraction()+"=========");

    imageView.setAlpha(1- valueAnimator.getAnimatedFraction());

    }

    }

    }

    然后就是在布局中将两个自定义View组合,写成一个自定义View的画太卡,onDraw最好不要有太复杂的运算。

    相关文章

      网友评论

          本文标题:自定义View之酷炫的波浪泡沫

          本文链接:https://www.haomeiwen.com/subject/atuhkxtx.html