目录表
- android 自定义view必备api
- android 可拖动圆环刻度条
- android 仿滴滴大头针跳动波纹效果
- android 仿网易云鲸云音效
- Android 仿滴滴首页嵌套滑动效果
- path 的圆角处理
在开发过程中,圆角背景和圆角图片应该都算是标配了,如下面效果:顶部一个自定义的进度背景 view,下面挨着路口放大图 ImageView。
实现一
由于都是代码动态设置的,所以就不考虑 xml 了。设置背景首先想到的是 GradientDrawable,我们可以通过其 setCornerRadii 方法来指定 4 个圆角的弧度。float[] 的长度是 8 ,2 个一组,很灵活。最后通过 setBackgroundDrawable(Drawable background) 直接设置即可。
private GradientDrawable getBackground(boolean isNightMode) {
int color;
if (isNightMode) {
color = Color.parseColor("#000000");
} else {
color = Color.parseColor("#3C3F46");
}
float radius = NaviUtil.dp2px(getContext(), 8);
GradientDrawable drawable = new GradientDrawable();
drawable.setShape(GradientDrawable.RECTANGLE);
drawable.setCornerRadii(new float[]{radius, radius, radius, radius
,0, 0, 0, 0});
drawable.setColor(color);
return drawable;
}
实现二
可以将整个 view 通过裁剪画布的方式,在 onDraw方法中进行绘制。主要方法即 path.addRoundRect(…) ,代码见下:
private void drawClipPathOnCanval(Canvas canvas) {
if(mClipPath == null){
mClipPath = new Path();
if(mClipRectF == null)
mClipRectF = new RectF(0, 0
, CommentUtils.dip2px(mContext, 150)
, CommentUtils.dip2px(mContext, 150));
// path为圆形矩形。裁剪圆形,弧等都同理
mClipPath.addRoundRect(mClipRectF
, CommentUtils.dip2px(mContext, 15)
, CommentUtils.dip2px(mContext, 15)
, Path.Direction.CW);
}
canvas.clipPath(mClipPath);
}
方法 addRoundRect(RectF, rx, ry, direction) 同时绘制 4 个角弧度是非常方便的,但如果只需绘制左上和左下两个弧角呢?所幸其还有带 float[] 参数的同载方法,可以灵活设置每个角的弧度,使用方法估计一看就明:
addRoundRect(RectF rect, float[] radii, Direction dir)
在对 canvas 进行裁剪前,我们需要锁定下画布,裁剪绘制完成之后,再恢复画布。在 onDraw方法见下:
// 锁定当前画布
canvas.save();
// 裁剪画布
drawClipPathOnCanval(canvas);
// 正常绘制逻辑:这里包括绘制进度条等
// 恢复画布
canvas.restore();
实现三
如果对于进度值的精度要求不高,完全可能通过多边形 + 圆弧的方式来实现两个角的圆弧矩形。例如上图中的绿色进度实现,方法可以如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float currW = getWidth() * mProgress;
if (currW < mRadus * 0.25) {
return;
} else if (currW <= mRadus) {
currW = mRadus;
} else if (currW > getWidth() - mRadus) {
// 绘制右上角弧度
canvas.drawArc(getRect(getWidth() - 2 * mRadus, 0
, getWidth(), 2 * mRadus)
, -90, 90
, true, mPbBgPaint);
canvas.drawRect(getRect(getWidth() - mRadus, mRadus
, getWidth(), mPbheight), mPbBgPaint);
currW = getWidth() - mRadus;
}
// 绘制左上角弧度
canvas.drawArc(getRect(0, 0, mRadus * 2, mRadus * 2)
, 180, 90
, true, mPbBgPaint);
// 绘制多边形
mMorePath.moveTo(0, mPbheight);
mMorePath.lineTo(0, mRadus);
mMorePath.lineTo(mRadus, mRadus);
mMorePath.lineTo(mRadus, 0);
mMorePath.lineTo(currW, 0);
mMorePath.lineTo(currW, mPbheight);
mMorePath.close();
canvas.drawPath(mMorePath, mPbBgPaint);
}
实现四
对于图片 Bitmap 的裁剪,我们也可以通过 path 来生成一个两个弧角的 Bitmap,方法见下:
public Bitmap getRoundedCornerBitmap(Bitmap bitmap, float[] rids) {
try {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(),
bitmap.getHeight());
final RectF rectF = new RectF(new Rect(0, 0, bitmap.getWidth(),
bitmap.getHeight()));
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.BLACK);
Path path = new Path();
// float[] rids 可灵活设置每个角的弧度
path.addRoundRect(rectF
, rids
, Path.Direction.CW);
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
final Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawBitmap(bitmap, src, rect, paint);
return output;
} catch (OutOfMemoryError outOfMemoryError){
outOfMemoryError.printStackTrace();
return bitmap;
}catch (Exception e) {
TLog.e(TAG, TLog.USR, e);
return bitmap;
}
}