ondrawjava的简单介绍

博主:adminadmin 2022-12-16 07:06:09 80

本篇文章给大家谈谈ondrawjava,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

Android 自定义View之Draw过程(上)

Draw 过程系列文章

Android 展示之三部曲:

前边我们已经分析了:

这俩最主要的任务是: 确定View/ViewGroup可绘制的矩形区域。

接下来将会分析,如何在这给定的区域内绘制想要的图形。

通过本篇文章,你将了解到:

Android 提供了关于View最基础的两个类:

然而ViewGroup 并没有约定其内部的子View是如何布局的,是叠加在一起呢?还是横向摆放、纵向摆放等。同样的View 也没有约定其展示的内容是啥样,是矩形、圆形、三角形、一张图片、一段文字抑或是不规则的形状?这些都要我们自己去实现吗?

不尽然,值得高兴的是Android已经考虑到上述需求了,为了开发方便已经预制了一些常用的ViewGroup、View。

如:

继承自ViewGroup的子类

继承自View的子类

虽然以上衍生的View/ViewGroup子类已经大大为我们提供了便利,但也仅仅是通用场景下的通用控件,我们想实现一些较为复杂的效果,比如波浪形状进度条、会发光的球体等,这些系统控件就无能为力了,也没必要去预制千奇百怪的控件。想要达到此效果,我们需要自定义View/ViewGroup。

通常来说自定义View/ViewGroup有以下几种:

3 一般不怎么用,除非布局比较特殊。1、2、4 是我们常用的手段,对于我们常说的"自定义View" 一般指的是 4。

接下来我们来看看 4是怎么实现的。

在xml里引用MyView

效果如下:

黑色部分为其父布局背景。

红色矩形+黄色圆形即是MyView绘制的内容。

以上是最简单的自定义View的实现,我们提取重点归纳如下:

由上述Demo可知,我们只需要在重写的onDraw(xx)方法里绘制想要的图形即可。

来看看View 默认的onDraw(xx)方法:

发现是个空实现,因此继承自View的类必须重写onDraw(xx)方法才能实现绘制。该方法传入参数为:Canvas类型。

Canvas翻译过来一般叫做画布,在重写的onDraw(xx)里拿到Canvas对象后,有了画布我们还需要一支笔,这只笔即为Paint,翻译过来一般称作画笔。两者结合,就可以愉快的作画(绘制)了。

你可能发现了,在Demo里调用

并没有传入Paint啊,是不是Paint不是必须的?实际上调用该方法后,底层会自动生成Paint对象。

可以看到,底层初始化了Paint,并且给其设置的颜色为在Java层设置的颜色。

onDraw(xx)比较简单,开局一个Canvas,效果全靠画。

试想,这个Canvas怎么来的呢,换句话说是谁调用了onDraw(xx)。发挥一下联想功能,在Measure、Layout 过程有提到过两者套路很像:

那么Draw过程是否也是如此套路呢?看见了onDraw(xx),那么draw(xx)还远吗?

没错,还真有draw(xx)方法:

可以看出,draw(xx)主要分为两个部分:

不管是A分支还是B分支,都进行了好几步的绘制。

通常来说,单一一个View的层次分为:

后面绘制的可能会遮挡前边绘制的。

对于一个ViewGroup来说,层次分为:

来看看A分支标注的4个点:

(1)

onDraw(canvas)

前面分析过,对于单一的View,onDraw(xx)是空实现,需要由我们自定义绘制。

而对于ViewGroup,也并没有具体实现,如果在自定义ViewGroup里重写onDraw(xx),它会执行吗?默认是不会执行的,相关分析请移步:

Android ViewGroup onDraw为什么没调用

(2)

dispatchDraw(canvas),来看看在View.java里的实现:

发现是个空实现,再看看ViewGroup.java里的实现:

也即是说,对于单一View,因为没有子布局,因此没必要再分发Draw,而对于ViewGroup来说,需要触发其子布局发起Draw过程(此过程后续分析),可以类比事件分发过程View、ViewGroup的处理。感兴趣的请移步:

Android 输入事件一撸到底之View接盘侠(3)

(3)

OverLay,顾名思义就是"盖在某个东西上面",此处是在绘制内容之后,绘制前景之前。怎么用呢?

以上是给一个ViewGroup设置overLay,效果如下:

你可能发现了,这和设置overLay差不多的嘛,实际还是有差别的。在onDrawForeground(xx)里会重新调整Drawable的尺寸,该尺寸与View大小一致,之前给Drawable设置的尺寸会失效。运行效果如下:

可以看出,ViewGroup都被前景盖住了。

再来看看B分支的重点:边缘渐变效果

先来看看TextView 边缘渐变效果:

加上这俩参数。

实际上系统自带的一些控件也使用了该效果,如NumberPicker、YearPickerView

以上是NumberPicker 的效果,可以看出是垂直方向渐变的。

对于View.java 里的onDraw(xx)、draw(xx),ViewGroup.java里并没有重写。

而对于dispatchDraw(xx),在View.java里是空实现。在ViewGroup.java里发起对子布局的绘制。

来看看标记的2点:

(1)

设置padding的目的是为了让子布局留出一定的空隙出来,因此当设置了padding后,子布局的canvas需要根据padding进行裁减。判断标记为:

FLAG_CLIP_TO_PADDING 默认设置为true

FLAG_PADDING_NOT_NULL 只要有padding不为0,该标记就会打上。

也就是说:只要设置了padding 不为0,子布局显示区域需要裁减。

能不能不让子布局裁减显示区域呢?

答案是可以的。

考虑到一种场景:使用RecyclerView的时候,我们需要设置paddingTop = 20px,效果是:RecyclerView Item展示时离顶部有20px,但是滚动的时候永远滚不到顶部,看起来不是那么友好。这就是上述的裁减起作用了,需要将此动作禁止。通过设置:

当然也可以在xml里设置:

(2)

drawChild(xx)

从方法名上看是调用子布局进行绘制。

child.draw(x1,x2,x3)里分两种情况:

这两者具体作用与区别会在下篇文章分析,不管是硬件加速绘制还是软件加速绘制,最终都会调用View.draw(xx)方法,该方法上面已经分析过。

注意,draw(x1,x2,x3)与draw(xx)并不一样,不要搞混了。

用图表示:

View/ViewGroup Draw过程的联系:

一般来说,我们通常会自定义View,并且重写其onDraw(xx)方法,有没有绘制内容的ViewGroup需求呢?

是有的,举个例子,大家可以去看看RecyclerView ItemDecoration 的绘制,其中运用到了ViewGroup draw(xx)、ViewGroup onDraw(xx) 、View onDraw(xx)绘制的先后顺序来实现分割线,分组头部悬停等功能的。

本篇文章基于 Android 10.0

android自定义view onDraw报空指针错误但是可以运行程序

看报错是在java文件的第37行,如果运行正常没问题,在你java文件的第37行代码放在一个if判断中试试

if(isInEditMode()) {

//你的第37行代码,或对自定义view进行绘制的整个代码

}

Android自定义控件复写onDraw(Canvas canvas),canvas是怎样获取的?

看源码View.java

上图,draw方法会调用onDraw。

ViewRootImpl.java中

如果是软件绘制的话,drawSoftWare方法会调用view.draw()方法。

从上图中可以看到canvas来源于mSurface.lockCanvas。这里会调用到native层,简单点说就是去申请了一块buffer。这个时候canvas就可以用了,接下来就会调用view.draw方法。

具体点的过程自己可以去看看。

java如何在已有的背景图片上贴上其他图片

你的背景图片可以在一个jpanel上,图片在jpane之上的jpane容器.别使用setcontentpane方法,使用.

public class WelcomePanel extends JPanel {

private ImageIcon welcomImageIcon = null;

public WelcomePanel(){

URL url = this.getClass().getResource("/images/welcome.jpg");

this.welcomImageIcon = new ImageIcon(url);

}

public void paintComponent(Graphics g) {

g.drawImage(this.welcomImageIcon.getImage(), 0, 0, this.getWidth(), this.getHeight(), this);

}

}

JAVA drawLine()方法怎么用?

这个方法是画一条直线,都知道两点确定一条直线,而在坐标中由横(X)、纵坐标(y)确定一个点,这四参数实际就是确定两个点,要画的直线的起始点横纵坐标和终点的横纵坐标。

X1,Y1是确定直线的起始点,即横坐标为x1,纵坐标为y1的点。同理x2,y2确定直线的终点。

例:

A(x1,y1) B(x2,y2) 就可以画出直线AB了。

参数:

x1 - 第一个点的 x 坐标。

y1 - 第一个点的 y 坐标。

x2 - 第二个点的 x 坐标。

y2 - 第二个点的 y 坐标。

扩展资料:

注意事项

该方法只能绘制单条直线;如果需要同时绘制多条直线,则可以使用drawLines方法。

基本语法:public void drawLine (float startX, float startY, float stopX, float stopY, Paint paint)

protected void onDraw(Canvas canvas) {

// TODO Auto-generated method stub

super.onDraw(canvas);

paint.setColor(Color.BLACK);                    //设置画笔颜色

canvas.drawColor(Color.WHITE);                  //设置背景颜色

paint.setStrokeWidth((float) 1.0);              //设置线宽

canvas.drawLine(50, 50, 450, 50, paint);        //绘制直线

paint.setStrokeWidth((float) 5.0);              //设置线宽

canvas.drawLine(50, 150, 450, 150, paint);      //绘制直线

paint.setStrokeWidth((float) 10.0);             //设置线宽

canvas.drawLine(50, 250, 450, 250, paint);      //绘制直线

paint.setStrokeWidth((float) 15.0);             //设置线宽

canvas.drawLine(50, 350, 450, 350, paint);      //绘制直线

paint.setStrokeWidth((float) 20.0);             //设置线宽

canvas.drawLine(50, 450, 450, 450, paint);      //绘制直线

}

安卓编程语言开发 canvas 关于ondraw绘制问题

自定义View的实现方式大概可以分为三种,自绘控件、组合控件、以及继承控件。本文将介绍自绘控件的用法。自绘控件的意思是,这个控件上的内容是用onDraw函数绘制出来的。关于onDraw函数的介绍可参看 Android视图绘制流程完全解析,带你一步步深入了解View(二) 。

例子1:在layout文件中使用自绘控件

出处:

下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次。新建一个CounterView继承自View,代码如下所示:

[java] view plaincopy

public class CounterView extends View implements OnClickListener {

private Paint mPaint;

private Rect mBounds;

private int mCount;

public CounterView(Context context, AttributeSet attrs) {

super(context, attrs);

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mBounds = new Rect();

setOnClickListener(this);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

mPaint.setColor(Color.BLUE);

canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);

mPaint.setColor(Color.YELLOW);

mPaint.setTextSize(30);

String text = String.valueOf(mCount);

mPaint.getTextBounds(text, 0, text.length(), mBounds);

float textWidth = mBounds.width();

float textHeight = mBounds.height();

canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2

+ textHeight / 2, mPaint);

}

@Override

public void onClick(View v) {

mCount++;

invalidate();

}

}

可以看到,首先我们在CounterView的构造函数中初始化了一些数据,并给这个View的本身注册了点击事件,这样当CounterView被点击的时候,onClick()方法就会得到调用。而onClick()方法中的逻辑就更加简单了,只是对mCount这个计数器加1,然后调用invalidate()方法。通过 Android视图状态及重绘流程分析,带你一步步深入了解View(三) 这篇文章的学习我们都已经知道,调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用。

在布局文件中加入如下代码:

[html] view plaincopy

RelativeLayout xmlns:android=""

android:layout_width="match_parent"

android:layout_height="match_parent"

com.example.customview.CounterView

android:layout_width="100dp"

android:layout_height="100dp"

android:layout_centerInParent="true" /

/RelativeLayout

可以看到,这里我们将CounterView放入了一个RelativeLayout中。注意,自定义的View在使用的时候一定要写出完整的包名,不然系统将无法找到这个View。

例子2:通过实例化对象的方式使用自定义控件

出处:

Android绘图操作,通过继承View实现,在onDraw函数中实现绘图。

下面是一个简单的例子:

[java] view plaincopy

public class AndroidTest extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

MyView mv = new MyView(this);

setContentView(mv);

}

public class MyView extends View {

MyView(Context context) {

super(context);

}

@Override

protected void onDraw(Canvas canvas) {

// TODO Auto-generated method stub

super.onDraw(canvas);

// 首先定义一个paint

Paint paint = new Paint();

// 绘制矩形区域-实心矩形

// 设置颜色

paint.setColor(Color.BLUE);

// 设置样式-填充

paint.setStyle(Style.FILL);

// 绘制一个矩形

canvas.drawRect(new Rect(0, 0, getWidth(), getHeight()), paint);

// 绘空心矩形

// 设置颜色

paint.setColor(Color.RED);

// 设置样式-空心矩形

paint.setStyle(Style.STROKE);

// 绘制一个矩形

canvas.drawRect(new Rect(10, 10, 100, 30), paint);

// 绘文字

// 设置颜色

paint.setColor(Color.GREEN);

// 绘文字

canvas.drawText("Hello", 10, 50, paint);

// 绘图

// 从资源文件中生成位图

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);

// 绘图

canvas.drawBitmap(bitmap, 10, 60, paint);

}

}

ondrawjava的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、ondrawjava的信息别忘了在本站进行查找喔。

The End

发布于:2022-12-16,除非注明,否则均为首码项目网原创文章,转载请注明出处。