【仙女】Android获取全部控件的点击事件

PageViewInfo

获取Android页面全部控件的点击事件java

GitHub issues
GitHub forks
GitHub stars
GitHub license
Travis CI


github地址android

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

Table of Contents

分三种方法实现github

FrameLayout方式

代码实现
PageViewLifecycleHelper.with(this).addPageViewListener(PageViewType.frameLayout,basePageViewListener)
复制代码
参数说明
参数 参数类型 参数说明
PageViewType.frameLayout int 具体实现方式
basePageViewListener BasePageViewListener 点击回调
BasePageViewListener回调

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

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

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

参数 参数类型 参数说明
parent AdapterView 当前的AdapterView
view View 当前的AdapterView的item的view的布局
position int 当前item在AdapterView中适配器里的位置
id long 当前item在AdapterView中的行数

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

参数 参数类型 参数说明
parent AdapterView 当前的AdapterView
view View 当前的AdapterView的item的view的布局
position int 当前item在AdapterView中适配器里的位置
id long 当前item在AdapterView中的行数

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

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

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

参数 参数类型 参数说明
recyclerView RecyclerView 当前的RecyclerView
view View 当前的RecyclerView的item的view的布局
position int 当前item在RecyclerView中适配器里的位置
原理说明
  1. 在Application中经过registerActivityLifecycleCallbacks来注册Activity的生命周期。
  2. 在onActivityStarted对当前页面的View进行遍历并保存至List中。
  3. 在每个Activity的最外层实现FrameLayout。
  4. 经过onInterceptTouchEvent的触摸事件来遍历View来实现。
  5. 对AdapterView与RecyclerView则经过重写点击事件来实现。
  6. 在onActivityPaused对当前页面的View进行清空。

反射方式

代码实现
PageViewLifecycleHelper.with(this).addPageViewListener(PageViewType.hookView,basePageViewListener)
复制代码
参数说明
参数 参数类型 参数说明
PageViewType.frameLayout int 具体实现方式
basePageViewListener BasePageViewListener 点击回调
原理说明
  1. 在Application中经过registerActivityLifecycleCallbacks来注册Activity的生命周期。
  2. 在onActivityStarted对当前页面的View进行遍历并保存至List中。
  3. 反射在View的mOnClickListener中设置自定义的点击事件。
  4. 对AdapterView与RecyclerView则经过重写点击事件来实现。
  5. 在onActivityPaused对当前页面的View进行清空。

AOP方式

代码实现
PageViewAspectjHelper.with().setBasePageViewListener(basePageViewListener)
复制代码
参数说明
参数 参数类型 参数说明
basePageViewListener BasePageViewListener 点击回调
原理说明
  1. 经过Aspectj框架来对全局的View进行切入。
  2. 使用@Aspect表示切入的类。
  3. 使用@After在切入的方法执行异步执行自定义的相关逻辑。

疑问解答

Aspectj框架的集成方式

现阶段有开源的框架,能够简单的在Android中使用,如gradle_plugin_android_aspectjx。 若是想本身集成,则步骤以下:svg

  • 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等等。

相关文章
相关标签/搜索