我想将我加载的图像更改为圆角。
您知道的任何提示,教程和最佳做法?
答案 0 :(得分:43)
对于更受控制的方法,使用绘制的porter-duff Xfer模式绘制圆角矩形并将其蒙版到图像上。
首先设置Xfer绘图和圆角位图:
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);
带圆角的位图现在位于结果中。
答案 1 :(得分:29)
为什么不使用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);
}
答案 2 :(得分:16)
Romain Guy自己在his blog写道:
为了生成圆形图像,我只需编写一个自定义Drawable 使用Canvas.drawRoundRect()绘制一个圆角矩形。诀窍是 使用带有BitmapShader的Paint来填充圆角矩形 纹理而不是简单的颜色。这是代码的样子:
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相结合来实现效果。
答案 3 :(得分:7)
这是我发现用ImageView做的一种方式。我尝试了其他方法,包括这里的答案和类似的问题,但我发现它们对我来说效果不好,因为我需要将角应用于图像视图而不是直接应用于位图。如果你正在缩放/裁剪/平移该位图,直接应用于位图将无法工作,因为角也将被缩放/裁剪/平移。
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();
}
}
起初我无法使用这种方法,因为我的角落变黑了;我后来才意识到在阅读这个问题后问题是什么:Android how to apply mask on ImageView?。事实证明,修改画布中的alpha实际上是&#34;抓住它&#34;直接在屏幕上,并打孔到下面的黑色窗口。这就是为什么需要两个图层的原因:一个用于应用蒙版,另一个用于将合成图像应用到屏幕。
答案 4 :(得分:5)
如何创建一个只有圆角且具有透明体的NinePatchDrawable图像。使用适当重新调整大小的NinePatchDrawable版本覆盖您的图像。
答案 5 :(得分:4)
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;
}
}
答案 6 :(得分:0)
这是另一个使用ImageView
的四舍五入Path
实现。性能很好,但是在某些情况下,由于硬件图纸,模拟器上可能会出现一些错误。
public class RoundImageView extends ImageView {
private Path mPath;
private RectF mRect;
private Paint mPaint;
private int mCornerRadius;
private float mImageAlpha;
private boolean mIsCircular;
public RoundImageView(Context context) {
this(context, null);
}
public RoundImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.roundImageViewStyle);
}
public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.RoundImageView, defStyle, 0);
mCornerRadius = a.getDimensionPixelSize(R.styleable.RoundImageView_cornerRadius, 0);
mIsCircular = a.getBoolean(R.styleable.RoundImageView_isCircular, false);
mImageAlpha = a.getFloat(R.styleable.RoundImageView_imageAlpha, 1);
a.recycle();
setAlpha((int) (mImageAlpha * 255));
// Avoid expensive off-screen drawing
setLayerType(LAYER_TYPE_HARDWARE, null);
mPath = new Path();
mRect = new RectF();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
if (mIsCircular) {
float halfWidth = canvas.getWidth() / 2;
float halfHeight = canvas.getHeight() / 2;
float radius = Math.max(halfWidth, halfHeight);
mPath.addCircle(halfWidth, halfHeight, radius, Path.Direction.CW);
} else {
mRect.right = canvas.getWidth();
mRect.bottom = canvas.getHeight();
mPath.addRoundRect(mRect, mCornerRadius, mCornerRadius, Path.Direction.CW);
}
canvas.drawPath(mPath, mPaint);
}
}
P.S。 Learn OpenGL ES提供了最佳解决方案。它非常平滑,并且也可以在模拟器上运行。
答案 7 :(得分:0)
我找到的最佳解决方案->
1)创建可绘制的圆角。并设置为imageview作为背景。
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners
android:radius="10dp" /></shape>
2)然后在Java代码中设置setClipToOutline(true)的图像视图对象属性。
imageview.setClipToOutline(true);
就像魅力一样