public class CButton extends Button {
@Override
public boolean onTouchEvent(MotionEvent event) {
PressEffect.TouchEffect(this, event.getAction());
return super.onTouchEvent(event);
}
}
当然,不仅仅是Button,你可以自定义任意View,只要复写其onTouch()事件,然后设置clickable属性为true,就可以生效。
有人说,这还要自定义View,太费劲了,其实这是不对的,我们的项目如果要(或者将来可能)对app的所有界面进行整体处理,怎么办?如果你用了自定义View,只需要将所有View进行横切处理即可,如果没有,那你可能就很费劲了。所以我们要有面向未来的思想。
比如下面的App黑白化处理。
黑白模式
先上代码,下面代码将View设置为黑白模式:
public static void darkTheme(View view) {
if (view == null) return;
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0);
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
}
这是通过设置饱和度实现的。
下面代码则将黑白模式还原:
public static void resetTheme(View view) {
if (view == null) return;
view.setLayerType(View.LAYER_TYPE_HARDWARE, new Paint());
}
我们看到,点击Dark就变成黑白模式,点击Reset就还原了。而且,Dark按钮按下时是没有阴影的,而是变为透明的,抬起则还原;点击Reset是有阴影的。这是因为Dark使用了上面的定义的CButton,PressEffect生效了。
那么,如果整个App全部需要黑白化处理呢,这里就有两种方案:
-
1 遍历每一个Activity/Dialog然后获取到DecorView来进行设置。
-
2 定义一套完整的自定义View,然后在这些View里面处理。
方案2是比较灵活的,对业务无侵入性。你可以自己定义一套TextView、Button、LinearLayout等,继承自系统自带的,后续如果有更改,可以统一在这些自定义View里面处理(因为系统自带的View你没法改)。
Switch的坑
我们知道,对于Switch来说,如果设置了OnCheckedChangeListener,那么调用switch.setChecked(true)就会触发事件里面的回调,导致走一些非必要的逻辑,这是不对的。
说白了,我们希望的是: 如果是checked属性是通过代码设置的,就不触发;如果是用户点击导致的,就触发,所以我们可以通过是否按下来判断:
switch.setOnCheckedChangeListener{ buttonView, isChecked ->
// 如果没有按下,则认为是代码设置的,直接拦截
if(!buttonView.isPressed()){
return;
}
// …其他业务
}
这里就不再展示效果了。
连点拦截器
在我们的业务中,有很多因为用户频繁点击导致的问题,比如点击某个按钮去刷新数据,如果频繁点击就会请求好多次接口,不处理的话单身30年手速的人可能会直接干死一台服务器。
所以我们需要添加保护,避免频繁点击的情况发生,我们可以给点击事件添加一个间隔,小于这个间隔就不触发点击事件,如下:
public abstract class ClickProtector implements View.OnClickListener {
// 点击时间间隔: ms
private long delay = 0;
// 实际的点击事件
abstract void onRealClick(View v);
/**
-
设置点击间隔
-
@param delay 单位:ms
*/
public ClickProtector delay(long delay) {
this.delay = delay;
return this;
}
@Override
public void onClick(View v) {
int key = v.hashCode();
Long lastTime = (Long) v.getTag(key);
// 没点击过 或者 本次点击跟上次点击时间差小于delay,就拦截
if (lastTime != null && System.currentTimeMillis() - lastTime < delay) {
return;
}
// 触发点击事件
onRealClick(v);
// 记录本次点击时间
v.setTag(key, System.currentTimeMillis());
}
}
其中只有Add设置了拦截器如下:
最后附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总)
面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验,下面这份PDF是我翻阅了差不多1个月左右一些Android大博主的博客从他们那里取其精华去其糟泊所整理出来的一些Android的核心知识点, 全部都是精华中的精华,我能面试到现在资深开发人员跟我整理的这本Android核心知识点有密不可分的关系,在这里本着共赢的心态分享给各位朋友。
这份PDF囊括了JVM,Java集合,Java多线程并发,Java基础,生命周期,微服务, 进程,Parcelable 接口,IPC,屏幕适配,线程异步,ART,架构,Jetpack,NDK开发,计算机网络基础,类加载器,Android 开源库源码分析,设计模式汇总,Gradle 知识点汇总…
由于篇幅有限,就不做过多的介绍,大家请自行脑补
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
生命周期,微服务, 进程,Parcelable 接口,IPC,屏幕适配,线程异步,ART,架构,Jetpack,NDK开发,计算机网络基础,类加载器,Android 开源库源码分析,设计模式汇总,Gradle 知识点汇总…
由于篇幅有限,就不做过多的介绍,大家请自行脑补
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!