【仙女】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等等。

相關文章
相關標籤/搜索