Android自定义View
什么是自定义View?
通过直接继承或者重写View子类实现逻辑的View,称之为自定义View。
为什么要自定义View?
在实际项目中android 自带的View无法满足特定的需求,所以需要扩展或者修改原生View,满足特定的需求;
android自带View结构
自定义View类型?
- 自绘控件:直接继承View类的方式自绘控件。
- 重写控件:简介继承View子类的方式是重写控件。
- 组合控件:简介继承View子类,需要用到原生控件组合到一起。
下面以案例的形式记录自己所学的这几种自定义View。
自绘控件:
使用步骤:
* 继承View
* 实现接口Listener接口(没有可以不用)
* 重写构造方法(两个参数的)
* 重写onDraw方法
* Paint画笔
* Canvas绘制
* invalidate方法刷新
* 在布局文件中引用
画笔的常用方法及解释:
* setAntilias():设置画笔的锯齿效果
* setColor():设置画笔颜色
* setARGB():设置画笔的A.R.G.B值
* setAlpha():设置画笔的透明度
* setStyle():设置画笔的风格(空心或者实心)
* setStrokeWidth():设置空心边框的宽度
* getColor():获取画笔的颜色
* setTextSize():设置字体的尺寸
画布的常用方法及解释:
* drawLine():绘制直线
* drawCircle():绘制圆形
* drawBirmap():绘制图形
* drawRect():绘制矩形
* drawText():绘制字符
invalidate()方法:调用这个方法后,会再次 执行onDraw()方法
案例一:绘制计数器
第一步:创建一个类,继承View
package com.lenovo.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class CountNumView extends View {
}
第二步:重写构造方法,两个参数的
public CountNumView(Context context, AttributeSet attrs) {
super(context, attrs);
}
第三步:重写onDraw()方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//创建画笔
Paint p = new Paint();
//设置画笔颜色
p.setColor(Color.RED);
//绘制圆形画布:参数
//圆心的x轴,圆心的y轴,半径大小,画笔
canvas.drawCircle(getWidth()/2, getHeight()/2, 150, p);
}
第四步:在布局中调用
<RelativeLayout 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"
tools:context="com.lenovo.activity.MainActivity" >
<com.lenovo.view.CountNumView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
重写控件
步骤:
1. 新建一个类继承系统提供的View
2. 重写对应的构造方法
3. 实现逻辑并定义时间监听
4. 在布局文件中引用
四个案例在一起:
案例一:重写Button实现自定义返回Button
第一步:新建一个类继承Button
public class FinishButtonView extends Button implements OnClickListener{
}
第二步:构造方法(两个参数的)
private Activity mActivity;
// 实现构造方法
public FinishButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
//获取到activity
mActivity = (Activity) getContext();
//设置监听
this.setOnClickListener(this);
}
第三步:监听销毁页面
//监听
@Override
public void onClick(View v) {
//销毁页面
mActivity.finish();
}
第四步:在布局中引用(控件名称是包名+类名)
<com.example.view.FinishButtonView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="销毁页面" />
案例二:重写ImageView实现自定义相框
第一步:新建一个类继承ImageView
public class CustomImageView extends ImageView{
}
第二步:构造方法(两个参数的),并初始化画笔
private Paint mPain;
//构造方法
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化画笔
private void init() {
mPain = new Paint();
mPain.setColor(Color.RED);
//空心
mPain.setStyle(Paint.Style.STROKE);
//宽度
mPain.setStrokeWidth(10);
}
第三步:重写onDraw方法
//重写onDraw方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//得到图片边缘轮廓
Rect bounds = canvas.getClipBounds();
bounds.bottom--;
bounds.right--;
canvas.drawRect(bounds, mPain);
}
第四步:在布局中引用
<com.example.view.CustomImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="@drawable/ic_launcher"
/>
案例三:重写ListView实现下拉刷新
提示:只是实现了样式,没有实现功能。
首先,建立一个头部布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="下拉刷新" />
</LinearLayout>
* PS:必须是Linear Layout布局 *
第一步:新建一个类继承ListView
public class CustomListView extends ListView {}
第二步:构造方法(两个参数的)
// 阻尼系数
private double damping = 0.3;
// 视图
private View view;
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
// 绑定布局
view = View.inflate(context, R.layout.header, null);
// 测量模式
view.measure(0, 0);
// 获取高度
height = view.getMeasuredHeight();
// 隐藏头部
view.setPadding(0, -height, 0, 0);
// 添加到头部
addHeaderView(view);
}
第三步:监听手势
// 高度
private int height;
// 按下
private int downY;
// 滑动
private int moveY;
// 手势监听
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
// 按下
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
// 抬起
case MotionEvent.ACTION_UP:
// 隐藏头部
view.setPadding(0, -height, 0, 0);
// 刷新
view.invalidate();
break;
// 移动
case MotionEvent.ACTION_MOVE:
// 获取滑动Y
moveY = (int) ev.getY();
// 下拉
view.setPadding(0, (int) (((moveY - downY) - height) * damping), 0, 0);
// 刷新
view.invalidate();
break;
}
return super.onTouchEvent(ev);
}
第四步:引用,填充数据,这里不再赘述,不会的可以去看看我之前写的。
BaseAdapter
ArrayAdapter
组合控件
案例一:将多个控件组合在一起使用。
步骤:
1. 新建一个布局
2. 新建类继承跟布局标签
3. 绑定布局
第一步:新建一个布局。
二三步:
public class FinishButtonView extends Button implements OnClickListener{
private Activity mActivity;
// 实现构造方法
public FinishButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
//获取到activity
mActivity = (Activity) getContext();
//设置监听
this.setOnClickListener(this);
}
//监听
@Override
public void onClick(View v) {
//销毁页面
mActivity.finish();
}
}
自定义布局就到这里了。