Android自定义视图
创始人
2024-03-16 09:44:55
0

View

自定义视图主要涉及四个方面:绘图交互性能封装

绘图

主要涉及两个对象:画布(Canvas)画笔(Paint),画布主要解决画什么的问题,在画布上可以绘制各种各样的图形,可以通过移动、放大、缩小等来实现不同的效果;画笔主要解决如何画、怎么画的问题,通过控制画笔的大小,线条的粗细,路径上所要实现的特殊效果(填充、文字大小、字体等)

交互

涉及触摸(TouchEvent)和动画(Animation),设计触摸或手势动作过程中引发的动画效果,如过渡、渐变等

性能

绘图的onDraw()方法工作在主线程上,要考虑主线程安全问题,遇到复杂的绘制内容可能会导致用户界面卡顿,此时可以考虑使用SurfaceView开辟出另一个绘画的表面,使用副线程绘图

封装

一方面可以将一些属性(Attributes)封装起来,在自定义视图时就可以通过这些属性去设置视图的一些特性;另一方面考虑到视图的通用性,需要计算它们的尺寸(Measure),如果是在特定的场合使用,可以不考虑尺寸问题,但如果是泛用性广的视图,类似于控件,就需要考虑尺寸问题

帧速率

在这里插入图片描述
需要在16ms内绘制完所有内容,否则会掉帧

生命周期

在这里插入图片描述
measure():测量自身尺寸

layout():将要放置的位置

因为有60帧的限制,只能通过dispatchToDraw()调度告诉系统将要在下一个帧来临时绘制图形

通过invalidate()通知系统在下一帧来临时刷新视图

FindMe(路径与遮罩)

找到隐藏在阴影下的脸,实现效果如下:

在这里插入图片描述

  1. 创建一个FindMe类继承于View,在R.layout.activity_main.xml中拖入一个view,类型改为FindMe,填充整个屏幕


  1. 在FindMe中设置一个drawableToBitamp方法将图片资源转换为位图对象用于接下来的绘制
private Bitmap drawableToBitamp(Drawable drawable){Bitmap bitmap = null;//图片位深,PixelFormat.OPAQUE代表没有透明度,RGB_565就是没有透明度的位深,否则就用ARGB_8888Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;//创建一个空的Bitmap,大小为100X100bitmap = Bitmap.createBitmap(100,100,config);//在bitmap上创建一个画布Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, 100, 100);drawable.draw(canvas);return bitmap;
}
  1. 定义变量faceX和faceY用来记录图片的位置,写一个randomPosition函数来记录图片的随机位置
private void randomPosition(){Random random = new Random();//图片尺寸为100X100,设置-100来使图片不离开屏幕范围内faceX = random.nextInt(getWidth()-100);faceY = random.nextInt(getHeight()-100);
}
  1. 在onDraw方法中将图片画在屏幕上
@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制的目标为图片,画笔可以为空canvas.drawBitmap(drawableToBitamp(getResources().getDrawable(R.drawable.ic_baseline_face_24)), faceX, faceY, null);Paint paint = new Paint();//绘制鼠标移动路径canvas.drawPath(path, paint);
}
  1. 处理鼠标事件,ACTION_DOWN鼠标按下,ACTION_MOVE鼠标移动,ACTION_UP鼠标松开
@Override
public boolean onTouchEvent(MotionEvent event) {if(event.getAction() == MotionEvent.ACTION_DOWN){//鼠标按下时,生成一个随机位置赋给图片randomPosition();//每次改变时,需要重置路径path.reset();path.addRect(0, 0, getWidth(), getHeight(), Path.Direction.CW);path.addCircle(event.getX(), event.getY(), 100, Path.Direction.CCW);//每次处理完事件后需刷新视图invalidate();}else if(event.getAction() == MotionEvent.ACTION_MOVE){path.reset();//鼠标移动时,创建一个跟随路径,用一个黑色矩形填满屏幕,中间挖出一个圆形孔path.addRect(0, 0, getWidth(), getHeight(), Path.Direction.CW);//鼠标位置作为圆心path.addCircle(event.getX(), event.getY(), 100, Path.Direction.CCW);invalidate();}else if(event.getAction() == MotionEvent.ACTION_UP){path.reset();invalidate();}performClick();return true;
}@Override
public boolean performClick() {return super.performClick();
}

SurfaceView

View上进行绘图,View和用户界面共用一个绘图的表面,因此不能绘制太过复杂的东西,否则会拖慢用户界面,造成用户界面卡顿,影响用户体验

SurfaceView在另外一个独立的表面上进行绘制,和用户界面无关,可以高效刷新界面,常用于游戏开发中

例如,绘制一个两万个圈的同心圆,用View绘制可以通过ProgressBar明显监测到卡顿,而SurfaceView十分流畅

View

@Overrideprotected void onDraw(Canvas canvas) {Random random = new Random();canvas.drawColor(Color.BLACK);int x = 0;while (x < 20000) {Paint paint = new Paint();paint.setStyle(Paint.Style.STROKE);paint.setColor(colors[random.nextInt(4)]);canvas.drawCircle(centerX, centerY, x, paint);x++;}super.onDraw(canvas);}@Overridepublic boolean onTouchEvent(MotionEvent event) {centerX = event.getX();centerY = event.getY();invalidate();return super.onTouchEvent(event);}

在这里插入图片描述
SurfaceView

@Overridepublic boolean onTouchEvent(MotionEvent event) {centerX = event.getX();centerY = event.getY();Random random = new Random();Canvas canvas = getHolder().lockCanvas();canvas.drawColor(Color.BLACK);int x = 0;while (x<20000){Paint paint = new Paint();paint.setStyle(Paint.Style.STROKE);paint.setColor(colors[random.nextInt(4)]);canvas.drawCircle(centerX,centerY,x, paint);x++;}getHolder().unlockCanvasAndPost(canvas);return super.onTouchEvent(event);}

在这里插入图片描述

作者:许宝文

原文链接 https://blog.csdn.net/weixin_61586825/article/details/128166946

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...