Android realizes the animation effect of face recognition

Effect display

Implementation steps

1. Draw a circle mask

Here we use the mixed mode to realize the deduction of the circle part. Here we use PorterDuff.Mode.CLEAR

/**
     * Draw circle mask
     * @param canvas
     */
    private void drawCircleMask(Canvas canvas) {
        canvas.save();
        //Target map Dst
        canvas.drawRect(new Rect(0,0,getWidth(),getHeight()), mPaint);
        //Set blend mode
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        //Source image Src, lower right corner of overlapping area
        canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 3, mPaint);
        //Clear blend mode
        mPaint.setXfermode(null);
        canvas.restore();
    }

The effect is as follows

2. Draw two animated circles

The two pictures we draw are as follows

What we need to do is to scale the Bitmap to the same size as the circle of the previous mask effect by calculation, because the two pictures we use here are the same size, so we only need to calculate the scaling ratio of the inner circle picture and the mask circle, because the radius we set for the mask circle is: control width / 3

Therefore, the width and height of the scaled circle Bitmap should be the total length of the middle red line plus the blue parts on both sides as shown in the figure below

The middle red line is: control width / 3  , The blue line can be measured by PhotoShop and other tools, and then calculated according to the proportion with the red line. The code is as follows, where mInnerCircleBitmap is the inner circle and mOutCircleBitmap is the outer circle

/**
     * Draw a picture of the circle outside the circle
     */
    private void drawBitmapCircle(Canvas canvas) {
        if(mInnerCircleBitmap == null){
            int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
            mInnerCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_innercircle);
            mInnerCircleBitmap = Bitmap.createScaledBitmap(mInnerCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
        }
        if(mOutCircleBitmap == null){
            int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
            mOutCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_outcircle);
            mOutCircleBitmap = Bitmap.createScaledBitmap(mOutCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
        }
        int left = (getWidth() - mInnerCircleBitmap.getWidth()) / 2;
        int top = (int) (getWidth() / 2 - getWidth() / 3 - getWidth() / 1.5f / 8);

        canvas.drawBitmap(mInnerCircleBitmap,left,top,mPaint);

        canvas.drawBitmap(mOutCircleBitmap,left,top,mPaint);
    }

The effect is as follows

3. Realize the rotation animation effect

Next, we can realize the rotation effect of the circle through ValueAnimator. From the effect at the beginning of the article, we can see that the rotation directions of the two circles are different. Therefore, we should also pay attention to the clockwise rotation and the counterclockwise rotation logically. The code is as follows

private float mDegress = 0;//Rotation angle
private void init() {
        //Define animation
        valueAnimator = ValueAnimator.ofFloat(0f, 360f);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(6000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mDegress = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        valueAnimator.start();
    }
/**
     * Draw a picture of the circle outside the circle
     */
    private void drawBitmapCircle(Canvas canvas) {
        if(mInnerCircleBitmap == null){
            int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
            mInnerCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_innercircle);
            mInnerCircleBitmap = Bitmap.createScaledBitmap(mInnerCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
        }
        if(mOutCircleBitmap == null){
            int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
            mOutCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_outcircle);
            mOutCircleBitmap = Bitmap.createScaledBitmap(mOutCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
        }
        int left = (getWidth() - mInnerCircleBitmap.getWidth()) / 2;
        int top = (int) (getWidth() / 2 - getWidth() / 3 - getWidth() / 1.5f / 8);
        //Clockwise rotation
        canvas.save();
        canvas.rotate(mDegress,getWidth() / 2, getWidth() / 2);
        canvas.drawBitmap(mInnerCircleBitmap,left,top,mPaint);
        canvas.restore();
         //Counterclockwise rotation
        canvas.save();
        canvas.rotate(-mDegress,getWidth() / 2, getWidth() / 2);
        canvas.drawBitmap(mOutCircleBitmap,left,top,mPaint);
        canvas.restore();
    }

The effect is as follows

4. Add prompt text

Drawing text is relatively simple. It is mainly used to prompt users for operations. The code is as follows

canvas.drawText("Please move your face into the circle",getWidth() / 2, (float) (getWidth() * 1.2),mTextPaint);

The final effect is as follows

Case source code

The source code in the above implementation steps is split. The detailed and complete code can be obtained at the following address https://gitee.com/itfitness/f...

Original link: https://www.jianshu.com/p/938...

end of document

Your favorite collection is my greatest encouragement!
Welcome to follow me, share Android dry goods and exchange Android technology.
If you have any opinions on the article or any technical problems, please leave a message in the comment area for discussion!

Keywords: Android Back-end

Added by bljepp69 on Thu, 09 Dec 2021 04:10:01 +0200