How to Clip a Star in android ? But the appearance of the star is clear

南楼画角 提交于 2019-11-27 23:20:12

It seems that you can't perform Anti Aliasing with clipPath. Instead of using clipPath for masking, try bitmap masking (it's a bit more complicated that clipPath, but it gives a clear edges for the star). I have modified your code to use bitmap masking instead of clip path.

Code:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by chozarajan.pandiyarajan on 10/9/2015.
 */

public class SfRatingItem extends View {

    private int fillColor, minDim, topXPoint, topYPoint;
    private double bigHypot, bigA, bigB, littleHypot, littleA, littleB, value;
    private Paint starPaint;
    private Path path;
    private Bitmap starBitmap;
    private Bitmap backBitmap;

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

    public SfRatingItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initialize();
    }

    public SfRatingItem(Context context) {
        super(context);
        initialize();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        initialDraw();
        Paint q = new Paint(Paint.ANTI_ALIAS_FLAG);

        //canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),q); // expensive call, instead set a hardware layer
        setLayerType(LAYER_TYPE_HARDWARE, q);

        canvas.drawBitmap(backBitmap, 0, 0, q);
        q.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        canvas.drawBitmap(starBitmap, 0, 0, q);
        q.setXfermode(null);

    }

    private void initialDraw() {
        starPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        starPaint.setAntiAlias(true);

        minDim = Math.min(this.getWidth() - this.getPaddingLeft() - this.getPaddingRight(), this.getHeight() - this.getPaddingTop() - this.getPaddingBottom());

        bigHypot = (minDim / Math.cos(Math.toRadians(18)));
        bigB = minDim;
        bigA = Math.tan(Math.toRadians(18)) * bigB;

        littleHypot = bigHypot / (2 + Math.cos(Math.toRadians(72)) + Math.cos(Math.toRadians(72)));
        littleA = Math.cos(Math.toRadians(72)) * littleHypot;
        littleB = Math.sin(Math.toRadians(72)) * littleHypot;

        topXPoint = (this.getWidth() - this.getPaddingLeft() - this.getPaddingRight()) / 2;
        topYPoint = this.getPaddingTop();

        path.moveTo(topXPoint, topYPoint);
        path.lineTo((int) (topXPoint + bigA), (int) (topYPoint + bigB));
        path.lineTo((int) (topXPoint - littleA - littleB), (int) (topYPoint + littleB));
        path.lineTo((int) (topXPoint + littleA + littleB), (int) (topYPoint + littleB));
        path.lineTo((int) (topXPoint - bigA), (int) (topYPoint + bigB));
        path.lineTo(topXPoint, topYPoint);
        path.close();

        // Draw the STAR mask in a bitmap
        RectF bounds = new RectF();
        path.computeBounds(bounds, true);
        starBitmap = Bitmap.createBitmap((int) bounds.width(), (int) bounds.height(), Bitmap.Config.ARGB_8888);
        Canvas starCanvas = new Canvas(starBitmap);
        starPaint.setColor(Color.BLACK);
        starCanvas.drawPath(path, starPaint);

        // Draw the background rectangle in a bitmap
        starPaint.setColor(Color.RED);
        backBitmap = Bitmap.createBitmap((int) bounds.width(), (int) bounds.height(), Bitmap.Config.ARGB_8888);
        Canvas backCanvas = new Canvas(backBitmap);
        final Rect backRect = new Rect(0, 0, backBitmap.getWidth(), backBitmap.getHeight());
        backCanvas.drawRect(backRect, starPaint);
    }

    private void initialize() {
        starPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        path = new Path();
    }
}

Here I have created two bitmaps, one for the star mask and the other for the background rectangle. Then using Paint.setXfermode(), I have masked one bitmap over the other. You can dynamically show the partial filling by modifying the width of the background rectangle (i.e, width of backRect). Currently I am creating the bitmaps in the onDraw() method, but this is a bad idea and you need to do this in the `constructor itself, based on the size of the star required.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!