我应该怎样给图像在Android的圆angular?
我想改变我加载的图像有圆angular。
你知道的任何提示,教程,最佳实践?
对于更受控制的方法,绘制一个圆angular的矩形,并使用paint的porter-duff Xfer模式将其蒙版到图像上。
首先设置Xfer颜色和圆angular位图:
Bitmap myCoolBitmap = ... ; // <-- Your bitmap you want rounded int w = myCoolBitmap.getWidth(), h = myCoolBitmap.getHeight(); // We have to make sure our rounded corners have an alpha channel in most cases Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(rounder); // We're going to apply this paint eventually using a porter-duff xfer mode. // This will allow us to only overwrite certain pixels. RED is arbitrary. This // could be any color that was fully opaque (alpha = 255) Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG); xferPaint.setColor(Color.RED); // We're just reusing xferPaint to paint a normal looking rounded box, the 20.f // is the amount we're rounding by. canvas.drawRoundRect(new RectF(0,0,w,h), 20.0f, 20.0f, xferPaint); // Now we apply the 'magic sauce' to the paint xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
现在将这个位图应用到图像的顶部:
Bitmap result = Bitmap.createBitmap(myCoolBitmap.getWidth(), myCoolBitmap.getHeight() ,Bitmap.Config.ARGB_8888); Canvas resultCanvas = new Canvas(result) resultCanvas.drawBitmap(myCoolBitmap, 0, 0, null); resultCanvas.drawBitmap(rounder, 0, 0, xferPaint);
现在圆形的位图位于结果中。
为什么不使用clipPath?
protected void onDraw(Canvas canvas) { Path clipPath = new Path(); float radius = 10.0f; float padding = radius / 2; int w = this.getWidth(); int h = this.getHeight(); clipPath.addRoundRect(new RectF(padding, padding, w - padding, h - padding), radius, radius, Path.Direction.CW); canvas.clipPath(clipPath); super.onDraw(canvas); }
Romain Guy自己在他的博客中写道:
为了生成圆angular的图像,我只写了一个自定义的Drawable,使用Canvas.drawRoundRect()绘制一个圆angular的矩形。 诀窍是使用带有BitmapShader的Paint来使用纹理填充圆angular矩形,而不是简单的颜色。 这是代码的样子:
BitmapShader shader; shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setShader(shader); RectF rect = new RectF(0.0f, 0.0f, width, height); // rect contains the bounds of the shape // radius is the radius in pixels of the rounded corners // paint contains the shader that will texture the shape canvas.drawRoundRect(rect, radius, radius, paint);
示例应用程序稍微进一步,并通过将BitmapShader与RadialGradient结合来伪装成一个小插曲效果。
这是我用ImageView发现的一种方法。 我尝试了其他方法,包括这里和类似问题上的答案,但是我发现它们对我来说工作不好,因为我需要将angular落应用到图像视图,而不是直接应用到位图。 如果您正在缩放/裁剪/平移位图,则直接应用于位图将不起作用,因为angular点也将被缩放/裁剪/平移。
public class RoundedCornersImageView extends ImageView { private final Paint restorePaint = new Paint(); private final Paint maskXferPaint = new Paint(); private final Paint canvasPaint = new Paint(); private final Rect bounds = new Rect(); private final RectF boundsf = new RectF(); public RoundedCornersImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public RoundedCornersImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RoundedCornersImageView(Context context) { super(context); init(); } private void init() { canvasPaint.setAntiAlias(true); canvasPaint.setColor(Color.argb(255, 255, 255, 255)); restorePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); maskXferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); } @Override protected void onDraw(Canvas canvas) { canvas.getClipBounds(bounds); boundsf.set(bounds); canvas.saveLayer(boundsf, restorePaint, Canvas.ALL_SAVE_FLAG); super.onDraw(canvas); canvas.saveLayer(boundsf, maskXferPaint, Canvas.ALL_SAVE_FLAG); canvas.drawARGB(0, 0, 0, 0); canvas.drawRoundRect(boundsf, 75, 75, canvasPaint); canvas.restore(); canvas.restore(); } }
下面是使用最终图层组合的硬件层的替代方法:
public class RoundedCornersImageView extends ImageView { private final Paint restorePaint = new Paint(); private final Paint maskXferPaint = new Paint(); private final Paint canvasPaint = new Paint(); private final Rect bounds = new Rect(); private final RectF boundsf = new RectF(); public RoundedCornersImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public RoundedCornersImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RoundedCornersImageView(Context context) { super(context); init(); } private void init() { canvasPaint.setAntiAlias(true); canvasPaint.setColor(Color.argb(255, 255, 255, 255)); restorePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); maskXferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); setLayerType(View.LAYER_TYPE_HARDWARE, restorePaint); } @Override protected void onDraw(Canvas canvas) { canvas.getClipBounds(bounds); boundsf.set(bounds); super.onDraw(canvas); canvas.saveLayer(boundsf, maskXferPaint, Canvas.ALL_SAVE_FLAG); canvas.drawARGB(0, 0, 0, 0); canvas.drawRoundRect(boundsf, 75, 75, canvasPaint); canvas.restore(); } }
起初我不能用这个方法来工作,因为我的angular落变黑了。 我后来意识到这个问题后,看到这个问题: Android如何在ImageView上应用蒙版? 。 事实certificate,在canvas上修改alpha实际上是直接在屏幕上“刮出”的,并在黑色的底层窗口上打孔。 这就是为什么需要两个图层:一个应用蒙版,另一个将合成图像应用到屏幕。
如何创build一个只有圆angular并具有透明体的NinePatchDrawable图像。 用NinePatchDrawable的适当重新resize的版本覆盖图像。
package com.pkg; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Bitmap.Config; import android.graphics.PorterDuff.Mode; import android.os.Bundle; import android.os.Environment; import android.widget.ImageView; public class RoundedImage extends Activity { /** Called when the activity is first created. */ ImageView imag; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imag=(ImageView)findViewById(R.id.image); //ImageView img1=(ImageView)findViewById(R.id.imageView1); BitmapFactory.Options bitopt=new BitmapFactory.Options(); bitopt.inSampleSize=1; // String img=Environment.getExternalStorageDirectory().toString(); // String filepath =Environment.getExternalStorageDirectory().toString(); String filepath ="/mnt/sdcard/LOST.DIR"; File imagefile = new File(filepath + "/logo.jpg"); FileInputStream fis = null; try { fis = new FileInputStream(imagefile); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } Bitmap bi = BitmapFactory.decodeStream(fis); if(bi!=null){ imag.setImageBitmap(getRoundedCornerBitmap(bi)); } } public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = 12; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } }