Developers Club geek daily blog

1 year, 8 months ago
image

Introduction


Presently there are many users on whose mobile devices the Instagram application is installed. In this application there is a remarkable function – will share the pleasant image. And at the choice of the user to which we wish to send pleasant a post we see the rounded avatar on which at a clique animation is displayed and selection is performed. I wanted to repeat implementation of this element.

Initial stage

Let's create a new class, the successor of android.widget.ImageView.

public class MyView extends ImageView {

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

Let's create the init method () in which we initialize objects of Paint for drawing of graphic objects.

public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        redBorder = new Paint();
        redBorder.setAntiAlias(true);
        redBorder.setColor(Color.RED);
        redBorder.setStrokeWidth(redStrokeWidth);
        redBorder.setStyle(Paint.Style.STROKE);

        imgPaint = new Paint();
        imgPaint.setAntiAlias(true);
        imgPaint.setFilterBitmap(true);
        imgPaint.setDither(true);
    }

The object of Paint redBoard is responsible for drawing of a red frame which will be displayed at selection. The flag of setAntiAlias (true) provides smoothing. Then we set red color (setColor(Color.RED)), width of a circuit of setStrokeWidth (redStrokeWidth), redStrokeWidth a normal variable (private int redStrokeWidth = 10;) also we set style of drawing setStyle(Paint.Style.STROKE) — to draw outlines of a graphic primitive.

The object of Paint imgPaint is responsible for a rounding off of an avatar of the user. The flag of setFilterBitmap (true) says that filtering will exert impact on the bitmap image at transformation. The flag of setDither (true) is used for smoothing of flowers, allows to reduce visual artifacts.

Conversion of the image

We receive the image over which we will do all necessary conversions.

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        decrement = (w * decrementFactor)/100;
        bitmapPosition = decrement /2;

        Drawable drawable = getDrawable();
        if (drawable != null) {
            Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
            roundBitmap = getRoundedCroppedBitmap(bitmap, getWidth() - decrement);
        } else {
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            roundBitmap = getRoundedCroppedBitmap(bitmap, getWidth() - decrement);
        }
    }

Since at selection it is necessary to draw a red frame and an indent from the image, we enter the decrementFactor variable which, as in given cases, will make 15% of all size of an element (private int decrementFactor = 15;). I.e. the element has the size w, and the image in it will be 15% less. Also we calculate value for the bitmapPosition variable which will be used when positioning the image. We perform check on existence of the image. If the image is set, we do conversions over it (getRoundedCroppedBitmap method) differently, we take a logo.

The getRoundedCroppedBitmap method () is responsible for an image rounding off.

private Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
        Bitmap finalBitmap = bitmap.createScaledBitmap(bitmap, radius , radius, false);
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(), finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Rect rect = new Rect(0, 0, output.getWidth(), output.getHeight());

        Canvas canvas = new Canvas(output);
        canvas.drawCircle(
                finalBitmap.getWidth()  / 2,
                finalBitmap.getHeight() / 2,
                finalBitmap.getWidth() / 2,
                imgPaint);

        imgPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, imgPaint);

        return output;
    }

By means of the createScaledBitmap method () we change image size, on the basis of the smashtabirovanny image we create new which will be result of work of a method. We create object of Rect rect on the basis of which we will draw bitmap. We receive canvas, rusuy a circle and for object of Paint we change the Xfermode mode which influences a method of imposing of new flowers of atop already drawn.

I.e. we changed image size on that which is necessary to us. Drew a circle over this image and performed imposing of a circle on the image, having told that what enters a circle will be visible.

Let's draw the received element:

@Override
 protected void onDraw(Canvas canvas) {
     canvas.drawBitmap(roundBitmap, bitmapPosition, bitmapPosition, null);
     if (imgSelected) {
         canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - redStrokeWidth, redBorder);
     }
 }

In order that our element began to react to clicking, we will redefine a method:

@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Animation scale = AnimationUtils.loadAnimation(getContext(), R.anim.scale);
                startAnimation(scale);
                break;
            case MotionEvent.ACTION_UP:
                imgSelected = !imgSelected;
                invalidate();
                Animation scale2 = AnimationUtils.loadAnimation(getContext(), R.anim.scale_2);
                startAnimation(scale2);
                break;
        }
        return true;
    }

By clicking we will reduce a little an element. We load a XML file in which animation for reduction is described:

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="1.0"
    android:toXScale="0.9"
    android:fromYScale="1.0"
    android:toYScale="0.9"
    android:duration="200"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fillAfter="true">
</scale>

And when the user will release a finger, we will draw a red frame and we will a little increase an element:

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="1.0"
    android:toXScale="1.1"
    android:fromYScale="1.0"
    android:toYScale="1.1"
    android:duration="200"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fillAfter="true">
</scale>

Conclusion

As a result the lovely element with simple animation turned out.

The code of the project is available on git.

I will be glad to comments. Thanks.

image

This article is a translation of the original post at habrahabr.ru/post/274801/
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here: sysmagazine.com@gmail.com.

We believe that the knowledge, which is available at the most popular Russian IT blog habrahabr.ru, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus