前言:终于开通了自己的博客专栏,主要是针对android自定义VIew系列的,由浅入深,一步步学习,记录。我刚接触自定义View不久,正好作为学习笔记,也可以分享给各位童鞋,欢迎指正。
概要:android中虽然有很多可以调用的控件,但是由于样式等过于单一,想要实现一些酷炫的界面效果,就需要通过自定义View的方法来实现。学习自定义VIew是进阶必须的一个过程,合理地设计使用自定义界面,可以让APP更具操作性,更能吸引用户。在阅读API基础上,本文会对onLayout,onDraw,onMeasure等方法做一些说明,然后实现一些简单的自定义View的效果,作为案例,本文是第一篇,后面会慢慢加深。
专栏地址:http://blog.csdn.net/column/details/13877.html
一,自定义View主要方法:
目前开发过程中主要是用的自定义View的方法主要是三种:
1)继承控件;
2)组合控件;
3)绘制控件;
说到自定义View,会重写使用到三个方法onLayout(),onDraw(),onMeasure()。本系列文章将会针对这三种方法以及实现自定义View的三种方式来学习介绍。
二,onLayout(),onDraw(),onMeasure()介绍
一般自定义View都需要经历一个过程:测量(measure),布局(layout),绘制(draw)对应的就是onMeasure(),onLayout(),onDraw()三个方法。
onMeasure():
官方API给出的说明:Called to determine the size requirements for this view and all of its children.
翻译成中文:当按要求确定该视图和下面所有子视图的大小的时候调用这个方法。
使用:通常View在屏幕上显示出来之前能,需要先经历测量(measure)的过程,在调用这个方法的时候会涉及到使用MeasureSpec。MeasureSpec封装了父视图传给子视图的布局要求,每个MeasureSpec代表了对宽度和者高度的要求,包含大小和模式。
MeasureSpec有三种模式:
UNSPECIFIED:父视图对子视图没有任何约束限制,子视图可以是任意大小。
EXACTLY:父视图对子视图给出明确的大小,子视图将按给出的要求展示大小,忽略自身的大小。
AT_MOST:子视图大小最多达到指定的大小。
onLayout():
官方API给出的说明:Called when this view should assign a size and position to all of its children.
翻译成中文:当该视图需要给下面所有的子视图分配大小和位置的时候调用这个方法。
使用:布局视图控件,在测量后执行,有父视图决定子View的位置,通过childView.layout()来确定位置。
onDraw():
官方API给出的说明:Called when the view should render its content.
翻译成中文:当视图需要显示其内容的时候调用这个方法。
使用:绘制View并展示。
三,简单示例
1)继承控件
下面我们来介绍一下什么是继承控件实现自定义View,我们自定义一个Button。
首先自定义一个View继承自Button:
public class MyView extends Button {
public MyView(Context context) {
this(context,null);
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
设置初始化调用的构造方法是含三个参数的,一般默认是调用含两个参数的。
给按钮设置padding值,再添加一个设置背景色和文字的方法:
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setPadding(15,10,15,10);
}
//设置按钮文字
public void setStringText(String str){
setText(str);
}
//设置按钮背景色
public void setBackColor(int color){
mColor = color;
setBackgroundColor(color);
}
然后在布局文件引入这个自定义的控件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.testsafekey.MainActivity"
>
<com.example.testsafekey.MyView
android:id="@+id/mv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
在activity文件中查找组件,设置文字和背景色:
public class MainActivity extends AppCompatActivity {
private MyView mv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mv = (MyView) findViewById(R.id.mv);
mv.setStringText("click");
mv.setBackColor(Color.BLUE);
}
}
此时运行就会出现一个蓝色的button
2)组合控件
这种是比较简单的实现方式,这里我们来实现一个上面图片下面文字的效果,组合ImageView和TextView来实现。
首先定义一个xml布局文件,排列ImageView和TextView的组合:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:id="@+id/iv"
android:layout_width="40dp"
android:layout_height="40dp" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"/>
</LinearLayout>
自定义View继承LinearLayout:
public class MyView extends LinearLayout{
private ImageView iv;
private TextView tv;
public MyView1(Context context) {
this(context,null);
}
public MyView1(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.item_lay,this,true);
iv = (ImageView) findViewById(R.id.iv);
tv = (TextView) findViewById(R.id.tv);
}
}
在构造函数里面加载解析布局文件,并查找组件。
在自定义View里面添加设置文字和图片的方法:
public void setTextStr(String str){
tv.setText(str);
}
public void setImageRes(int res){
iv.setImageResource(res);
}
添加自定义的控件到主布局文件中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.testsafekey.MainActivity"
>
<com.example.testsafekey.MyView
android:id="@+id/mv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {
private MyView mv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mv = (MyView) findViewById(R.id.mv);
mv.setTextStr("安卓");
mv.setImageRes(R.mipmap.ic_launcher);
}
}
运行:
3)绘制控件
最后我们来绘制一个简单的按钮控件:
首先自定义View,绘图需要Paint画笔,Canvas画布,画布在onDraw里面自带了,所以需要实例化一个画笔。
public class MyView extends View {
//画笔
private Paint mPaint;
//矩形区域
private Rect mRect;
//文字
private String textTitle = "4321";
//view宽高
private int mWidth = 200;
private int mHeight = 100;
public MyView2(Context context) {
this(context,null);
}
public MyView2(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyView2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mRect = new Rect(0,0,mWidth,mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制矩形区域
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(3);
mPaint.setAntiAlias(true);
canvas.drawRect(mRect,mPaint);
//绘制文字
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(3);
mPaint.setTextSize(40);
mPaint.getTextBounds(textTitle,0,textTitle.length(),mRect);
canvas.drawText(textTitle,mWidth/2-mRect.width()/2,mHeight/2+mRect.height()/2,mPaint);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.testsafekey.MainActivity"
>
<com.example.liujibin.MyView2
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
运行就可以看到效果了:
由于时间仓促,写的比较简单,后面会最加一些详解。见谅。