飞道的博客

Android 心形图片心形ImageView、带边框的的心形图片和圆形图片

384人阅读  评论(0)

源码地址心形图片、心形ImageView、圆形图片、圆形ImageView

实际效果如下:

一、思路

1、图片尺寸:加载的图片尺寸不会完全统一,可以是正方形,长方形等,这里不需要考虑正方形,因为一般的头像是正方形,需要考虑的是长方形,需要取长方形中边长的最大的居中的正方形,否则会拉伸,不好看。

2、心形边框:可以通过画笔或者一个心形的图片

3、细节:心形边框覆盖在图片上,并且只显示心形里面的部分图片,心形以外的图片不显示

二、实现

        结合思路中第二点和第三点,心形边框部分不可以使用心形边框图片遮盖图片。因为这样限制性太大,不同背景颜色的页面需要做对应颜色的心形边框图片。这样太费劲了,不能这么做。我们很懒!!!

        那么,我们需要自定义view用画笔 paint 来绘制一个心形边框,并且需要满足“心形边框覆盖在图片上,并且只显示心形里面的部分图片,心形以外的图片不显示”这样的需求。

 

涉及技术关键词:

贝赛尔曲线 : 参考 安卓自定义View进阶-Path之贝塞尔曲线  学习贝塞尔曲线的基础用法和适用场景

Paint Xfermode :参考 Android Paint Xfermode 学习paint.setXfermode的用途

 

三、代码

attrs.xml


  
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="heartimageview">
  4. <attr name="border_size" format="dimension" />
  5. <attr name="in_border_color" format="color" />
  6. <attr name="out_border_color" format="color"/>
  7. <attr name="shape_type" format="string"/>
  8. </declare-styleable>
  9. <declare-styleable name="CircleImageView">
  10. <attr name="civ_border_width" format="dimension" />
  11. <attr name="civ_border_color" format="color" />
  12. <attr name="civ_border_overlay" format="boolean" />
  13. <attr name="civ_circle_background_color" format="color" />
  14. </declare-styleable>
  15. </resources>

HeartImageView.java


  
  1. /**
  2. * 心形ImageView 可以设置边框
  3. * @author DerekYan
  4. */
  5. public class HeartImageView extends ImageView {
  6. private Context mContext;
  7. private int border_size = 0; // 边框厚度
  8. private int in_border_color = 0; // 内圆边框颜色
  9. private int out_border_color = 0; // 外圆边框颜色
  10. private int defColor = 0xFFFFFFFF; // 默认颜色
  11. private int width = 0; // 控件的宽度
  12. private int height = 0; // 控件的高度
  13. private String shape_type; // 形状的类型
  14. public HeartImageView(Context context) {
  15. super(context);
  16. // TODO Auto-generated constructor stub
  17. this.mContext = context;
  18. }
  19. public HeartImageView(Context context, AttributeSet attrs) {
  20. super(context, attrs);
  21. // TODO Auto-generated constructor stub
  22. this.mContext = context;
  23. setAttributes(attrs);
  24. }
  25. public HeartImageView(Context context, AttributeSet attrs, int defStyle) {
  26. super(context, attrs, defStyle);
  27. // TODO Auto-generated constructor stub
  28. this.mContext = context;
  29. setAttributes(attrs);
  30. }
  31. /**
  32. * 获得自定义属性
  33. *
  34. * @param attrs
  35. */
  36. private void setAttributes(AttributeSet attrs) {
  37. // TODO Auto-generated method stub
  38. TypedArray mArray = mContext.obtainStyledAttributes(attrs,
  39. R.styleable.heartimageview);
  40. // 得到边框厚度,否则返回0
  41. border_size = mArray.getDimensionPixelSize(
  42. R.styleable.heartimageview_border_size, 0);
  43. // 得到内边框颜色,否则返回默认颜色
  44. in_border_color = mArray.getColor(
  45. R.styleable.heartimageview_in_border_color, defColor);
  46. // 得到外边框颜色,否则返回默认颜色
  47. out_border_color = mArray.getColor(
  48. R.styleable.heartimageview_out_border_color, defColor);
  49. // 得到形状的类型
  50. shape_type = mArray.getString(R.styleable.heartimageview_shape_type);
  51. mArray.recycle(); // 回收mArray
  52. }
  53. @Override
  54. protected void onDraw(Canvas canvas) {
  55. // TODO Auto-generated method stub
  56. // super.onDraw(canvas); 必须去掉该行或注释掉,否则会出现两张图片
  57. // 得到传入的图片
  58. Drawable drawable = getDrawable();
  59. if (drawable == null) {
  60. return;
  61. }
  62. if (getWidth() == 0 || getHeight() == 0) {
  63. return;
  64. }
  65. this.measure( 0, 0);
  66. if (drawable.getClass() == NinePatchDrawable.class) { // 如果该传入图片是.9格式的图片
  67. return;
  68. }
  69. // 将图片转为位图
  70. Bitmap mBitmap = ((BitmapDrawable) drawable).getBitmap();
  71. Bitmap cpBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);
  72. // 得到画布宽高
  73. width = getWidth();
  74. height = getHeight();
  75. //
  76. int radius = 0; //
  77. radius = (width < height ? width : height) / 2;
  78. //
  79. Bitmap shapeBitmap = drawShapeBitmap(cpBitmap, radius);
  80. canvas.drawBitmap(shapeBitmap, width / 2 - radius, height / 2 - radius,
  81. null);
  82. }
  83. /**
  84. * 画出指定形状的图片
  85. *
  86. * @param radius
  87. * @return
  88. */
  89. private Bitmap drawShapeBitmap(Bitmap bmp, int radius) {
  90. // TODO Auto-generated method stub
  91. Bitmap squareBitmap; // 根据传入的位图截取合适的正方形位图
  92. Bitmap scaledBitmap; // 根据diameter对截取的正方形位图进行缩放
  93. Log.i( "HeartImageView", "radius:" + radius);
  94. int diameter = radius * 2;
  95. // 位图的宽高
  96. int w = bmp.getWidth();
  97. int h = bmp.getHeight();
  98. // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片
  99. squareBitmap = bmp;
  100. // 对squareBitmap进行缩放为diameter边长的正方形位图
  101. if (w != diameter
  102. || h != diameter) {
  103. if (w < diameter || h < diameter) {
  104. //位图宽高没有ImageView的宽高大 需要放大
  105. float scale; //缩放倍数
  106. scale = 1f * diameter / (Math.min(w, h));
  107. Matrix matrix = new Matrix();
  108. matrix.postScale(scale,scale);
  109. squareBitmap = Bitmap.createBitmap(squareBitmap, 0, 0,w,h,matrix, false);
  110. if (w != h) {
  111. //从矩形图中截取正中间的正方形部分。
  112. scaledBitmap = centerSquareScaleBitmap(squareBitmap, diameter);
  113. } else {
  114. scaledBitmap = squareBitmap;
  115. }
  116. } else {
  117. //从矩形图中截取正中间的正方形部分。
  118. scaledBitmap = centerSquareScaleBitmap(squareBitmap, diameter);
  119. }
  120. } else {
  121. scaledBitmap = squareBitmap;
  122. }
  123. Bitmap outputbmp = Bitmap.createBitmap(scaledBitmap.getWidth(),
  124. scaledBitmap.getHeight(), Config.ARGB_8888);
  125. Canvas canvas = new Canvas(outputbmp); // 创建一个相同大小的画布
  126. Paint paint = new Paint(); // 定义画笔
  127. paint.setAntiAlias( true); // 设置抗锯齿
  128. paint.setFilterBitmap( true);
  129. paint.setDither( true);
  130. canvas.drawARGB( 0, 0, 0, 0);
  131. //设置边框
  132. Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  133. borderPaint.setColor(out_border_color);
  134. borderPaint.setStyle(Paint.Style.STROKE);
  135. borderPaint.setStrokeWidth(border_size);
  136. Path path = new Path();
  137. //右心形
  138. path.moveTo(diameter / 2f, diameter / 7f);
  139. path.cubicTo((diameter / 6f) * 5 , 0 - ( diameter / 5f), (diameter / 5f) * 7 , (diameter / 5f) * 2 , diameter / 2f, diameter- border_size );
  140. //左心形
  141. path.moveTo(diameter / 2f, diameter / 7f);
  142. path.cubicTo(diameter / 6f , 0 - ( diameter / 5f), 0 - (diameter / 5f) * 2, (diameter / 5f) * 2, diameter / 2f, diameter - border_size );
  143. canvas.drawPath(path, paint);
  144. // 设置Xfermode的Mode
  145. paint.setXfermode( new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  146. canvas.drawBitmap(scaledBitmap, 0, 0, paint);
  147. canvas.drawPath(path, borderPaint);
  148. bmp = null;
  149. squareBitmap = null;
  150. scaledBitmap = null;
  151. return outputbmp;
  152. }
  153. /**
  154. * @param bitmap 原图
  155. * @param edgeLength 希望得到的正方形部分的边长
  156. * @return 缩放截取正中部分后的位图。
  157. */
  158. public static Bitmap centerSquareScaleBitmap(Bitmap bitmap, int edgeLength)
  159. {
  160. if( null == bitmap || edgeLength <= 0)
  161. {
  162. return null;
  163. }
  164. Bitmap result = bitmap;
  165. int widthOrg = bitmap.getWidth();
  166. int heightOrg = bitmap.getHeight();
  167. if(widthOrg > edgeLength && heightOrg > edgeLength)
  168. {
  169. //压缩到一个最小长度是edgeLength的bitmap
  170. int longerEdge = ( int)(edgeLength * Math.max(widthOrg, heightOrg) / Math.min(widthOrg, heightOrg));
  171. int scaledWidth = widthOrg > heightOrg ? longerEdge : edgeLength;
  172. int scaledHeight = widthOrg > heightOrg ? edgeLength : longerEdge;
  173. Bitmap scaledBitmap;
  174. try{
  175. scaledBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true);
  176. }
  177. catch(Exception e){
  178. return null;
  179. }
  180. //从图中截取正中间的正方形部分。
  181. int xTopLeft = (scaledWidth - edgeLength) / 2;
  182. int yTopLeft = (scaledHeight - edgeLength) / 2;
  183. try{
  184. result = Bitmap.createBitmap(scaledBitmap, xTopLeft, yTopLeft, edgeLength, edgeLength);
  185. scaledBitmap.recycle();
  186. }
  187. catch(Exception e){
  188. return null;
  189. }
  190. }
  191. return result;
  192. }
  193. }

CircleImageView.java


  
  1. public class CircleImageView extends ImageView {
  2. private static final ImageView.ScaleType SCALE_TYPE = ImageView.ScaleType.CENTER_CROP;
  3. private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
  4. private static final int COLORDRAWABLE_DIMENSION = 2;
  5. private static final int DEFAULT_BORDER_WIDTH = 0;
  6. private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
  7. private static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = Color.TRANSPARENT;
  8. private static final int DEFAULT_IMAGE_ALPHA = 255;
  9. private static final boolean DEFAULT_BORDER_OVERLAY = false;
  10. private final RectF mDrawableRect = new RectF();
  11. private final RectF mBorderRect = new RectF();
  12. private final Matrix mShaderMatrix = new Matrix();
  13. private final Paint mBitmapPaint = new Paint();
  14. private final Paint mBorderPaint = new Paint();
  15. private final Paint mCircleBackgroundPaint = new Paint();
  16. private int mBorderColor = DEFAULT_BORDER_COLOR;
  17. private int mBorderWidth = DEFAULT_BORDER_WIDTH;
  18. private int mCircleBackgroundColor = DEFAULT_CIRCLE_BACKGROUND_COLOR;
  19. private int mImageAlpha = DEFAULT_IMAGE_ALPHA;
  20. private Bitmap mBitmap;
  21. private Canvas mBitmapCanvas;
  22. private float mDrawableRadius;
  23. private float mBorderRadius;
  24. private ColorFilter mColorFilter;
  25. private boolean mInitialized;
  26. private boolean mRebuildShader;
  27. private boolean mDrawableDirty;
  28. private boolean mBorderOverlay;
  29. private boolean mDisableCircularTransformation;
  30. public CircleImageView(Context context) {
  31. super(context);
  32. init();
  33. }
  34. public CircleImageView(Context context, AttributeSet attrs) {
  35. this(context, attrs, 0);
  36. }
  37. public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
  38. super(context, attrs, defStyle);
  39. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
  40. mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);
  41. mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);
  42. mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);
  43. mCircleBackgroundColor = a.getColor(R.styleable.CircleImageView_civ_circle_background_color, DEFAULT_CIRCLE_BACKGROUND_COLOR);
  44. a.recycle();
  45. init();
  46. }
  47. private void init() {
  48. mInitialized = true;
  49. super.setScaleType(SCALE_TYPE);
  50. mBitmapPaint.setAntiAlias( true);
  51. mBitmapPaint.setDither( true);
  52. mBitmapPaint.setFilterBitmap( true);
  53. mBitmapPaint.setAlpha(mImageAlpha);
  54. mBitmapPaint.setColorFilter(mColorFilter);
  55. mBorderPaint.setStyle(Paint.Style.STROKE);
  56. mBorderPaint.setAntiAlias( true);
  57. mBorderPaint.setColor(mBorderColor);
  58. mBorderPaint.setStrokeWidth(mBorderWidth);
  59. mCircleBackgroundPaint.setStyle(Paint.Style.FILL);
  60. mCircleBackgroundPaint.setAntiAlias( true);
  61. mCircleBackgroundPaint.setColor(mCircleBackgroundColor);
  62. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  63. setOutlineProvider( new OutlineProvider());
  64. }
  65. }
  66. @Override
  67. public void setScaleType(ImageView.ScaleType scaleType) {
  68. if (scaleType != SCALE_TYPE) {
  69. throw new IllegalArgumentException(String.format( "ScaleType %s not supported.", scaleType));
  70. }
  71. }
  72. @Override
  73. public void setAdjustViewBounds(boolean adjustViewBounds) {
  74. if (adjustViewBounds) {
  75. throw new IllegalArgumentException( "adjustViewBounds not supported.");
  76. }
  77. }
  78. @SuppressLint( "CanvasSize")
  79. @Override
  80. protected void onDraw(Canvas canvas) {
  81. if (mDisableCircularTransformation) {
  82. super.onDraw(canvas);
  83. return;
  84. }
  85. if (mCircleBackgroundColor != Color.TRANSPARENT) {
  86. canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mCircleBackgroundPaint);
  87. }
  88. if (mBitmap != null) {
  89. if (mDrawableDirty && mBitmapCanvas != null) {
  90. mDrawableDirty = false;
  91. Drawable drawable = getDrawable();
  92. drawable.setBounds( 0, 0, mBitmapCanvas.getWidth(), mBitmapCanvas.getHeight());
  93. drawable.draw(mBitmapCanvas);
  94. }
  95. if (mRebuildShader) {
  96. mRebuildShader = false;
  97. BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  98. bitmapShader.setLocalMatrix(mShaderMatrix);
  99. mBitmapPaint.setShader(bitmapShader);
  100. }
  101. canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);
  102. }
  103. if (mBorderWidth > 0) {
  104. canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);
  105. }
  106. }
  107. @Override
  108. public void invalidateDrawable(@NonNull Drawable dr) {
  109. mDrawableDirty = true;
  110. invalidate();
  111. }
  112. @Override
  113. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  114. super.onSizeChanged(w, h, oldw, oldh);
  115. updateDimensions();
  116. invalidate();
  117. }
  118. @Override
  119. public void setPadding(int left, int top, int right, int bottom) {
  120. super.setPadding(left, top, right, bottom);
  121. updateDimensions();
  122. invalidate();
  123. }
  124. @Override
  125. public void setPaddingRelative(int start, int top, int end, int bottom) {
  126. super.setPaddingRelative(start, top, end, bottom);
  127. updateDimensions();
  128. invalidate();
  129. }
  130. public int getBorderColor() {
  131. return mBorderColor;
  132. }
  133. public void setBorderColor(@ColorInt int borderColor) {
  134. if (borderColor == mBorderColor) {
  135. return;
  136. }
  137. mBorderColor = borderColor;
  138. mBorderPaint.setColor(borderColor);
  139. invalidate();
  140. }
  141. public int getCircleBackgroundColor() {
  142. return mCircleBackgroundColor;
  143. }
  144. public void setCircleBackgroundColor(@ColorInt int circleBackgroundColor) {
  145. if (circleBackgroundColor == mCircleBackgroundColor) {
  146. return;
  147. }
  148. mCircleBackgroundColor = circleBackgroundColor;
  149. mCircleBackgroundPaint.setColor(circleBackgroundColor);
  150. invalidate();
  151. }
  152. /**
  153. * @deprecated Use {@link #setCircleBackgroundColor(int)} instead
  154. */
  155. @Deprecated
  156. public void setCircleBackgroundColorResource(@ColorRes int circleBackgroundRes) {
  157. setCircleBackgroundColor(getContext().getResources().getColor(circleBackgroundRes));
  158. }
  159. public int getBorderWidth() {
  160. return mBorderWidth;
  161. }
  162. public void setBorderWidth(int borderWidth) {
  163. if (borderWidth == mBorderWidth) {
  164. return;
  165. }
  166. mBorderWidth = borderWidth;
  167. mBorderPaint.setStrokeWidth(borderWidth);
  168. updateDimensions();
  169. invalidate();
  170. }
  171. public boolean isBorderOverlay() {
  172. return mBorderOverlay;
  173. }
  174. public void setBorderOverlay(boolean borderOverlay) {
  175. if (borderOverlay == mBorderOverlay) {
  176. return;
  177. }
  178. mBorderOverlay = borderOverlay;
  179. updateDimensions();
  180. invalidate();
  181. }
  182. public boolean isDisableCircularTransformation() {
  183. return mDisableCircularTransformation;
  184. }
  185. public void setDisableCircularTransformation(boolean disableCircularTransformation) {
  186. if (disableCircularTransformation == mDisableCircularTransformation) {
  187. return;
  188. }
  189. mDisableCircularTransformation = disableCircularTransformation;
  190. if (disableCircularTransformation) {
  191. mBitmap = null;
  192. mBitmapCanvas = null;
  193. mBitmapPaint.setShader( null);
  194. } else {
  195. initializeBitmap();
  196. }
  197. invalidate();
  198. }
  199. @Override
  200. public void setImageBitmap(Bitmap bm) {
  201. super.setImageBitmap(bm);
  202. initializeBitmap();
  203. invalidate();
  204. }
  205. @Override
  206. public void setImageDrawable(Drawable drawable) {
  207. super.setImageDrawable(drawable);
  208. initializeBitmap();
  209. invalidate();
  210. }
  211. @Override
  212. public void setImageResource(@DrawableRes int resId) {
  213. super.setImageResource(resId);
  214. initializeBitmap();
  215. invalidate();
  216. }
  217. @Override
  218. public void setImageURI(Uri uri) {
  219. super.setImageURI(uri);
  220. initializeBitmap();
  221. invalidate();
  222. }
  223. @Override
  224. public void setImageAlpha(int alpha) {
  225. alpha &= 0xFF;
  226. if (alpha == mImageAlpha) {
  227. return;
  228. }
  229. mImageAlpha = alpha;
  230. // This might be called during ImageView construction before
  231. // member initialization has finished on API level >= 16.
  232. if (mInitialized) {
  233. mBitmapPaint.setAlpha(alpha);
  234. invalidate();
  235. }
  236. }
  237. @Override
  238. public int getImageAlpha() {
  239. return mImageAlpha;
  240. }
  241. @Override
  242. public void setColorFilter(ColorFilter cf) {
  243. if (cf == mColorFilter) {
  244. return;
  245. }
  246. mColorFilter = cf;
  247. // This might be called during ImageView construction before
  248. // member initialization has finished on API level <= 19.
  249. if (mInitialized) {
  250. mBitmapPaint.setColorFilter(cf);
  251. invalidate();
  252. }
  253. }
  254. @Override
  255. public ColorFilter getColorFilter() {
  256. return mColorFilter;
  257. }
  258. private Bitmap getBitmapFromDrawable(Drawable drawable) {
  259. if (drawable == null) {
  260. return null;
  261. }
  262. if (drawable instanceof BitmapDrawable) {
  263. return ((BitmapDrawable) drawable).getBitmap();
  264. }
  265. try {
  266. Bitmap bitmap;
  267. if (drawable instanceof ColorDrawable) {
  268. bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
  269. } else {
  270. bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
  271. }
  272. Canvas canvas = new Canvas(bitmap);
  273. drawable.setBounds( 0, 0, canvas.getWidth(), canvas.getHeight());
  274. drawable.draw(canvas);
  275. return bitmap;
  276. } catch (Exception e) {
  277. e.printStackTrace();
  278. return null;
  279. }
  280. }
  281. private void initializeBitmap() {
  282. mBitmap = getBitmapFromDrawable(getDrawable());
  283. if (mBitmap != null && mBitmap.isMutable()) {
  284. mBitmapCanvas = new Canvas(mBitmap);
  285. } else {
  286. mBitmapCanvas = null;
  287. }
  288. if (!mInitialized) {
  289. return;
  290. }
  291. if (mBitmap != null) {
  292. updateShaderMatrix();
  293. } else {
  294. mBitmapPaint.setShader( null);
  295. }
  296. }
  297. private void updateDimensions() {
  298. mBorderRect.set(calculateBounds());
  299. mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
  300. mDrawableRect.set(mBorderRect);
  301. if (!mBorderOverlay && mBorderWidth > 0) {
  302. mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);
  303. }
  304. mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
  305. updateShaderMatrix();
  306. }
  307. private RectF calculateBounds() {
  308. int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight();
  309. int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();
  310. int sideLength = Math.min(availableWidth, availableHeight);
  311. float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
  312. float top = getPaddingTop() + (availableHeight - sideLength) / 2f;
  313. return new RectF(left, top, left + sideLength, top + sideLength);
  314. }
  315. private void updateShaderMatrix() {
  316. if (mBitmap == null) {
  317. return;
  318. }
  319. float scale;
  320. float dx = 0;
  321. float dy = 0;
  322. mShaderMatrix.set( null);
  323. int bitmapHeight = mBitmap.getHeight();
  324. int bitmapWidth = mBitmap.getWidth();
  325. if (bitmapWidth * mDrawableRect.height() > mDrawableRect.width() * bitmapHeight) {
  326. scale = mDrawableRect.height() / ( float) bitmapHeight;
  327. dx = (mDrawableRect.width() - bitmapWidth * scale) * 0.5f;
  328. } else {
  329. scale = mDrawableRect.width() / ( float) bitmapWidth;
  330. dy = (mDrawableRect.height() - bitmapHeight * scale) * 0.5f;
  331. }
  332. mShaderMatrix.setScale(scale, scale);
  333. mShaderMatrix.postTranslate(( int) (dx + 0.5f) + mDrawableRect.left, ( int) (dy + 0.5f) + mDrawableRect.top);
  334. mRebuildShader = true;
  335. }
  336. @SuppressLint( "ClickableViewAccessibility")
  337. @Override
  338. public boolean onTouchEvent(MotionEvent event) {
  339. if (mDisableCircularTransformation) {
  340. return super.onTouchEvent(event);
  341. }
  342. return inTouchableArea(event.getX(), event.getY()) && super.onTouchEvent(event);
  343. }
  344. private boolean inTouchableArea(float x, float y) {
  345. if (mBorderRect.isEmpty()) {
  346. return true;
  347. }
  348. return Math.pow(x - mBorderRect.centerX(), 2) + Math.pow(y - mBorderRect.centerY(), 2) <= Math.pow(mBorderRadius, 2);
  349. }
  350. @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  351. private class OutlineProvider extends ViewOutlineProvider {
  352. @Override
  353. public void getOutline(View view, Outline outline) {
  354. if (mDisableCircularTransformation) {
  355. ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
  356. } else {
  357. Rect bounds = new Rect();
  358. mBorderRect.roundOut(bounds);
  359. outline.setRoundRect(bounds, bounds.width() / 2.0f);
  360. }
  361. }
  362. }
  363. }

 

源码地址:github 源码


转载:https://blog.csdn.net/u012885461/article/details/105165122
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场