20170831工作日记--自定义View学习
Posted buder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20170831工作日记--自定义View学习相关的知识,希望对你有一定的参考价值。
学习了LayoutInflater的原理分析、视图的绘制流程、视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件、组合控件、以及继承控件。那么下面我们就来依次学习一下,每种方式分别是如何自定义View的。
(一)自绘控件
自绘控件的意思就是,这个View上所展现的内容全部都是我们自己绘制出来的。绘制的代码是写在onDraw()方法中的。参考相关博客 http://blog.csdn.net/guolin_blog/article/details/17357967
下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次。新建一个CounterView继承自View,代码如下所示:
1 /** 2 * Created by nubia on 2017/8/31. 3 */ 4 5 public class CounterView extends View implements View.OnClickListener { 6 7 private Paint mPaint; 8 private Rect mBounds; 9 private int mCount; 10 11 public CounterView(Context context, @Nullable AttributeSet attrs) { 12 super(context, attrs); 13 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 14 mBounds = new Rect(); 15 setOnClickListener(this); 16 } 17 18 @Override 19 protected void onDraw(Canvas canvas) { 20 super.onDraw(canvas); 21 /** 22 * 蓝色画笔,画出来个矩形 23 */ 24 mPaint.setColor(Color.BLUE); 25 canvas.drawRect(0,0,getWidth(),getHeight(),mPaint); 26 27 /** 28 * 画笔变成黄色,绘制文字 29 */ 30 mPaint.setColor(Color.YELLOW); 31 mPaint.setTextSize(30); 32 String text = String.valueOf(mCount); 33 mPaint.getTextBounds(text,0,text.length(),mBounds); 34 float textWidth = mBounds.width(); 35 float textHeight = mBounds.height(); 36 canvas.drawText(text,getWidth()/2-textWidth/2,getHeight()/2+textHeight/2,mPaint);; 37 } 38 39 /** 40 * 调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用 41 * @param view 42 */ 43 @Override 44 public void onClick(View view) { 45 mCount++; 46 invalidate(); 47 } 48 }
可以看到,首先我们在CounterView的构造函数中初始化了一些数据,并给这个View的本身注册了点击事件,这样当CounterView被点击的时候,onClick()方法就会得到调用。而onClick()方法中的逻辑就更加简单了,只是对mCount这个计数器加1,然后调用invalidate()方法。通过 Android视图状态及重绘流程分析,带你一步步深入了解View(三) 这篇文章的学习我们都已经知道,调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用。
既然CounterView是一个自绘视图,那么最主要的逻辑当然就是写在onDraw()方法里的了,下面我们就来仔细看一下。这里首先是将Paint画笔设置为蓝色,然后调用Canvas的drawRect()方法绘制了一个矩形,这个矩形也就可以当作是CounterView的背景图吧。接着将画笔设置为黄色,准备在背景上面绘制当前的计数,注意这里先是调用了getTextBounds()方法来获取到文字的宽度和高度,然后调用了drawText()方法去进行绘制就可以了。
这样,一个自定义的View就已经完成了,并且目前这个CounterView是具备自动计数功能的。那么剩下的问题就是如何让这个View在界面上显示出来了,其实这也非常简单,我们只需要像使用普通的控件一样来使用CounterView就可以了。比如在布局文件中加入如下代码:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" > 4 5 <com.example.myview.CounterView 6 android:layout_width="100dp" 7 android:layout_height="100dp" 8 android:layout_centerInParent="true" /> 9 10 </RelativeLayout>
可以看到,这里我们将CounterView放入了一个RelativeLayout中,然后可以像使用普通控件来给CounterView指定各种属性,比如通过layout_width和layout_height来指定CounterView的宽高,通过android:layout_centerInParent来指定它在布局里居中显示。只不过需要注意,自定义的View在使用的时候一定要写出完整的包名,不然系统将无法找到这个View。
(二)组合控件
组合控件的意思就是,我们并不需要自己去绘制视图上显示的内容,而只是用系统原生的控件就好了,但我们可以将几个系统原生的控件组合到一起,这样创建出的控件就被称为组合控件。
举个例子来说,标题栏就是个很常见的组合控件,很多界面的头部都会放置一个标题栏,标题栏上会有个返回按钮和标题,点击按钮后就可以返回到上一个界面。那么下面我们就来尝试去实现这样一个标题栏控件。
建一个title.xml布局文件,代码如下所示:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="50dp" 5 android:background="#9999cc"> 6 7 <Button 8 android:id="@+id/button_left" 9 android:layout_width="80dp" 10 android:layout_height="60dp" 11 android:layout_centerVertical="true" 12 android:layout_marginLeft="2dp" 13 android:background="@mipmap/aaa" /> 14 15 <TextView 16 android:id="@+id/title_text" 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:layout_centerInParent="true" 20 android:text="this is Title" 21 android:textColor="#fff" 22 android:textSize="30sp" 23 android:textStyle="bold" /> 24 25 26 </RelativeLayout>
接下来创建一个TitleView继承自FrameLayout,代码如下所示:
/** * Created by nubia on 2017/8/31. */ public class TitleView extends FrameLayout { private Button leftButton; private TextView titleText; public TitleView(final Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.title, this); titleText = findViewById(R.id.title_text); leftButton = findViewById(R.id.button_left); leftButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //((Activity)getContext()).finish(); TextView t = findViewById(R.id.title_text); t.setText("sha bi "); } }); } }
TitleView中的代码非常简单,在TitleView的构建方法中,我们调用了LayoutInflater的inflate()方法来加载刚刚定义的title.xml布局,这部分内容我们已经在 Android LayoutInflater原理分析,带你一步步深入了解View(一) 这篇文章中学习过了。
到了这里,一个自定义的标题栏就完成了,那么下面又到了如何引用这个自定义View的部分,其实方法基本都是相同的,在布局文件中添加如下代码:
1 <com.example.myview.TitleView 2 android:id="@+id/title_view" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" />
(三)继承控件
还没看明白 http://blog.csdn.net/guolin_blog/article/details/17357967
以上是关于20170831工作日记--自定义View学习的主要内容,如果未能解决你的问题,请参考以下文章
学习日记0827异常处理 元类 自定义元类 自定义元类来实例化类 属性查找顺序