Android自定义控件之onDraw详解

    前面两篇我们以Linealayout为入口分析了自定义控件的onMeasure方法和onLayout方法,本篇我们分析自定义控件比较重要的一个方法onDraw,该方法与之前的两个方法调用过程有所区别,并不是由ViewGroup来调用View的方法,而是相对独立的,这里我们需要先分析View的onDraw,再分析Linealayout的方法。

 一.Draw详解

    View 的onDraw方法是通过draw方法调用,这里我们从draw方法开始分析:
   这里小字部分解释了draw方法绘制整个界面的过程具体如下:
        1. Draw the background(绘制背景)
        2. If necessary, save the canvas’ layers to prepare for fading(如果需要,为保存这层为边缘的滑动效果作准备)
        3. Draw view’s content(绘制内容) 
        4. Draw children(绘制子View) 
        5. If necessary, draw the fading edges and restore layers(如果需要,绘制边缘效果并且保存图层)
        6. Draw decorations (scrollbars for instance)(绘制边框,比如scrollbars,TextView)

继续看后续实现:

1.绘制背景

    如果需要背景就绘制背景,背景实际就是一个Drawable,设置时先设置边界,再调用draw方法完成绘制。

2.跳过第二步和第五步

    由于第二步和第五步是绘制View滑到边缘时的效果等等的边缘特效,一般用不到。

3.绘制内容

     绘制View的内容,这里就调用了onDraw方法,也就是说onDraw方法是实现View的具体显示内容的,因此我们在自定义View 的时候只重写onDraw,在View部分没有给出具体实现,需要按照自己需求做重写。

4.绘制子View

这个方法实际上不是为View准备的而是给viewGroup准备的,由于ViewGroup是继承自View,后续我们再做分析。

5.绘制前景

    这里绘制的主要是滑动条,也就说实际上说有的View都是有滑动条的,只是显示与隐藏的区别。

6.绘制默认焦点高亮

    

二.扩展

    这里重点分析一下onDraw和dispatchDraw这两个方法的区别:

1.onDraw()

    该方法用于绘制自身内容,之前也说过调用时在绘制完背景以后调用。

2.dispatchDraw()

    该方法用于绘制子View,需要注意的是当ViewGroup没有背景时,不会调用draw方法,会直接调用dispatchDraw,但是在draw方法中会调用dispatchDraw,也就是说我们在自定义ViewGroup时应该重写dispatchDraw方法。

3.Canvas

    控件的所有绘制工作最终都会交由canvas来处理,Canvas被draw调用,当draw的时候需要4个基本的元素:

    1、a Bitmap to hold the pixels (一个bitmap来存放所有的像素)
    2、a Canvas to host the draw calls (writing into the bitmap)(canvas来主持draw的调用,将像素写入bitmap)
    3、a drawing primitive (e.g. Rect, Path, text, Bitmap), (绘制的具体内容,可以文本,图片,形状之类)
    4、a paint (to describe the colors and styles for the drawing).(一只‘笔’,用来定义颜色,和绘制的类型)
    在实际的使用中我们主要是paint和Canvas配合使用,这里需要提一下很多新手会在onDraw方法中去新建paint,这里需要注意onDraw方法会重复调用,如果在此处新建paint的话就形成了重复造轮子的尴尬,最好的方法是在构造方法来初始化。

发布了4 篇原创文章 · 获赞 2 · 访问量 2819
展开阅读全文

请问我如何把edittext的文字通过onDraw放在画板上

05-04

我想做一个画板,现在想实现插入文字功能,目前点击屏幕时能弹出popupwindow,然后可以编辑EditText,请问如果在点击其他地方的时候让文字留在画板上 这是showTextPopup方法部分 ``` public void showTextPopup(float preX,float preY){ int x = (int) preX; int y = (int) preY; dp = new DrawPath(); dp.mOffX = preX; dp.mOffY = preY; dp.paint = mpaint; EditText mEditText = new EditText(getContext()); mEditText.setText("输入文字"); PopupWindow mTextPopup = new PopupWindow(mEditText, WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,true); mEditText.setFocusable(true); mEditText.setFocusableInTouchMode(true); //让popup显示在软键盘上面 mTextPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); mEditText.requestFocus(); mTextPopup.setOutsideTouchable(true); mTextPopup.setBackgroundDrawable(new BitmapDrawable()); //自动弹出软键盘,会导致布局变化,重测量、绘制 InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Service.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0,InputMethodManager.HIDE_NOT_ALWAYS); mTextPopup.showAtLocation(this, Gravity.TOP | Gravity.LEFT, x, y); invalidate(); } ``` 这是DrawPath类 ``` static class DrawPath{ public Path path;//路径 public Paint paint;//画笔 public Editable mText;//文本 //public int mWidth;//宽度 public float mOffX;//X轴偏移 public float mOffY;//Y轴偏移 } ``` 点击事件 ``` public boolean onTouchEvent(MotionEvent event){ //获取拖动事件的发生位置 float x = event.getX(); float y = event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: //从前一个点绘制到当前点之后,把当前点定义成下次绘制的一个点 if(currentStyle==3){ showTextPopup(x,y); } mpath = new Path(); //每一次记录的路径对象是不一样的 dp = new DrawPath(); dp.path = mpath; dp.paint = mpaint; mpath.moveTo(x,y); preX = x; preY = y; invalidate(); break; case MotionEvent.ACTION_MOVE: mpath.quadTo(preX,preY,x,y); preX = x; preY = y; break; case MotionEvent.ACTION_UP: mpath.lineTo(preX,preY); cachecanvas.drawPath(mpath,mpaint); //将一条完整的路径保存下来 savePath.add(dp); mpath = null;//重新置空 break; } invalidate(); //返回true表明处理方法已经处理该事件 return true; } ``` onDraw方法 ``` public void onDraw(Canvas canvas){ //Paint bmpPaint = new Paint(); //将cacheBitmap绘制到该View组件上 canvas.drawBitmap(cacheBitmap,0,0,mBitmapPaint);//显示旧的画布 //沿着path绘制 if(mpath != null) { canvas.drawPath(mpath, mpaint); } } ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览