Repository: liys666666/DoubleClick
Branch: master
Commit: 1072281f1793
Files: 60
Total size: 67.9 KB
Directory structure:
gitextract_6gmwq0dw/
├── .gitignore
├── .idea/
│ ├── codeStyles/
│ │ └── Project.xml
│ ├── gradle.xml
│ ├── misc.xml
│ ├── runConfigurations.xml
│ └── vcs.xml
├── README.md
├── README1.0.4.md
├── README2.0.6.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── liys/
│ │ └── doubleclickdemo/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── liys/
│ │ │ └── doubleclickdemo/
│ │ │ ├── AppApplication.java
│ │ │ ├── LogUtil.java
│ │ │ ├── LoginClickListener.java
│ │ │ ├── MainActivity.java
│ │ │ ├── UnifiedDoubleClick.java
│ │ │ ├── UnifiedDoubleClick2.java
│ │ │ └── fragment/
│ │ │ ├── MainActivity2.java
│ │ │ ├── MyFragment.java
│ │ │ └── MyFragment2.java
│ │ └── res/
│ │ ├── drawable/
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24/
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout/
│ │ │ ├── activity_main.xml
│ │ │ ├── activity_main2.xml
│ │ │ ├── fragment_my.xml
│ │ │ └── fragment_my2.xml
│ │ ├── mipmap-anydpi-v26/
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── liys/
│ └── doubleclickdemo/
│ └── ExampleUnitTest.java
├── build.gradle
├── doubleclicklibrary/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── liys/
│ │ └── doubleclicklibrary/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── liys/
│ │ │ └── doubleclicklibrary/
│ │ │ ├── DoubleClickHelper.java
│ │ │ ├── annotation/
│ │ │ │ ├── AAddDoubleClick.java
│ │ │ │ ├── ACancelActivity.java
│ │ │ │ ├── AClickListener.java
│ │ │ │ └── helper/
│ │ │ │ └── AnnotationHelper.java
│ │ │ ├── aspect/
│ │ │ │ ├── AspectDoubleClick.java
│ │ │ │ └── Attrs.java
│ │ │ ├── hook/
│ │ │ │ ├── BaseHookView.java
│ │ │ │ ├── HookOnClickListener.java
│ │ │ │ └── IHookView.java
│ │ │ └── listener/
│ │ │ └── IOnClickListener.java
│ │ └── res/
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── com/
│ └── liys/
│ └── doubleclicklibrary/
│ └── ExampleUnitTest.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/caches/build_file_checksums.ser
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
.DS_Store
/build
/captures
.externalNativeBuild
================================================
FILE: .idea/codeStyles/Project.xml
================================================
================================================
FILE: .idea/gradle.xml
================================================
================================================
FILE: .idea/misc.xml
================================================
================================================
FILE: .idea/runConfigurations.xml
================================================
================================================
FILE: .idea/vcs.xml
================================================
================================================
FILE: README.md
================================================
# DoubleClick
简书:
[DoubleClick---3.0版本](https://www.jianshu.com/p/daac21821c43)
[DoubleClick---2.0版本](https://www.jianshu.com/p/df0ef3866cc1)
[DoubleClick---1.0版本](https://www.jianshu.com/p/7f3e5c8b8643)
**V3.0 的使用方法:**
**1.导入:**
```
//项目根目录下,build.gradle
buildscript {
...
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8' //添加
}
}
allprojects {
repositories {
...
maven { url 'https://jitpack.io' } //添加
}
}
```
```
//app目录下build.gradle
apply plugin: 'android-aspectjx' //添加
dependencies {
implementation 'com.github.liys666666:DoubleClick:V3.0.0' //添加
}
```
如果不需要额外处理的话, 到这里就结束了, 同一个按钮点击, 默认最小间隔时间是500毫秒.
**2.添加自定义属性:**
```
public class AppApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
DoubleClickHelper
.getInstance()
.delayTime(500) //间隔时间
.addAnnotationClass(UnifiedDoubleClick.class) //自定义属性, 可叠加
.addAnnotationClass(UnifiedDoubleClick2.class);
}
}
```
```
public interface UnifiedDoubleClick{ //用户自定义接口
// >>>>>>>>>>>>>>>>>>>屏蔽DoubleClick的Activity>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// @ACancelActivity(activitys = {
// MainActivity.class,
// })
// void cancelActivity();
// >>>>>>>>>>>>>>>>>>>单个view处理>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@AAddDoubleClick(activity = MainActivity.class,
addIds = {R.id.btn1, R.id.btn2},
times = {0, 2000}) //点击的间隔时间
void mainActivity();
// >>>>>>>>>>>>>>>>>插入自定义clickListener>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@AClickListener(activity = MainActivity.class,
lisenner = LoginClickListener.class, //自定义clickListener
ids = {R.id.btn2})
void interceptMain();
}
```
```
public class LoginClickListener implements IOnClickListener {
public static boolean isLogin = false;
@Override
public boolean isNext(View v) {
//判断登录逻辑
if(!isLogin){
LogUtil.d("未登录");
Toast.makeText(v.getContext(), "未登录", Toast.LENGTH_SHORT).show();
}
return isLogin;
}
@Override
public void after(View view) {
//执行click后
}
}
```
**扩展---可调用方法**
```
DoubleClickHelper.openAll(); //开启
DoubleClickHelper.closeAll(); //关闭
//(可选)用hook方式处理单个view, 时间会和上面的时间叠加, 一般使用场景: Activity只有个别按钮需要doubleClick
DoubleClickHelper.hookView(View view, long delayTime);
```
# 三.历史版本:
**V3.0.0:**
使用AOP的方式处理, 使用方式和2.0基本一样, 比2.0的方式性能更好.
[V2.0版本](https://github.com/liys666666/DoubleClick/blob/master/README2.0.6.md).
[V1.0版本](https://github.com/liys666666/DoubleClick/blob/master/README1.0.4.md)
* 如果框架中存在不足或者有什么建议, 欢迎指出, 我这边会尽快处理, 让框架更完善, 希望这个框架能帮助更多人, 如果觉得好用, 欢迎star.
================================================
FILE: README1.0.4.md
================================================
# DoubleClick
# 一. 基本使用
框架主要有两个功能(基本用法):
**1. 无入侵解决按钮重复点击.** [使用方法](https://www.jianshu.com/p/7f3e5c8b8643)
**2. onClick重复逻辑统一处理.** [使用方法](https://www.jianshu.com/p/b4038a2d68eb)
**① 导入框架**
```
//项目根目录下,build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' } //添加
}
}
```
```
//app目录下build.gradle
dependencies {
implementation 'com.github.liys666666:DoubleClick:V1.0.4' //添加
}
```
**② 自定义的Application初始化即可**
```
public class AppApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
ViewDoubleHelper.init(this); //默认时间:1秒
// ViewDoubleHelper.init(this, 2000); //自定义点击间隔时间(单位:毫秒)
}
}
```
# 二.扩展:
**V.1.0.2(包含)以上**
1. onClick重复逻辑统一处理--添加新写法(可选):
建议先看基本用法: [onClick重复逻辑统一处理](https://www.jianshu.com/p/b4038a2d68eb)
```
public class MainActivity extends AppCompatActivity implements IAddCustomHookClick{
@Override
public List getCustomHookList() {
int[] ids = {R.id.btn1, R.id.btn2}; //需要处理的id
List list = new ArrayList<>();
for (int i = 0; i < ids.length; i++) { //添加
list.add(new CustomHookBean(ids[i], new LoginClickListener()));
}
return list;
}
}
```
2. 如果有更好的具体实现方法, 也可以自己实现, 具体做法, 其它不变, 在AppApplication是添加:
```
//连续重复点击多次, 自定义具体实现
// ViewDoubleHelper.setIViewDoubleClick(new IViewDoubleClick() {
// @Override
// public void hookActivityViews(Activity activity, long delayTime) {
// //hook Activity内所有View
// }
//
// @Override
// public void hookResView(Activity activity, int viewResId, long delayTime) {
// //根据ViewId hook对应的View
// }
//
// @Override
// public void hookView(Activity activity, View view, long delayTime) {
// //hook对应的View
// }
// });
//onClick重复逻辑统一处理: 自定义具体实现
// ViewDoubleHelper.setICustomHookClick(new ICustomHookClick() {
// @Override
// public void hookResView(Activity activity, int viewResId, IOnClickListener iClickListener) {
//
// }
//
// @Override
// public void hookView(Activity activity, View view, IOnClickListener iClickListener) {
//
// }
// });
```
# 三.历史版本:
**V1.0.4:** 修复:版本兼容问题
**V1.0.3:** 修复bug: 每次pause返回, 都重复hookView
**V1.0.2:**
* ①.onClick重复逻辑统一处理使用IAddCustomHookClick处理, 添加自由扩展实现.
* ②. 新增方法 ViewDoubleHelper.setIViewDoubleClick(IViewDoubleClick), ViewDoubleHelper.setICustomHookClick(ICustomHookClick);
**V1.0.1:** 新增功能: onClick重复逻辑统一处理
**V1.0.0:** 新增功能: 无入侵解决按钮重复点击
================================================
FILE: README2.0.6.md
================================================
# DoubleClick
V2.0 的使用方法:
简书: https://www.jianshu.com/p/df0ef3866cc1
CSDN: https://blog.csdn.net/qq_33199629/article/details/101563232
**简单介绍:**
```
//项目根目录下,build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' } //添加
}
}
```
```
//app目录下build.gradle
dependencies {
implementation 'com.github.liys666666:DoubleClick:V2.0.6' //添加
}
```
```
public class AppApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
// ViewDoubleHelper.init(this); //默认时间:1秒
// ViewDoubleHelper.init(this, 500); //自定义点击间隔时间(单位:毫秒)
ViewDoubleHelper.init(this, 1000, UnifiedDoubleClick.class); //自定义点击间隔时间(单位:毫秒)
//单独设置, 不同的AnnotationClass可叠加(V2.0.5版本后可用)
ViewDoubleHelper.addAnnotationClass(UnifiedDoubleClick2.class);
}
}
```
```
public interface UnifiedDoubleClick{ //用户自定义接口
// >>>>>>>>>>>>>>>>>>>屏蔽DoubleClick的Activity>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// @ACancelActivity(activitys = {
// MainActivity.class,
// })
// void cancelActivity();
// >>>>>>>>>>>>>>>>>>>单个view处理>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@AAddDoubleClick(activity = MainActivity.class,
addIds = {R.id.btn1, R.id.btn2},
times = {0, 2000}) //点击的间隔时间
void mainActivity();
// >>>>>>>>>>>>>>>>>插入自定义clickListener>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@AClickListener(activity = MainActivity.class,
lisenner = LoginClickListener.class, //自定义clickListener
ids = {R.id.btn2})
void interceptMain();
}
```
```
public class LoginClickListener extends BaseClickListener{
public static boolean isLogin = false; //模拟是否登陆
@Override
public boolean isNext(View v) {
//判断登录逻辑 (onClick前执行)
return isLogin; //true继续执行onClick, false不再执行
}
@Override
public void after(View view) {
//onClick后 执行
}
}
```
**扩展---可调用方法**
```
//hook单个view(子View不会跟着变化) 例如: Recyclerview使用的话, itemView是不起作用的
ViewDoubleHelper.hookView(View view, long delayTime);
hook单个view(所有子View会跟着一起变化) 例如: Recyclerview使用的话, itemView以及子控件全部有用
ViewDoubleHelper.hookChildViews(View view, long delayTime);
//重新hook当前Activity
ViewDoubleHelper.hookActivity();
//如果你有更好的实现方法, 也可以自己实现
ViewDoubleHelper.addIViewDoubleClick(IViewDoubleClick iHookView);
```
# 三.历史版本:
**V2.0.6:**
* 修复:
* ViewDoubleHelper.hookChildViews() 不起作用
* ViewDoubleHelper.hookActivity()在onResume()前 调用不起作用.
**V2.0.5:**
* 优化: 问题描述:原来的注解只能在Application初始化时传一个类进去;
* 问题1: 如果注解使用过多, 所有的注解都写在一个类里面, 不好管理.
* 问题2: 在组件化架构中, 有个id无法在Application中获取.
* 解决办法: 使用新增方法 ViewDoubleHelper.addAnnotationClass(annotationClass); 可设置多个
**V2.0.4:**
* 修复: 动态加载View不起作用(包括自定义View, Fragment, RecyclerView中不起作用等等)。
**V2.0.2:**
* 1. 修复兼容问题:注解android9.0不起作用.
* 2. 手动重新hookActivity
**V2.0.1:**
* 1. 完全不需要在具体的Activity和Fragment加代码.
* 2. 是否屏蔽hook、单个View处理, 自定义拦截器,全部使用接口注解处理.
* 3. 单个View处理、自定义拦截器,兼容Fragment.
[V1.0版本](https://github.com/liys666666/DoubleClick/blob/master/README1.0.4.md)
* 如果框架中存在不足或者有什么建议, 欢迎指出, 我这边会尽快处理, 让框架更完善, 希望这个框架能帮助更多人, 如果觉得好用, 欢迎star.
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'android-aspectjx'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.liys.doubleclickdemo"
minSdkVersion 19
targetSdkVersion 28
versionCode 6
versionName "3.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':doubleclicklibrary')
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: app/src/androidTest/java/com/liys/doubleclickdemo/ExampleInstrumentedTest.java
================================================
package com.liys.doubleclickdemo;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.liys.doubleclickdemo", appContext.getPackageName());
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/AppApplication.java
================================================
package com.liys.doubleclickdemo;
import android.app.Application;
import com.liys.doubleclicklibrary.DoubleClickHelper;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/22 11:01
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/22 11:01
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class AppApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
DoubleClickHelper
.getInstance()
.delayTime(500) //间隔时间
.addAnnotationClass(UnifiedDoubleClick.class)
.addAnnotationClass(UnifiedDoubleClick2.class);
}
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/LogUtil.java
================================================
package com.liys.doubleclickdemo;
import android.util.Log;
/**
* @Description: 输出日志
* @Author: liys
* @CreateDate: 2019/5/28 10:55
* @UpdateUser: 更新者
* @UpdateDate: 2019/5/28 10:55
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class LogUtil {
//是否需要打印信息
public static boolean isDebug = true;
//打印信息的标识
public static final String TAG = "66";
public static void e(String msg) {
if (isDebug) Log.e(TAG, msg);
}
public static void d(String msg) {
if (isDebug) Log.d(TAG, msg);
}
public static void i(String msg) {
if (isDebug) Log.i(TAG, msg);
}
public static void w(String msg) {
if (isDebug) Log.w(TAG, msg);
}
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/LoginClickListener.java
================================================
package com.liys.doubleclickdemo;
import android.view.View;
import android.widget.Toast;
import com.liys.doubleclicklibrary.listener.IOnClickListener;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/22 15:52
* @UpdateUser: 更新者
* @UpdateDate: 2019/11/23 22:52
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class LoginClickListener implements IOnClickListener {
public static boolean isLogin = false;
@Override
public boolean isNext(View v) {
//判断登录逻辑
if(!isLogin){
LogUtil.d("未登录");
Toast.makeText(v.getContext(), "未登录", Toast.LENGTH_SHORT).show();
}
return isLogin;
}
@Override
public void after(View view) {
//执行click后
}
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/MainActivity.java
================================================
package com.liys.doubleclickdemo;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.liys.doubleclickdemo.fragment.MainActivity2;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
TextView tvHint;
long num = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvHint = findViewById(R.id.tv_hint);
findViewById(R.id.btn1).setOnClickListener(this);
findViewById(R.id.btn2).setOnClickListener(this);
findViewById(R.id.login).setOnClickListener(this);
findViewById(R.id.logout).setOnClickListener(this);
findViewById(R.id.start).setOnClickListener(this);
// Log.d("66", "btn1="+R.id.btn1);
// Log.d("66", "onCreate");
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1:
num++;
tvHint.setText(num+"");
break;
case R.id.btn2:
num--;
tvHint.setText(num+"");
break;
case R.id.login:
LoginClickListener.isLogin = true;
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
break;
case R.id.logout:
LoginClickListener.isLogin = false;
Toast.makeText(this, "取消登录", Toast.LENGTH_SHORT).show();
break;
case R.id.start:
startActivity(new Intent(this, MainActivity2.class));
break;
}
}
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/UnifiedDoubleClick.java
================================================
package com.liys.doubleclickdemo;
import com.liys.doubleclickdemo.fragment.MainActivity2;
import com.liys.doubleclicklibrary.annotation.AAddDoubleClick;
import com.liys.doubleclicklibrary.annotation.AClickListener;
/**
* @Description: 统一处理 DoubleClick
* @Author: liys
* @CreateDate: 2019/8/26 16:46
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/26 16:46
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public interface UnifiedDoubleClick{
// >>>>>>>>>>>>>>>>>>>屏蔽DoubleClick的Activity>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// @ACancelActivity(activitys = {
// MainActivity.class,
// })
// void cancelActivity();
// >>>>>>>>>>>>>>>>>>>单个view处理>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// @AAddDoubleClick(activity = MainActivity.class,
// addIds = {R.id.btn1, R.id.btn2},
// times = {2000, 0})
// void mainActivity();
@AAddDoubleClick(activity = MainActivity2.class,
addIds = {R.id.btn_add_fragment, R.id.btn_fragment},
times = {2000, 2000})
void mainActivity2();
// >>>>>>>>>>>>>>>>>自定义click拦截器>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@AClickListener(activity = MainActivity.class,
lisenner = LoginClickListener.class,
ids = {R.id.btn2})
void interceptMain();
@AClickListener(activity = MainActivity2.class,
lisenner = LoginClickListener.class,
ids = {R.id.btn_add_fragment, R.id.btn_fragment})
void interceptMain2();
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/UnifiedDoubleClick2.java
================================================
package com.liys.doubleclickdemo;
import com.liys.doubleclicklibrary.annotation.ACancelActivity;
/**
* @Description: 统一处理 DoubleClick
* @Author: liys
* @CreateDate: 2019/8/26 16:46
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/26 16:46
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public interface UnifiedDoubleClick2 {
// >>>>>>>>>>>>>>>>>>>屏蔽DoubleClick的Activity>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@ACancelActivity(activitys = {
MainActivity.class,
})
void cancelActivity();
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/fragment/MainActivity2.java
================================================
package com.liys.doubleclickdemo.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import com.liys.doubleclickdemo.R;
public class MainActivity2 extends AppCompatActivity implements OnClickListener{
ViewPager viewPage;
TextView tvNum;
int num = 0;
MyFragment myFragment = new MyFragment();
MyFragment2 myFragment2 = new MyFragment2();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
viewPage = findViewById(R.id.viewPage);
tvNum = findViewById(R.id.tv_num);
findViewById(R.id.btn_add_fragment).setOnClickListener(this);
findViewById(R.id.btn_add_fragment2).setOnClickListener(this);
findViewById(R.id.btn_add).setOnClickListener(this);
viewPage.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int i) {
if(i==0){
return myFragment;
}
return myFragment2;
}
@Override
public int getCount() {
return 2;
}
});
}
Fragment curFragment;
@Override
public void onClick(View v) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch (v.getId()){
case R.id.btn_add_fragment:
// transaction.replace(R.id.myFragment, myFragment);
// transaction.commit();
if(myFragment.isAdded()){
transaction
.hide(myFragment2)
.show(myFragment)
.commit();
}else{
transaction
.hide(myFragment2)
.add(R.id.myFragment, myFragment)
.show(myFragment)
.commit();
}
break;
case R.id.btn_add_fragment2:
if(myFragment2.isAdded()){
transaction
.hide(myFragment)
.show(myFragment2)
.commit();
}else{
transaction
.hide(myFragment)
.add(R.id.myFragment, myFragment2)
.show(myFragment2)
.commit();
}
break;
case R.id.btn_fragment:
num--;
tvNum.setText(num+"");
break;
case R.id.btn_add:
num++;
tvNum.setText(num+"");
break;
}
}
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/fragment/MyFragment.java
================================================
package com.liys.doubleclickdemo.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.liys.doubleclickdemo.R;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/28 13:45
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/28 13:45
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class MyFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
view.findViewById(R.id.btn_fragment).setOnClickListener((View.OnClickListener)getActivity());
return view;
}
}
================================================
FILE: app/src/main/java/com/liys/doubleclickdemo/fragment/MyFragment2.java
================================================
package com.liys.doubleclickdemo.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.liys.doubleclickdemo.R;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/28 13:45
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/28 13:45
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class MyFragment2 extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my2, container, false);
view.findViewById(R.id.btn_fragment).setOnClickListener((View.OnClickListener)getActivity());
return view;
}
}
================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
================================================
FILE: app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_main2.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_my.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_my2.xml
================================================
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
================================================
FILE: app/src/main/res/values/colors.xml
================================================
#008577
#00574B
#D81B60
================================================
FILE: app/src/main/res/values/strings.xml
================================================
DoubleClickDemo
================================================
FILE: app/src/main/res/values/styles.xml
================================================
================================================
FILE: app/src/test/java/com/liys/doubleclickdemo/ExampleUnitTest.java
================================================
package com.liys.doubleclickdemo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: doubleclicklibrary/.gitignore
================================================
/build
================================================
FILE: doubleclicklibrary/build.gradle
================================================
apply plugin: 'com.android.library'
//apply plugin: 'android-aspectjx'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 15
targetSdkVersion 26
versionCode 6
versionName "3.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// api 'org.aspectj:aspectjrt:1.8.9'
implementation 'org.aspectj:aspectjrt:1.8.9'
}
================================================
FILE: doubleclicklibrary/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: doubleclicklibrary/src/androidTest/java/com/liys/doubleclicklibrary/ExampleInstrumentedTest.java
================================================
package com.liys.doubleclicklibrary;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.liys.doubleclicklibrary.test", appContext.getPackageName());
}
}
================================================
FILE: doubleclicklibrary/src/main/AndroidManifest.xml
================================================
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/DoubleClickHelper.java
================================================
package com.liys.doubleclicklibrary;
import android.view.View;
import com.liys.doubleclicklibrary.aspect.Attrs;
import com.liys.doubleclicklibrary.hook.BaseHookView;
import com.liys.doubleclicklibrary.hook.IHookView;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/11/20
* @UpdateUser: 更新者
* @UpdateDate: 2019/11/20
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class DoubleClickHelper {
private static IHookView mIHookView;
private static DoubleClickHelper doubleClickHelper = new DoubleClickHelper();
public static DoubleClickHelper getInstance(){
return doubleClickHelper;
}
public DoubleClickHelper delayTime(long delayTime){
Attrs.delayTime = delayTime;
return this;
}
public DoubleClickHelper addAnnotationClass(Class annotationClass){
Attrs.addAnnotationClass(annotationClass);
return this;
}
public static void openAll(){
Attrs.isOpen = true;
}
public static void closeAll(){
Attrs.isOpen = false;
}
public static void hookView(final View view, final long delayTime){
if(mIHookView==null){
mIHookView = new BaseHookView();
}
view.post(new Runnable() {
@Override
public void run() {
mIHookView.hookView(view, delayTime);
}
});
}
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/AAddDoubleClick.java
================================================
package com.liys.doubleclicklibrary.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/27 12:19
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/27 12:19
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AAddDoubleClick {
Class activity();
int[] addIds();
long[] times();
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/ACancelActivity.java
================================================
package com.liys.doubleclicklibrary.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/27 12:19
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/27 12:19
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ACancelActivity {
Class[] activitys();
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/AClickListener.java
================================================
package com.liys.doubleclicklibrary.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/27 17:27
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/27 17:27
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AClickListener {
Class activity();
Class lisenner();
int[] ids();
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/helper/AnnotationHelper.java
================================================
package com.liys.doubleclicklibrary.annotation.helper;
import com.liys.doubleclicklibrary.annotation.AAddDoubleClick;
import com.liys.doubleclicklibrary.annotation.ACancelActivity;
import com.liys.doubleclicklibrary.annotation.AClickListener;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 解析注解
* @Author: liys
* @CreateDate: 2019/8/27 14:29
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/27 14:29
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class AnnotationHelper {
/**
* 获取ACancelActivity集合
* @param annotationClass
*/
public static Map getACancelActivity(Class annotationClass){
Map classMap = new HashMap<>();
Method[] methods = annotationClass.getDeclaredMethods(); //解析方法上的注解
for(Method method : methods){
boolean methodHasAnno = method.isAnnotationPresent(ACancelActivity.class);
if(methodHasAnno){
ACancelActivity methodAnno = method.getAnnotation(ACancelActivity.class); //得到注解
Class[] clazzs = methodAnno.activitys();
for (int i = 0; i < clazzs.length; i++) {
classMap.put(clazzs[i], clazzs[i].getName());
}
return classMap;
}
}
return classMap;
}
/**
* 获取AAddDoubleClick集合
* @param
*/
public static Map> getAddDoubleClick(Class annotationClass){
Map> addViewMap = new HashMap<>();
Method[] methods = annotationClass.getDeclaredMethods(); //解析方法上的注解
for(Method method : methods){
boolean methodHasAnno = method.isAnnotationPresent(AAddDoubleClick.class);
if(methodHasAnno){
AAddDoubleClick methodAnno = method.getAnnotation(AAddDoubleClick.class); //得到注解
Class clazz = methodAnno.activity();
int[] ids = methodAnno.addIds();
long[] times = methodAnno.times();
Map idsMap = new HashMap<>();
for (int i = 0; i < ids.length; i++) {
idsMap.put(ids[i], times[i]);
}
addViewMap.put(clazz, idsMap);
}
}
return addViewMap;
}
/**
* 获取AClickListener集合
* @param annotationClass
* @return
*/
public static Map> getClickListener(Class annotationClass){
Map> viewListenerMap = new HashMap<>();
Method[] methods = annotationClass.getDeclaredMethods(); //解析方法上的注解
for(Method method : methods){
boolean methodHasAnno = method.isAnnotationPresent(AClickListener.class);
if(methodHasAnno){
AClickListener methodAnno = method.getAnnotation(AClickListener.class); //得到注解
Class activityClazz = methodAnno.activity();
Class lisennerClazz = methodAnno.lisenner();
int[] ids = methodAnno.ids();
Map idsMap = new HashMap<>();
for (int i = 0; i < ids.length; i++) {
idsMap.put(ids[i], lisennerClazz);
}
viewListenerMap.put(activityClazz, idsMap);
}
}
return viewListenerMap;
}
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/aspect/AspectDoubleClick.java
================================================
package com.liys.doubleclicklibrary.aspect;
import android.view.View;
import com.liys.doubleclicklibrary.listener.IOnClickListener;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import java.util.Map;
/**
* @Description: AOP主要类
* @Author: liys
* @CreateDate: 2019/11/18 20:48
* @UpdateUser: 更新者
* @UpdateDate: 2019/11/18 20:48
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
@Aspect
public class AspectDoubleClick{
private IOnClickListener iOnClickListener = null;
private long lastTime; //上次间隔时间
private View lastView; //点击的view
@Around("execution(* android.view.View.OnClickListener.onClick(..))")
public void onClickListener(ProceedingJoinPoint joinPoint) throws Throwable {
if(!Attrs.isOpen){ //未打开拦截
joinPoint.proceed();
return;
}
Object[] args = joinPoint.getArgs();
View view = (View)args[0];
if(view != lastView){ //不是同一个View直接过
iOnClickListener = null; //还原
setListenerAnnotation(view); //拦截信息
execution(joinPoint, view);
Attrs.annotationDelayTime = -1; //还原
setViewAnnotation(view); //View
lastView = view;
lastTime = System.currentTimeMillis();
return;
}
long delayTime = Attrs.delayTime; //默认值
if(Attrs.annotationDelayTime != -1){
delayTime = Attrs.annotationDelayTime;
}
//4.执行
if(System.currentTimeMillis()- lastTime >= delayTime){
execution(joinPoint, view);
lastTime = System.currentTimeMillis();
lastView = view;
}
}
//继续执行
private void execution(ProceedingJoinPoint joinPoint, View view){
try {
if(iOnClickListener == null){ //无拦截
joinPoint.proceed();
}else{
if(iOnClickListener.isNext(view)){ //继续执行
joinPoint.proceed();
iOnClickListener.after(view);
}
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
//解析View注解信息
private void setViewAnnotation(View view){
Class activityClass = view.getContext().getClass();
//1.对应Activity取消的话
if(Attrs.mCancelClassMap.containsKey(activityClass)){ //取消
Attrs.annotationDelayTime = 0;
}
//2.单个View添加
if(Attrs.mAddViewMap.containsKey(activityClass)){
Map viewMap = Attrs.mAddViewMap.get(activityClass);
if(viewMap.containsKey(view.getId())){
Attrs.annotationDelayTime = viewMap.get(view.getId());
}
}
}
//解析Listener注解信息
private void setListenerAnnotation(View view) {
Class activityClass = view.getContext().getClass();
//3. onclick前后插入自定义方法
if (Attrs.mViewListenerMap.containsKey(activityClass)) {
Map viewMap = Attrs.mViewListenerMap.get(activityClass);
if (viewMap.containsKey(view.getId())) {
try {
Object obj = viewMap.get(view.getId()).newInstance();
if (obj instanceof IOnClickListener) {
iOnClickListener = (IOnClickListener) obj;
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/aspect/Attrs.java
================================================
package com.liys.doubleclicklibrary.aspect;
import com.liys.doubleclicklibrary.annotation.helper.AnnotationHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: 传递进来的属性
* @Author: liys
* @CreateDate: 2019/11/23 21:42
* @UpdateUser: 更新者
* @UpdateDate: 2019/11/23 21:42
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class Attrs {
public static boolean isOpen = true; //是否打开
public static long delayTime = 500; //全局间隔时间
public static long annotationDelayTime = -1; //注解里面设置的时间, 如果没有设置,设为-1
private static List mAnnotationClassList = new ArrayList<>(); //注解类--集合
public static Map mCancelClassMap = new HashMap<>(); //取消的Activity
public static Map> mAddViewMap = new HashMap<>(); //单个添加
public static Map> mViewListenerMap = new HashMap<>(); //拦截 并自定义click
public static void addAnnotationClass(Class annotationClass) {
if(annotationClass == null ){
return;
}
if(!mAnnotationClassList.contains(annotationClass)){ //添加注解类信息
mAnnotationClassList.add(annotationClass);
mCancelClassMap.putAll(AnnotationHelper.getACancelActivity(annotationClass));
mAddViewMap.putAll(AnnotationHelper.getAddDoubleClick(annotationClass));
mViewListenerMap.putAll(AnnotationHelper.getClickListener(annotationClass));
}
}
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/BaseHookView.java
================================================
package com.liys.doubleclicklibrary.hook;
import android.annotation.SuppressLint;
import android.view.View;
import com.liys.doubleclicklibrary.listener.IOnClickListener;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/26 17:24
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/26 17:24
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class BaseHookView implements IHookView {
/**
* hook点击事件
* @param view
* @param delayTime
* @param iOnClickListener 替换成自定义监听器
*/
@Override
public void hookView(View view, long delayTime) {
try {
Class viewClazz = Class.forName("android.view.View");
//事件监听器都是这个实例保存的
Method listenerInfoMethod = viewClazz.getDeclaredMethod("getListenerInfo");
if (!listenerInfoMethod.isAccessible()) {
listenerInfoMethod.setAccessible(true);
}
Object listenerInfoObj = listenerInfoMethod.invoke(view);
@SuppressLint("PrivateApi")
Class listenerInfoClazz = Class.forName("android.view.View$ListenerInfo");
Field onClickListenerField = listenerInfoClazz.getDeclaredField("mOnClickListener");
//修改修饰符带来不能访问的问题
if (!onClickListenerField.isAccessible()) {
onClickListenerField.setAccessible(true);
}
View.OnClickListener mOnClickListener = (View.OnClickListener) onClickListenerField.get(listenerInfoObj);
HookOnClickListener hookOnClickListener = new HookOnClickListener(delayTime);
if(!(mOnClickListener instanceof HookOnClickListener)) { //没有hook过
hookOnClickListener.setOnclickListener(mOnClickListener);
}
//更换成自己的点击事件
onClickListenerField.set(listenerInfoObj, hookOnClickListener);
} catch (Exception e) {
e.printStackTrace();
}
}
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/HookOnClickListener.java
================================================
package com.liys.doubleclicklibrary.hook;
import android.view.View;
import java.util.Calendar;
/**
* @Description: 默认事件监听器
* @Author: liys
* @CreateDate: 2019/8/22 10:25
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/22 10:25
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class HookOnClickListener implements View.OnClickListener{
private long min_click_delay_time = 500; //点击最小间隔时间
private long lastClickTime = 0;
private View.OnClickListener onClickListener;
public HookOnClickListener() {}
public HookOnClickListener(long min_click_delay_time) {
this.min_click_delay_time = min_click_delay_time;
}
public void setOnclickListener(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
@Override
public void onClick(View v) {
long currentTime = Calendar.getInstance().getTimeInMillis();
if (currentTime - lastClickTime > min_click_delay_time) {
onClickListener.onClick(v);
lastClickTime = currentTime;
}
}
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/IHookView.java
================================================
package com.liys.doubleclicklibrary.hook;
import android.view.View;
/**
* @Description:
* @Author: liys
* @CreateDate: 2019/8/22 11:46
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/22 11:46
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public interface IHookView {
/**
* hook单个View
* @param view 需要hook的view
* @param delayTime 间隔时间
*/
void hookView(final View view, final long delayTime);
}
================================================
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/listener/IOnClickListener.java
================================================
package com.liys.doubleclicklibrary.listener;
import android.view.View;
/**
* @Description: 自定义拦截onclick
* @Author: liys
* @CreateDate: 2019/11/23 21:23
* @UpdateUser: 更新者
* @UpdateDate: 2019/11/23 10:46
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public interface IOnClickListener {
/**
* 是否继续往下执行(click前执行)
* @return
*/
boolean isNext(View view);
/**
* 执行完click之后
* @param view
*/
void after(View view);
}
================================================
FILE: doubleclicklibrary/src/main/res/values/strings.xml
================================================
DoubleClickLibrary
================================================
FILE: doubleclicklibrary/src/test/java/com/liys/doubleclicklibrary/ExampleUnitTest.java
================================================
package com.liys.doubleclicklibrary;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app', ':doubleclicklibrary'