Android自定义视图

news2024/12/23 15:06:34

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,填充整个屏幕
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    <com.example.myblog.FindMe
        android:id="@+id/findMe"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
  1. 在FindMe中设置一个drawableToBitamp方法将图片资源转换为位图对象用于接下来的绘制
private Bitmap drawableToBitamp(Drawable drawable){
    Bitmap bitmap = null;
    //图片位深,PixelFormat.OPAQUE代表没有透明度,RGB_565就是没有透明度的位深,否则就用ARGB_8888
    Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
    //创建一个空的Bitmap,大小为100X100
    bitmap = 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

@Override
  protected 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);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
      centerX = event.getX();
      centerY = event.getY();
      invalidate();
      return super.onTouchEvent(event);
  }

在这里插入图片描述
SurfaceView

@Override
  public 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/59427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《CTFshow - Web入门》04. Web 31~40

Web 31~40web31知识点题解web32知识点题解web33知识点题解web34知识点题解web35知识点题解web36知识点题解web37知识点题解web38知识点题解web39知识点题解web40知识点题解web31 知识点 这里依旧可以用到 web29 的方法&#xff1a; 嵌套eval逃逸参数 当然&#xff0c;能多学…

# 智慧社区管理系统-基础信息管理-06抄表管理

一后端 1:entity package com.woniu.community.entity;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;Data AllArgsConstructor NoArgsConstructor public class Records {private int id;private int typeId;private Double num…

博安生物更新招股书:上半年亏1.5亿 绿叶制药与建银聚源是股东

雷递网 雷建平 12月3日山东博安生物技术股份有限公司&#xff08;简称&#xff1a;“博安生物”&#xff09;日前再次递交招股书&#xff0c;并更新招股书&#xff0c;准备在香港上市。上半年期内亏损1.53亿元博安生物是绿叶制药集团的附属公司&#xff0c;于2013年成立&#x…

远程桌面树莓派【内网穿透】

本篇文章主要分享如何在公网环境下&#xff0c;远程桌面连接家里的树莓派。 远程桌面环境&#xff0c;我们选择通过XRDP来实现&#xff0c;它内部使用的是windows远程桌面的协议。 而由于现在普遍处于大内网环境&#xff0c;绝大部分人都没有公网IP&#xff0c;所以我们这里用…

(9)点云数据处理学习——Global registration(全局注册)

1、主要参考 &#xff08;1&#xff09;官网的地址 Global registration — Open3D 0.16.0 documentation 2、作用和原理 2.1个人理解 PS理解&#xff1a;&#xff08;1&#xff09;ICP的作用是&#xff0c;2个点云数据在初步转换关系&#xff08;已知不精确&#xff09;的…

【关系抽取】TPLinker:单阶段联合抽取,并解决暴漏偏差

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

车载GNSS/INS/LiDAR坐标系定义与理解

目录一、基本坐标系1.1 地心惯性坐标系&#xff08;Inertial coordinate system&#xff0c;i系&#xff09;1.2 地心地固坐标系&#xff08;Earth-Centered, Earth-Fixed&#xff0c;e系&#xff09;1.3 导航坐标系&#xff08;Navigation&#xff0c;n系&#xff09;1.4 车体…

[附源码]计算机毕业设计springboot疫苗药品批量扫码识别追溯系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

一、领域驱动设计核心思想与设计过程

一、软件发展的必然规律 1、软件是对真是世界的模拟&#xff0c;但真实世界软件十分复杂。 2、人在认识真实世界的时候总是有一个从简单到复杂的过程 3、软件需求的变更成为一种必然的事情&#xff0c;并且总是由简单向复杂转变 4、初期软件的业务逻辑十分简单清晰命令&#x…

C语言画直方图

前言 最近在看K&R的《C语言程序设计语言》这本书&#xff0c;第一单元的练习13要求画一个统计单词长度的直方图&#xff0c;这里忽略了计算单词长度的代码&#xff0c;假设已知单词长度存入一个digit数组中&#xff0c;根据这个数组画水平直方图和垂直直方图。实话说&…

C++11新特性-原始字面量

当我们书写文件路径的时候&#xff0c;会发现&#xff0c;文件路径无法正确输出&#xff0c;如下&#xff1a; 这是因为反斜杠本身就是转义的意思&#xff0c;如果想要输出反斜杠则需要两个反斜杠&#xff0c;如下&#xff1a; 当然这只是其中一种解决方法&#xff0c;还有一种…

实战项目如何抵御即跨站脚本(XSS)攻击

一、XSS攻击的危害 XSS攻击通常指的是通过利用网页开发时留下的漏洞&#xff0c;通过巧妙的方法注入恶意指令代码到网页&#xff0c;使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、VBScript、ActiveX、Flash或者甚至是…

思派健康通过上市聆讯:F轮估值17亿美元 腾讯是大股东

雷递网 雷建平 12月3日思派健康科技日前通过聆讯&#xff0c;准备在香港上市。思派健康早在2021年8月就已经递交招股书&#xff0c;这是时隔一年多后&#xff0c;这之前第三次递交招股书。这也意味着&#xff0c;时隔一年多后&#xff0c;思派健康终于要上市了。上半年亏损3.5亿…

SpringSecurity(八)【会话管理】

八、会话管理 简介 当浏览器调用登录接口登录成功之后&#xff0c;服务端会和浏览器之间创建一个会话&#xff08;Session&#xff09;&#xff0c;浏览器在每次发送请求时都会携带一个 SessionId&#xff0c;服务端则根据这个 SessionId 来判断用户身份。当浏览器关闭之后&…

从硬件角度看服务器性能调优

bios整体配置bios系统设置Hyper Thread开启超线程&#xff0c;设置后lscpu命令Thread(s) per core 值显示为 2。超线程可以理解为CPU的虚拟化&#xff0c;一颗物理CPU并行执行两条流水线指令。确认处理器基本频率及睿频频率&#xff0c;部分处理器基础频率低&#xff0c;但是睿…

看完了你还能不懂JAVA内存模型(JMM),我输了

前言 开篇一个例子&#xff0c;我看看都有谁会&#xff1f;如果不会的&#xff0c;或者不知道原理的&#xff0c;还是老老实实看完这篇文章吧。 Slf4j(topic "c.VolatileTest") public class VolatileTest { static boolean run true; public static void main(S…

基于Java+Swing实现《扫雷》游戏

基于JavaSwing实现《扫雷》游戏一、系统介绍二、功能展示三、其他系统一、系统介绍 windows自带的游戏《扫雷》是陪伴了无数人的经典游戏&#xff0c;本程序参考《扫雷》的规则进行了简化&#xff0c;用java语言实现&#xff0c;采用了swing技术进行了界面化处理&#xff0c;设…

基于蚁群算法求解运钞车路径规划问题(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

[附源码]JAVA毕业设计桔子酒店客房管理系统(系统+LW)

[附源码]JAVA毕业设计桔子酒店客房管理系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

vue app开发调用原生方法实现权限访问授权处理(一)

vue app开发调用原生方法实现权限访问授权处理 前提&#xff1a;在写代码之前应该想清楚调用原生安卓、ios的方法&#xff0c;就应该遵循双端的方法规则&#xff0c;调用方法时应该注意&#xff0c;在这里先主要介绍一下注意事项&#xff1a; 根据App发布应用市场的要求&…