700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android冒险之旅-22-自定义View--涟漪效果|波浪效果

Android冒险之旅-22-自定义View--涟漪效果|波浪效果

时间:2023-04-05 13:23:31

相关推荐

Android冒险之旅-22-自定义View--涟漪效果|波浪效果

RippleView效果图

希望是你们心心念念的有涟漪、波浪效果的自定义View

说明

RippleView系列- ->RippleView、 RippleView2、RippleView3

RippleView基础功能:

中心圆控制开启 / 关闭 / 修改颜色涟漪控制 开启 / 关闭 / 修改颜色初始半径控制 涟漪初始大小与中心圆大小一致涟漪扩散速度控制 实际上就是一个涟漪从出现到消亡的时间 越小扩散越快涟漪扩散间距控制就是指涟漪两两之间的间距绘制次数控制 就是一个涟漪从出现到消亡被绘制的次数 相当于动画总帧数

代码

人狠话不多 注释超级详细

不要被长度吓到 开放性很高 所有属性基本都可以修改 因此GetSet方法很多

/*** create by 星航指挥官* create on /12/13* 不过是大梦一场空* 课不过是孤影照惊鸿*/public class RippleView extends View {//中心点坐标private float x = 0;private float y = 0;//是否需要中心圆 默认需要private boolean centry = true;//是否开启涟漪private boolean startRipple = true;//中心圆颜色private int centryColor = 0;//涟漪颜色private int rippleColor = 0;//中心圆半径,同时也是涟漪扩散初始半径的默认值private float minR = 25;//涟漪扩散最大半径默认值private float maxR = 100;//涟漪扩散一圈的时间默认值private float speed = 2;//涟漪扩散间距默认值private float spacing = 75;//绘制次数private float drawCount = 400;//涟漪集合private ArrayList<Ripple> ripples;/** 构造器* */public RippleView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);//初始化数组ripples = new ArrayList<>();//获取用户自定义属性TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RippleView);//获取用户是否需要中心圆centry = ta.getBoolean(R.styleable.RippleView_centry, centry);//是否开启涟漪startRipple = ta.getBoolean(R.styleable.RippleView_startRipple, startRipple);//获取用户定义的涟漪最小半径minR = ta.getDimension(R.styleable.RippleView_minR, minR);//获取用户定义的涟漪扩散一圈时间speed = ta.getFloat(R.styleable.RippleView_speed, speed);//获取用户定义的绘制次数drawCount = ta.getFloat(R.styleable.RippleView_drawCount, drawCount);//获取用户定义的涟漪扩散间隔spacing = ta.getDimension(R.styleable.RippleView_spacing, spacing);//中心圆颜色centryColor = ta.getColor(R.styleable.RippleView_centryColor, Color.parseColor("#FFA6A8"));//涟漪颜色rippleColor = ta.getColor(R.styleable.RippleView_rippleColor, Color.parseColor("#FFA6A8"));//资源回收ta.recycle();}//封装涟漪类static class Ripple {//涟漪半径private float r = 0;//涟漪画笔private Paint paint;//透明度private float alpha;}/** 测量* */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//获取控件宽高的一半,即确定中心点x = MeasureSpec.getSize(widthMeasureSpec) / 2;y = MeasureSpec.getSize(heightMeasureSpec) / 2;//将宽高中的较小值作为涟漪最大半径maxR = x > y ? y : x;}/** 绘制* */@Overrideprotected void onDraw(Canvas canvas) {//调用父View的onDraw函数,因为View这个类帮我们实现了一些//基本的绘制功能,比如绘制背景颜色、背景图片等super.onDraw(canvas);//-------------中心圆---------------//判断用户是否需要中心圆 默认不需要if (centry) {Paint paint = new Paint();//画笔颜色paint.setColor(centryColor);//画笔样式 填充满paint.setStyle(Paint.Style.FILL);//画笔 抗锯齿paint.setAntiAlias(true);//绘制中心圆canvas.drawCircle(x, y, minR, paint);}//-------------涟 漪---------------//如果涟漪集合中一个涟漪都没有if (ripples.size() == 0 && startRipple) {//创建涟漪addRipple();}if(ripples.size() != 0) {//先判空 避免涟漪被清除时空指针异常//遍历涟漪集合for (int i = 0; i < ripples.size(); i++) {//获取第i个涟漪对象Ripple ripple = ripples.get(i);//绘制涟漪canvas.drawCircle(x, y, ripple.r, ripple.paint);}//speed为一个涟漪扩散一圈的时间//由于一个涟漪遍历drawCount次//那么handler的延时就应该为 speed*1000/drawCounthandler.sendEmptyMessageDelayed(0, (long) (speed * 1000 / drawCount));}}/** 添加涟漪* */private void addRipple() {//创建涟漪对象Ripple ripple = new Ripple();//设置初始半径ripple.r = minR;//创建画笔Paint paint = new Paint();//画笔颜色paint.setColor(rippleColor);//设置画笔风格为绘制边框paint.setStyle(Paint.Style.STROKE);//设置边框宽度为半径的四分之一paint.setStrokeWidth(ripple.r / 4);//抗锯齿paint.setAntiAlias(true);//将设置好的画笔交给对象ripple.paint = paint;//设置透明度ripple.alpha = 255f;//将涟漪对象添加到涟漪集合ripples.add(ripple);}/** 刷新涟漪半径、透明度、宽度* */private void flushRipple() {for (int i = 0; i < ripples.size(); i++) {//获取第i个涟漪对象Ripple ripple = ripples.get(i);//如果第i个涟漪的半径加上边框大于最大半径 则删除涟漪if (ripple.r + ripple.r / 8 >= maxR) {//移除涟漪对象ripples.remove(i);//因为移除了一个对象 导致后续对象前移 i-- 确保完全遍历i--;//遍历下一个对象continue;}//透明度递减//由于一个涟漪遍历drawCount次//所以每次减少255f/drawCount ripple.alpha -= 255f/drawCount;//如果透明度<0 设置为0 防止负数if (ripple.alpha < 0)ripple.alpha = 0;//将递减的透明度设置给当前涟漪ripple.paint.setAlpha((int) ripple.alpha);//maxR-minR的值为涟漪可增长的长度//而涟漪设置了StrokeWidth//边框宽度固定为半径的四分之一 即r/4//所以涟漪的 实际半径=画笔半径+边框宽度/2=r+r/4/2 = r/8*9//那么 涟漪可增长的长度包括了涟漪半径与边框//因此我们要算出涟漪实际可以增长的半径为 (maxR-minR)/9*8//由于我们想要每个涟漪重绘drawCount次 因此每次增加 可增长半径的1/drawCount 即(maxR-minR)/9*8/drawCount//绘制drawCount次之后 涟漪半径就会因为超过最大半径而被删除ripple.r += (maxR - minR) * 8 / 9 / drawCount;ripple.paint.setStrokeWidth(ripple.r / 4);}}//内部Handler 实现涟漪周期荡漾private Handler handler = new Handler() {@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);//刷新涟漪flushRipple();if (ripples.size()!=0) {//先判空 避免涟漪被清除时空指针异常//如果最内圈涟漪的半径大于初始半径+间隔半径,那么新增涟漪if (ripples.get(ripples.size() - 1).r > minR + spacing && startRipple) {addRipple();}//重新绘制reDraw();}}};//-----------------------对外提供的Get、Set方法------------------------------------//查询是否存在中心圆public boolean isCentry() {return centry;}//设置是否有中心圆public void setCentry(boolean centry) {this.centry = centry;//刷新reDraw();}//查询是否开启涟漪public boolean isStartRipple() {return startRipple;}//设置是否开启涟漪public void setStartRipple(boolean startRipple) {//清空涟漪// ripples.clear();//设置是否开启this.startRipple = startRipple;//刷新reDraw();}//获取中心圆颜色public int getCentryColor() {return centryColor;}//设置中心圆颜色public void setCentryColor(int centryColor) {this.centryColor = centryColor;//刷新reDraw();}//获取涟漪颜色public int getRippleColor() {return rippleColor;}//设置涟漪颜色public void setRippleColor(int rippleColor) {this.rippleColor = rippleColor;//刷新reDraw();}//获取涟漪最小半径,即中心圆半径public float getMinR() {return minR;}//设置涟漪最小半径,即中心圆半径public void setMinR(float minR) {this.minR = minR / 2;//刷新reDraw();}//获取涟漪最大半径public float getMaxR() {return maxR;}//设置涟漪最大半径public void setMaxR(float maxR) {this.maxR = maxR / 2;//刷新reDraw();}//获取涟漪荡漾速率public float getSpeed() {return speed;}//设置涟漪荡漾速率public void setSpeed(float speed) {this.speed = speed;//刷新reDraw();}//获取涟漪间距public float getSpacing() {return spacing;}//设置涟漪间距public void setSpacing(float spacing) {this.spacing = spacing;//刷新reDraw();}//刷新Viewprivate void reDraw() {//清除handler的回调与Message 避免同时传递多个Message导致速率异常handler.removeCallbacksAndMessages(null);//同时重绘Viewinvalidate();}}

自定义属性

添加到res/values/attrs.xml里 没有就自己创建当然你想放在strings.xml和styles.xml也行

<declare-styleable name="RippleView"><!--中心圆半径与涟漪初始半径--><attr name="minR" format="dimension"/><!--涟漪扩散频率--><attr name="speed" format="float"/><!--涟漪间距--><attr name="spacing" format="dimension"/><!--是否需要中心圆--><attr name="centry" format="boolean"/><!--是否开启涟漪--><attr name="startRipple" format="boolean"/><!--中心圆颜色--><attr name="centryColor" format="reference|color"/><!--涟漪颜色--><attr name="rippleColor" format="reference|color"/></declare-styleable>

使用

xml中

<qiyuan.lin.helloandroid.rippleview.RippleViewandroid:id="@+id/rippleview"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"app:centry="true"app:startRipple="true"app:centryColor="@color/mypink"app:spacing="100dp"app:speed="1"app:minR="25dp"app:rippleColor="@color/mypink" />

Activity中

//绑定控件RippleView rippleView = findViewById(R.id.rippleview);//开启圆心rippleView.setCentry(true);//开启涟漪rippleView.setStartRipple(true);//设置圆心颜色rippleView.setCentryColor(Color.GREEN);//设置涟漪颜色rippleView.setRippleColor(Color.GREEN);//设置涟漪速率rippleView.setSpeed(1);//设置涟漪间距rippleView.setSpacing(100);

若有指点或者疑问,欢迎留言

END

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。