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
================================================
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
</code_scheme>
</component>
================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/doubleclicklibrary" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="7">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="6">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8 (3)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
================================================
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<CustomHookBean> getCustomHookList() {
int[] ids = {R.id.btn1, R.id.btn2}; //需要处理的id
List<CustomHookBean> 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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@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
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.liys.doubleclickdemo">
<application
android:name=".AppApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".fragment.MainActivity2"/>
</application>
</manifest>
================================================
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
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
================================================
FILE: app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeWidth="1"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮1"/>
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮2"/>
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="no"
android:text="登录"/>
<Button
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="no"
android:text="取消登录"/>
</LinearLayout>
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="no"
android:text="跳转"/>
<TextView
android:id="@+id/tv_hint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="100sp"
android:text="0"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/activity_main2.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_add_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="add_fragment"/>
<Button
android:id="@+id/btn_add_fragment2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="add_fragment2"/>
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="activity++"/>
<FrameLayout
android:id="@+id/myFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewPage"
android:layout_width="match_parent"
android:layout_height="100dp"/>
<TextView
android:id="@+id/tv_num"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:textSize="50sp"
android:text="0"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/fragment_my.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<Button
android:id="@+id/btn_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="btn_fragment1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="Fragment1"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/fragment_my2.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<Button
android:id="@+id/btn_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="btn_fragment2"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="Fragment2"/>
</LinearLayout>
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>
================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">DoubleClickDemo</string>
</resources>
================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
================================================
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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@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
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.liys.doubleclicklibrary" />
================================================
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<Class, String> getACancelActivity(Class annotationClass){
Map<Class, String> 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<Class, Map<Integer, Long>> getAddDoubleClick(Class annotationClass){
Map<Class, Map<Integer, Long>> 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<Integer, Long> 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<Class, Map<Integer, Class>> getClickListener(Class annotationClass){
Map<Class, Map<Integer, Class>> 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<Integer, Class> 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<Integer, Long> 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<Integer, Class> 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<Class> mAnnotationClassList = new ArrayList<>(); //注解类--集合
public static Map<Class, String> mCancelClassMap = new HashMap<>(); //取消的Activity
public static Map<Class, Map<Integer, Long>> mAddViewMap = new HashMap<>(); //单个添加
public static Map<Class, Map<Integer, Class>> 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
================================================
<resources>
<string name="app_name">DoubleClickLibrary</string>
</resources>
================================================
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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
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'
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
SYMBOL INDEX (64 symbols across 21 files)
FILE: app/src/androidTest/java/com/liys/doubleclickdemo/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 19) | @Test
FILE: app/src/main/java/com/liys/doubleclickdemo/AppApplication.java
class AppApplication (line 16) | public class AppApplication extends Application{
method onCreate (line 18) | @Override
FILE: app/src/main/java/com/liys/doubleclickdemo/LogUtil.java
class LogUtil (line 14) | public class LogUtil {
method e (line 20) | public static void e(String msg) {
method d (line 24) | public static void d(String msg) {
method i (line 28) | public static void i(String msg) {
method w (line 32) | public static void w(String msg) {
FILE: app/src/main/java/com/liys/doubleclickdemo/LoginClickListener.java
class LoginClickListener (line 18) | public class LoginClickListener implements IOnClickListener {
method isNext (line 22) | @Override
method after (line 33) | @Override
FILE: app/src/main/java/com/liys/doubleclickdemo/MainActivity.java
class MainActivity (line 13) | public class MainActivity extends AppCompatActivity implements View.OnCl...
method onCreate (line 18) | @Override
method onClick (line 35) | @Override
FILE: app/src/main/java/com/liys/doubleclickdemo/UnifiedDoubleClick.java
type UnifiedDoubleClick (line 16) | public interface UnifiedDoubleClick{
method mainActivity2 (line 33) | @AAddDoubleClick(activity = MainActivity2.class,
method interceptMain (line 41) | @AClickListener(activity = MainActivity.class,
method interceptMain2 (line 46) | @AClickListener(activity = MainActivity2.class,
FILE: app/src/main/java/com/liys/doubleclickdemo/UnifiedDoubleClick2.java
type UnifiedDoubleClick2 (line 14) | public interface UnifiedDoubleClick2 {
method cancelActivity (line 18) | @ACancelActivity(activitys = {
FILE: app/src/main/java/com/liys/doubleclickdemo/fragment/MainActivity2.java
class MainActivity2 (line 15) | public class MainActivity2 extends AppCompatActivity implements OnClickL...
method onCreate (line 24) | @Override
method onClick (line 53) | @Override
FILE: app/src/main/java/com/liys/doubleclickdemo/fragment/MyFragment.java
class MyFragment (line 22) | public class MyFragment extends Fragment {
method onCreateView (line 24) | @Override
FILE: app/src/main/java/com/liys/doubleclickdemo/fragment/MyFragment2.java
class MyFragment2 (line 22) | public class MyFragment2 extends Fragment {
method onCreateView (line 24) | @Override
FILE: app/src/test/java/com/liys/doubleclickdemo/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
FILE: doubleclicklibrary/src/androidTest/java/com/liys/doubleclicklibrary/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 19) | @Test
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/DoubleClickHelper.java
class DoubleClickHelper (line 18) | public class DoubleClickHelper {
method getInstance (line 23) | public static DoubleClickHelper getInstance(){
method delayTime (line 27) | public DoubleClickHelper delayTime(long delayTime){
method addAnnotationClass (line 32) | public DoubleClickHelper addAnnotationClass(Class annotationClass){
method openAll (line 38) | public static void openAll(){
method closeAll (line 42) | public static void closeAll(){
method hookView (line 46) | public static void hookView(final View view, final long delayTime){
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/helper/AnnotationHelper.java
class AnnotationHelper (line 20) | public class AnnotationHelper {
method getACancelActivity (line 26) | public static Map<Class, String> getACancelActivity(Class annotationCl...
method getAddDoubleClick (line 48) | public static Map<Class, Map<Integer, Long>> getAddDoubleClick(Class a...
method getClickListener (line 74) | public static Map<Class, Map<Integer, Class>> getClickListener(Class a...
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/aspect/AspectDoubleClick.java
class AspectDoubleClick (line 22) | @Aspect
method onClickListener (line 30) | @Around("execution(* android.view.View.OnClickListener.onClick(..))")
method execution (line 65) | private void execution(ProceedingJoinPoint joinPoint, View view){
method setViewAnnotation (line 81) | private void setViewAnnotation(View view){
method setListenerAnnotation (line 99) | private void setListenerAnnotation(View view) {
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/aspect/Attrs.java
class Attrs (line 19) | public class Attrs {
method addAnnotationClass (line 31) | public static void addAnnotationClass(Class annotationClass) {
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/BaseHookView.java
class BaseHookView (line 20) | public class BaseHookView implements IHookView {
method hookView (line 29) | @Override
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/HookOnClickListener.java
class HookOnClickListener (line 16) | public class HookOnClickListener implements View.OnClickListener{
method HookOnClickListener (line 22) | public HookOnClickListener() {}
method HookOnClickListener (line 24) | public HookOnClickListener(long min_click_delay_time) {
method setOnclickListener (line 28) | public void setOnclickListener(View.OnClickListener onClickListener) {
method onClick (line 33) | @Override
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/IHookView.java
type IHookView (line 14) | public interface IHookView {
method hookView (line 21) | void hookView(final View view, final long delayTime);
FILE: doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/listener/IOnClickListener.java
type IOnClickListener (line 14) | public interface IOnClickListener {
method isNext (line 20) | boolean isNext(View view);
method after (line 26) | void after(View view);
FILE: doubleclicklibrary/src/test/java/com/liys/doubleclicklibrary/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
Condensed preview — 60 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (81K chars).
[
{
"path": ".gitignore",
"chars": 176,
"preview": "*.iml\n.gradle\n/local.properties\n/.idea/caches/build_file_checksums.ser\n/.idea/libraries\n/.idea/modules.xml\n/.idea/worksp"
},
{
"path": ".idea/codeStyles/Project.xml",
"chars": 1775,
"preview": "<component name=\"ProjectCodeStyleConfiguration\">\n <code_scheme name=\"Project\" version=\"173\">\n <Objective-C-extension"
},
{
"path": ".idea/gradle.xml",
"chars": 690,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"GradleSettings\">\n <option name=\"linke"
},
{
"path": ".idea/misc.xml",
"chars": 2105,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"NullableNotNullManager\">\n <option nam"
},
{
"path": ".idea/runConfigurations.xml",
"chars": 564,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"RunConfigurationProducerService\">\n <o"
},
{
"path": ".idea/vcs.xml",
"chars": 167,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": "README.md",
"chars": 2830,
"preview": "# DoubleClick\n\n简书: \n[DoubleClick---3.0版本](https://www.jianshu.com/p/daac21821c43)\n\n[DoubleClick---2.0版本](https://www.jia"
},
{
"path": "README1.0.4.md",
"chars": 2631,
"preview": "# DoubleClick\n# 一. 基本使用\n框架主要有两个功能(基本用法): \n\n**1. 无入侵解决按钮重复点击.** [使用方法](https://www.jianshu.com/p/7f3e5c8b8643)\n\n**2. onCl"
},
{
"path": "README2.0.6.md",
"chars": 3117,
"preview": "# DoubleClick\nV2.0 的使用方法: \n\n简书: https://www.jianshu.com/p/df0ef3866cc1\nCSDN: https://blog.csdn.net/qq_33199629/article/d"
},
{
"path": "app/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "app/build.gradle",
"chars": 1014,
"preview": "apply plugin: 'com.android.application'\napply plugin: 'android-aspectjx'\n\nandroid {\n compileSdkVersion 28\n default"
},
{
"path": "app/proguard-rules.pro",
"chars": 751,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "app/src/androidTest/java/com/liys/doubleclickdemo/ExampleInstrumentedTest.java",
"chars": 732,
"preview": "package com.liys.doubleclickdemo;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\n"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 915,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:to"
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/AppApplication.java",
"chars": 640,
"preview": "package com.liys.doubleclickdemo;\n\nimport android.app.Application;\n\nimport com.liys.doubleclicklibrary.DoubleClickHelper"
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/LogUtil.java",
"chars": 706,
"preview": "package com.liys.doubleclickdemo;\n\nimport android.util.Log;\n\n/**\n * @Description: 输出日志\n * @Author: liys\n * @CreateDate: "
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/LoginClickListener.java",
"chars": 745,
"preview": "package com.liys.doubleclickdemo;\n\nimport android.view.View;\nimport android.widget.Toast;\n\nimport com.liys.doubleclickli"
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/MainActivity.java",
"chars": 1824,
"preview": "package com.liys.doubleclickdemo;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v7.ap"
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/UnifiedDoubleClick.java",
"chars": 1465,
"preview": "package com.liys.doubleclickdemo;\n\nimport com.liys.doubleclickdemo.fragment.MainActivity2;\nimport com.liys.doubleclickli"
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/UnifiedDoubleClick2.java",
"chars": 508,
"preview": "package com.liys.doubleclickdemo;\n\nimport com.liys.doubleclicklibrary.annotation.ACancelActivity;\n\n/**\n * @Description: "
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/fragment/MainActivity2.java",
"chars": 3174,
"preview": "package com.liys.doubleclickdemo.fragment;\n\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport and"
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/fragment/MyFragment.java",
"chars": 894,
"preview": "package com.liys.doubleclickdemo.fragment;\n\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport "
},
{
"path": "app/src/main/java/com/liys/doubleclickdemo/fragment/MyFragment2.java",
"chars": 896,
"preview": "package com.liys.doubleclickdemo.fragment;\n\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport "
},
{
"path": "app/src/main/res/drawable/ic_launcher_background.xml",
"chars": 5606,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:wi"
},
{
"path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
"chars": 1880,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:aapt=\"http://schemas.android.com/aapt\"\n "
},
{
"path": "app/src/main/res/layout/activity_main.xml",
"chars": 1714,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "app/src/main/res/layout/activity_main2.xml",
"chars": 1575,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "app/src/main/res/layout/fragment_my.xml",
"chars": 649,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/layout/fragment_my2.xml",
"chars": 649,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/values/colors.xml",
"chars": 208,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"colorPrimary\">#008577</color>\n <color name=\"color"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 78,
"preview": "<resources>\n <string name=\"app_name\">DoubleClickDemo</string>\n</resources>\n"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 383,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "app/src/test/java/com/liys/doubleclickdemo/ExampleUnitTest.java",
"chars": 385,
"preview": "package com.liys.doubleclickdemo;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit "
},
{
"path": "build.gradle",
"chars": 615,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n \n"
},
{
"path": "doubleclicklibrary/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "doubleclicklibrary/build.gradle",
"chars": 935,
"preview": "apply plugin: 'com.android.library'\n//apply plugin: 'android-aspectjx'\n\nandroid {\n compileSdkVersion 26\n\n\n\n defaul"
},
{
"path": "doubleclicklibrary/proguard-rules.pro",
"chars": 751,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "doubleclicklibrary/src/androidTest/java/com/liys/doubleclicklibrary/ExampleInstrumentedTest.java",
"chars": 743,
"preview": "package com.liys.doubleclicklibrary;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistr"
},
{
"path": "doubleclicklibrary/src/main/AndroidManifest.xml",
"chars": 114,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.liys.doubleclicklibrary\" />\n"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/DoubleClickHelper.java",
"chars": 1376,
"preview": "package com.liys.doubleclicklibrary;\n\nimport android.view.View;\n\nimport com.liys.doubleclicklibrary.aspect.Attrs;\nimport"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/AAddDoubleClick.java",
"chars": 542,
"preview": "package com.liys.doubleclicklibrary.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Re"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/ACancelActivity.java",
"chars": 504,
"preview": "package com.liys.doubleclicklibrary.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Re"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/AClickListener.java",
"chars": 542,
"preview": "package com.liys.doubleclicklibrary.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Re"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/annotation/helper/AnnotationHelper.java",
"chars": 3409,
"preview": "package com.liys.doubleclicklibrary.annotation.helper;\n\nimport com.liys.doubleclicklibrary.annotation.AAddDoubleClick;\ni"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/aspect/AspectDoubleClick.java",
"chars": 3634,
"preview": "package com.liys.doubleclicklibrary.aspect;\n\nimport android.view.View;\n\nimport com.liys.doubleclicklibrary.listener.IOnC"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/aspect/Attrs.java",
"chars": 1491,
"preview": "package com.liys.doubleclicklibrary.aspect;\n\nimport com.liys.doubleclicklibrary.annotation.helper.AnnotationHelper;\n\nimp"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/BaseHookView.java",
"chars": 1974,
"preview": "package com.liys.doubleclicklibrary.hook;\n\nimport android.annotation.SuppressLint;\nimport android.view.View;\n\nimport com"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/HookOnClickListener.java",
"chars": 1057,
"preview": "package com.liys.doubleclicklibrary.hook;\n\nimport android.view.View;\n\nimport java.util.Calendar;\n\n/**\n * @Description: 默"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/hook/IHookView.java",
"chars": 422,
"preview": "package com.liys.doubleclicklibrary.hook;\n\nimport android.view.View;\n\n/**\n * @Description:\n * @Author: liys\n * @CreateDa"
},
{
"path": "doubleclicklibrary/src/main/java/com/liys/doubleclicklibrary/listener/IOnClickListener.java",
"chars": 464,
"preview": "package com.liys.doubleclicklibrary.listener;\n\nimport android.view.View;\n\n/**\n * @Description: 自定义拦截onclick\n * @Author: "
},
{
"path": "doubleclicklibrary/src/main/res/values/strings.xml",
"chars": 81,
"preview": "<resources>\n <string name=\"app_name\">DoubleClickLibrary</string>\n</resources>\n"
},
{
"path": "doubleclicklibrary/src/test/java/com/liys/doubleclicklibrary/ExampleUnitTest.java",
"chars": 388,
"preview": "package com.liys.doubleclicklibrary;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local un"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 200,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "gradle.properties",
"chars": 727,
"preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
},
{
"path": "gradlew",
"chars": 5296,
"preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n## Gradle start up"
},
{
"path": "gradlew.bat",
"chars": 2176,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "settings.gradle",
"chars": 38,
"preview": "include ':app', ':doubleclicklibrary'\n"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the liys666666/DoubleClick GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 60 files (67.9 KB), approximately 20.7k tokens, and a symbol index with 64 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.