一、简述

  • 或多或少老哥们都了解自定义View是啥,本篇文章选了一个比较简单的例子来当做示例,希望大佬们能够喜欢。

  • 知识点:自定义属性attrs的简单使用,通过继承View重写onDraw方法使用Canvas来绘制,关于Canvas的用法和View基础可以看我前面写的文章。

Android自定义View入门 - 图1

二、重写onDraw方法

在开始之前,默认老哥您了解Canvas及View的位置参数,如果不了解请到我的博客瞅一眼。

我在处理边距时是将多余的区域平分放到了两侧,也就是相当于内容居中,详细内容可以看代码,注释很详细。

  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. super.onDraw(canvas);
  4. // 获取宽度与高度
  5. int width = getWidth();
  6. int height = getHeight();
  7. //圆的个数
  8. int count;
  9. try {
  10. // 计算可以显示多少个圆
  11. count = (width - gap) / (radius * 2 + gap);
  12. } catch (Exception e) {
  13. count = 0;
  14. Log.e(TAG, "onDraw: ", e);
  15. }
  16. // 圆的直径
  17. int h = (radius * 2);
  18. // 圆以外的长度
  19. int cgap = (width - (count * h));
  20. // 两侧端点的长度,
  21. int x1 = (cgap + gap - (gap * count)) / 2;
  22. // 绘制
  23. for (int i = 0; i < count; i++) {
  24. int x = x1 + radius + (h + gap) * i;
  25. canvas.drawCircle(x, 0, radius, mPaint);
  26. canvas.drawCircle(x, height, radius, mPaint);
  27. }
  28. }

三、供外部类操作属性的公有方法

  1. // 读取圆的半径
  2. public int getRadius() {
  3. return Utils.px2dp(mContext, radius);
  4. }
  5. // 设置圆的半径
  6. public void setRadius(int radius) {
  7. this.radius = Utils.dp2px(mContext, radius);
  8. // 刷新视图
  9. invalidate();
  10. }

四、View自定义属性

  1. 创建属性文件(res/values/attrs.xml)
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="ViewZ2View">
  4. <attr name="circle_color" format="color" />
  5. <attr name="radius" format="dimension" />
  6. <attr name="gap" format="dimension" />
  7. </declare-styleable>
  8. </resources>
  1. 上面的XML文件声明了一个名字为ViewZ2View的自定义属性集合。

  2. name是自定义属性的名字。

  3. format是自定义属性的类型,color是颜色属性,integer是基本数据类型,除此之外还有很多,可以阅读文档或直接使用as的代码提示。

  1. 在布局文件中添加属性
  1. xmlns:app="http://schemas.android.com/apk/res-auto"
  2. ... ...
  3. <com.sdwfqin.sample.view.viewz2.ViewZ2View
  4. ... ...
  5. app:circle_color="#ffffff"
  6. app:gap="10dp"
  7. app:radius="10dp" />
  1. 在代码中读取设置的属性
  1. private void init(Context context, @Nullable AttributeSet attrs) {
  2. // 加载自定义属性集合
  3. TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ViewZ2View);
  4. // Color.WHITE为默认颜色
  5. mColor = typedArray.getColor(R.styleable.ViewZ2View_circle_color, Color.WHITE);
  6. radius = typedArray.getDimensionPixelSize(R.styleable.ViewZ2View_radius, radius);
  7. gap = typedArray.getDimensionPixelSize(R.styleable.ViewZ2View_gap, gap);
  8. typedArray.recycle();
  9. }

五、示例代码

  1. Java文件
  1. public class ViewZ2View extends LinearLayout {
  2. private static final String TAG = "ViewZ2View";
  3. private Context mContext;
  4. private int mColor = Color.WHITE;
  5. private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  6. // 要提高精度可以使用float
  7. //圆的半径
  8. private int radius = 10;
  9. //圆之间的间距
  10. private int gap = 10;
  11. public ViewZ2View(Context context) {
  12. super(context);
  13. init(context);
  14. }
  15. public ViewZ2View(Context context, @Nullable AttributeSet attrs) {
  16. super(context, attrs);
  17. init(context, attrs);
  18. }
  19. public ViewZ2View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  20. super(context, attrs, defStyleAttr);
  21. init(context, attrs);
  22. }
  23. private void init(Context context) {
  24. mContext = context;
  25. mPaint.setColor(mColor);
  26. gap = Utils.dp2px(context, 10);
  27. }
  28. private void init(Context context, @Nullable AttributeSet attrs) {
  29. mContext = context;
  30. TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ViewZ2View);
  31. // Color.WHITE为默认颜色
  32. mColor = typedArray.getColor(R.styleable.ViewZ2View_circle_color, Color.WHITE);
  33. radius = typedArray.getDimensionPixelSize(R.styleable.ViewZ2View_radius, radius);
  34. gap = typedArray.getDimensionPixelSize(R.styleable.ViewZ2View_gap, gap);
  35. typedArray.recycle();
  36. mPaint.setColor(mColor);
  37. }
  38. public int getColor() {
  39. return mColor;
  40. }
  41. public void setColor(int color) {
  42. this.mColor = color;
  43. mPaint.setColor(mColor);
  44. // 刷新视图
  45. invalidate();
  46. }
  47. // 读取圆的半径
  48. public int getRadius() {
  49. return Utils.px2dp(mContext, radius);
  50. }
  51. // 设置圆的半径
  52. public void setRadius(int radius) {
  53. this.radius = Utils.dp2px(mContext, radius);
  54. // 刷新视图
  55. invalidate();
  56. }
  57. public int getGap() {
  58. return Utils.px2dp(mContext, gap);
  59. }
  60. public void setGap(int gap) {
  61. this.gap = Utils.dp2px(mContext, gap);
  62. invalidate();
  63. }
  64. @Override
  65. protected void onDraw(Canvas canvas) {
  66. super.onDraw(canvas);
  67. // 获取宽度与高度
  68. int width = getWidth();
  69. int height = getHeight();
  70. //圆的个数
  71. int count;
  72. try {
  73. // 计算可以显示多少个圆
  74. count = (width - gap) / (radius * 2 + gap);
  75. } catch (Exception e) {
  76. count = 0;
  77. Log.e(TAG, "onDraw: ", e);
  78. }
  79. // 圆的直径
  80. int h = (radius * 2);
  81. // 圆以外的长度
  82. int cgap = (width - (count * h));
  83. // 两侧端点的长度,
  84. int x1 = (cgap + gap - (gap * count)) / 2;
  85. // 绘制
  86. for (int i = 0; i < count; i++) {
  87. int x = x1 + radius + (h + gap) * i;
  88. canvas.drawCircle(x, 0, radius, mPaint);
  89. canvas.drawCircle(x, height, radius, mPaint);
  90. }
  91. }
  92. }
  1. xml文件
  1. <com.sdwfqin.sample.view.viewz2.ViewZ2View
  2. android:id="@+id/viewz2_main"
  3. android:layout_width="match_parent"
  4. android:layout_height="200dp"
  5. android:layout_margin="20dp"
  6. android:background="@color/bar"
  7. android:gravity="center"
  8. app:circle_color="#ffffff"
  9. app:gap="10dp"
  10. app:radius="10dp">
  11. <TextView
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:text="抽奖券" />
  15. </com.sdwfqin.sample.view.viewz2.ViewZ2View>

六、源码地址

https://github.com/sdwfqin/AndroidSamples