Android碎裂的粒子效果

最近看到一段時(shí)間都沒怎么更新文章了,一直在學(xué)習(xí)iOS相關(guān)內(nèi)容。偶然間看到一個(gè)碎裂的粒子效果,覺得很有意思,就查了查,參考下網(wǎng)上的思路自己擼了個(gè)輪子。

好了,說了這么多,先看看效果吧~

粒子破碎效果

依慣例,先說下行文思路吧,首先我們先簡單分析下效果,拆分關(guān)注點(diǎn),粒子效果是怎么產(chǎn)生的?我的解決方案就是先獲取當(dāng)前要碎裂的view的緩存視圖,然后根據(jù)圖片獲取各個(gè)坐標(biāo)點(diǎn)的顏色值,在整個(gè)DecorView蓋上一層視圖,這個(gè)視圖就根據(jù)獲取的顏色值在要碎裂的view的位置drawCircle,之后變化圓心和半徑以及透明度從而產(chǎn)生碎裂效果。那么,我們要解決的問題已經(jīng)簡化為幾個(gè)點(diǎn)了,看怎么一個(gè)一個(gè)將其擊破。

一、獲取view的視圖
二、獲取要碎裂的view的位置以及獲取各個(gè)位置的顏色值
三、變化各個(gè)屬性值產(chǎn)生動(dòng)畫碎裂效果

一、獲取view的視圖

獲取view的視圖也就是要獲取這個(gè)視圖的截圖,有兩種方式可以來做:

1、可以用Canvas來獲取Bitmap

public Bitmap getBitmapFromView(View view) {
    Bitmap bmp = Bitmap.createBitmap(webView.getWidth(),       
    webView.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bmp);
    view.draw(canvas);
    return bmp;
}

2、用getDrawingCache來獲取Bitmap

    private static Bitmap getCacheBitmapFromView(View view) {
        final boolean drawingCacheEnabled = true;
        view.setDrawingCacheEnabled(drawingCacheEnabled);
        view.buildDrawingCache(drawingCacheEnabled);
        final Bitmap drawingCache = view.getDrawingCache();
        Bitmap bitmap;
        if (drawingCache != null) {
            bitmap = Bitmap.createBitmap(drawingCache);
            view.setDrawingCacheEnabled(false);
        } else {
            bitmap = null;
        }
        return bitmap;
    }

通過這兩種方式都可以獲取這個(gè)視圖的圖片,而為什么我們要獲取這個(gè)視圖的圖片呢,因?yàn)橐鶕?jù)這個(gè)圖片來獲取各個(gè)位置的顏色值,為之后繪制粒子效果服務(wù)。

二、獲取要碎裂的view的位置以及獲取各個(gè)位置的顏色值

獲取view的位置,之前使用過getGlobalVisibleRect方法來獲取位置,但很多時(shí)候并不是很準(zhǔn)確,比如有ActionBar的時(shí)候。

Rect rect = new Rect();
view.getGlobalVisibleRect(rect);

之后測(cè)試使用getLocationInWindow這種方式挺不錯(cuò),這個(gè)方法的官方注釋為這樣寫Computes the coordinates of this view in its window.

 int[] location = new int[2];
 view.getLocationInWindow(location);
 Rect rect = new Rect(location[0],location[1],location[0]+view.getMeasuredWidth(),location[1]+view.getMeasuredHeight());

在獲取視圖位置之后,我們要獲取各個(gè)位置的顏色值來繪制在這片區(qū)域內(nèi),調(diào)用bitmap.getPixel方法獲取各個(gè)位置的顏色值:

public static Particle[][] generateParticles(Bitmap bitmap, Rect bound) {
        int w = bound.width();
        int h = bound.height();

        int partW_Count = w / Particle.PART_WH;
        int partH_Count = h / Particle.PART_WH;

        Particle[][] particles = new Particle[partH_Count][partW_Count];
        Point point = null;
        for (int row = 0; row < partH_Count; row ++) { //行
            for (int column = 0; column < partW_Count; column ++) { //列
                //取得當(dāng)前粒子所在位置的顏色
                int color = bitmap.getPixel(column * Particle.PART_WH, row * Particle.PART_WH);
                point = new Point(column, row); //x是列,y是行
                particles[row][column] = Particle.generateParticle(color, bound, point);
            }
        }
        return particles;
    }

三、變化各個(gè)屬性值產(chǎn)生動(dòng)畫碎裂效果

首先我們要在當(dāng)前視圖上覆蓋一層產(chǎn)生碎裂效果的視圖:

 private void attachToActivity(Activity activity) {
        ViewGroup rootView = (ViewGroup) activity.getWindow().getDecorView();
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

        rootView.addView(this, lp);
    }

將我們要繪制粒子動(dòng)畫效果的添加進(jìn)布局視圖中,然后我們就可以開始繪制了。
開啟屬性動(dòng)畫,根據(jù)動(dòng)畫流程變化Particle的相關(guān)屬性:

    //x值
    public float cx;
    //y值
    public float cy;
    //繪制圓的半徑
    public float radius;
    //顏色
    public int color;
    //透明度
    public float alpha;

在自定義視圖的onDraw方法,遍歷所有我們保存的粒子Particle,改變相關(guān)屬性值:

@Override
    protected void onDraw(Canvas canvas) {
        if (mParticleAnimator !=null)
            drawParticle(canvas);
    }

    public void drawParticle(Canvas canvas) {
        //動(dòng)畫結(jié)束停止
        if(!mParticleAnimator.isRunning()) {
            return;
        }
        for (Particle[] particle : mParticleAnimator.getParticles()) {
            for (Particle p : particle) {
                p.update((Float) mParticleAnimator.getAnimatedValue());
                mPaint.setColor(p.color);
                mPaint.setAlpha((int) (Color.alpha(p.color) * p.alpha));
                canvas.drawCircle(p.cx, p.cy, p.radius, mPaint);//
            }
        }
        invalidate();
    }
      //更新相關(guān)屬性值  主要是隨機(jī)生成x y值以及碎裂大小
      public void update(float factor) {
        cx = cx + factor * random.nextInt(mBound.width()) * (random.nextFloat() - 0.5f);
        cy = cy + factor * (mBound.height()/(random.nextInt(4)+1)) ;
        radius = radius - factor * random.nextInt(3);;
        if (radius<=0)
            radius = 0;
        alpha = 1f - factor;
    }

OK,到這里我們就基本實(shí)現(xiàn)了這個(gè)碎裂效果,整體注意點(diǎn)基本就這么多,我把它簡單封裝了下,使用方式也很簡單:

  final ParticleView particleAnimator = new ParticleView(MainActivity.this,3000);//3000為動(dòng)畫持續(xù)時(shí)間 
        particleAnimator.setOnAnimationListener(new ParticleView.OnAnimationListener() {
            @Override
            public void onAnimationStart(View view,Animator animation) {
                //動(dòng)畫開始
                view.setVisibility(View.INVISIBLE);
            }
            @Override
            public void onAnimationEnd(View view,Animator animation) {
                //動(dòng)畫結(jié)束
            }
        });
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                particleAnimator.boom(v);//開始動(dòng)畫
            }
        });

github地址:ParticleDismissLayout

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,315評(píng)論 25 708
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,572評(píng)論 6 30
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,241評(píng)論 4 61
  • 誰執(zhí)著 誰想寞落 記憶忘過 什么痛 什么你說 我曾記得 話說你 話說清風(fēng) 話說雨輕劃過 審視著 瞳孔緊縮 會(huì)有光火...
    小秀子乖乖閱讀 233評(píng)論 0 2
  • 青臺(tái)柳,青臺(tái)柳,細(xì)鎖山風(fēng)黛眉 影影綽綽,煢煢孑立 執(zhí)一念,兩蒼茫,三世輪回 只愿攀折君之手
    高山子閱讀 232評(píng)論 0 2