Android自定义View实现圆形切图效果
2017-12-02 14:50
387 查看
使用自定义View实现圆形ImageView的效果,具体内容如下
目前圆形边框还需要调整,这里有点问题
实现思路
使用一个Paint,将得到的Bitmap设置成paint的Shader,设置完成后,使用Matrix调整图片至居中,使用RectF约束边框,最后完成绘制
初始化Paint,设置Shader
private void init() { getBitmapFromDrawable(); if (mBitmap == null) { return; } mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // bitmap paint mFillPaint = new Paint(); mFillPaint.setAntiAlias(true); mFillPaint.setStyle(Paint.Style.FILL); mFillPaint.setShader(mShader); // border paint mBoundPaint = new Paint(); mBoundPaint.setAntiAlias(true); mBoundPaint.setStyle(Paint.Style.STROKE); mBoundPaint.setStrokeWidth(mBorderWidth); mBoundPaint.setColor(mBorderColor); // border rectF mBorderBound.set(calculateBitmapBound()); // bitmap rectF mBitmapBound.set(calculateBitmapBound()); mBitmapBound.inset(mBorderWidth - 10, mBorderWidth - 10); updateShaderMatrix(); }
获取Drawable
private Bitmap getBitmapFromDrawable() { Drawable drawable = getDrawable(); if (drawable instanceof BitmapDrawable) { mBitmap = ((BitmapDrawable) drawable).getBitmap(); mBitmapWidth = mBitmap.getWidth(); mBitmapHeight = mBitmap.getHeight(); return mBitmap; } return null; }
计算边距
/** * 计算Bitmap边距 */ private RectF calculateBitmapBound() { int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom(); int sideLength = Math.min(availableWidth, availableHeight); // 可用的直径 mRadius = sideLength / 2; int left = getPaddingLeft() + (availableWidth - sideLength) / 2; int top = getPaddingTop() + (availableHeight - sideLength) / 2; Log.d(TAG, "calculateBitmapBound: left >>> " + left + " top >>> " + top + " right >>> " + (left + sideLength) + " right >>> " + top + " bottom >>> " + (top + sideLength)); return new RectF(left, top, left + sideLength, top + sideLength); }
调整Matrix,防止只显示图片边角
/** * 调整图片缩放,目前只支持CenterCrop */ private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); // 调整缩放,使图片居中 if (mBitmapWidth * mBitmapBound.height() > mBitmapBound.width() * mBitmapHeight) { scale = mBitmapBound.height() / (float) mBitmapHeight; dx = (mBitmapBound.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mBitmapBound.width() / (float) mBitmapWidth; dy = (mBitmapBound.height() - mBitmapHeight * scale) * 0.5f; } Log.d(TAG, "updateShaderMatrix: scale >>> " + scale); mShaderMatrix.setScale(scale, scale); // TODO: 16-10-15 http://chroya.iteye.com/blog/713869 // 回到中心点,便于下次缩放 mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBitmapBound.left, (int) (dy + 0.5f) + mBitmapBound.top); mShader.setLocalMatrix(mShaderMatrix); }
onDraw
@Override protected void onDraw(Canvas canvas) { if (mBitmap == null) { super.onDraw(canvas); } Log.d(TAG, "onDraw: centerX >>> " + mBitmapBound.centerX() + " centerY >>> " + mBitmapBound.centerY()); canvas.drawCircle(mBitmapBound.centerX(), mBitmapBound.centerY(), mRadius, mFillPaint); // 绘制边框 canvas.drawCircle(mBorderBound.centerX(), mBorderBound.centerY(), mRadius, mBoundPaint); }
完整代码
/** * Created by shixi_tianrui1 on 16-10-7. * 显示圆形图片的ImageView */ public class CircleImageView extends ImageView { private static final String TAG = "LOGGER"; private BitmapShader mShader; private Paint mFillPaint; // 绘图 private Paint mBoundPaint; // 绘制圆边 private Bitmap mBitmap; private Drawable mDrawable; private int mBorderColor; // 边框颜色 private float mBorderWidth; // 边框宽度 private RectF mBorderBound = new RectF(); private RectF mBitmapBound = new RectF(); private Matrix mShaderMatrix = new Matrix(); private int mRadius; private int mBitmapWidth; private int mBitmapHeight; private static final float DEFAULT_BORDER_WIDTH = 5; public CircleImageView(Context context) { this(context, null); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = getResources().obtainAttributes(attrs, R.styleable.CircleImageView); mBorderColor = a.getColor(R.styleable.CircleImageView_borderColor, Color.BLUE); mBorderWidth = a.getDimension(R.styleable.CircleImageView_borderWidth, DEFAULT_BORDER_WIDTH); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_borderWidth, 20); a.recycle(); }private void init() { getBitmapFromDrawable(); if (mBitmap == null) { return; } mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // bitmap paint mFillPaint = new Paint(); mFillPaint.setAntiAlias(true); mFillPaint.setStyle(Paint.Style.FILL); mFillPaint.setShader(mShader); // border paint mBoundPaint = new Paint(); mBoundPaint.setAntiAlias(true); mBoundPaint.setStyle(Paint.Style.STROKE); mBoundPaint.setStrokeWidth(mBorderWidth); mBoundPaint.setColor(mBorderColor); // border rectF mBorderBound.set(calculateBitmapBound()); // bitmap rectF mBitmapBound.set(calculateBitmapBound()); mBitmapBound.inset(mBorderWidth - 10, mBorderWidth - 10); updateShaderMatrix(); }@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); init(); } /** * 计算Bitmap边距 */ private RectF calculateBitmapBound() { int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom(); int sideLength = Math.min(availableWidth, availableHeight); // 可用的直径 mRadius = sideLength / 2; int left = getPaddingLeft() + (availableWidth - sideLength) / 2; int top = getPaddingTop() + (availableHeight - sideLength) / 2; Log.d(TAG, "calculateBitmapBound: left >>> " + left + " top >>> " + top + " right >>> " + (left + sideLength) + " right >>> " + top + " bottom >>> " + (top + sideLength)); return new RectF(left, top, left + sideLength, top + sideLength); }private Bitmap getBitmapFromDrawable() { Drawable drawable = getDrawable(); if (drawable instanceof BitmapDrawable) { mBitmap = ((BitmapDrawable) drawable).getBitmap(); mBitmapWidth = mBitmap.getWidth(); mBitmapHeight = mBitmap.getHeight(); return mBitmap; } return null; } @Override protected void onDraw(Canvas canvas) { if (mBitmap == null) { super.onDraw(canvas); } Log.d(TAG, "onDraw: centerX >>> " + mBitmapBound.centerX() + " centerY >>> " + mBitmapBound.centerY()); canvas.drawCircle(mBitmapBound.centerX(), mBitmapBound.centerY(), mRadius, mFillPaint); // 绘制边框 canvas.drawCircle(mBorderBound.centerX(), mBorderBound.centerY(), mRadius, mBoundPaint); }/** * 调整图片缩放,目前只支持CenterCrop */ private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); // 调整缩放,使图片居中 if (mBitmapWidth * mBitmapBound.height() > mBitmapBound.width() * mBitmapHeight) { scale = mBitmapBound.height() / (float) mBitmapHeight; dx = (mBitmapBound.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mBitmapBound.width() / (float) mBitmapWidth; dy = (mBitmapBound.height() - mBitmapHeight * scale) * 0.5f; } Log.d(TAG, "updateShaderMatrix: scale >>> " + scale); mShaderMatrix.setScale(scale, scale); // TODO: 16-10-15 http://chroya.iteye.com/blog/713869 // 回到中心点,便于下次缩放 mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBitmapBound.left, (int) (dy + 0.5f) + mBitmapBound.top); mShader.setLocalMatrix(mShaderMatrix); }}
目前仍有点问题,解决后会及时更新。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
- Android使用CircleImageView实现圆形头像的方法
- Android布局自定义Shap圆形ImageView可以单独设置背景与图片
- Android实现圆角矩形和圆形ImageView的方式
- Android项目实战手把手教你画圆形水波纹loadingview
- Android开发中TextView 实现右上角跟随文本动态追加圆形红点
- Android自定义控件之圆形、圆角ImageView
- Android中使用CircleImageView和Cardview制作圆形头像的方法
- Android自定义view实现圆形与半圆形菜单
- Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码
- Android利用CircleImageView实现圆形头像的方法
相关文章推荐
- Android自定义View实现简单的圆形Progress效果
- Android自定义圆形View实现小球跟随手指移动效果
- Android中使用自定义的view实现圆形图片的效果
- Android使用自定义ImageView实现圆形图片效果
- Android 自定义View实现圆形环绕效果
- Android 自定义View实现圆形切图的效果
- Android自定义ImageView实现图片缩放滑动,双击放大缩小,多点触控旋转,圆角矩形,圆形和仿刮刮卡效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果 .
- Android 自定义RecyclerView 实现真正的Gallery效果
- Android自定义View实现转盘旋转的效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- android自定义view实现progressbar的效果
- android自定义view实现progressbar的效果
- Android UI设计之<四>自定义TextView属性,实现带边框效果的TextView
- Android 自定义RecyclerView 实现真正的Gallery效果
- Android 自定义View修炼-自定义HorizontalScrollView视图实现仿ViewPager效果
- 实现自定义view(2):仿Android QQ多屏幕显示ListView的效果
- Android自定义View实现HTML图文环绕效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- Android自定义ViewGroup自动换行实现滑动任意布局及事件处理效果