android自定义控件几种,Android 自定义View一个控件搞定多种水波纹涟漪扩散效果 - CSDN博客...

效果图

20b81a4ecc55b294c6171959e1054504.gif

实现思路

这个效果实现起来并不难,重要的是思路

此View满足了多种水波纹涟漪扩散效果,这要求它能满足很多的变化

根据上面的样式,可以看出此View需要满足以下变化

圆圈从中心可循环向外扩散

圆圈之间的扩散间距可以改变

可控制扩散圆的渐变度

圆圈可以是线条样式或者实心样式

圆圈扩散的速度可以控制

适配圆圈不同大小下的扩散效果

具体实现

创建自定义属性

首先为View创建自定义的xml属性

在工程的values目录下新建attrs.xml文件

各个属性的作用如下

cColor:View控件的颜色

cSpeed:向外扩散的速度

cDensity:圆形波纹扩散的间距

cIsFill:是否开启填充模式,true为实心圆

cIsAlpha:是否开启渐变效果,true为开启

创建自定义View控件

新建RippleView类继承View类,重写它的三个构造方法,获取用户设置的属性,同时指定默认值

public RippleView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

// 获取用户配置属性

TypedArray tya = context.obtainStyledAttributes(attrs, R.styleable.mRippleView);

mColor = tya.getColor(R.styleable.mRippleView_cColor, Color.BLUE);

mSpeed = tya.getInt(R.styleable.mRippleView_cSpeed, 1);

mDensity = tya.getInt(R.styleable.mRippleView_cDensity, 10);

mIsFill = tya.getBoolean(R.styleable.mRippleView_cIsFill, false);

mIsAlpha = tya.getBoolean(R.styleable.mRippleView_cIsAlpha, false);

tya.recycle();

init();

}

使用TypedArray读取完自定义的属性后一定要记得调用recycle方法释放掉

重写onMeasure

测量onMeasure,首先需要测量出View的宽和高,并指定View在wrap_content时的最小范围,对于View绘制流程还不熟悉的同学,可以先去了解下具体的绘制流程

重写onMeasure方法,其中我们要考虑当View的宽高被指定为wrap_content时的情况,如果我们不对wrap_content的情况进行处理,那么当使用者指定View的宽高为wrap_content时将无法正常显示出View

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int myWidthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

int myWidthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

int myHeightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

int myHeightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

// 获取宽

if (myWidthSpecMode == MeasureSpec.EXACTLY) {

// match_parent/精确值

mWidth = myWidthSpecSize;

} else {

// wrap_content

mWidth = DensityUtil.dip2px(mContext, 120);

}

// 获取高

if (myHeightSpecMode == MeasureSpec.EXACTLY) {

// match_parent/精确值

mHeight = myHeightSpecSize;

} else {

// wrap_content

mHeight = DensityUtil.dip2px(mContext, 120);

}

// 设置该view的宽高

setMeasuredDimension(mWidth, mHeight);

}

MeasureSpec的状态分为三种EXACTLY、AT_MOST、UNSPECIFIED,这里只要单独指定非精确值EXACTLY之外的情况就好了

本文中使用到的DensityUtil类,是为了将dp转换为px来使用,以便适配不同的屏幕显示效果

public static int dip2px(Context context, float dpValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

重写onDraw

设计的整体思路如下图所示

20b81a4ecc55b294c6171959e1054504.gif

先要实现圆形向外扩散的效果

初始化第一个圆

这里的动画效果本来是想使用ValueAnimator属性动画的数值发生器来实现,但是我们这里有很多的计算需求,所以最后还是选择使用算法来实现,方便控制圆的一些参数

想要实现扩散的效果,这里思路是在每次更新View时动态改变圆的半径,同时还需要给圆设置渐变度数,所以决定用一个类来保存圆的状态,所有圆都存在一个List里

// 添加第一个圆圈

mRipples = new ArrayList<>();

Circle c = new Circle(0, 255);

mRipples.add(c);

传入Circle类里的两个参数,第一个0表示圆的初始宽度,第二个255表示初始透明度

添加新圆

要想实现不断有圆向外扩散,就需要在第一个圆扩散到一定范围时在圆心处再添加一个圆,这个的范围可以由圆的半径来控制,当List集合中最后一个圆的半径增加到某个值mDensity时,新的圆就从圆心处创建出来

// 添加圆

if (mRipples.size() > 0) {

// 控制第二个圆出来的间距

if (mRipples.get(mRipples.size() - 1).width > DensityUtil.dip2px(mContext, mDensity)) {

mRipples.add(new Circle(0, 255));

}

}

删除List中多余的圆

List中的圆存储的数量不宜过多,多了内存消耗大,需要在当圆的半径超过View的宽度时就删掉这个圆

// 当圆超出View的宽度后删除

if (c.width > mWidth / 2) {

mRipples.remove(i);

}

我们也可以在外切正方形的顶点处删除这个圆,需要用到勾股定律来计算扩散圆到外切正方形顶点的位置

20b81a4ecc55b294c6171959e1054504.gif

如上图所示,得出计算公式为

// 使用勾股定律求得一个外切正方形中心点离顶点的距离

sqrtNumber = (int) (Math.sqrt(mWidth * mWidth + mHeight * mHeight) / 2);

这样就需要修改删除圆的位置了

if (c.width > sprtNumber) {

mRipples.remove(i);

}

控制扩散圆的渐变度

当圆在向View的边缘扩散时,渐变度数的改变需要动态来计算,渐变的计算算法要适配不同的圆宽度大小,我们知道透明度是0~255之间的,0表示完全透明,255表示百分百不透明,计算的时候就是需要将这个数值等份分配到圆的宽度里

这里要区分一点,对于圆来说,宽度是由圆心从0开始向外递增,而渐变度数则是由圆心从255开始向外递减,当圆与最外围的正方形内切时渐变度必须变为0,由此分析得知,公式如下

透明度 = 255 - 圆的宽度 * (255 / View宽度)

double alpha = 255 - c.width * (255 / ((double) mWidth / 2));

c.alpha = (int) alpha;

GitHub地址

总结

关于自定义View的总结部分在我的其它博客中已经写过蛮多了,有兴趣的可以去看看

做自定义View,思路很重要,当想到一种方法可以实现时,先不要着急的做出来,试着换一个角度再多思考一下还有没有更好的实现方式

本例子还缺少一些控制逻辑代码,将在之后添加上去并更新在GitHub中

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

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

相关文章

centos7 hadoop3.0.1安装

安装JDKrpm -qa | grep java找出OPENJDKyum -y remove java 上一步复制的jdk文件名卸载openjdkrpm -ivh jdk文件名安装jdk设置jdk环境变量需要修改配置文件/etc/profile&#xff0c;追加export JAVA_HOME"/usr/java/jdk-10"export PATH$JAVA_HOME/bin:$PATH修改完毕后…

excel函数怎么用android,在Android中阅读Excel

对于那些需要使用全功能excel文件(即绘图,VBA等等)的应用程序,你应该使用Apache POI,它很简单,但现在仍然是最好的解决方案.但是,如果您只需要阅读Excel,那么使用JavaScript解决方案可能会更好.使用js-xlsx库,您可以将Excel文件传输到JSON.库大小很小,只有395KB(仅包括xlsx.cor…

.net core2.0 Memcached.ClientLibrary

Memcached的.net core2.0驱动dll 引用了nuget包log4net和SharpZipLib.NETStandard nuget包名为Memcached.ClientLibrary.NetStandard 可以直接通过nuget搜索安装 地址https://www.nuget.org/packages/Memcached.ClientLibrary.NetStandard/ 源码详见 https://github.com/wa…

python设置格式模板

# -*- coding: utf-8 -*- """ __mktime__ ${DATE} __author__ ${USER} __filename__ ${NAME} """ if __name__ "__main__": pass 转载于:https://www.cnblogs.com/BigFishFly/p/6580692.html

给android应用程序默认的菜单添加一个菜单项关于,android菜单详解

1.菜单的生成对一个Android应用中的每一个屏幕&#xff0c;也就是说&#xff0c;对每一个Activity类&#xff0c;都会拥有一个默认菜单。在Activity类中&#xff0c;定义了几个与菜单有关的方法&#xff0c;供继承于Activity类的子类去重载&#xff0c;从而定制我们自己的菜单。…

Eclipse Memory Analysis分析Java运行内存情况

获取java进程的dump文件jmap -dump:formatb,file<dumpfile.hprof> <pid>安装Eclipse Memory AnalysisHelp 》 Install New Software输入地址&#xff1a;http://archive.eclipse.org/mat/1.0/update-site/安装点击右侧Open Perspective选Memory Analysis插件&#…

C#对用户密码使用MD5加密与解密

C#中常涉及到对用户密码的加密于解密的算法&#xff0c;其中使用MD5加密是最常见的的实现方式。本文总结了通用的算法并结合了自己的一点小经验&#xff0c;分享给大家。 一.使用16位、32位、64位MD5方法对用户名加密 1&#xff09;16位的MD5加密 ?123456789101112/// <sum…

android默认代码混淆,Android SDK默认混淆配置文件

一.介绍通常情况下编译后的字节码包含了大量调试信息(如源类名/行号等)混淆代码就能删除这些调试信息&#xff0c;并用无意义字符替换所有名字&#xff0c;增加反编译难度&#xff01;ProGuard是一个混淆代码的开源项目&#xff0c;主要作用如下&#xff1a;混淆Obfuscate 用无…

前端学习(2334):angular之内置属性指令ngclass

child.html <p>child4 works!</p><div class"us">我是歌谣</div> <div [ngClass]"currentClass" class"col">我是歌谣</div>child.ts import { Component, OnInit } from angular/core;Component({select…

spring cloud consul整合

本文基于spring cloud Finchley.SR1 consul如何搭建可以看文章consul docker方式搭建 本文章源码位置&#xff1a;https://github.com/wanghongqi/springcloudconsul_test/ 目录 服务端 客户端 测试 服务端 pom.xml <properties><project.build.sourceEncodin…

event android,androidEvent 对 android 事件分发机制的一点个人理解,将事件机制进行了简单化处理,刚方便理解! @codeKK Android开源站...

android 中的事件处理一直以来困扰不少刚刚从事 android 开发的同学&#xff0c;网上也有不少讲解 android 事件分发的文章&#xff0c;然而讲解的都不够简洁&#xff01;现在我将用另一种简洁的方式来讲解 android 事件的分发机制&#xff01;android 的事件分发可以简单的归位…

consul docker方式搭建

目录 获取镜像 运行 集群搭建 官网&#xff1a;https://www.consul.io/ 文档&#xff1a;https://www.consul.io/docs/index.html 获取镜像 docker pull consul:1.3.0 运行 如果已存在dev-consul先移除 docker rm -f dev-consul 创建容器&#xff0c;守护进程方式启动&…

锁屏壁纸开发 Android,Android开发自己的锁屏壁纸

SurfaceView SurfaceHolder MediaPlayer Service BroadcastReceiver KeyguardManager PowerManager思路&#xff1a;启动一个服务&#xff0c;监听灭屏广播&#xff0c;当收到广播的时候&#xff0c;点亮屏幕&#xff0c;禁用锁屏&#xff0c;调用使用SurfaceV…

[转载来之雨松:NGUI研究院之为什么打开界面太慢(十三)]

本文固定链接: http://www.xuanyusong.com/archives/2799转载于:https://www.cnblogs.com/yexiaopeng/p/6591482.html

前端学习(2335):angular之内置结构指令ngif

child.html <p>child4 works!</p><div class"us">我是歌谣</div> <div [ngClass]"currentClass" class"col">我是歌谣</div><div *ngIf"true">aaaa</div> <div *ngIf"false…

centos7 postgresql安装

安装 Install the repository RPM: yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-centos11-11-2.noarch.rpm Install the client packages: yum install postgresql11 Optionally install the server packages: yum install …

android密码可见不可见的光标控制,Android EditText 在设置为输入密码的时候 密码是否可见 光标在最后显示...

释放双眼&#xff0c;带上耳机&#xff0c;听听看~&#xff01;今天在开发登录注册模块的时候&#xff0c;用EditText实现密码的输入&#xff0c;项目需要密码是可以选择可见或者默认的隐藏模式&#xff0c;很简单&#xff0c;但是第一次遇到就记录下来分享给大家。布局文件and…

centos6 postgresql安装

安装 Install the repository RPM: yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-6-x86_64/pgdg-centos11-11-2.noarch.rpm Install the client packages: yum install postgresql11 Optionally install the server packages: yum install…

l2-006 树的遍历

L2-006. 树的遍历 时间限制400 ms内存限制65536 kB代码长度限制8000 B判题程序Standard作者陈越给定一棵二叉树的后序遍历和中序遍历&#xff0c;请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。 输入格式&#xff1a; 输入第一行给出一个正整数N&#xff08;&l…