写点什么

android 方式实现 imageview 圆角,已开源下载

作者:嘟嘟侠客
  • 2021 年 11 月 27 日
  • 本文字数:3106 字

    阅读完需:约 10 分钟

/**


  • 构造函数:获取自定义属性


*/


public RoundImageView(Context context, AttributeSet attrs) {


super(context, attrs);


mMatrix = new Matrix();


mBitmapPaint = new Paint();


mBitmapPaint.setAntiAlias(true);


TypedArray a = context.obtainStyledAttributes(attrs,


R.styleable.RoundImageView);


mBorderRadius = a.getDimensionPixelSize(


R.styleable.RoundImageView_borderRadius, (int) TypedValue


.applyDimension(TypedValue.COMPLEX_UNIT_DIP,


BODER_RADIUS_DEFAULT, getResources()


.getDisplayMetrics()));// 默认为 10dp


type = a.getInt(R.styleable.RoundImageView_type, TYPE_CIRCLE);// 默认为 Circle


a.recycle();


}


/**


  • 关于 view 的宽高:主要用于当设置类型为圆形时,我们强制让 view 的宽和高一致


*/


@Override


protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


Log.e("TAG", "onMeasure");


super.onMeasure(widthMeasureSpec, heightMeasureSpec);


/**


  • 如果类型是圆形,则强制改变 view 的宽高一致,以小值为准;如果是圆角则不用管宽高问题


*/


if (type == TYPE_CIRCLE) {


mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());


mRadius = mWidth / 2;


setMeasuredDimension(mWidth, mWidth);


}


}


/**


  • 设置 BitmapShader

  • 绘制


*/


@Override


protected void onDraw(Canvas canvas) {


if (getDrawable() == null) {


return;


}


setUpShader();


if (type == TYPE_ROUND) {


canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius,


mBitmapPaint);


} else {


canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint);


// drawSomeThing(canvas);


}


}


@Override


protected void onSizeChanged(int w, int h, int oldw, int oldh) {


super.onSizeChanged(w, h, oldw, oldh);


// 圆角图片的范围


if (type == TYPE_ROUND)


mRoundRect = new RectF(0, 0, getWidth(), getHeight());


}


/**


  • 初始化 BitmapShader//给 paint 附加一个具有某种魔力(缩放)的 shader

  • drawable 转化为我们的 bitmap

  • 设置 shader 的 mode

  • 设置 scale: 因为最终缩放完成的图片一定要大于我们的 view 的区域

  • scale 设置给 matrix

  • matrix 设置给 shader

  • shader 设置给 paint


*/


private void setUpShader() {


Drawable drawable = getDrawable();


if (drawable == null) {


return;


}


Bitmap bmp = drawableToBitamp(drawable);


// 将 bmp 作为着色器,就是在指定区域内绘制 bmp;此构造方法用的是拉伸 mode: clamp


mBitmapShader = new BitmapShader(bmp, CLAMP, CLAMP);


float scale = 1.0f;


if (type == TYPE_CIRCLE) {


// 拿到 bitmap 宽或高的小值//我们需要画正方形


int bSize = Math.min(bmp.getWidth(), bmp.getHeight());


scale = mWidth * 1.0f / bSize;


} else if (type == TYPE_ROUND) {


// 如果图片的宽或者高与 view 的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们 view 的宽高;所以我们这里取大值;//view 的宽度/bitmap 的宽度=缩放倍数


scale = Math.max(getWidth() * 1.0f / bmp.getWidth(), getHeight()


  • 1.0f / bmp.getHeight());


}


// shader 的变换矩阵,我们这里主要用于放大或者缩小


mMatrix.setScale(scale, scale);


// 设置变换矩阵


mBitmapShader.setLocalMatrix(mMatrix);


// 先给 paint 设置 shader;然后画笔会有所不同哦,例如


mBitmapPaint.setShader(mBitmapShader);


}


/**


  • drawable 转 bitmap

  • @param drawable

  • @return


*/


private Bitmap drawableToBitamp(Drawable drawable) {


if (drawable instanceof BitmapDrawable) {


BitmapDrawable bd = (BitmapDrawable) drawable;


return bd.getBitmap();


}


//以下为 drawable 转 bitmap 的通用方法


int w = drawable.getIntrinsicWidth();


int h = drawable.getIntrinsicHeight();


Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);


Canvas canvas = new Canvas(bitmap);


drawable.setBounds(0, 0, w, h);


drawable.draw(canvas);


return bitmap;


}


/**


  • 添加一个方法

  • bitmap 转 drawable


*/


private Drawable bitmapToDrawable(Bitmap bitmap) {


Drawable drawable = new BitmapDrawable(null, bitmap);


return drawable;


}


//状态存储与恢复


private static final String STATE_INSTANCE = "state_instance";


private static final String STATE_TYPE = "state_type";


private static final String STATE_BORDER_RADIUS = "state_border_radius";


@Override


protected Parcelable onSaveInstanceState() {


Bundle bundle = new Bundle();


bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());


bundle.putInt(STATE_TYPE, type);


bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius);


return bundle;


}


@Override


protected void onRestoreInstanceState(Parcelable state) {


if (state instanceof Bundle) {


Bundle bundle = (Bundle) state;


super.onRestoreInstanceState(((Bundle) state)


.getParcelable(STATE_INSTANCE));


this.type = bundle.getInt(STATE_TYPE);


this.mBorderRadius = bundle.getInt(STATE_BORDER_RADIUS);


} else {


super.onRestoreInstanceState(state);


}


}


/**


  • 动态修改圆角大小

  • */


public void setBorderRadius(int borderRadius) {


int pxVal = dp2px(borderRadius);


if (this.mBorderRadius != pxVal) {


this.mBorderRadius = pxVal;


invalidate();


}


}


/**


  • 动态设置 type

  • */


public void setType(int type) {


if (this.type != type) {


this.type = type;


if (this.type != TYPE_ROUND && this.type != TYPE_CIRCLE) {


this.type = TYPE_CIRCLE;


}


requestLayout();


}


}


private int dp2px(int dpVal) {


return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,


dpVal, getResources().getDisplayMetrics());


}

《设计思想解读开源框架》


第一章、 热修复设计


  • 第一节、 AOT/JIT & dexopt 与 dex2oat

  • **第二节、 热修


《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享


复设计之 CLASS_ISPREVERIFIED 问题**


  • 第三节、热修复设计之热修复原理

  • 第四节、Tinker 的集成与使用(自动补丁包生成)


  • 第二章、 插件化框架设计

  • 第一节、 Class 文件与 Dex 文件的结构解读

  • 第二节、 Android 资源加载机制详解

  • 第三节、 四大组件调用原理

  • 第四节、 so 文件加载机制

  • 第五节、 Android 系统服务实现原理


  • 第三章、 组件化框架设计

  • 第一节、阿里巴巴开源路由框——ARouter 原理分析

  • 第二节、APT 编译时期自动生成代码 &动态类加载

  • 第三节、 Java SPI 机制

  • 第四节、 AOP&IOC

  • 第五节、 手写组件化架构


  • 第四章、图片加载框架

  • 第一节、图片加载框架选型

  • 第二节、Glide 原理分析

  • 第三节、手写图片加载框架实战


  • 第五章、网络访问框架设计

  • 第一节、网络通信必备基础

  • 第二节、OkHttp 源码解读

  • 第三节、Retrofit 源码解析


  • 第六章、 RXJava 响应式编程框架设计

  • 第一节、链式调用

  • 第二节、 扩展的观察者模式

  • 第三节、事件变换设计

  • 第四节、Scheduler 线程控制


  • 第七章、 IOC 架构设计

  • 第一节、 依赖注入与控制反转

  • 第二节、ButterKnife 原理上篇、中篇、下篇

  • 第三节、Dagger 架构设计核心解密


  • 第八章、 Android 架构组件 Jetpack

  • 第一节、 LiveData 原理

  • 第二节、 Navigation 如何解决 tabLayout 问题

  • 第三节、 ViewModel 如何感知 View 生命周期及内核原理

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期

  • 本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…


本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

用户头像

嘟嘟侠客

关注

还未添加个人签名 2021.03.19 加入

还未添加个人简介

评论

发布
暂无评论
android 方式实现imageview圆角,已开源下载