Android BitmapShader和createCircularReveal結合仿放大鏡動畫

上篇動畫實現方式對比說過要將實現的動畫效果在本篇敘述,說着說着這就來總結一下了。先看下圖效果:

直接切入正題,本人的實現方式是將其分爲兩步去實現:

第一步:實現人臉的收縮成爲一個圓

第二部:實現圓圈的轉動看到相應圖片部分,類似放大鏡效果

先上佈局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".image.LoaderActivity">
    <!--底部黑色背景-->
    <ImageView
        android:id="@+id/bg_iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/black" />
    <!--實現放大鏡效果自定義view-->
    <com.xxx.frame.image.BitmapShaderView
        android:id="@+id/iv_shader"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!--收縮人像-->
    <ImageView
        android:id="@+id/iv_crcular_reveal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        android:src="@mipmap/bg_shader" />
</android.support.constraint.ConstraintLayout>

實現第一步:

使用ViewAnimationUtils中的createCircularReveal實現收縮成圓的效果,以下是官網描述:

當您顯示或隱藏一組界面元素時,揭露動畫可爲用戶提供視覺連續性。ViewAnimationUtils.createCircularReveal() 方法讓您能夠爲裁剪圓形添加動畫以揭露或隱藏視圖。此動畫在 ViewAnimationUtils 類中提供,適用於 Android 5.0(API 級別 21)及更高版本。

先上代碼:

        final DisplayMetrics dm = this.getResources().getDisplayMetrics();
        final int centerX = dm.widthPixels / 2;
        final int centerY = dm.heightPixels / 2;
        iv_circular_reveal.postDelayed(new Runnable() {
            @Override
            public void run() {
                Animator anim = ViewAnimationUtils.createCircularReveal(
                        iv_circular_reveal,
                        centerX,
                        centerY,
                        (float) Math.hypot(dm.widthPixels, dm.heightPixels), 0);
                anim.setDuration(1000);
                anim.setInterpolator(new AccelerateDecelerateInterpolator());
                anim.start();
                anim.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        iv_circular_reveal.setVisibility(View.GONE);
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });
            }
        }, 500);
參量
view View:視圖將被剪切到動畫圓。

 

centerX int:動畫圓心相對於的x座標 view

 

centerY int:動畫圓心的y座標,相對於 view

 

startRadius float:動畫圓的起始半徑。

 

endRadius float:動畫圓的結束半徑。

 以上就是動畫參數的解釋,這裏我是以屏幕中心爲原點收縮,收縮直到消失(這裏可以收縮到第二步旋轉圓的大小會更好,由於時間問題,當時並沒有這樣做),第一步就完成了。

實現第二步:

這裏使用了BitmapShader(位圖着色器),看似比較不好實現的動畫,其實就是一隻半徑比較大的筆在畫圈而已,關鍵代碼:

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!isDraw) return;
        if (this.bgBitmap == null) {
            this.bgBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);//創建一個新空白位圖
            Canvas canvasBg = new Canvas(this.bgBitmap);
            canvasBg.drawBitmap(this.bitmap, null, new Rect(0, 0, getWidth(), getHeight()), this.paint);
        }
        this.paint.setShader(new BitmapShader(this.bgBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));

        mDst.reset();
        float stop = mLength * mAnimatorValue;
        float start = stop - 1;
        mPathMeasure.getSegment(start, stop, mDst, true);
        canvas.drawPath(mDst, paint);
    }

重點代碼: 

 this.paint.setShader(new BitmapShader(this.bgBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));

BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY) 

參量
bitmap Bitmap:在着色器中使用的位圖此值一定不能爲null

 

tileX Shader.TileMode:x的平鋪模式以繪製位圖。此值不得爲null

 

tileY Shader.TileMode:y的平鋪模式繪製位圖。此值不得爲null

這樣我們的Paint也就擁有了我們的圖,使用這隻Paint去畫圓也就實現上動畫效果。

更多相關知識大家可以看篇末的相關鏈接,這裏就是我實現動畫的全部思路,如果大家還有更多更好的實現思路歡迎留言,共同學習。

 

相關鏈接:

https://developer.android.com/reference/android/view/ViewAnimationUtils.html#createCircularReveal(android.view.View,%20int,%20int,%20float,%20float)

https://developer.android.com/reference/android/graphics/BitmapShader

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章