当前位置: 首页 > news >正文

让低版本的 Android 项目显示出 Material 风格的点击效果

   每天都被不同的需求纠缠的生活是幸福而又不幸的,这不我们家亲爱的设计师们又让我们在低版本的 Android 平台上实现一下类似于 Material Design 的点击效果。

       虽然大家都知道 MaterialDesign 的确好看很多,但是让我们为低版本适配也是一个苦逼的活儿。

       不过还好,在使用了 nineoldandroids 这个开源库之后,总算是实现了这个效果。

       先放出一个 Github 地址,大家如果可以去那里看看源码: https://github.com/Kifile/MaterialView, 能够 Star 一下就更好了。      

       再给出两张效果图,分别是基于 TextView 和 ImageView 的点击效果:

图1 TextView、ImageView应用后的点击效果示意图

1.代码实现逻辑

       首先我们分析一下这种点击效果的实现逻辑。

       点击效果的处理主要分为两个阶段:

       a.手指按下:

              当用户触摸到控件的时候,首先我们先让控件显示一层浅色遮罩,然后从手指按下位置开始,有一个深色遮罩逐渐扩大至整个控件。

       b.手指弹起:

              当用户松开手指之后,这里存在两种情况,一种是深色遮罩已经扩大到了整个控件的范围,一种是深色遮罩尚未完全包围整个控件。

              对于前一种情况,我们简单做一次透明度变化,让遮罩逐渐消失即可;

              对于后一种情况,我们需要让深色遮罩从当前的位置快速扩散到整个控件,同时也要做透明度变化,放置遮罩消失太过突兀。

       具体代码实现逻辑请参看这里: https://github.com/Kifile/MaterialView/blob/master/materialwidget/src/main/java/com/kifile/materialwidget/MaterialBackgroundDetector.java,MaterialBackgroundDetector 中 onTouchEvent 的处理。

2.使用库文件实现 Material 点击效果

       目前我已经将这个项目部署到了 Maven 中心库中,如果大家对部署的逻辑感兴趣,可以看看这篇文章(一步一步教你分享开源项目到 Maven 中心仓库),因此如果大家是使用 Android Studio 来开发项目,可以通过使用以下代码将本库进行集成:

 

[ruby]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. dependencies {  
  2.     compile 'com.kifile:MaterialView:1.0'  
  3. }  

       通过在 gradle.build 文件中引入 maven 项目,我们现在就可以正式使用这个点击效果了。

 

       a.继承你希望实现的控件,代码如下:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. public class MaterialImageView extends ImageView {  
  2.     public MaterialImageView(Context context) {  
  3.         super(context);  
  4.         init(null, 0);  
  5.     }  
  6.   
  7.     public MaterialImageView(Context context, AttributeSet attrs) {  
  8.         super(context, attrs);  
  9.         init(attrs, 0);  
  10.     }  
  11.   
  12.     public MaterialImageView(Context context, AttributeSet attrs, int defStyle) {  
  13.         super(context, attrs, defStyle);  
  14.         init(attrs, defStyle);  
  15.     }  
  16. }  


       b.在 init 方法中创建一个 MaterialBackgroundDetector 对象,用于事件委托:

 

 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. private MaterialBackgroundDetector mDetector;  
  2.   
  3. private void init(AttributeSet attrs, int defStyle) {  
  4.     final TypedArray a = getContext().obtainStyledAttributes(  
  5.             attrs, com.kifile.materialwidget.R.styleable.MaterialTextView, defStyle, 0);  
  6.     int color = a.getColor(com.kifile.materialwidget.R.styleable.MaterialTextView_maskColor, MaterialBackgroundDetector.DEFAULT_COLOR);  
  7.     a.recycle();  
  8.     mDetector = new MaterialBackgroundDetector(getContext(), this, null, color);  
  9. }  


       c.重写父类方法,将相应事件委托给 mDetector 对象处理

 

 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. @Override  
  2. protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  3.     super.onSizeChanged(w, h, oldw, oldh);  
  4.     mDetector.onSizeChanged(w, h);  
  5. }  
  6.   
  7. @Override  
  8. public boolean onTouchEvent(MotionEvent event) {  
  9.     boolean superResult = super.onTouchEvent(event);  
  10.     return mDetector.onTouchEvent(event, superResult);  
  11. }  
  12.   
  13. @Override  
  14. protected void onDraw(Canvas canvas) {  
  15.     super.onDraw(canvas);  
  16.     if (isInEditMode()) {  
  17.         return;  
  18.     }  
  19.     mDetector.draw(canvas);  
  20. }  


       d.(可选)将点击事件的处理也交给 mDetector

 

              当我们对控件进行点击的时候,android 自身的点击事件处理机制会起作用,如果你的点击回调函数中存在页面跳转,那么你可能会发现,当你进行点击之后,按键中深色遮罩尚未扩散到整个控件,整个界面就已经跳转。这样会导致Material 动画看起来会在跳转的一刹那停止。

              为了解决这种问题,我们需要在继承的空间中对点击事件做处理,我们先让 mDetector 接收到点击请求,当动画执行完毕之后,再进行分发给控件做点击处理。

              因此,你需要实现以下代码:

              1)在 init 方法里,将 null,改为 this,令控件实现Callback接口

 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. mDetector = new MaterialBackgroundDetector(getContext(), this, this, color);  


                  2)重写以下方法:

 

 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. @Override  
  2. public boolean performClick() {  
  3.     return mDetector.handlePerformClick();  
  4. }  
  5.   
  6. @Override  
  7. public boolean performLongClick() {  
  8.     return mDetector.handlePerformLongClick();  
  9. }  
  10.   
  11. @Override  
  12. public void performClickAfterAnimation() {  
  13.     super.performClick();  
  14. }  
  15.   
  16. @Override  
  17. public void performLongClickAfterAnimation() {  
  18.     super.performLongClick();  
  19. }  

       到目前为止,你已经成功的完成了整个界面效果的实现,恭喜你!

 

3.关于混淆

       其实很多时候,我们都可能涉及到对代码进行混淆,为了避免在混淆过程中,混淆工具对代码的处理导致程序应用失败,我们需要在混淆配置文件中加入以下代码:

 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. -keep class com.kifile.materialwidget.MaterialBackgroundDetector {  
  2.     public void setRadius(...);  
  3.     public void setAlpha(...);  
  4. }  

 

       

       基本上整个代码的使用流程就到这里了,感谢大家的阅览,如果觉得对自己有帮助,还请顶一下。

 

其他精彩文章文章

 

jQuery教程(10)-DOM树操作之内容setter和getter方法

android学习笔记(37)使用 DatePickerDialog、TimePickerDialog

android学习笔记(36)使用AlertDialog创建自定义对话框

 

 

更多关于android开发文章

 

相关文章:

  • eclipse安装pydev插件时没有任何错误提示,但是就是装完了后不显示pydev的设置项...
  • bzoj2337
  • android sqlite 数据类型
  • 来一篇新鲜的招聘笔试题(2014秋招版)
  • 接口和实现分离的好处
  • SQL数据库如何存储?
  • UIGestureRecognizerState
  • HashMap工作原理(转载)
  • hive 更多资料urls
  • hive0.13.1配置hwi
  • CSS3 Filter的十种特效
  • Memcache学习总结
  • Laravel 上手教程之实现用户注册和登录
  • 网页文字图片异步加载方式
  • python基础教程(第2版)第五章读后总结;
  • #Java异常处理
  • $translatePartialLoader加载失败及解决方式
  • 【391天】每日项目总结系列128(2018.03.03)
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 【剑指offer】让抽象问题具体化
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • ES6--对象的扩展
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • java多线程
  • JS变量作用域
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • node入门
  • Redux 中间件分析
  • 读懂package.json -- 依赖管理
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 全栈开发——Linux
  • 一文看透浏览器架构
  • 用Canvas画一棵二叉树
  • 原生 js 实现移动端 Touch 滑动反弹
  • #git 撤消对文件的更改
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (2)MFC+openGL单文档框架glFrame
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)项目管理杂谈-我所期望的新人
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • ../depcomp: line 571: exec: g++: not found
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .Net MVC + EF搭建学生管理系统
  • .net 生成二级域名
  • .net 怎么循环得到数组里的值_关于js数组
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .netcore 获取appsettings
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout