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

 每天都被不同的需求纠缠的生活是幸福而又不幸的,这不我们家亲爱的设计师们又让我们在低版本的 Android 平台上实现一下类似于 Material Design 的点击效果。
       虽然大家都知道 MaterialDesign 的确好看很多,但是让我们为低版本适配也是一个苦逼的活儿。
       不过还好,在使用了 nineoldandroids 这个开源库之后,总算是实现了这个效果。
       先放出一个 Github 地址,大家如果可以去那里看看源码: https://github.com/Kifile/MaterialView.
       再给出两张效果图,分别是基于 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 来开发项目,可以通过使用以下代码将本库进行集成:

  • 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(...);
  • }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值