java 检测点击事件控件,【仙女】Android获取所有控件的点击事件

PageViewInfo

获取Android页面所有控件的点击事件

PageViewInfo.svg

PageViewInfo.svg

PageViewInfo.svg

PageViewInfo.svg

1

\

本产品不提供远程依赖,仅提供思路与实现方式

Table of Contents

分三种方法实现

FrameLayout方式

代码实现

PageViewLifecycleHelper.with(this).addPageViewListener(PageViewType.frameLayout,basePageViewListener)

复制代码

参数说明

参数参数类型参数说明PageViewType.frameLayoutint具体实现方式

basePageViewListenerBasePageViewListener点击回调

BasePageViewListener回调

onClick(view) 普通View的点击事件

参数参数类型参数说明viewView当前点击的控件布局

onItemClick(parent,view,position,id) AdapterView的点击事件

参数参数类型参数说明parentAdapterView当前的AdapterView

viewView当前的AdapterView的item的view的布局

positionint当前item在AdapterView中适配器里的位置

idlong当前item在AdapterView中的行数

onItemSelected(parent,view,position,id) AdapterView的选择事件

参数参数类型参数说明parentAdapterView当前的AdapterView

viewView当前的AdapterView的item的view的布局

positionint当前item在AdapterView中适配器里的位置

idlong当前item在AdapterView中的行数

onNothingSelected(parent,view,position,id) AdapterView的未选择事件

参数参数类型参数说明parentAdapterView当前的AdapterView

onItemClick(RecyclerView recyclerView, View view, int position) RecyclerView的点击事件

参数参数类型参数说明recyclerViewRecyclerView当前的RecyclerView

viewView当前的RecyclerView的item的view的布局

positionint当前item在RecyclerView中适配器里的位置

原理说明

在Application中通过registerActivityLifecycleCallbacks来注册Activity的生命周期。

在onActivityStarted对当前页面的View进行遍历并保存至List中。

在每一个Activity的最外层实现FrameLayout。

通过onInterceptTouchEvent的触摸事件来遍历View来实现。

对AdapterView与RecyclerView则通过重写点击事件来实现。

在onActivityPaused对当前页面的View进行清空。

反射方式

代码实现

PageViewLifecycleHelper.with(this).addPageViewListener(PageViewType.hookView,basePageViewListener)

复制代码

参数说明

参数参数类型参数说明PageViewType.frameLayoutint具体实现方式

basePageViewListenerBasePageViewListener点击回调

原理说明

在Application中通过registerActivityLifecycleCallbacks来注册Activity的生命周期。

在onActivityStarted对当前页面的View进行遍历并保存至List中。

反射在View的mOnClickListener中设置自定义的点击事件。

对AdapterView与RecyclerView则通过重写点击事件来实现。

在onActivityPaused对当前页面的View进行清空。

AOP方式

代码实现

PageViewAspectjHelper.with().setBasePageViewListener(basePageViewListener)

复制代码

参数说明

参数参数类型参数说明basePageViewListenerBasePageViewListener点击回调

原理说明

通过Aspectj框架来对全局的View进行切入。

使用@Aspect表示切入的类。

使用@After在切入的方法执行异步执行自定义的相关逻辑。

疑问解答

Aspectj框架的集成方式

现阶段有开源的框架,可以简单的在Android中使用,如gradle_plugin_android_aspectjx。 如果想自己集成,则步骤如下:

在aspectj上找到最新的版本。

在项目的根build文件内加入相关依赖。如: classpath 'org.aspectj:aspectjtools:1.9.4'

在使用Aspectj的module中的build文件内加入相关代码与依赖。如

import com.android.build.gradle.LibraryPlugin

import org.aspectj.bridge.IMessage

import org.aspectj.bridge.MessageHandler

import org.aspectj.tools.ajc.Main

android.libraryVariants.all {

variant -> LibraryPlugin plugin = project.plugins.getPlugin(LibraryPlugin)

JavaCompile javaCompile = variant.javaCompile

javaCompile.doLast {

String[] args = ["-showWeaveInfo",

"-1.8",

"-inpath", javaCompile.destinationDir.toString(),

"-aspectpath", javaCompile.classpath.asPath,

"-d", javaCompile.destinationDir.toString(),

"-classpath", javaCompile.classpath.asPath,

"-bootclasspath", plugin.project.android.bootClasspath.join(

File.pathSeparator)]

MessageHandler handler = new MessageHandler(true)

new Main().run(args, handler)

def log = project.logger

for (IMessage message : handler.getMessages(null, true)) {

switch (message.getKind()) {

case IMessage.ABORT:

case IMessage.ERROR:

case IMessage.FAIL:

log.error message.message, message.thrown

break

case IMessage.WARNING:

case IMessage.INFO:

log.info message.message, message.thrown

break

case IMessage.DEBUG:

log.debug message.message, message.thrown

break

}

}

}

}

dependencies {

api 'org.aspectj:aspectjrt:1.9.4'

}

复制代码

在app中的build文件中加入相关代码,如:

import org.aspectj.bridge.IMessage

import org.aspectj.bridge.MessageHandler

import org.aspectj.tools.ajc.Main

final def log = project.logger

final def variants = project.android.applicationVariants

variants.all { variant ->

if (!variant.buildType.isDebuggable()) {

log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")

return

}

JavaCompile javaCompile = variant.javaCompile

javaCompile.doLast {

String[] args = ["-showWeaveInfo",

"-1.8",

"-inpath", javaCompile.destinationDir.toString(),

"-aspectpath", javaCompile.classpath.asPath,

"-d", javaCompile.destinationDir.toString(),

"-classpath", javaCompile.classpath.asPath,

"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]

log.debug "ajc args: " + Arrays.toString(args)

MessageHandler handler = new MessageHandler(true)

new Main().run(args, handler)

for (IMessage message : handler.getMessages(null, true)) {

switch (message.getKind()) {

case IMessage.ABORT:

case IMessage.ERROR:

case IMessage.FAIL:

log.error message.message, message.thrown

break

case IMessage.WARNING:

log.warn message.message, message.thrown

break

case IMessage.INFO:

log.info message.message, message.thrown

break

case IMessage.DEBUG:

log.debug message.message, message.thrown

break

}

}

}

}

复制代码

相关配置完成之后,即可根据相关方法来实现自己的逻辑。

三种方法的区别

AOP的方式侵入的更全面一点,动态的静态的布局都可以使用。但是只针对设置了相关方法的View才可以。比如View未设置OnClick事件则无法监听。

FrameLayout的方式只能获取到静态的布局,但是所有控件的点击都可以拿到,无论是否设置了相关方法。

反射的方式速度相对比较慢,但也是只能拿到静态布局。

获取更多View的点击方法

现阶段只获取了普通View,AdapterView,RecycleView这几个,当然同样的思路可以放在更多的View上,如:ExpandableListView等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值