Android進階之路 - 隱藏入口

在開發中其實不論前臺、後臺都會留一些後門,方便管理人員操作(有點超級權限的意思),但是這樣的入口我們又不能讓用戶直接看到,所以就有一些芝麻開門的操作 ~

今天真是個好日子啊 - 2020.5.20, 計劃終究還是趕不上變化 ~

後門效果

在這裏插入圖片描述

長按監聽 (原生版)

Android系統自帶的一種長按監聽,長按時間差不多在0.5秒-1.5秒左右,如果入口想做的深一點,其實不必考慮這種,因爲有的用戶可能無意就會觸發到 ~ 同時不太利於擴展,例如領導說做個5秒響應,那就涼涼了~

當然 - 如果說要求沒有那麼嚴格,那麼可以直接使用這種方式,畢竟系統自帶,分秒實現 ~

      findViewById(R.id.btn_1).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(MainActivity.this, "觸發:隱藏入口", Toast.LENGTH_LONG).show();
                return true;
            }
        });

長按時長監聽(乞丐版)

此種方式主要利用了Android中onTouch機制,在手指Down的時候記錄當前時間,UP的時候計算時間差 ~

但是有一些瑕疵,因爲你要一直不擡起手指的話,豈不是一直進不去隱藏入口 …

        Long startTime;
        Long endTime;
        findViewById(R.id.btn_2).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                    	//記錄起始時間
                        startTime = System.currentTimeMillis();
                        break;
                    case MotionEvent.ACTION_UP:
                    	//獲取手指擡起時間,然後計算按壓操作的時間差
                        endTime = System.currentTimeMillis();
                        if (endTime - startTime > 3 * 1000) {
                            Log.e("tag", "觸發:隱藏入口");
                            Toast.makeText(MainActivity.this, "觸發:隱藏入口", Toast.LENGTH_LONG).show();
                        } else {
                            Log.e("tag", "未超過5秒");
                            Toast.makeText(MainActivity.this, "未超過5秒", Toast.LENGTH_LONG).show();
                        }
                        break;
                    default:
                        break;
                }
                return true;
            }
        });

長按時長監聽(主推:土豪版)

起初我想着通過onTouch的Down事件記錄時間和按壓狀態,開啓計時器,當滿足條件則開啓入口,同時UP的時候判斷是時間差,取消計時器,看是否滿足開啓入口條件,但是果斷使用TimerTask 後如果第二次去創建調用schedule會報錯 ~ 一時間想不到什麼好的方式去處理,就直接搜索到了成型的方法 … 當然也是通過OnTouch這種方式執行的 ~ 但是有Handler的使用哈 ~

以下方法,早已流傳多時,使用也確實沒什麼問題

長按時長監聽

LongClickUtils(此類可直接copy)

package nk.com.hideentrance;

import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;

/**
 * @author MrLiu
 * @date 2020/5/20
 * desc
 */
public class LongClickUtils {
    private static final String TAG = "LongClickUtils";

    /**
     * @param handler           外界handler(爲了減少handler的泛濫使用,最好全局傳handler引用,如果沒有就直接傳 new Handler())
     * @param longClickView     被長按的視圖(任意控件)
     * @param delayMillis       長按時間,毫秒
     * @param longClickListener 長按回調的返回事件
     */
    public static void setLongClick(final Handler handler, final View longClickView, final long delayMillis, final View.OnLongClickListener longClickListener) {
        longClickView.setOnTouchListener(new View.OnTouchListener() {
            private int TOUCH_MAX = 50;
            private int mLastMotionX;
            private int mLastMotionY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getX();
                int y = (int) event.getY();

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // 每次按下重新計時
                        // 按下前,先移除 已有的Runnable回調,防止用戶多次單擊導致多次回調長按事件的bug
                        handler.removeCallbacks(r);
                        mLastMotionX = x;
                        mLastMotionY = y;
                        // 按下時,開始計時
                        handler.postDelayed(r, delayMillis);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (Math.abs(mLastMotionX - x) > TOUCH_MAX || Math.abs(mLastMotionY - y) > TOUCH_MAX) {
                            // 移動誤差閾值
                            // xy方向判斷
                            // 移動超過閾值,則表示移動了,就不是長按(看需求),移除 已有的Runnable回調
                            handler.removeCallbacks(r);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        // 擡起時,移除已有Runnable回調,擡起就算長按了(不需要考慮用戶是否長按了超過預設的時間)
                        handler.removeCallbacks(r);
                        break;
                }
                //onclick等其他事件不能用請改這裏
                return true;
            }

            private Runnable r = new Runnable() {
                @Override
                public void run() {
                    // 回調給用戶,用戶可能傳null,需要判斷null
                    if (longClickListener != null) {
                        longClickListener.onLongClick(longClickView);
                    }
                }
            };
        });
    }
}
使用方式
        LongClickUtils.setLongClick(new Handler(), view, 3000, new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(MainActivity.this, "觸發:隱藏入口", Toast.LENGTH_LONG).show();
                return true;
            }
        });

規定時間,點擊次數(主推:土豪版)

這份功能代碼其實網上早就有了,主要是在一個時間差內記錄用戶的點擊次數是否達標,如果滿足條件即出發入口,反之重置時間與次數 ~

        //臨時時間
        private long mTempTime;
        //點擊次數
        private int mClickNum;
        /*規定時間內:點擊次數的方式*/
        findViewById(R.id.btn_3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                long time = System.currentTimeMillis();
                //第一次點擊隱藏入口,保存臨時時間
                if (mTempTime == 0) {
                    mTempTime = time;
                } else {
                    //這裏設置兩秒的超時時間,如果超過兩秒,重置狀態
                    if (time - mTempTime > 2000) {
                        //給臨時時間和點擊次數進行初始化
                        mTempTime = time;
                        mClickNum = 0;
                        return;
                    }
                    mClickNum++;
                    mTempTime = time;
                    //因爲一次點擊走if語句,這裏可以設置對應的點擊次數,但是最少也要2次,不然用這個沒有意義,mClickNum == 連續點擊數-1
                    if (mClickNum == 4) {
                        Toast.makeText(MainActivity.this, "連續點擊五次", Toast.LENGTH_SHORT).show();
                        //給臨時時間和點擊次數進行初始化
                        mTempTime = 0;
                        mClickNum = 0;
                    }
                }
            }
        });

基於實踐 - Demo

可通過此處,下載Demo ~

監聽方式

LongClickUtils(針對時長監聽,此類可直接copy)

package nk.com.hideentrance;

import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;

/**
 * @author MrLiu
 * @date 2020/5/20
 * desc
 */
public class LongClickUtils {
    private static final String TAG = "LongClickUtils";

    /**
     * @param handler           外界handler(爲了減少handler的泛濫使用,最好全局傳handler引用,如果沒有就直接傳 new Handler())
     * @param longClickView     被長按的視圖(任意控件)
     * @param delayMillis       長按時間,毫秒
     * @param longClickListener 長按回調的返回事件
     */
    public static void setLongClick(final Handler handler, final View longClickView, final long delayMillis, final View.OnLongClickListener longClickListener) {
        longClickView.setOnTouchListener(new View.OnTouchListener() {
            private int TOUCH_MAX = 50;
            private int mLastMotionX;
            private int mLastMotionY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getX();
                int y = (int) event.getY();

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // 每次按下重新計時
                        // 按下前,先移除 已有的Runnable回調,防止用戶多次單擊導致多次回調長按事件的bug
                        handler.removeCallbacks(r);
                        mLastMotionX = x;
                        mLastMotionY = y;
                        // 按下時,開始計時
                        handler.postDelayed(r, delayMillis);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (Math.abs(mLastMotionX - x) > TOUCH_MAX || Math.abs(mLastMotionY - y) > TOUCH_MAX) {
                            // 移動誤差閾值
                            // xy方向判斷
                            // 移動超過閾值,則表示移動了,就不是長按(看需求),移除 已有的Runnable回調
                            handler.removeCallbacks(r);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        // 擡起時,移除已有Runnable回調,擡起就算長按了(不需要考慮用戶是否長按了超過預設的時間)
                        handler.removeCallbacks(r);
                        break;
                }
                //onclick等其他事件不能用請改這裏
                return true;
            }

            private Runnable r = new Runnable() {
                @Override
                public void run() {
                    // 回調給用戶,用戶可能傳null,需要判斷null
                    if (longClickListener != null) {
                        longClickListener.onLongClick(longClickView);
                    }
                }
            };
        });
    }
}

MainActivity
package nk.com.hideentrance;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    //Down按下時間
    Long startTime;
    //UP擡起時間
    Long endTime;
    //臨時時間
    private long mTempTime;
    //點擊次數
    private int mClickNum;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**
         *長按監聽 (原生版)
         */
        findViewById(R.id.btn_1).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(MainActivity.this, "觸發:隱藏入口", Toast.LENGTH_LONG).show();
                return true;
            }
        });

        /**
         *長按時長監聽(乞丐版)
         */
        findViewById(R.id.btn_2).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        startTime = System.currentTimeMillis();
                        Log.e("tag", "startTime:" + startTime);
                        break;
                    case MotionEvent.ACTION_UP:
                        endTime = System.currentTimeMillis();
                        Log.e("tag", "開始:" + startTime);
                        Log.e("tag", "結束:" + endTime);

                        if (endTime - startTime > 3 * 1000) {
                            Log.e("tag", "觸發:隱藏入口");
                            Toast.makeText(MainActivity.this, "觸發:隱藏入口", Toast.LENGTH_LONG).show();
                        } else {
                            Log.e("tag", "未超過5秒");
                            Toast.makeText(MainActivity.this, "未超過5秒", Toast.LENGTH_LONG).show();
                        }
                        break;
                    default:
                        break;
                }
                return true;
            }
        });

        /**
         *長按時長監聽(主推:土豪版)
         */
        LongClickUtils.setLongClick(new Handler(), findViewById(R.id.btn_3), 3000, new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(MainActivity.this, "觸發:隱藏入口", Toast.LENGTH_LONG).show();
                return true;
            }
        });

        /**
         *規定時間,點擊次數(主推:土豪版)
         */
        findViewById(R.id.btn_4).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                long time = System.currentTimeMillis();
                //第一次點擊隱藏入口,保存臨時時間
                if (mTempTime == 0) {
                    mTempTime = time;
                } else {
                    //這裏設置兩秒的超時時間,如果超過兩秒,重置狀態
                    if (time - mTempTime > 2000) {
                        //給臨時時間和點擊次數進行初始化
                        mTempTime = time;
                        mClickNum = 0;
                        return;
                    }
                    mClickNum++;
                    mTempTime = time;
                    //因爲一次點擊走if語句
                    if (mClickNum == 4) {
                        Toast.makeText(MainActivity.this, "已連續點擊五次 - 觸發:隱藏入口", Toast.LENGTH_SHORT).show();
                        //給臨時時間和點擊次數進行初始化
                        mTempTime = 0;
                        mClickNum = 0;
                    }
                }
            }
        });
    }
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/btn_1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="長按監聽 (原生版) - 隱藏入口" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#fb5" />

    <TextView
        android:id="@+id/btn_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="長按時長監聽(乞丐版) - 隱藏入口" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#fb5" />

    <TextView
        android:id="@+id/btn_3"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="長按時長監聽(主推:土豪版) - 隱藏入口" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#fb5" />

    <TextView
        android:id="@+id/btn_4"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="規定時間,點擊次數(主推:土豪版) - 隱藏入口" />
</LinearLayout>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章