天天都被不一样的需求纠缠的生活是幸福而又不幸的,这不咱们家亲爱的设计师们又让咱们在低版本的 Android 平台上实现一下相似于 Material Design 的点击效果。html
虽然你们都知道 MaterialDesign 的确好看不少,可是让咱们为低版本适配也是一个苦逼的活儿。java
不过还好,在使用了 nineoldandroids 这个开源库以后,总算是实现了这个效果。android
先放出一个 Github 地址,你们若是能够去那里看看源码: https://github.com/Kifile/MaterialView, 可以 Star 一下就更好了。 git
再给出两张效果图,分别是基于 TextView 和 ImageView 的点击效果:github


图1 TextView、ImageView应用后的点击效果示意图json
1.代码实现逻辑
首先咱们分析一下这种点击效果的实现逻辑。canvas
点击效果的处理主要分为两个阶段:ruby
a.手指按下:mvc
当用户触摸到控件的时候,首先咱们先让控件显示一层浅色遮罩,而后从手指按下位置开始,有一个深色遮罩逐渐扩大至整个控件。maven
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 来开发项目,能够经过使用如下代码将本库进行集成:
- dependencies {
- compile 'com.kifile:MaterialView:1.0'
- }
经过在 gradle.build 文件中引入 maven 项目,咱们如今就能够正式使用这个点击效果了。
a.继承你但愿实现的控件,代码以下:
- public class MaterialImageView extends ImageView {
- public MaterialImageView(Context context) {
- super(context);
- init(null, 0);
- }
-
- public MaterialImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(attrs, 0);
- }
-
- public MaterialImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(attrs, defStyle);
- }
- }
b.在 init 方法中建立一个 MaterialBackgroundDetector 对象,用于事件委托:
- private MaterialBackgroundDetector mDetector;
-
- private void init(AttributeSet attrs, int defStyle) {
- final TypedArray a = getContext().obtainStyledAttributes(
- attrs, com.kifile.materialwidget.R.styleable.MaterialTextView, defStyle, 0);
- int color = a.getColor(com.kifile.materialwidget.R.styleable.MaterialTextView_maskColor, MaterialBackgroundDetector.DEFAULT_COLOR);
- a.recycle();
- mDetector = new MaterialBackgroundDetector(getContext(), this, null, color);
- }
c.重写父类方法,将相应事件委托给 mDetector 对象处理
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mDetector.onSizeChanged(w, h);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean superResult = super.onTouchEvent(event);
- return mDetector.onTouchEvent(event, superResult);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (isInEditMode()) {
- return;
- }
- mDetector.draw(canvas);
- }
d.(可选)将点击事件的处理也交给 mDetector
当咱们对控件进行点击的时候,android 自身的点击事件处理机制会起做用,若是你的点击回调函数中存在页面跳转,那么你可能会发现,当你进行点击以后,按键中深色遮罩还没有扩散到整个控件,整个界面就已经跳转。这样会致使Material 动画看起来会在跳转的一刹那中止。
为了解决这种问题,咱们须要在继承的空间中对点击事件作处理,咱们先让 mDetector 接收到点击请求,当动画执行完毕以后,再进行分发给控件作点击处理。
所以,你须要实现如下代码:
1)在 init 方法里,将 null,改成 this,令控件实现Callback接口
- mDetector = new MaterialBackgroundDetector(getContext(), this, this, color);
2)重写如下方法:
- @Override
- public boolean performClick() {
- return mDetector.handlePerformClick();
- }
-
- @Override
- public boolean performLongClick() {
- return mDetector.handlePerformLongClick();
- }
-
- @Override
- public void performClickAfterAnimation() {
- super.performClick();
- }
-
- @Override
- public void performLongClickAfterAnimation() {
- super.performLongClick();
- }
到目前为止,你已经成功的完成了整个界面效果的实现,恭喜你!
3.关于混淆
其实不少时候,咱们均可能涉及到对代码进行混淆,为了不在混淆过程当中,混淆工具对代码的处理致使程序应用失败,咱们须要在混淆配置文件中加入如下代码:
- -keep class com.kifile.materialwidget.MaterialBackgroundDetector {
- public void setRadius(...);
- public void setAlpha(...);
- }
基本上整个代码的使用流程就到这里了,感谢你们的阅览,若是以为对本身有帮助,还请顶一下。
其余精彩文章文章
更多关于android开发文章