先来看一张动态图

昨天跟着视频学了如何自定义View并做成仿360悬浮球与加速球的样式

可以看出来,做成的效果有:

  • 点击按钮后退出Activity,呈现一个圆形的悬浮球,可以随意拖动并会自动依靠到屏幕一侧,且拖动时会变成一张图片
  • 当点击悬浮球时,悬浮球隐藏,底部出现一个加速球,双击加速球时,呈现水量逐渐增高且波动幅度较小的效果,单击时波浪上下波动且幅度渐小
  • 点击屏幕不包含底部加速球的部位,加速球会隐藏,悬浮球重新出现

要做出这么一个效果,需要两个自定义View与一个自定义ViewGroup

首先,需要先设计悬浮球View——FloatBall
简单起见,为FloatBall指定一个默认宽度和高度——150像素
然后在onDraw(Canvas canvas)方法中,判断FloatBall是否正在被拖动isDrag,如果是,则绘制一张默认图片bitmap,否则则根据绘图函数绘制圆形与居中文本

/*** Created by ZY on 2016/8/10.* 悬浮球*/
public class FloatBall extends View {public int width = 150;public int height = 150;//默认显示的文本private String text = "50%";//是否在拖动private boolean isDrag;private Paint ballPaint;private Paint textPaint;private Bitmap bitmap;public FloatBall(Context context) {super(context);init();}public FloatBall(Context context, AttributeSet attrs) {super(context, attrs);init();}public FloatBall(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public void init() {ballPaint = new Paint();ballPaint.setColor(Color.GRAY);ballPaint.setAntiAlias(true);textPaint = new Paint();textPaint.setTextSize(25);textPaint.setColor(Color.WHITE);textPaint.setAntiAlias(true);textPaint.setFakeBoldText(true);Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.ninja);//将图片裁剪到指定大小bitmap = Bitmap.createScaledBitmap(src, width, height, true);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {if (!isDrag) {canvas.drawCircle(width / 2, height / 2, width / 2, ballPaint);float textWidth = textPaint.measureText(text);Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();float dy = -(fontMetrics.descent + fontMetrics.ascent) / 2;canvas.drawText(text, width / 2 - textWidth / 2, height / 2 + dy, textPaint);} else {//正在被拖动时则显示指定图片canvas.drawBitmap(bitmap, 0, 0, null);}}//设置当前移动状态public void setDragState(boolean isDrag) {this.isDrag = isDrag;invalidate();}
}

因为FloatBall是不存在于Activity中而在屏幕单独显示的,所以需要用WindowManager来添加View并显示
新建一个类,命名为ViewManager,用来总的管理View的显示与删除
私有化构造函数并采用单例模式

    private static ViewManager manager;//私有化构造函数private ViewManager(Context context) {this.context = context;init();}//获取ViewManager实例public static ViewManager getInstance(Context context) {if (manager == null) {manager = new ViewManager(context);}return manager;}

ViewManager包含有显示与隐藏悬浮球与加速球的函数

//显示浮动小球public void showFloatBall() {if (floatBallParams == null) {floatBallParams = new LayoutParams();floatBallParams.width = floatBall.width;floatBallParams.height = floatBall.height - getStatusHeight();floatBallParams.gravity = Gravity.TOP | Gravity.LEFT;floatBallParams.type = LayoutParams.TYPE_TOAST;floatBallParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL;floatBallParams.format = PixelFormat.RGBA_8888;}windowManager.addView(floatBall, floatBallParams);}//显示底部菜单private void showFloatMenu() {if (floatMenuParams == null) {floatMenuParams = new LayoutParams();floatMenuParams.width = getScreenWidth();floatMenuParams.height = getScreenHeight() - getStatusHeight();floatMenuParams.gravity = Gravity.BOTTOM;floatMenuParams.type = LayoutParams.TYPE_TOAST;floatMenuParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL;floatMenuParams.format = PixelFormat.RGBA_8888;}windowManager.addView(floatMenu, floatMenuParams);}//隐藏底部菜单public void hideFloatMenu() {if (floatMenu != null) {windowManager.removeView(floatMenu);}}

将悬浮球置于Service中开启,这样悬浮球就不那么容易被系统去除了
在onCreate()方法中调用showFloatBall()

public class StartFloatBallService extends Service {public StartFloatBallService() {}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}@Overridepublic void onCreate() {ViewManager manager = ViewManager.getInstance(this);manager.showFloatBall();super.onCreate();}
}

此时,只要为MainActivity添加一个按钮,并设定当点击按钮后开启Service,此时即可看到屏幕显示了一个悬浮球

    public void startService(View view) {Intent intent = new Intent(this, StartFloatBallService.class);startService(intent);finish();}

不过此时悬浮球还不支持拖动与点击,还需要为其添加OnTouchListener与OnClickListener

View.OnTouchListener touchListener = new View.OnTouchListener() {float startX;float startY;float tempX;float tempY;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:startX = event.getRawX();startY = event.getRawY();tempX = event.getRawX();tempY = event.getRawY();break;case MotionEvent.ACTION_MOVE:float x = event.getRawX() - startX;float y = event.getRawY() - startY;//计算偏移量,刷新视图floatBallParams.x += x;floatBallParams.y += y;floatBall.setDragState(true);windowManager.updateViewLayout(floatBall, floatBallParams);startX = event.getRawX();startY = event.getRawY();break;case MotionEvent.ACTION_UP://判断松手时View的横坐标是靠近屏幕哪一侧,将View移动到依靠屏幕float endX = event.getRawX();float endY = event.getRawY();if (endX < getScreenWidth() / 2) {endX = 0;} else {endX = getScreenWidth() - floatBall.width;}floatBallParams.x = (int) endX;floatBall.setDragState(false);windowManager.updateViewLayout(floatBall, floatBallParams);//如果初始落点与松手落点的坐标差值超过6个像素,则拦截该点击事件//否则继续传递,将事件交给OnClickListener函数处理if (Math.abs(endX - tempX) > 6 && Math.abs(endY - tempY) > 6) {return true;}break;}return false;}};OnClickListener clickListener = new OnClickListener() {@Overridepublic void onClick(View v) {windowManager.removeView(floatBall);showFloatMenu();floatMenu.startAnimation();}};floatBall.setOnTouchListener(touchListener);floatBall.setOnClickListener(clickListener);

加速球ProgressBall的设计较为复杂,需要用到贝塞尔曲线来呈现波浪效果,且单击双击的效果也需要分开呈现
同样是让ProgressBall继承于View
进度值的意义在于限制水面最终上升到的高度,即根据目标进度值与最大进度值的比例来决定水面高度
波浪总的起伏次数Count用于在单击加速球时,水面上下波动的次数

    //view的宽度private int width = 200;//view的高度private int height = 200;//最大进度值private final int maxProgress = 100;//当前进度值private int currentProgress = 0;//目标进度值private final int targetProgress = 70;//是否为单击private boolean isSingleTop;//设定波浪总的起伏次数private final int Count = 20;//当前起伏次数private int currentCount;//初始振幅大小private final int startAmplitude = 15;//波浪周期性出现的次数private final int cycleCount = width / (startAmplitude * 4) + 1;

自定义View:悬浮球与加速球相关推荐

  1. android代码实现手机加速功能,Android自定义View实现内存清理加速球效果

    Android自定义View实现内存清理加速球效果 发布时间:2020-09-21 22:21:57 来源:脚本之家 阅读:105 作者:程序员的自我反思 前言 用过猎豹清理大师或者相类似的安全软件, ...

  2. android悬浮球代码,Android 仿360悬浮球与加速球

    先来看一张动态图 昨天跟着视频学了如何自定义View并做成仿360悬浮球与加速球的样式 可以看出来,做成的效果有: 点击按钮后退出Activity,呈现一个圆形的悬浮球,可以随意拖动并会自动依靠到屏幕 ...

  3. android 悬浮球动画,Android 仿360悬浮球与加速球

    先来看一张动态图 昨天跟着视频学了如何自定义View并做成仿360悬浮球与加速球的样式 可以看出来,做成的效果有: 点击按钮后退出Activity,呈现一个圆形的悬浮球,可以随意拖动并会自动依靠到屏幕 ...

  4. android自定义水波纹,android 自定义view-水波纹进度球

    android 进阶之路-自定义view-水波纹进度球 如果你是老司机,一看标题就会就return吧,嘻嘻. 在我们的日常开发中自定义控件还是用的挺多的,设计师或者产品为了更好的漂亮,美观,交互都会做 ...

  5. 自定义View仿魅族手机加速(手机管家)效果

    转载请注明出处:http://blog.csdn.net/MAGIC_JSS/article/details/52245844: 看着魅族手机管家上的手机加速效果不错,决定自己实现之.希望自己加深对自 ...

  6. android 自定义progressbar demo,Android自定义View――动态ProgressBar之模仿360加速球

    在之前一篇文章中我们讲解了三种ProgressBar的做法,详见-><Android 自定义View--自定义ProgressBar >.这一节中我们模仿360加速球制作一个动态Pr ...

  7. android 图片处理过程中添加进度条,『Android自定义View实战』给我一个图标,还你一个水波纹进度球...

    前言 我们都知道,平时表现进度的方式有千千万万种(没有UI想不到的,只有你做不到的= =.),其中有一种就是水波纹进度球的形式,网上很多种实现都是直接采用纯色填充的方式,即水波纹都是纯颜色填充,效果看 ...

  8. 球体动画Android,Android自定义View实现简单炫酷的球体进度球实例代码

    前言 最近一直在研究自定义view,正好项目中有一个根据下载进度来实现球体进度的需求,所以自己写了个进度球,代码非常简单.先看下效果: 效果还是非常不错的. 准备知识 要实现上面的效果我们只要掌握两个 ...

  9. Android自定义View之实现简单炫酷的球体进度球

    前言 最近一直在研究自定义view,正好项目中有一个根据下载进度来实现球体进度的需求,所以自己写了个进度球,代码非常简单.先看下效果: 效果还是非常不错的. 准备知识 要实现上面的效果我们只要掌握两个 ...

  10. android 立体 流量球,Android自定义View——实现水波纹效果类似剩余流量球

    Android自定义View--实现水波纹效果类似剩余流量球 三个点   pre   ber   block   span   初始化   move   理解最近突然手痒就想搞个贝塞尔曲线做个水波纹效 ...

最新文章

  1. JPA2.0回调函数的使用
  2. 宜昌高新区三峡云计算机大楼,【智慧宜昌】CREATOR快捷CS分布式系统成功入驻三峡云计算中心...
  3. 表单form数据默认以键值对的形式将数据回发到服务器,回发非纯文本需使用enctype=multipart/form-data方式编码为整条消息...
  4. C#代码总结02---使用泛型来获取Asp前台页面全部控件,并进行属性修改
  5. leetcode117. 填充每个节点的下一个右侧节点指针 II(dfs)
  6. 利用Python只需3行代码即可生成验证码
  7. html5 input file样式修改,css为input type=file设置自定义样式
  8. Java 跌落神坛,Python 继续夺冠....凭啥?
  9. Linux C语言解析并显示.bmp格式图片
  10. linux创建表空间 没有权限,ORA-12913: 无法创建字典管理的表空间
  11. 计算机算法设计与分析第三章答案,《计算机算法设计与分析》第三章动态规划法.ppt...
  12. RS485通讯的工作原理?
  13. IPTV机顶盒刷机过程--山东电信【天邑TY608】
  14. 快速给视频批量添加水印,操作简单
  15. 解决Visual Studio 2017 无法启动程序,系统找不到指定文件
  16. android自定义rx库,Android下载库(OkHttp3+Retrofit2+RxJava2)
  17. 抖音实战~实现App端视频上传、发布、落库
  18. STAF rc = 6
  19. eccv 2018 image caption generation论文导读
  20. 华为研究院高级研究员几年心得终得趣谈网络协议文档,附资深架构师讲解

热门文章

  1. 《算法的乐趣》终于出版了
  2. 算法学习系列(MCMC):MCMC采样
  3. CentOS5.8分区与文件系统
  4. 9月份红帽认证考试又 PASS 19位同学
  5. WPF 加载Gif动态图片的方法
  6. 77GHz毫米波雷达快速chirp信号技术(三):测角原理
  7. pmp第六版一到三章笔记
  8. Oracle报998,无法加载oracle in oradb10g_home2 odbc驱动程序,系统错误代码998解决方法(转载+部分原创)...
  9. php使用redis实例,php中使用redis队列操作实例代码
  10. WeUI for 小程序使用教程文档总结