如何在android中剪辑星星?但星星的样子是清晰的 [英] How to Clip a Star in android ? But the appearance of the star is clear

查看:27
本文介绍了如何在android中剪辑星星?但星星的样子是清晰的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

先看下图.

package com.syncfusion.rating;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Region;
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;

public SfRatingItem(Context context) {
    super(context);
    starPaint=new Paint();
    fillPaint=new Paint();
    path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
    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();
    starPaint.setColor(Color.RED); 

 //Use below code to paint the star
 canvas.drawPath(path, starPaint);

 // Use below code to clip the star path.
     // canvas.clipPath(path, Region.Op.DIFFERENCE);
     //  canvas.drawColor(Color.WHITE);
    super.onDraw(canvas);
 } 

如果你看到上面的图片,你就知道这两张图片的区别了.

If you see the above images, you know the difference of this two images.

第一个是剪切图像.边缘剪下的星星不清晰.

First one is clipped image. The clipped star of the edges is not clear.

第二个是画图.边缘的彩绘星形清晰.

Second one is Painted image. The painted star of the edges are clear.

因为在绘制的图像中,我习惯于将 setAntiAlise() 属性设置为 true.

Because in painted image, i am use to set true of setAntiAlise() property.

我的问题是如何让裁剪后的图像边缘清晰?

My question is how to get the clipped image edges are clear?

推荐答案

clipPath 似乎无法执行抗锯齿.不要使用 clipPath 进行遮罩,而是尝试位图遮罩(它比 clipPath 复杂一点,但它为星星提供了清晰的边缘).我已将您的代码修改为使用位图遮罩而不是剪辑路径.

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.

代码:

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();
    }
}

这里我创建了两个位图,一个用于星形蒙版,另一个用于背景矩形.然后使用 Paint.setXfermode(),我将一个位图屏蔽在另一个上.您可以通过修改背景矩形的宽度(即backRect的宽度)来动态显示部分填充.目前,我正在 onDraw() 方法中创建位图,但这是一个坏主意,您需要根据所需的星形大小在`构造函数本身中执行此操作.

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.

这篇关于如何在android中剪辑星星?但星星的样子是清晰的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆