如何在 android 中剪辑星星?但是明星的样子很清晰
Posted
技术标签:
【中文标题】如何在 android 中剪辑星星?但是明星的样子很清晰【英文标题】:How to Clip a Star in android ? But the appearance of the star is clear 【发布时间】:2016-01-22 22:47:28 【问题描述】:先看下图。
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);
如果你看到上面的图片,你就知道这两张图片的区别了。
第一个是剪辑图像。边缘被剪掉的星形不清晰。
第二个是画图。边缘的彩绘星形清晰。
因为在绘制的图像中,我习惯于将 setAntiAlise() 属性设置为 true。
我的问题是如何让剪裁的图像边缘清晰?
【问题讨论】:
【参考方案1】:您似乎无法使用clipPath
执行抗锯齿。不要使用clipPath
进行遮罩,而是尝试位图遮罩(它比clipPath
稍微复杂一点,但它为星星提供了清晰的边缘)。我已修改您的代码以使用位图遮罩而不是剪辑路径。
代码:
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
的宽度)来动态显示partial filling
。目前我正在onDraw()
方法中创建位图,但这是一个坏主意,您需要根据所需星的大小在`构造函数本身中执行此操作。
【讨论】:
谢谢,但请避免在onDraw
中创建对象(特别是Paint
:)以上是关于如何在 android 中剪辑星星?但是明星的样子很清晰的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Flash 中为 MovieClip 分配属性并在 Flex 中访问它们?
如何在 android/andengine 中剪辑或屏蔽实体?