按下效果器
Android在5.0以上 Button默認自帶陰影效果,這是為了增加立體性和視覺效果,是非常好的,但是TMD,產品一句話: "跟IOS一樣!",苦逼的Android開發就要去掉了,我們可以在xml中添加如下代碼去掉:
style="?android:attr/borderlessButtonStyle"
這樣還不行,因為IOS的Button還有個按下的透明度效果,那么我們就需要再加上透明度效果,
我們先實作個簡單的透明度工具類:
public class PressEffect {
public static void TouchEffect(View view, int action) {
if (view == null) return;
if (!view.isClickable()) return;
if (MotionEvent.ACTION_DOWN == action) {
// 接近0.618趨緊完美
view.setAlpha(0.6f);
} else {
view.setAlpha(1.0f);
}
}
}
然后,我們自定義一個Button,在onTouch里面呼叫即可:
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設定了攔截器如下:
findViewById<Button>(R.id.btn_add).setOnClickListener(object : ClickProtector() {
override fun onRealClick(v: View?) {
tvCount.text = "${++number}"
}
}.delay(1000))
我們設定了delay為1000,也就是1s內觸發一次,
當然,你也可以改進這個點擊保護器,比如添加"攔截時候的回呼",可以給用戶提示資訊等,如下:
// 攔截的回呼
private List<Runnable> runnables = new ArrayList<>();
// 沒點擊過 或者 本次點擊跟上次點擊時間差小于delay,就攔截
if (lastTime != null && System.currentTimeMillis() - lastTime < delay) {
// 執行攔截的回呼
for (Runnable runnable : runnables) {
runnable.run();
}
return;
}
也可以擴展其他攔截器,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/337740.html
標籤:其他
