@H_301_8@* onDraw()* diapatchDraw()* 通过Bitmap创建* 通过SurfaceVIEw的SurfaceHolder.lockCanvas()Drawable类可以通过创建dawable对象,然后将画好的drawable对象画在画布上,也是创建Bitmap的一种方式ShapeDrawableshape标签与GradIEntDrawable首先shap标签所对应的类是GradIEntDrawable而不是ShapeDrawable,但是GradIEnntDrawable并不能完成shape标签的所有功能,GradIEntDrawable的构造函数如下
@H_301_8@GradIEntDrawable(GradIEntDrawable.OrIEntation orIEntation, int[] colors)构造函数可以看出GradIEntDrawable对应的是gradIEnt标签的功能,并不能完成shape标签的构造矩形、椭圆等功能,但是获得shape的时候需要将其强制转换为GradIEntDrawable获取shape标签的实例
eg: 获取shape对象并设置为圆角:
@H_301_8@public class AndroIDHuaBuActivity extends AppCompatActivity { private button button; private TextVIEw textVIEw; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_androID_hua_bu); button = (button)findVIEwByID(R.ID.add_shape_corner); textVIEw = (TextVIEw)findVIEwByID(R.ID.shape_tv); button.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { //通过textVIEw的getBackground获得shape标签 GradIEntDrawable gradIEntDrawable = (GradIEntDrawable)textVIEw.getBackground(); gradIEntDrawable.setCornerRadius(20); } }); }}通过textVIEw的背景将下面的xml引入:<?xml version="1.0" enCoding="utf-8"?><shape xmlns:androID="http://schemas.androID.com/apk/res/androID"> <solID androID:color="#ff0000"/> <stroke androID:wIDth="2dp" androID:color="#00ff00" androID:dashGap="5dp" androID:dashWIDth="5dp"/></shape>ShapeDrawable的构造函数:
@H_301_8@ShapeDrawable()ShapeDrawable(Shape shape)注意:ShapeDrawable对象是需要与Shape对象进行关联的,所以如果使用第一个构造函数,必须使用ShapeDrawable.setShape(Shape shape)函数来设置 Shape对象,一般使用第二个构造函数Shape类是一个基类,draw()函数是一个虚函数,每个子类可以根据不同的需求来绘出不同的图形,所以构造ShapeDrawable并不能直接传递shape类型的队形,因为shape中没有实现draw(),而是需要传入已经实现了draw()函数的Shape类的派生类Shape的派生类:
派生类 | 意义 |
---|---|
RectShape | 构造一个矩形Shape |
ArcShape | 构造一个扇形Shape |
OcalShape | 构造一个椭圆的Shape |
RoundRectShape | 构造一个圆角矩形Shape, 可带有镂空矩形效果 |
PathShape | 构造一个可根据路径绘制的Shape |
@H_301_8@public class ShapeVIEw extends VIEw { private ShapeDrawable shapeDrawable; public ShapeVIEw(Context context) { super(context); init(); } public ShapeVIEw(Context context, AttributeSet attributeSet){ super(context, attributeSet); init(); } public ShapeVIEw(Context context, AttributeSet attributeSet, int defStyle){ super(context, attributeSet, defStyle); init(); } private voID init() { setLayerType(LAYER_TYPE_SOFTWARE,null); //生成一个ShapeDrawable,并将这个形状的定义为矩形 shapeDrawable = new ShapeDrawable(new RectShape()); //设置shapeDrawable在空间中的显示位置(在当前控件中的位置) shapeDrawable.setBounds(new Rect(50, 50, 200, 100)); //获取画笔,并将整个Drawable填充为黄色 shapeDrawable.getPaint().setcolor(color.YELLOW); } @OverrIDe protected voID onDraw(Canvas canvas) { super.onDraw(canvas); //将shape实例画在画布上 shapeDrawable.draw(canvas); }}<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:app="http://schemas.androID.com/apk/res-auto" xmlns:tools="http://schemas.androID.com/tools" androID:orIEntation="vertical" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" tools:context=".AndroIDHuabu.ShapeExample.ShapeActivity"> <com.example.adminstator.myvIEwdesign.AndroIDHuabu.ShapeExample.ShapeVIEw androID:layout_wIDth="250px" androID:layout_height="150px" androID:layout_margin="100dp" androID:background="#ffffff"/></linearLayout>
结论:
整个矩形区域水平居中显示,可以证明ShapeDrawable.setBounds()函数所设置的矩形位置是指所在控件中的位置,并非整个屏幕Drawable画布问题:
通过getPaint()获得画笔,但是ShapeDrawable.draw(canvas)是将shape画到控件上,并没有绘制shapeDrawable本身。shapeDrawable是自带画笔的,质押奥得到了画笔。改变 paint的任何内容,就会立刻在ShapeDrawable上重画ArcShapeArcShape是在 ovalShape所形成的椭圆的基础上,将其进行角度切割所形成的扇形,其中扇形开始的0度在椭圆的x轴正方向上@H_301_8@//startAngle:指的是开始的角度,扇形开始的0度在椭圆的X轴正方向上,即右中间的位置(顺时针方向)//sweepAngle:指扇形所扫过的角度public ArcShape(ffloat startAngle, float sweepAngle)RoundRectShape字面上的意思是圆角矩形,它不止可以实现圆角矩形,他的本意是实现镂空的圆角矩形效果:可以实现单纯的圆角矩形可以实现中间带有镂空的圆角矩形,而且中间镂空的矩形也可以带有圆角
@H_301_8@//outerRadii:外围矩形的各个角的角度大小,需要填充8个数字,每两个数字一组,分别对应(左上角,右上角, 右下角,左下角)4个角的角度组(x, y),每两个一组的数字构成一个椭圆。第一个数字代表椭圆的X轴半径,第二个数字代表椭圆的Y轴半径, 如果不需要指定外围矩形的各个角的角度,可以传入null//RectF inset:表示内部矩形与 外部矩形各边的边距,RectF的4个值分别对应left,top, right, bottom, 如果不需要内部矩形的镂空效果,则可以传入null//float[] innerRadii:表示内部矩形的各个角的角度大小,同样需要填充8个数字,其含义与outerRadii一样,如果不指定各个角的角度,则传入null即可public RoundRectShape(float[] outerRadii, RectF inset, float[] innerRadii)
eg:
@H_301_8@public class ShapeVIEw extends VIEw { private ShapeDrawable shapeDrawable; public ShapeVIEw(Context context) { super(context); init(); } public ShapeVIEw(Context context, AttributeSet attributeSet){ super(context, attributeSet); init(); } public ShapeVIEw(Context context, AttributeSet attributeSet, int defStyle){ super(context, attributeSet, defStyle); init(); } private voID init() { setLayerType(LAYER_TYPE_SOFTWARE,null);// //生成一个ShapeDrawable,并将这个形状的定义为矩形// shapeDrawable = new ShapeDrawable(new ArcShape(0, 300));// //设置shapeDrawable在空间中的显示位置(在当前控件中的位置)// shapeDrawable.setBounds(new Rect(50, 50, 200, 100));// //获取画笔,并将整个Drawable填充为黄色 float[] outerRadii = new float[]{12, 12, 12, 12, 0, 0, 0, 0}; RectF inset = new RectF(6, 6, 6, 6); float[] innerRadii = new float[]{50, 12, 0, 0, 12, 50, 0, 0}; shapeDrawable = new ShapeDrawable(new RoundRectShape(outerRadii, inset, innerRadii)); shapeDrawable.setBounds(50, 50, 200, 100); shapeDrawable.getPaint().setcolor(color.BLUE); } @OverrIDe protected voID onDraw(Canvas canvas) { super.onDraw(canvas); //将shape实例画在画布上 shapeDrawable.draw(canvas); }}PathShape
@H_301_8@//path:所要画的路径//stDWIDth:表示标注宽度,即将整个ShapeDrawable的宽度分成多少份,Path中moveto(x, y),lineto(x, y)这些函数中的数值在这里起始都是以每一份的位置来计算的,当ShapeDrawable动态变大、变小时,每一份都会变小,而根据这些分的数值画出来的Path图形就是动态缩放//stdHeight:表示标准高度,即将ShapeDrawable的高度分成多少份public PathShape(Path path, float stDWIDth, float stdHeight)
eg:
@H_301_8@public class ShapeVIEw extends VIEw { private ShapeDrawable shapeDrawable; public ShapeVIEw(Context context) { super(context); init(); } public ShapeVIEw(Context context, AttributeSet attributeSet){ super(context, attributeSet); init(); } public ShapeVIEw(Context context, AttributeSet attributeSet, int defStyle){ super(context, attributeSet, defStyle); init(); } private voID init() { setLayerType(LAYER_TYPE_SOFTWARE,null); Path path = new Path(); //注意这里此时的单位是份 path.moveto(0, 0); path.lineto(100, 0); path.lineto(100, 100); path.lineto(0, 100); path.close(); //首先我们要知道这里的单位是份的概念而不是px,所以为了对比,我们将shapeDrawable和画布大小设为一致 // 开始将shape 100, 100 可以发现它填满了控件如果使用的是px当然是不可能将其填满的, // 将ShapeDrawable的高设置成200,则原来的只能占1/2,所以只能展示为控件的一半 shapeDrawable = new ShapeDrawable(new PathShape(path, 100, 200)); shapeDrawable.setBounds(new Rect(0, 0, 250, 150)); shapeDrawable.getPaint().setcolor(color.BLUE); } @OverrIDe protected voID onDraw(Canvas canvas) { super.onDraw(canvas); //将shape实例画在画布上 shapeDrawable.draw(canvas); }}自定义shape想要自定义shape,必须先看他的各个派生类的源码是如何实现相应的draw()
@H_301_8@public class PathShape extends Shape { private final float mStDWIDth; private final float mStdHeight; private Path mPath; private float mScaleX; // cached from onResize private float mScaleY; // cached from onResize /** * PathShape constructor. * * @param path a Path that defines the geometric paths for this shape * @param stDWIDth the standard wIDth for the shape. Any changes to the * wIDth with resize() will result in a wIDth scaled based * on the new wIDth divIDed by this wIDth. * @param stdHeight the standard height for the shape. Any changes to the * height with resize() will result in a height scaled based * on the new height divIDed by this height. */ public PathShape(@NonNull Path path, float stDWIDth, float stdHeight) { mPath = path; mStDWIDth = stDWIDth; mStdHeight = stdHeight; } @OverrIDe public voID draw(Canvas canvas, Paint paint) { canvas.save(); canvas.scale(mScaleX, mScaleY); canvas.drawPath(mPath, paint); canvas.restore(); } @OverrIDe protected voID onResize(float wIDth, float height) { mScaleX = wIDth / mStDWIDth; mScaleY = height / mStdHeight; } @OverrIDe public PathShape clone() throws CloneNotSupportedException { final PathShape shape = (PathShape) super.clone(); shape.mPath = new Path(mPath); return shape; }}发现这个派生类做的就是在创建PathShape的时候将path传递进去,然后利用draw()函数将其画出来(onResize()函数是根据我们刚才发现的份的关系,进行重新的计算)
@H_301_8@package com.example.adminstator.myvIEwdesign.AndroIDHuabu.ShapeExample;import androID.graphics.Canvas;import androID.graphics.Paint;import androID.graphics.Rect;import androID.graphics.Region;import androID.graphics.RegionIterator;import androID.graphics.drawable.shapes.Shape;/*** Created with AndroID Studio.* Description:** @author: 王拣贤* @date: 2019/06/27* Time: 21:32*/public class OwnShapeVIEw extends Shape { private Region region; public OwnShapeVIEw(Region region){ if(region!=null){ this.region = region; } } @OverrIDe public voID draw(Canvas canvas, Paint paint) { RegionIterator iter = new RegionIterator(region); Rect r = new Rect(); while (iter.next(r)){ canvas.drawRect(r, paint); } }}总结
以上是内存溢出为你收集整理的Android画布(一 )全部内容,希望文章能够帮你解决Android画布(一 )所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)