Android画布(一 )

Android画布(一 ),第1张

概述获取画布的方法*onDraw()*diapatchDraw()*通过Bitmap创建*通过SurfaceView的SurfaceHolder.lockCanvas()Drawable类可以通过创建dawable对象,然后将画好的drawable对象画在画布上,也是创建Bitmap的一种方式ShapeDrawableshape标签与GradientDrawable首先shap 获取画布的方法
@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
RectShape
@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画布(一 )所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1119506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存