自定义View
来源:互联网 发布:淘宝刷单一单的价格 编辑:程序博客网 时间:2024/06/06 16:33
自定义View之前要掌握的东西
一、Android绘图三大API1.Canvas类
(1)功能:Canvas代表了"依附"于指定View的画布,通过Canvas类的成员方法能够实现绘制各种图形。绘制一个图形由四部分组成:Bitmap、Canvas、Path/Rect/text等、Paint,其中Bitmap为绘制图形存放的像素位图,Canvas用于提供绘制图像方法、Paint为画笔、Path/Rect/text等分别为绘制图形的(轨迹/矩形/文本)。
(2)构造方法Canvas() :构造空的canvas对象Canvas(Bitmap bitmap) :构造一个Canvas对象,并指定其bitmap
(3)常用方法
booleanclipRegion(Region region):剪切指定区域voiddrawBitmap(Bitmap bitmap, float left, float top, Paint paint):在指定点(x,y)使用指定的画笔paint绘制位图voiddrawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint):在指定点(x,y)绘制从源位图中"挖取"的一块voiddrawCircle(float cx, float cy, float radius, Paint paint):绘制原点为(cx,cy),半径为radius的圆voiddrawLine(float startX, float startY, float stopX, float stopY, Paint paint):绘制一条起点为(startX,startY),终点为(stopX,stopY)直线voiddrawLines(float[] pts, int offset, int count, Paint paint):绘制多条直线,其中pts为一个浮点型数组提供绘制一条直接所需的数据(4个/条),count为绘制直线的条数voiddrawOval(RectF oval, Paint paint):绘制一个椭圆,oval为绘制椭圆的矩形边界voiddrawPath(Path path, Paint paint):沿着路径path绘制图形voiddrawPoint(float x, float y, Paint paint):绘制一个点(x,y)voiddrawPoints(float[] pts, int offset, int count, Paint paint):绘制pts数组中的多个点(2个值/点)voiddrawRect(float left, float top, float right, float bottom, Paint paint):绘制一个矩形,其参数为距离屏幕边界的距离(边界为0)voiddrawRoundRect(RectF rect, float rx, float ry, Paint paint):使用指定的画笔绘制圆角矩形,其中rect为矩形边界、rx/ry分别为以矩形顶点为(0,0)相对位置圆的x半径、y半径voiddrawText(String text, float x, float y, Paint paint):以(x,y)为原点,使用指定画笔绘制文本voiddrawTextOnPath(String text, Path path, float x, float y, Paint paint):以(x,y)为原点,使用指定的画笔沿着指定路径绘制文本intgetHeight():返回当前图层的高度intgetWidth():返回当前绘图层的宽度voidrotate(float degrees):对Canvas执行旋转变换;voidsetBitmap(Bitmap bitmap):指定Canvas(画布)的位图Bitmapvoidtranslate(float dx, float dy):相对于当前位置移动Canvas。向右移动dx距离(dx为负数即向左移动);向下移动dy距离(dy为负数即向上移动)voidskew(float sx,float sy):对Canvas执行倾斜变换
2.Paint类
(1)功能:Paint代表了Canvas上的画笔,Paint类主要用于设置绘制风格,包括画笔的颜色、画笔笔触粗细、填充风格等。
(2)构造方法Paint() :使用默认设置构造一个Paint对象Paint(int flags) :使用指定flags构造一个Paint对象Paint(Paint paint) :使用已有画笔的设置构造一个新的Paint对象
(3)常用方法
voidreset():恢复画笔到默认配置voidsetARGB(int a, int r, int g, int b):设置画笔透明度和颜色,其参数分别代表透明度、红色、绿色、蓝色voidsetAlpha(int a):设置画笔的透明度voidsetAntiAlias(boolean aa):设置是否抗锯齿voidsetColor(int color):设置画笔的颜色voidsetFlags(int flags):设置画笔的flags(HINTING_OFF、HINTING_ON等)voidsetHinting(int mode):设置画笔的提示模式PathEffectsetPathEffect(PathEffect effect):设置绘制路径时的路径效果(ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect)RasterizersetRasterizer(Rasterizer rasterizer)ShadersetShader(Shader shader):设置画笔的填充效果(BitmapShader, ComposeShader, LinearGradient, RadialGradient, SweepGradient)voidsetShadowLayer(float radius, float dx, float dy, int color):设置阴影效果voidsetStrokeJoin(Paint.Join join):设置画笔转弯处的连接风格(BEVEL-直线、MITER -锐角、ROUND-圆弧 )voidsetStrokeWidth(float width):设置画笔宽度voidsetStyle(Paint.Style style):设置Paint的填充风格(FILL-、FILL_AND_STROKE、STROKE )voidsetTextAlign(Paint.Align align):设置绘制文本时的文字对齐方式(CENTER -居中、LEFT-靠左、RIGHT -靠右:以(x,y)为中心)voidsetTextSize(float textSize):设置绘制文本的文字大小3.Path类
(1)功能:Android提供的Path类预先在View上将N个点连成一条"路径",然后调用Canvas的drawPath(path,paint)方法即可沿着路径绘制图形。另外,Android还提供了PathEffect来定义绘制路径图形效果,其包含ComposePathEffect、CornerPathEffect、DashPathEffect、DiscretePathEffect、PathDashPathEffect、SumPathEffect六种效果。
(2)构造方法Path():构造一个Path对象Path(Path src) :从另一个Path对象构造一个新的Path对象
(3)常用方法
booleanisEmpty():判定Path对象是否为空(即不包含直线或曲线),如果为空返回truevoidlineTo(float x, float y):增加一条从上一点到当前点(x,y)的直线voidmoveTo(float x, float y):设置下一个轮廓的开始点(x,y)voidrLineTo(float dx, float dy):以坐标为参照增加一条从上一点到当前点(x,y)的直线voidrMoveTo(float dx, float dy):以坐标为参照设置下一个轮廓的开始点(x,y)voidreset():删除Path对象的所有直线和曲线voidset(Path src):将当前Path对象的内容替换为对象src所包含的内容voidsetFillType(Path.FillType ft):设置路径的填充类型voidsetLastPoint(float dx, float dy):设置路径的最后一个点的坐标为(x,y)voidtransform(Matrix matrix):通过matrix转换该路径中的点void
close() :释放资源
close() :释放资源
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure
4、重写onDraw
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
format是值该属性的取值类型:
reference : 资源id
color : 颜色值
boolean : 布尔值
dimension : 尺寸值
float : 浮点值
integer : 整形值
string : 字符串
fraction : 百分数
enum : 枚举值
flag : 位或运算
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--圆-->
<attr name="rotateBack" format="color"/>
<declare-styleable name="RotateView">
<attr name="rotateBack" />
</declare-styleable>
</resources>
<resources>
<!--圆-->
<attr name="rotateBack" format="color"/>
<declare-styleable name="RotateView">
<attr name="rotateBack" />
</declare-styleable>
</resources>
//这是是获取值的
public RotateView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RotateView,defStyleAttr,0);
int n = a.getIndexCount();
for (int i = 0 ; i < n ; i++ )
{
int attr = a.getIndex(i);
switch (attr){
case R.styleable.RotateView_rotateBack:
rotateBack = a.getColor(attr,Color.BLUE);
Log.d(TAG ,"颜色值---------->"+rotateBack);
break;
}
}
a.recycle();
init();
}
super(context, attrs, defStyleAttr);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RotateView,defStyleAttr,0);
int n = a.getIndexCount();
for (int i = 0 ; i < n ; i++ )
{
int attr = a.getIndex(i);
switch (attr){
case R.styleable.RotateView_rotateBack:
rotateBack = a.getColor(attr,Color.BLUE);
Log.d(TAG ,"颜色值---------->"+rotateBack);
break;
}
}
a.recycle();
init();
}
初始PaInt
/**
* 初始化
*/
public void init(){
mPaint = new Paint();
//样式填充分3种 Paint.Style.FILL :填充内部 Paint.Style.FILL_AND_STROKE :填充内部和描边 Paint.Style.STROKE :仅描边
mPaint.setStyle(Paint.Style.FILL);
//颜色
mPaint.setColor(rotateBack);
//锯齿功能
mPaint.setAntiAlias(true);
//画笔宽度
mPaint.setStrokeWidth(4);
//设置阴影
// mPaint.setShadowLayer(160,305,305,Color.GREEN);
mWidth = 200;
mHigth = 200;
rotate(true);
}
* 初始化
*/
public void init(){
mPaint = new Paint();
//样式填充分3种 Paint.Style.FILL :填充内部 Paint.Style.FILL_AND_STROKE :填充内部和描边 Paint.Style.STROKE :仅描边
mPaint.setStyle(Paint.Style.FILL);
//颜色
mPaint.setColor(rotateBack);
//锯齿功能
mPaint.setAntiAlias(true);
//画笔宽度
mPaint.setStrokeWidth(4);
//设置阴影
// mPaint.setShadowLayer(160,305,305,Color.GREEN);
mWidth = 200;
mHigth = 200;
rotate(true);
}
mPaint.setStyle(Paint.Style.FILL);
Paint.Style.FILL :填充内部
Paint.Style.FILL_AND_STROKE :填充内部和描边
Paint.Style.FILL_AND_STROKE :填充内部和描边
Paint.Style.STROKE :仅描边
一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"
我们的命名空间,后面的包路径指的是项目的package
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:weightSum="1">
<com.example.jiangtao.testevent.custom_view.CustomTitleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:titleText = "2342"
android:layout_gravity="center"
android:id="@+id/custom_title_view"
android:padding="20dp"
custom:mTitleTextColor="#000000"
android:layout_centerInParent="true"
custom:titleTextSize="50sp"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:weightSum="1">
<com.example.jiangtao.testevent.custom_view.CustomTitleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:titleText = "2342"
android:layout_gravity="center"
android:id="@+id/custom_title_view"
android:padding="20dp"
custom:mTitleTextColor="#000000"
android:layout_centerInParent="true"
custom:titleTextSize="50sp"
/>
</LinearLayout>
系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。
所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:
重写之前先了解MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 重写onMeasure的目的是处理warp_content模式
// 获取宽度的模式
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
// 获取高度的模式
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
// 获取宽度的规格
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
// 获取高度的规格
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
// 如果宽高的模式都是warp_content,则使用默认的宽高值
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, mHigth);
}
// 如果只有宽度模式是warp_content,则设置宽度为默认值,高度为测量出的值
else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, heightSpecSize);
}
// 如果只有高度模式是warp_content,则设置高度为默认值,宽度为测量出的值
else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, mHigth);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 重写onMeasure的目的是处理warp_content模式
// 获取宽度的模式
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
// 获取高度的模式
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
// 获取宽度的规格
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
// 获取高度的规格
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
// 如果宽高的模式都是warp_content,则使用默认的宽高值
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, mHigth);
}
// 如果只有宽度模式是warp_content,则设置宽度为默认值,高度为测量出的值
else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, heightSpecSize);
}
// 如果只有高度模式是warp_content,则设置高度为默认值,宽度为测量出的值
else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, mHigth);
}
}
从写onDraw()
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int width = getWidth() - paddingLeft - paddingRight;
int height = getHeight() - paddingBottom - paddingTop;
mPaint.setColor(rotateBack);
//画布设置颜色
// canvas.drawColor(Color.RED);
//画圆(第一个参数是x点、 第二个是y点、 第三个半径 )
radius = Math.min(width,height)/2;
canvas.drawCircle(paddingLeft+width/2,paddingTop+height/2,radius,mPaint);
//画线startX:起始端点的X坐标。startY:起始端点的Y坐标。stopX:终止端点的X坐标。stopY:终止端点的Y坐标
// canvas.drawLine(0, 0, 100, 100,mPaint);
//画多条直线 前两个表示的是直线起点的横纵坐标,后两个表示的是直线终点的横纵坐标。(两两为一个点)
// float []pts={10,10,100,100,200,200,400,400};
// canvas.drawLines(pts,mPaint);
// 绘制圆角矩形
// RectF re1 = new RectF(30,30, 200, 200);
// canvas.drawRoundRect(re1, 30,30, mPaint);
// 绘制椭圆
// RectF re11 = new RectF(30,30,300, 200);
// canvas.drawOval(re11, mPaint);
//定义一个Path对象,封闭成一个三角形并根据Path对象绘制
// Path path1 = new Path();
// path1.moveTo(10, 340);
// path1.lineTo(70, 340);
// path1.lineTo(40, 290);
// path1.close();
// canvas.drawPath(path1, mPaint);
// 根据Path绘制五角形
// Path path2 = new Path();
// path2.moveTo(26, 360);
// path2.lineTo(54, 360);
// path2.lineTo(70, 392);
// path2.lineTo(40, 420);
// path2.lineTo(10, 392);
// path2.close();
// canvas.drawPath(path2, mPaint);
//c.绘制正方形
// canvas.drawRect(170,80,230,140,mPaint);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int width = getWidth() - paddingLeft - paddingRight;
int height = getHeight() - paddingBottom - paddingTop;
mPaint.setColor(rotateBack);
//画布设置颜色
// canvas.drawColor(Color.RED);
//画圆(第一个参数是x点、 第二个是y点、 第三个半径 )
radius = Math.min(width,height)/2;
canvas.drawCircle(paddingLeft+width/2,paddingTop+height/2,radius,mPaint);
//画线startX:起始端点的X坐标。startY:起始端点的Y坐标。stopX:终止端点的X坐标。stopY:终止端点的Y坐标
// canvas.drawLine(0, 0, 100, 100,mPaint);
//画多条直线 前两个表示的是直线起点的横纵坐标,后两个表示的是直线终点的横纵坐标。(两两为一个点)
// float []pts={10,10,100,100,200,200,400,400};
// canvas.drawLines(pts,mPaint);
// 绘制圆角矩形
// RectF re1 = new RectF(30,30, 200, 200);
// canvas.drawRoundRect(re1, 30,30, mPaint);
// 绘制椭圆
// RectF re11 = new RectF(30,30,300, 200);
// canvas.drawOval(re11, mPaint);
//定义一个Path对象,封闭成一个三角形并根据Path对象绘制
// Path path1 = new Path();
// path1.moveTo(10, 340);
// path1.lineTo(70, 340);
// path1.lineTo(40, 290);
// path1.close();
// canvas.drawPath(path1, mPaint);
// 根据Path绘制五角形
// Path path2 = new Path();
// path2.moveTo(26, 360);
// path2.lineTo(54, 360);
// path2.lineTo(70, 392);
// path2.lineTo(40, 420);
// path2.lineTo(10, 392);
// path2.close();
// canvas.drawPath(path2, mPaint);
//c.绘制正方形
// canvas.drawRect(170,80,230,140,mPaint);
}
滚动
/**
* 根据标签判断滚动
* @param flag
*/
public void rotate(boolean flag){
if (flag==true){
RotateAnimation ra = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 0.5F,
Animation.RELATIVE_TO_SELF, 0.5F);
ra.setDuration(1000);
ra.setRepeatCount(-1);
this.startAnimation(ra);
}
}
* 根据标签判断滚动
* @param flag
*/
public void rotate(boolean flag){
if (flag==true){
RotateAnimation ra = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 0.5F,
Animation.RELATIVE_TO_SELF, 0.5F);
ra.setDuration(1000);
ra.setRepeatCount(-1);
this.startAnimation(ra);
}
}
资料来源于网络希望对你有帮助,菜鸟一枚正在起飞中~~~~~~~~~
0 0
- 自定义view
- 自定义View
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义View
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- 分离链接散列表
- python中的socket模块
- 【有毒的设计模式】建造者模式
- 机器学习3
- SDAU 练习三 1011 蜜蜂爬巢问题
- 自定义View
- ReentrantLock 源码
- Keepalived实现双机热备
- FPGA:下一代机器人感知处理器
- LintCode:丢失的第一个正整数
- Raspberry Pi如何使用MPU6050
- Codeforces Round #352 (Div. 2) C. Recycling Bottles
- mysql 5.7免安装版步骤
- 怎么在linux下用vim编写一个C程序