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的使用哈 ~

以下方法,早已流传多时,使用也确实没什么问题

扫描二维码关注公众号,回复: 11240458 查看本文章
长按时长监听

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>

猜你喜欢

转载自blog.csdn.net/qq_20451879/article/details/106216816