Android自定义View 一<最简单的自定义View>
来源:互联网 发布:java物联网项目实例 编辑:程序博客网 时间:2024/06/11 21:25
为什么要自定义View
android提供了很多控件供我们使用 但有些功能是系统所提供的实现不
了的 这时候我们就需要自定义一个View来实现我们所需要的效果.
在Android中所有的控件都直接或间接的继承自View,分View和ViewGroup两部分.
我们常用的一些View比如TextView,ImageView都是继承自View并添加了一些各自的特性,ViewGroup也是继承View但是它可以包含子View也就是我们经常用到的各种布局比如LinearLayout,RelativeLayout等。
如何自定义布局
所以我们要是实现一个自己的View那就集成View并添加一些自己需要的特性即可.
以下是一个最简单的自定义View
public class MVIew extends View { /** * 创建一个继承View的class *View一共有四个构造器 这里先说两个 * 第一个构造器的参数就是context,这是在Activity实例化的时候所需的,比如Button button = new Button(context); * 第二个构造器有两个参数 第一个同样是context 第二个参数AttributeSet放入了一些属性,这是我们在写XML文件时用到的比如 * android:layout_width="match_parent" * android:layout_height="match_parent"如果不写函数的话是无法通过XML添加View */ public MVIew(Context context) { super(context); } public MVIew(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } //重写onDraw方法 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.RED); //设置canvas的背景色 float radius = 50; //给定半径 //给定圆心的的坐标 float cx = 50; float cy = 50; Paint paint = new Paint(); //实例化一个Paint对象 paint.setColor(Color.BLUE); //设置圆的颜色 //通过canvas的drawCircle方法画一个圆圈. canvas.drawCircle(cx, cy, radius, paint); }}
这个自定义的View就是画了一个圆圈,接下来就是让这个view加载到activity上了.第一种就是直接在Activity上实例化一个并通过addView(View)来添加
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MVIew mvIew = new MVIew(getApplicationContext()); //实例化自定义的View RelativeLayout main_layout = (RelativeLayout) findViewById(R.id.main_layout); //获取布局的对象 main_layout.addView(mvIew); //向布局文件添加View }}
第二种就是最常用的通过XML文件去添加
<cn.lipengfei.myview.MVIew android:layout_width="wrap_content" android:layout_height="wrap_content" />
要注意的是标签名要写自定义的View的完整类名既包名.类名
以下是效果
效果很简单 就是一个红色的画板上有一个蓝色的半径为50的圆圈.
这里有一个问题
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
明明width和height都是wrap_content为什么出来的辣么大.
测量
这涉及到View的测量.
Android由一个MeasureSpec的类,可以通过它来说实现测量.
MeasureSpec是一个int型的值,并且采用了位运算,高两位为测量的模式,低30位是具体的值.
由三种测量模式
- EXACTLY 精确模式 例如layout_height=”50dp”或是=”match_parent”
- AT_MOST 最大值模式 就是warp_content
- UNSPECIFIED 通过字面意思就是没有指定尺寸
Android通过onMeasure()测量View的大小,默认情况下是EXACTLY模式,所以刚才的例子虽然写了warp_concent依然没有起作用,如果想实现AT_MOST模式那就需要我们重写onMeasure()这个方法.
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //先声明两个int值来表示最终的width和height并给定一个默认的大小 int width_size = 100; int height_size = 100; //使用MeasureSpec分别获取width和height的MODE和SIZE int HEIGHT_MODE = MeasureSpec.getMode(heightMeasureSpec); int HEIGHT_SIZE = MeasureSpec.getSize(heightMeasureSpec); int WIDTH_MODE = MeasureSpec.getMode(widthMeasureSpec); int WIDTH_SIZE = MeasureSpec.getSize(widthMeasureSpec); if (HEIGHT_MODE == MeasureSpec.EXACTLY) { height_size = HEIGHT_SIZE; //如果测量模式是精确的话 那么就直接使用获取到的值就好了 }else if (HEIGHT_MODE == MeasureSpec.AT_MOST){ //如果是最大值模式的话 那么久比较获取的和设定的默认值那个小就使用那个.ps:Math.min(int a,int b)是比较数值大小的. height_size = Math.min(HEIGHT_SIZE,height_size); } if (WIDTH_MODE == MeasureSpec.EXACTLY){ width_size = WIDTH_SIZE; }else if (WIDTH_MODE == MeasureSpec.AT_MOST){ width_size = Math.min(WIDTH_SIZE,width_size); } //测量完毕后得到的了width和height通过setMeasuredDimension()设置width和height,真正决定具体大小的是setMeasuredDimension()的两个参数. setMeasuredDimension(width_size,height_size); }
效果如下
可以看到这个时候控件的大小已经变成所设定的默认值了.
onDraw(Canvas canvas)
测量完成后就有了大小接下来就是内容了,我们需要在view上显示什么就重写onDraw来实现,以上例子是通过onDraw(Canvas canvas)绘制了一个圆圈.
首先要说的是Canvas,刚才的例子就是通过 canvas.drawCircle(cx, cy, radius, paint);这样一个方法来画了一个圆.这里不对Canvas展开来说,只是说一些Canvas的简单用法.
Canvas就是一个画板,可以在这个画板上话各种各样的东西
Paint paint = new Paint(); //实例化一个Paint对象 paint.setColor(Color.BLACK); paint.setStrokeWidth(10);//因为默认实在是太细了 设定了一个宽度值 canvas.drawLine(0,0,100,100,paint);
这就是在画了一条宽度为10的黑色的线drawLine()的前两个参数为开始点的坐标后两个为结束点的坐标,最后一个参数就是paint;
还有很多方法可以调这里就不一一列举了,可以根据canvas.的提示来试试
晚些时候我会把我总结的一些方法写出来方便初学者来看看.
除了Canvas外还有一个Paint的对象也总用到 这个是画笔的意思,比如化园的例子就是通过这个画笔来设定的园的颜色,还有画线的例子也是通过画笔来设定宽度值,如果我们吧之前的代码改一下
canvas.drawColor(Color.RED); //设置canvas的背景色 float radius = 50; //给定半径 //给定圆心的的坐标 float cx = 50; float cy = 50; Paint paint = new Paint(); //实例化一个Paint对象 paint.setColor(Color.BLACK); //设置圆的颜色 paint.setAntiAlias(true); //设置抗锯齿 paint.setStyle(Paint.Style.STROKE); //设置样式 paint.setStrokeWidth(3); //设置宽度 //通过canvas的drawCircle方法画一个圆圈. canvas.drawCircle(cx, cy, radius, paint);
其他的都没有变 只是添加了三个
paint.setAntiAlias(true); //设置抗锯齿 paint.setStyle(Paint.Style.STROKE); //设置样式 paint.setStrokeWidth(3); //设置宽度
效果就是这个样子 在样式里面设置了STROKE表示只描边也就是空心效果与之相对的还有两个属性分别是FILL_AND_STROKE,FILL,刚开始有些人搞不清这俩有啥区别,譬如我.FILL就是填充上也就是一个实心的圆圈,FILL_AND_STROKE是不仅填充成一个实心圆而且还有边框,Paint并没有单独给STROKE设置颜色的方法(至少我没发现)
这俩的区别我举个例子就很清楚了
paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(50);
这是设置成FILL并添加边框出来的效果
大家可以试试无论setStrokeWidth(50)填入多少其效果是没有任何区别的因为他就没有边框.
paint.setStyle(Paint.Style.FILL_AND_STROKE); paint.setStrokeWidth(50);
改成FILL_AND_STROKE后
这样的效果圆已经超出去一部分了,设定了填充+边框 不仅由填充效果还有边框,给边框设定了宽度值,再加上我设定的圆心坐标正好是半径值 所以边框的部分就出去了.但如果我们不设setStrokeWidth的话 这两者其实是没有什么区别的.另外要注意的是StrokeWidth的值是在园外面的,也就是说它并不占用园的实际大小,比如园的半径是100,这个半径指的是填充的部分,当把StrokeWidth设定为100时 这个圆会变大
刚才我提到Paint并没有设置STROKE的颜色的方法,所以我是通过两个画笔来实现的,通过多个画笔多个画布叠加图层来实现我们想要的各种效果
比如我现在想要一个边框为蓝色的填充为黑色的圆圈.
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.RED); float radius = 200; float cx = 500; float cy = 500; Paint paint = new Paint(); //实例化Paint paint.setColor(Color.BLACK); //设置圆的颜色 paint.setAntiAlias(true); //设置抗锯齿 paint.setStyle(Paint.Style.FILL_AND_STROKE); //设置样式 Paint paint2 = new Paint(); //实例化第二个paint对象 paint2.setColor(Color.BLUE); //设置颜色为蓝色 paint2.setStyle(Paint.Style.STROKE);//设置样式 paint2.setStrokeWidth(30); //设定边框宽度 //通过canvas的drawCircle方法画一个圆圈. canvas.drawCircle(cx, cy, radius, paint); canvas.drawCircle(cx, cy, radius, paint2); }
需要注意的是canvas.draw的先后顺序 因为这两个圆是一样大小的 只是一个多一个边框而已 所以先后是无所谓的.
- Android自定义View 一<最简单的自定义View>
- 浅谈安卓自定义view(一):制作一个最最最简单的自定义view
- Android自定义View(一) View的测量
- Android自定义简单的View
- Android自定义简单的View
- Android自定义简单的View
- android简单自定义view
- Android 简单自定义View
- 自定义View最简单的创建
- Android自定义View(一)
- Android 自定义View (一)
- Android 自定义View (一)
- Android自定义View(一)
- Android 自定义View (一)
- Android 自定义View(一)
- Android 自定义View (一)
- Android 自定义View (一)
- Android 自定义View (一)
- Matlab用三种格式来表示日期与时间
- hiho1482出勤记录II
- Java 8并发工具包漫游指南
- 猜算式
- [nODE之三]http模块练习1
- Android自定义View 一<最简单的自定义View>
- 一般开启Tomcat找不到类, java.lang.ClassNotFoundException:
- 单词句型汇总
- Codeforecs 465C No To Palindromes! 构造+思维
- rand函数与srand函数
- Git 和 SVN 之间的五个基本区别
- 新手JS:实现按钮全部不选、全部选择、反选择功能。
- 在eclipse中Arcgis for Android 环境配置
- 新的开始