https://www.jianshu.com/p/705a6cb6bfee
https://zhuanlan.zhihu.com/p/162945366

自定义view步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性:引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间
3、重写onMesure
4、重写onDraw

https://blog.csdn.net/guolin_blog/article/details/16330267
自定义控件的实现有三种方式
(一)组合控件
组合控件,顾名思义就是将一些小的控件组合起来形成一个新的控件,这些小的控件多是系统自带的控件。
(二)自绘控件
自绘控件的内容都是自己绘制出来的,在View的onDraw方法中完成绘制。
(三)继承控件
就是继承已有的控件,创建新控件,保留继承的父控件的特性,并且还可以引入新特性。下面就以支持横向滑动删除列表项的自定义ListView的实现来介绍。

实例:关于自定义录音声音分贝波纹
1.自定义View的属性 :vaules/attrs.xml,在自定义View的初始化使用此值

<declare-styleable name="LineWaveVoiceView"><attr name="voiceLineColor" format="color" /><attr name="voiceLineWidth" format="color" /><attr name="voiceTextSize" format="dimension" /><attr name="voiceTextColor" format="dimension" /><attr name="updateSpeed" format="color" /></declare-styleable>

2.自定义LineWaveVoiceView集成自View,重写onDraw方法

package com.example.demo.view;/*** 语音录制的动画效果*/
public class LineWaveVoiceView extends View {private static final String DEFAULT_TEXT = " 请录音 ";private static final int LINE_WIDTH = 9;//默认矩形波纹的宽度,9像素, 原则上从layout的attr获得private Paint paint = new Paint();private Runnable task;private ExecutorService executorService = Executors.newCachedThreadPool();private RectF rectRight = new RectF();//右边波纹矩形的数据,10个矩形复用一个rectFprivate RectF rectLeft = new RectF();//左边波纹矩形的数据private String text = DEFAULT_TEXT;private int updateSpeed;private int lineColor;private int textColor;private float lineWidth;private float textSize;public LineWaveVoiceView(Context context) {super(context);}public LineWaveVoiceView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LineWaveVoiceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(attrs, context);resetView(mWaveList, DEFAULT_WAVE_HEIGHT);task = new LineJitterTask();}private void initView(AttributeSet attrs, Context context) {//获取布局属性里的值TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.LineWaveVoiceView);lineColor = mTypedArray.getColor(R.styleable.LineWaveVoiceView_voiceLineColor, context.getColor(R.color.color_accent));lineWidth = mTypedArray.getDimension(R.styleable.LineWaveVoiceView_voiceLineWidth, LINE_WIDTH);textSize = mTypedArray.getDimension(R.styleable.LineWaveVoiceView_voiceTextSize, 42);textColor = mTypedArray.getColor(R.styleable.LineWaveVoiceView_voiceTextColor, context.getColor(R.color.color_accent));updateSpeed = mTypedArray.getColor(R.styleable.LineWaveVoiceView_updateSpeed, UPDATE_INTERVAL_TIME);mTypedArray.recycle();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//获取实际宽高的一半int widthCentre = getWidth() / 2;int heightCentre = getHeight() / 2;paint.setStrokeWidth(0);paint.setColor(textColor);paint.setTextSize(textSize);float textWidth = paint.measureText(text);canvas.drawText(text, widthCentre - textWidth / 2, heightCentre - (paint.ascent() + paint.descent()) / 2, paint);//设置颜色paint.setColor(lineColor);//填充内部paint.setStyle(Paint.Style.FILL);//设置抗锯齿paint.setAntiAlias(true);for (int i = 0; i < 10; i++) {rectRight.left = widthCentre + textWidth / 2 + (1 + 2 * i) * lineWidth;rectRight.top = heightCentre - lineWidth * mWaveList.get(i) / 2;rectRight.right = widthCentre + textWidth / 2 + (2 + 2 * i) * lineWidth;rectRight.bottom = heightCentre + lineWidth * mWaveList.get(i) / 2;//左边矩形rectLeft.left = widthCentre - textWidth / 2 - (2 + 2 * i) * lineWidth;rectLeft.top = heightCentre - mWaveList.get(i) * lineWidth / 2;rectLeft.right = widthCentre - textWidth / 2 - (1 + 2 * i) * lineWidth;rectLeft.bottom = heightCentre + mWaveList.get(i) * lineWidth / 2;canvas.drawRoundRect(rectRight, 6, 6, paint);canvas.drawRoundRect(rectLeft, 6, 6, paint);}}private static final int MIN_WAVE_HEIGHT = 2;//矩形线最小高private static final int MAX_WAVE_HEIGHT = 12;//矩形线最大高private static final int[] DEFAULT_WAVE_HEIGHT = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2};private static final int UPDATE_INTERVAL_TIME = 100;//100ms更新一次private LinkedList<Integer> mWaveList = new LinkedList<>();private float maxDb;private void resetView(List<Integer> list, int[] array) {list.clear();for (int anArray : array) {list.add(anArray);}}private synchronized void refreshElement() {Random random = new Random();maxDb = random.nextInt(5) + 2;int waveH = MIN_WAVE_HEIGHT + Math.round(maxDb * (MAX_WAVE_HEIGHT - MIN_WAVE_HEIGHT));mWaveList.add(0, waveH);mWaveList.removeLast();}public boolean isStart = false;private class LineJitterTask implements Runnable {@Overridepublic void run() {while (isStart) {refreshElement();try {Thread.sleep(updateSpeed);} catch (Exception e) {e.printStackTrace();}postInvalidate();}}}public synchronized void startRecord() {isStart = true;executorService.execute(task);}public synchronized void stopRecord() {isStart = false;mWaveList.clear();resetView(mWaveList, DEFAULT_WAVE_HEIGHT);postInvalidate();}public synchronized void setText(String text) {this.text = text;postInvalidate();}public void setUpdateSpeed(int updateSpeed) {this.updateSpeed = updateSpeed;}
}

3.在layout中引入该自定义View的控件:该控件名为自定义View类路径

<com.example.demo.view.LineWaveVoiceViewandroid:layout_width="300dp"android:layout_height="100dp"android:layout_gravity="center"android:layout_margin="8dp" />

若要引用自定义View的属性,需要根布局添加命名空间

xmlns:custom_android="http://schemas.android.com/apk/res-auto"

然后才可以添加自定义控件的属性:custom_android:voiceLineColor="@color/color_accent"

<com.example.demo.view.LineWaveVoiceViewandroid:layout_width="300dp"android:layout_height="100dp"android:layout_gravity="center"android:layout_margin="8dp"custom_android:voiceLineColor="@color/color_accent" />

附加

  1. 如果我们自定义属性,这个属性应该去我们的应用程序包中找,所以要引入我们应用包的命名空间xmlns:openxu="http://schemas.android.com/apk/res-auto”,res-auto表示自动查找

  2. 属性值的类型format

format支持的类型一共有11种:

(1). reference:参考某一资源ID
属性定义:
<declare-styleable name = "名称"><attr name = "background" format = "reference" />
</declare-styleable>
属性使用:
<ImageView android:background = "@drawable/图片ID"/>(2). color:颜色值
属性定义:
<attr name = "textColor" format = "color" />
属性使用:
<TextView android:textColor = "#00FF00" />(3). boolean:布尔值
属性定义:
<attr name = "focusable" format = "boolean" />
属性使用:
<Button android:focusable = "true"/>(4). dimension:尺寸值**
属性定义:
<attr name = "layout_width" format = "dimension" />
属性使用:
<Button android:layout_width = "42dip"/>(5). float:浮点值
属性定义:
<attr name = "fromAlpha" format = "float" />
属性使用:
<alpha android:fromAlpha = "1.0"/>(6). integer:整型值**
属性定义:
<attr name = "framesCount" format="integer" />
属性使用:
<animated-rotate android:framesCount = "12"/>(7). string:字符串
属性定义:
<attr name = "text" format = "string" />
属性使用:
<TextView android:text = "我是文本"/>(8). fraction:百分数**
属性定义:
<attr name = "pivotX" format = "fraction" />
属性使用:
<rotate android:pivotX = "200%"/>(9). enum:枚举值
属性定义:
<declare-styleable name="名称"> <attr name="orientation"> <enum name="horizontal" value="0" /><enum name="vertical" value="1" /></attr>
</declare-styleable>
属性使用:
<LinearLayout android:orientation = "vertical"></LinearLayout>
注意:枚举类型的属性在使用的过程中只能同时使用其中一个,不能 android:orientation = “horizontal|vertical"(10). flag:位或运算
属性定义:
<declare-styleable name="名称"> <attr name="gravity"> <flag name="top" value="0x30" /> <flag name="bottom" value="0x50" /><flag name="left" value="0x03" /> <flag name="right" value="0x05" /> <flag name="center_vertical" value="0x10" /></attr>
</declare-styleable>
属性使用:
<TextView android:gravity="bottom|left"/>
注意:位运算类型的属性在使用的过程中可以使用多个值(11). 混合类型:属性定义时可以指定多种类型值
属性定义:
<declare-styleable name = "名称"> <attr name = "background" format = "reference|color" />
</declare-styleable>
属性使用:
<ImageViewandroid:background = "@drawable/图片ID" />
或者:
<ImageViewandroid:background = "#00FF00" />

我们写好布局文件之后,要在控件中使用这些属性还需要将它解析出来。

Android自定义View基本使用相关推荐

  1. Android自定义View —— TypedArray

    在上一篇中Android 自定义View Canvas -- Bitmap写到了TypedArray 这个属性 下面也简单的说一下TypedArray的使用 TypedArray 的作用: 用于从该结 ...

  2. Android 自定义View —— Canvas

    上一篇在android 自定义view Paint 里面 说了几种常见的Point 属性 绘制图形的时候下面总有一个canvas ,Canvas 是是画布 上面可以绘制点,线,正方形,圆,等等,需要和 ...

  3. android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...

    转载:http://blog.csdn.net/xiabing082/article/details/48781489 1.  大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...

  4. Android自定义View:ViewGroup(三)

    自定义ViewGroup本质是什么? 自定义ViewGroup本质上就干一件事--layout. layout 我们知道ViewGroup是一个组合View,它与普通的基本View(只要不是ViewG ...

  5. android 自定义图形,Android自定义View之图形图像(模仿360的刷新球自定

    概述: 360安全卫士的那个刷新球(姑且叫它刷新球,因为真的不知道叫什么好,不是dota里的刷新球!!),里面像住了水一样,生动可爱,看似简单,写起来不太简单,本例程只是实现了它的部分功能而已,说实话 ...

  6. android代码实现手机加速功能,Android自定义View实现内存清理加速球效果

    Android自定义View实现内存清理加速球效果 发布时间:2020-09-21 22:21:57 来源:脚本之家 阅读:105 作者:程序员的自我反思 前言 用过猎豹清理大师或者相类似的安全软件, ...

  7. android中仿qq最新版抽屉,Android 自定义View实现抽屉效果

    Android 自定义View实现抽屉效果 说明 这个自定义View,没有处理好多点触摸问题 View跟着手指移动,没有采用传统的scrollBy方法,而是通过不停地重新布局子View的方式,来使得子 ...

  8. Android 自定义 圆环,Android自定义view实现圆环效果实例代码

    先上效果图,如果大家感觉不错,请参考实现代码. 重要的是如何实现自定义的view效果 (1)创建类,继承view,重写onDraw和onMesure方法 public class CirclePerc ...

  9. android自定义抽奖,Android自定义view制作抽奖转盘

    本文实例为大家分享了Android自定义view制作抽奖转盘的具体代码,供大家参考,具体内容如下 效果图 TurntableActivity package com.bawei.myapplicati ...

  10. android view 渐变动画,Android自定义view渐变圆形动画

    本文实例为大家分享了Android自定义view渐变圆形动画的具体代码,供大家参考,具体内容如下 直接上效果图 自定义属性 attrs.xml文件 创建一个类 ProgressRing继承自 view ...

最新文章

  1. java接口如何定义常量 c_在Java接口中怎样访问定义的常量呢?
  2. php模拟getua_php实现进行远程抓取百度网页内容,并伪装服务器端ip
  3. Long类型转json时前端js丢失精度解决方案
  4. IPFS Series -- Bitswap Protocol
  5. hdu4763 KMP
  6. 判断网络是否为真正的公网IP
  7. 交换机入门配置:IP和远程登录功能
  8. 人工操作阶段计算机是如何工作的,管理信息系统作业参考答案
  9. linux mysql 备份脚本_linux下mysql备份脚本
  10. 荷兰 转专业申请计算机,荷兰留学转专业申请须知
  11. VS中使用码云gitee建立源代码管理
  12. scanf和getch函数的区别
  13. 关于swiftUI和UIKit混用
  14. java小数位数保留
  15. sqlserver中计算日期差
  16. 深度学习( Deep Learning )软件资源列表
  17. 汽车覆盖件冲压模具铸造工艺研究
  18. 武汉轻工大学计算机学院宿舍,武汉轻工大学有几个校区及校区地址 哪个校区最好...
  19. iOS开发苹果支持中文字体,和使用字体
  20. 完美的正方形分割(二)

热门文章

  1. MyApplication
  2. 田野调查手记·浮山摩崖石刻(四)
  3. 如何通过学习开源项目来提高自己
  4. 进制转换python_进的解释|进的意思|汉典“进”字的基本解释
  5. 创业必读:没钱没技术,如何开发App?
  6. N1变砖有救N1 eMMC 镜像,理论用于TTL救砖 ,使用ddbr恢复官改系统救砖方法
  7. mysql 8 my.cnf 配置文件_mysql之my.cnf配置文件详解
  8. javascripts再进
  9. 17.03.05校内训练: 万圣节服饰
  10. 3.4 命令模式(5.2)