我目前通过绘制画布在我的应用中创建了一个圆形版本的图像。我想在图像周围画一个微弱的outershadow,但我不能完全正确。我有两个问题: 1.如何绘制外部阴影(我似乎只能绘制带有x或y偏移的阴影) 2.如何绘制阴影,使其没有附加图像中显示的工件。代码:
![public Bitmap getRoundedCornerBitmap(Bitmap bitmap, float cornerRadius) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth()+6, bitmap.getHeight() +6, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
int shadowRadius = getDipsFromPixel(3);
final Rect imageRect = new Rect(shadowRadius, shadowRadius, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(imageRect);
// This does not achieve the desired effect
Paint shadowPaint = new Paint();
shadowPaint.setAntiAlias(true);
shadowPaint.setColor(Color.BLACK);
shadowPaint.setShadowLayer((float)shadowRadius, 2.0f, 2.0f,Color.BLACK);
canvas.drawOval(rectF, shadowPaint);
canvas.drawARGB(0, 0, 0, 0);
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, imageRect, imageRect, paint);
return output;
}][1]
这是我想要实现的效果的一个例子:
答案 0 :(得分:29)
我想要类似的效果,但是在AppWidget上,很遗憾我无法使用@ EvelioTarazona的解决方案。这就是我提出的,它应该适用于任何形状的位图。
final Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
final Bitmap shadow = addShadow(src, src.getHeight(), src.getWidth(), Color.BLACK, 3, 1, 3);
final ImageView iv = (ImageView)findViewById(R.id.image);
iv.setImageBitmap(shadow);
public Bitmap addShadow(final Bitmap bm, final int dstHeight, final int dstWidth, int color, int size, float dx, float dy) {
final Bitmap mask = Bitmap.createBitmap(dstWidth, dstHeight, Config.ALPHA_8);
final Matrix scaleToFit = new Matrix();
final RectF src = new RectF(0, 0, bm.getWidth(), bm.getHeight());
final RectF dst = new RectF(0, 0, dstWidth - dx, dstHeight - dy);
scaleToFit.setRectToRect(src, dst, ScaleToFit.CENTER);
final Matrix dropShadow = new Matrix(scaleToFit);
dropShadow.postTranslate(dx, dy);
final Canvas maskCanvas = new Canvas(mask);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskCanvas.drawBitmap(bm, scaleToFit, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
maskCanvas.drawBitmap(bm, dropShadow, paint);
final BlurMaskFilter filter = new BlurMaskFilter(size, Blur.NORMAL);
paint.reset();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setMaskFilter(filter);
paint.setFilterBitmap(true);
final Bitmap ret = Bitmap.createBitmap(dstWidth, dstHeight, Config.ARGB_8888);
final Canvas retCanvas = new Canvas(ret);
retCanvas.drawBitmap(mask, 0, 0, paint);
retCanvas.drawBitmap(bm, scaleToFit, null);
mask.recycle();
return ret;
}
答案 1 :(得分:14)
我们走了
是的,我仍在挖掘Nexus S
首先,请停止以这种方式屏蔽位图,您可以在不分配其他Bitmap
,结帐this blog post about how to draw rounded (and actually any shape) images的情况下完成此操作。
第二次使用Drawable
你可能会弄清楚如何添加你的影子,只要确保它不会被剪裁,在18岁以上你可以使用ViewOverlay
来做到这一点,同时请记住there are several unsupported drawing operations for hardware accelerated layers,包括setShadowLayer
和BlurMaskFilter
,如果效果不是您的问题,您可以一如既往地停用它:
if (SDK_INT >= HONEYCOMB) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
并使用setShadowLayer
,因为您已尝试过:
somePaint.setShadowLayer(shadowSize, deltaX, deltaY, shadowColor);
如需样本,请查看最后的链接。
如果您仍然希望硬件加速,则必须假装它有过度绘制的风险,您可以使用径向渐变或绘制另一个椭圆模糊它(如前所述,不能使用BlurMaskFilter
)或使用预先模糊的Bitmap
(更多遮蔽)。
对于这样一个微妙的阴影,如果需要表现,我宁愿单调,the full sauce is in the banana stand。
答案 2 :(得分:2)
在drawable文件夹中创建一个xml名称round_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="1dp"
android:color="#bebebe" />
</shape>
将此round_shape设置为图像视图的背景,如下所示
<ImageView
android:id="@+id/img_profile"
android:layout_width="120dp"
android:layout_height="120dp"
android:padding="2dp"
android:scaleType="fitXY"
android:src="@drawable/camera" />
上面的代码在您对位图进行舍入后在图像视图周围创建一个薄层,下面的函数将执行此操作
public Bitmap roundBit(Bitmap bm) {
Bitmap circleBitmap = Bitmap.createBitmap(bm.getWidth(),
bm.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bm, TileMode.CLAMP,
TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
paint.setAntiAlias(true);
Canvas c = new Canvas(circleBitmap);
c.drawCircle(bm.getWidth() / 2, bm.getHeight() / 2, bm.getWidth() / 2,
paint);
return circleBitmap;
}
答案 3 :(得分:2)
ImageView imageView=findViewById(R.id.iv);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.images);
imageView.setImageBitmap(doHighlightImage(icon));
public static Bitmap doHighlightImage(Bitmap src) {
Bitmap bmOut = Bitmap.createBitmap(src.getWidth() + 96, src.getHeight() + 96, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmOut);
canvas.drawColor(0, Mode.CLEAR);
Paint ptBlur = new Paint();
ptBlur.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.NORMAL));
int[] offsetXY = new int[2];
Bitmap bmAlpha = src.extractAlpha(ptBlur, offsetXY);
Paint ptAlphaColor = new Paint();
ptAlphaColor.setColor(Color.BLACK);
canvas.drawBitmap(bmAlpha, offsetXY[0], offsetXY[1], ptAlphaColor);
bmAlpha.recycle();
canvas.drawBitmap(src, 0, 0, null);
return bmOut;
}
答案 4 :(得分:1)
这是我对 sharmitha 答案的修改。它是 Kotlin,它使用 bmAlpha 的大小作为结果位图,因此不会裁剪阴影。
private val metrics: DisplayMetrics by lazy {
val metrics = DisplayMetrics()
val manager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
manager.defaultDisplay.getMetrics(metrics)
metrics
}
private fun withDensity(value: Float): Float = metrics.density * value
private fun addShadow(src: Bitmap, blurRadius: Float, @ColorInt shadowColor: Int): Bitmap {
val offsetXY = IntArray(2)
val bmAlpha = src.extractAlpha(
Paint().apply { maskFilter = BlurMaskFilter(withDensity(blurRadius), BlurMaskFilter.Blur.NORMAL) },
offsetXY
)
val bmOut = Bitmap.createBitmap(bmAlpha.width, bmAlpha.height, Bitmap.Config.ARGB_8888)
Canvas(bmOut).apply {
drawColor(0, PorterDuff.Mode.CLEAR)
drawBitmap(
bmAlpha,
0f,
0f,
Paint().apply { color = shadowColor })
drawBitmap(
src,
0f - offsetXY[0].toFloat(),
0f - offsetXY[1].toFloat(),
null)
}
bmAlpha.recycle()
return bmOut
}