Android实现圆形图片

逃离我推掉我的手 2023-10-10 08:00 129阅读 0赞

一.概述

圆形图片现在越来越多应用于Android应用中, 但是用的最多的地方当属于, 头像的显示. 比如QQ, 新浪微博,微信中很多地方都是用了圆形头像,所以有必要深究一下.

二.圆形图片的实现方式

1.使用自定义控件

2.使用第三方库

下面先说第1种, 自定义控件

  1. package com.example.kun.widget;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.Bitmap;
  5. import android.graphics.Bitmap.Config;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Paint;
  9. import android.graphics.Path;
  10. import android.graphics.PorterDuff;
  11. import android.graphics.PorterDuffXfermode;
  12. import android.graphics.RectF;
  13. import android.util.AttributeSet;
  14. import android.widget.ImageView;
  15. import com.example.kun.R;
  16. /**
  17. * 自定义圆形图片
  18. */
  19. public class RoundAngleImageView extends ImageView {
  20. //定义2个画笔
  21. private Paint paint;
  22. private Paint paint2;
  23. private int roundWidth = 5;
  24. private int roundHeight = 5;
  25. //以下是必须实现的构造方法
  26. public RoundAngleImageView(Context context, AttributeSet attrs, int defStyle) {
  27. super(context, attrs, defStyle);
  28. init(context, attrs);
  29. }
  30. public RoundAngleImageView(Context context, AttributeSet attrs) {
  31. super(context, attrs);
  32. init(context, attrs);
  33. }
  34. public RoundAngleImageView(Context context) {
  35. super(context);
  36. init(context, null);
  37. }
  38. private void init(Context context, AttributeSet attrs) {
  39. if (attrs != null) {
  40. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundAngleImageView);
  41. //根据像素赋值
  42. roundWidth = a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundWidth, roundWidth);
  43. roundHeight = a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundHeight, roundHeight);
  44. } else {
  45. //根据设备密度计算
  46. float density = context.getResources().getDisplayMetrics().density;
  47. roundWidth = (int) (roundWidth * density);
  48. roundHeight = (int) (roundHeight * density);
  49. }
  50. paint = new Paint();
  51. paint.setColor(Color.WHITE);
  52. paint.setAntiAlias(true);//设置图片抗锯齿,就是设置图片边缘锯齿感 不明显
  53. //设置2张图片相交的模式, 圆形覆盖 方形
  54. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
  55. paint2 = new Paint();
  56. paint2.setXfermode(null);
  57. }
  58. @Override
  59. public void draw(Canvas canvas) {
  60. Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
  61. Canvas canvas2 = new Canvas(bitmap);
  62. super.draw(canvas2);
  63. drawLiftUp(canvas2);
  64. drawRightUp(canvas2);
  65. drawLiftDown(canvas2);
  66. drawRightDown(canvas2);
  67. canvas.drawBitmap(bitmap, 0, 0, paint2);
  68. bitmap.recycle();
  69. }
  70. private void drawLiftUp(Canvas canvas) {
  71. Path path = new Path();
  72. path.moveTo(0, roundHeight);
  73. path.lineTo(0, 0);
  74. path.lineTo(roundWidth, 0);
  75. path.arcTo(new RectF(
  76. 0,
  77. 0,
  78. roundWidth * 2,
  79. roundHeight * 2),
  80. -90,
  81. -90);
  82. path.close();
  83. canvas.drawPath(path, paint);
  84. }
  85. private void drawLiftDown(Canvas canvas) {
  86. Path path = new Path();
  87. path.moveTo(0, getHeight() - roundHeight);
  88. path.lineTo(0, getHeight());
  89. path.lineTo(roundWidth, getHeight());
  90. path.arcTo(new RectF(
  91. 0,
  92. getHeight() - roundHeight * 2,
  93. 0 + roundWidth * 2,
  94. getHeight()),
  95. 90,
  96. 90);
  97. path.close();
  98. canvas.drawPath(path, paint);
  99. }
  100. private void drawRightDown(Canvas canvas) {
  101. Path path = new Path();
  102. path.moveTo(getWidth() - roundWidth, getHeight());
  103. path.lineTo(getWidth(), getHeight());
  104. path.lineTo(getWidth(), getHeight() - roundHeight);
  105. path.arcTo(new RectF(
  106. getWidth() - roundWidth * 2,
  107. getHeight() - roundHeight * 2,
  108. getWidth(),
  109. getHeight()), 0, 90);
  110. path.close();
  111. canvas.drawPath(path, paint);
  112. }
  113. private void drawRightUp(Canvas canvas) {
  114. Path path = new Path();
  115. path.moveTo(getWidth(), roundHeight);
  116. path.lineTo(getWidth(), 0);
  117. path.lineTo(getWidth() - roundWidth, 0);
  118. path.arcTo(new RectF(
  119. getWidth() - roundWidth * 2,
  120. 0,
  121. getWidth(),
  122. 0 + roundHeight * 2),
  123. -90,
  124. 90);
  125. path.close();
  126. canvas.drawPath(path, paint);
  127. }
  128. }

对应的attrs.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="RoundAngleImageView">
  4. <attr name="roundWidth" format="dimension" />
  5. <attr name="roundHeight" format="dimension" />
  6. </declare-styleable>
  7. </resources>

布局文件:

  1. <com.example.kun.widget.RoundAngleImageView
  2. android:id="@+id/photoView"
  3. android:src="@mipmap/temp"
  4. app:roundHeight="100dp"
  5. app:roundWidth="100dp"
  6. android:scaleType="fitXY"
  7. android:layout_width="200dp"
  8. android:layout_height="200dp" />

布局需要注意: 自定义属性必须要有,并且宽高必须为 layout_width和layout_height的一半

还有一点注意:

  1. android:scaleType="fitXY"这个属性必须要有,否则不会实现图片圆形

java代码如下:

  1. public class MainActivity extends AppCompatActivity {
  2. private RoundAngleImageView photoView;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. initialize();
  8. }
  9. private void initialize() {
  10. photoView = (RoundAngleImageView) findViewById(R.id.photoView);
  11. }
  12. }

运行效果图:

538831-20160118105044841-1293707312.png

以上的自定义控件多少还是有些麻烦的 ,下面搞一个稍微简单点的工具类

  1. public class CircleTransform extends BitmapTransformation {
  2. public CircleTransform(Context context) {
  3. super(context);
  4. }
  5. @Override
  6. protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
  7. return circleCrop(pool, toTransform);
  8. }
  9. private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
  10. if (source == null) return null;
  11. int size = Math.min(source.getWidth(), source.getHeight());
  12. int x = (source.getWidth() - size) / 2;
  13. int y = (source.getHeight() - size) / 2;
  14. Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
  15. Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
  16. if (result == null) {
  17. result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
  18. }
  19. Canvas canvas = new Canvas(result);
  20. Paint paint = new Paint();
  21. paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
  22. paint.setAntiAlias(true);
  23. float r = size / 2f;
  24. canvas.drawCircle(r, r, r, paint);
  25. return result;
  26. }
  27. @Override
  28. public String getId() {
  29. return getClass().getName();
  30. }
  31. }

布局如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:orientation="vertical"
  5. android:layout_width="match_parent"
  6. android:gravity="center"
  7. android:layout_height="match_parent">
  8. <ImageView
  9. android:scaleType="fitXY"
  10. android:id="@+id/photoView"
  11. android:layout_width="100dp"
  12. android:layout_height="100dp" />
  13. </LinearLayout>

java代码:

  1. public class MainActivity extends AppCompatActivity {
  2. private ImageView photoView;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. initialize();
  8. runOnUiThread(new Runnable() {
  9. @Override
  10. public void run() {
  11. Glide.with(MainActivity.this).load(Uri.parse("http://pic13.nipic.com/20110415/1347158_132411659346_2.jpg"))
  12. .transform(new CircleTransform(MainActivity.this))
  13. .placeholder(R.mipmap.ic_launcher)
  14. .error(R.mipmap.ic_launcher)
  15. .into(photoView);
  16. }
  17. });
  18. }
  19. private void initialize() {
  20. photoView = (ImageView) findViewById(R.id.photoView);
  21. }
  22. }

以上代码使用GLide加载图片,需要引入glide库

运行截图:

538831-20160118115632482-979540733.png

分割线——————————————————————————————————————————————————————————-

以上方式虽然能实现图片圆形化,但是都是比较麻烦的,下面介绍一种我最常用的,也是最简单的一个方法

CircleImageView

github:https://github.com/hdodenhof/CircleImageView

直接上代码

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:orientation="vertical"
  5. android:layout_width="match_parent"
  6. android:gravity="center"
  7. android:layout_height="match_parent">
  8. <!--加入了边框宽度和颜色-->
  9. <de.hdodenhof.circleimageview.CircleImageView
  10. app:civ_border_width="2dp"
  11. app:civ_border_color="#FFFFFF"
  12. android:id="@+id/photoView"
  13. android:src="@mipmap/ic_launcher"
  14. android:layout_width="100dp"
  15. android:layout_height="100dp" />
  16. </LinearLayout>
  17. public class MainActivity extends AppCompatActivity {
  18. private CircleImageView photoView;
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_main);
  23. initialize();
  24. Picasso.with(this).load(R.mipmap.temp).into(photoView);
  25. }
  26. private void initialize() {
  27. photoView = (CircleImageView) findViewById(R.id.photoView);
  28. }
  29. }

引入的库文件

  1. compile 'de.hdodenhof:circleimageview:2.0.0'
  2. compile 'com.squareup.picasso:picasso:2.5.2'
  3. 运行截图:最外层带有一个白色边框

538831-20160118124141685-1239518128.png

转载于:https://www.cnblogs.com/android-zcq/p/5138462.html

发表评论

表情:
评论列表 (有 0 条评论,129人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Android圆形头像实现

    ![这里写图片描述][SouthEast] 如图所示,实现一个QQ圆形头像,话不多说,直接上代码,继承ImageView类,重写里面的方法: package com