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

欢迎各位关注我的新浪微博:http://weibo.com/kifile

转载请标明出处(http://blog.csdn.net/kifile)

每天都被不同的需求纠缠的生活是幸福而又不幸的,这不我们家亲爱的设计师们又让我们在低版本的 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 来开发项目,可以通过使用以下代码将本库进行集成:

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(...);
}

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

时间: 2024-10-08 11:13:23

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

android项目剖解之ViewPager+Fragment 实现tabhost效果

项目中需要用到底栏导航栏,滑动或者点击会切换上面的视图,如图: 这个效果使用Viewpager+Fragmen实现是主流方案,加入你之前对fragment不太了解,可以先看android之Fragment(官网资料翻译) 整个文件如下: 好了废话少说,先上布局文件:main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://sche

Android底部弹出iOS7风格对话选项框

<Android底部弹出iOS7风格对话选项框> 效果图如下: 网上流传的Android底部弹出iOS7风格的对话选项框开源代码,原作者不详.我在网上流传的代码基础上改进了一些地方,把原来作为Application发布的代码整理成一个Android的Library,如果在未来的Android项目中需要这样的对话选项框样式,则只需要下载我上次到CSDN的完整库项目(完整的Android库项目代码我已经上传到CSDN,下载地址:http://download.csdn.net/download/z

鼠标悬浮标题切换显示出标题的文字和图片效果

第一种效果: HTML结构: <div class="vewinfor"> <div class="leftin_hd"> <h3>作者热文</h3> <a href="" target="_blank" class="in_more">...</a> </div> <div class="leftin_bd

【Android分享】仿WIN8系统磁贴点击效果

[Android分享]仿WIN8系统磁贴点击效果 功能分类:特效 支持平台:Android 运行环境:Eclipse 开发语言:Java 开发工具:Eclipse 源码大小:188.47KB 下载地址:http://www.dwz.cn/xslIw 源码简介 Demo源自http://www.apkbus.com/forum.php?mod=viewthread&tid=84631,利用自定义ImageView+View点击事件+动画实现的效果,因为原Demo无注释,所以本人在主要部分加入了代码

使用VS2017开发APP中使用VUE.js开发遇到打包出来的android文件 在低版本的android(4.3)中无法正常使用

使用VS2017开发VUE的APP应用遇到的问题集合 1,  打包出来的apk文件在Android 6.0版本以上手机可以正常打开,在Android 4.3版本手机上无法打开 原因:一开始猜测是不是VS中安卓设置不正确,最后确定的问题是,低版本内置的浏览器(webview)版本太低,无法解析 ES2015最新的一些语法.需要在Webpack中配置babel-loader,还需要在项目最外层添加一个.babelrc文件用于babel默认解析ES2015中的特殊语法(例如: const,let等)

Web Uploader在低版本IE下无法显示Flash的一种情况

用户反馈在IE 8下无法正常显示Web Uploader控件,并已安装了Flash插件.调试发现在内部抛出了Runtime Error的错误,关键代码如下: Runtime.create = function( opts, orders ) { var type, runtime; orders = orders || Runtime.orders; $.each( orders.split( /\s*,\s*/g ), function() { if ( factories[ this ] )

react-native 0.31.0 低版本在Android上报网络的错误错

修改工程里 DashengChefuMerchant/node_modules/react-native/Libraries/Utilities/UIManager.js if (Platform.OS === 'ios')里面的 的代码为 var normalizePrefix = (moduleName: string)=>{ return moduleName.replace(/^(RCT|RK)/, '');}

(转)android底部弹出iOS7风格对话选项框(QQ对话框)--第三方开源--IOS_Dialog_Library

本文转载于:http://blog.csdn.net/zhangphil/article/details/44940339 完成这个效果的是使用了 IOS_Dialog_Library 下载地址:http://files.cnblogs.com/files/zzw1994/IOS_Dialog_Library.zip 或者:http://download.csdn.net/download/zhangphil/8573925 下载后导入到Eclipse中,然后作为Library引入到自己的工程中

Android较低版本(&lt;5.2) 页面默认Select选择框效果的BUG解决

Bug描述: 使用低版本安卓(<5.2),在微信上打开网页,点击下拉框,会出现如下图所示的用来展示select选项的弹出框: 在选项较少的时候,可以向下滑动,将选项滑到底部 滑动前: 滑动后: 期望达到的效果: 解决方案: 判断是否是微信环境: function isWeixinBrowser(){ return /micromessenger/.test(navigator.userAgent.toLowerCase()); } 判断安卓版号: var userAgent = navigato