日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

辅助模式最终考验的是想象力,先来看看怎么用!| Accessibility

發(fā)布時(shí)間:2024/4/14 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 辅助模式最终考验的是想象力,先来看看怎么用!| Accessibility 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、序

Hi,大家好,我是承香墨影!

Android 的輔助模式(Accessibility)功能非常的強(qiáng)大。基本上被獲取到授權(quán)之后,可以監(jiān)聽(tīng)手機(jī)上的任何事件,例如:屏幕點(diǎn)擊、窗口的變化、以及模擬點(diǎn)擊、模擬系統(tǒng)按鍵等等。

比較常見(jiàn)的實(shí)際使用例子,就是一般應(yīng)用市場(chǎng),會(huì)推薦開(kāi)啟輔助模式,以便在安裝 Apk 的時(shí)候,自動(dòng)幫你點(diǎn)擊“下一步”和“安裝”按鈕。還有個(gè)例子就是微信搶紅包插件,也是基于它來(lái)實(shí)現(xiàn)的。

Accessibility 的權(quán)限非常的高,基本上你授權(quán)開(kāi)啟某個(gè)別人提供的 AccessibilityService 之后,他就可以干很多事情而不讓你知道,而這些是不需要 Root 權(quán)限的。所以一般小體量的產(chǎn)品,可能支持它并沒(méi)有什么用,因?yàn)樾湃味忍土?#xff0c;大部分用戶(hù)根本不會(huì)打開(kāi)。比較常見(jiàn)的就是一些工具類(lèi)的 App,幫用戶(hù)節(jié)省一些點(diǎn)擊的時(shí)間。

雖然很多時(shí)候,Accessibility 不會(huì)被用在商業(yè)產(chǎn)品上,但是這并不妨礙我們使用 Accessibility 來(lái)做一些有意思的功能。

二、輔助模式的使用步驟

輔助模式是可以支持第三方開(kāi)發(fā),也就是我們可以按照文檔對(duì)其進(jìn)行支持,只要用戶(hù)授權(quán)開(kāi)啟此服務(wù),我們就可以利用 Accessibility 提供的一些標(biāo)準(zhǔn) Api 實(shí)現(xiàn)很多有意思的功能。

如果你想要使用輔助模式,你還需要如下步驟:

  • 實(shí)現(xiàn)一個(gè)繼承自 AccessibilityService 的服務(wù)類(lèi)。
  • 設(shè)定配置信息,以便系統(tǒng)知道該輔助模式的一些基本信息,例如監(jiān)聽(tīng)那些事件。
  • 在清單文件(AndroidManifest.xml)中,注冊(cè)此服務(wù)。
  • 在系統(tǒng)設(shè)置中,找到“無(wú)障礙”,并開(kāi)啟此服務(wù)。
  • 接下來(lái)我們一步一步講解這里的步驟和細(xì)節(jié)。

    2.1 繼承 AccessibilityService

    輔助模式,本質(zhì)上還是一個(gè)服務(wù),我們?nèi)绻胍С炙?#xff0c;首先需要繼承 AccessibilityService 這個(gè)類(lèi)。

    AccessibilityService 類(lèi)提供了很多需要重寫(xiě)的方法,其中有兩個(gè)是強(qiáng)制重寫(xiě)的:

    public abstract void onAccessibilityEvent(AccessibilityEvent event); public abstract void onInterrupt();

    當(dāng)開(kāi)啟了某個(gè) AccessibilityService 服務(wù)之后,系統(tǒng)會(huì)在該服務(wù)監(jiān)聽(tīng)的事件發(fā)生的時(shí)候,回調(diào)它的 onAccessibilityEvent() 方法,并將該事件的信息當(dāng)參數(shù)傳遞過(guò)去,如果你監(jiān)聽(tīng)的事件足夠多,它就會(huì)被頻繁調(diào)用。

    而 onInterrupt() 方法會(huì)在系統(tǒng)事件被打斷的時(shí)候回調(diào),也是會(huì)被頻繁調(diào)用,一般我們不需要做額外處理。

    通常我們只需要在 onAccessibilityEvent() 方法中,編寫(xiě)核心邏輯即可,其他的方法,只是輔助使用。

    2.2 配置輔助模式

    當(dāng)創(chuàng)建一個(gè) AccessibilityService 之后,我們還需要對(duì)其進(jìn)行一些基本的配置,否則在系統(tǒng)設(shè)置的“無(wú)障礙”中,是看不到我們編寫(xiě)的服務(wù)的。

    配置 AccessibilityService 有兩種方式,

    • 通過(guò) xml 配置文件
    • 通過(guò) Java 代碼中動(dòng)態(tài)配置。

    但是其實(shí)有一些屬性是只能通過(guò) XML 配置文件進(jìn)行配置的,Java 代碼只是讓某一些配置項(xiàng)更靈活了而已,后面會(huì)細(xì)說(shuō)。

    1、xml 配置文件

    想要使用 XML 配置文件,首先需要?jiǎng)?chuàng)建一個(gè) res/xml 的目錄,并在其內(nèi)創(chuàng)建一個(gè) xml 文件,文件名隨意無(wú)要求,內(nèi)部定義一個(gè) accessibility-service 標(biāo)簽,在其中設(shè)定 AccessibilityService 的各項(xiàng)配置。例如我這里創(chuàng)建一個(gè) accessibility_config.xml 的文件,后面會(huì)用到這個(gè)文件。

    XML 配置 AccessibilityService 是我們一個(gè)比較常用的配置方法,非常清晰且方便。

    <accessibility-servicexmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"android:accessibilityFeedbackType="feedbackAllMask"android:accessibilityFlags="flagReportViewIds"android:canRetrieveWindowContent="true"android:packageNames="com.forwarding.wechat"android:description="@string/accessbility_desc"android:notificationTimeout="100" />

    例如上面就是一個(gè)常見(jiàn)的配置,如果沒(méi)有特殊要求的話,直接復(fù)制過(guò)去,修改一些個(gè)別參數(shù)就可以使用。

    各項(xiàng)屬性的含義:

    • accessibilityEventTypes:監(jiān)聽(tīng)的事件類(lèi)型,例如:typeAllMask 表示全部事件,而 typeViewClicked 表示只監(jiān)聽(tīng)點(diǎn)擊事件。
    • accessibilityFeedbackType:監(jiān)聽(tīng)事件的反饋模式。
    • canRetrieveWindowContent:是否允許獲取視圖層級(jí)的訪問(wèn)權(quán),如果它被設(shè)置為 false,node.getSource() 方法會(huì)調(diào)用失敗。
    • accessibilityFlags:指定 Flag,一般用于指定根據(jù) Node 獲取 View ID 的權(quán)限。
    • packageNames:開(kāi)啟監(jiān)聽(tīng)的應(yīng)用包名,可以指定多個(gè)包名,通過(guò)逗號(hào)“,”分割,不設(shè)置此屬性標(biāo)識(shí)全局監(jiān)聽(tīng)。
    • description:輔助功能的描述,它會(huì)顯示在系統(tǒng)設(shè)置的“無(wú)障礙”中的描述信息中。
    • notificationTimeout:響應(yīng)的毫秒數(shù)。

    這些可配置的參數(shù),系統(tǒng)都提供了可選的配置參數(shù),正常不需要額外定制的時(shí)候,使用上面默認(rèn)的配置即可,如果有定制需要,還是查閱官方文檔獲得最全的介紹。

    AccessibilityService:

    https://developer.android.com/reference/android/accessibilityservice/AccessibilityService

    2、Java 代碼中動(dòng)態(tài)配置

    除了 XML 文件配置的方式,我們還可以通過(guò)重寫(xiě) AccessibilityService 的 onServiceConnected() 方法,我們首先需要構(gòu)建一個(gè) AccessibilityServiceInfo 對(duì)象,通過(guò)它的標(biāo)準(zhǔn) Api 進(jìn)行配置,再使用 setServiceInfo() 方法將它設(shè)置給輔助模式。

    onServiceConnected() 會(huì)在應(yīng)用成功連接到此輔助服務(wù)的時(shí)候系統(tǒng)調(diào)用,一般在其中做一些初始化的操作即可。

    override fun onServiceConnected() {super.onServiceConnected()var serviceInfo = AccessibilityServiceInfo()serviceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASKserviceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASKserviceInfo.notificationTimeout = 100serviceInfo.packageNames = arrayOf("com.forwarding.wechat")serviceInfo.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDSsetServiceInfo(serviceInfo) }

    這里提供的例子,其實(shí)和前面使用 XML 配置的效果一直。推薦使用 XML 的配置方式,會(huì)更清晰且靈活,而且像 description 這種屬性,在 AccessibilityServiceInfo 中,并沒(méi)有提供有效的類(lèi)似 setDescription() 方法,這一點(diǎn)也確實(shí)是設(shè)計(jì)如此,畢竟服務(wù)沒(méi)有運(yùn)行,就不存在描述信息,在系統(tǒng)設(shè)置的“無(wú)障礙”頁(yè)面,就讀取不到。

    也就是說(shuō)即便是使用 setServiceInfo() 方法動(dòng)態(tài)設(shè)置,也逃不脫使用 XML 配置文件的方式,我還是強(qiáng)烈建議都使用 XML 配置文件的方式配置輔助服務(wù),主要是為了省事。

    2.3 清單文件中注冊(cè)服務(wù)

    本質(zhì)上 AccessibilityService 還是一個(gè) Service,使用它我們還需要在清單文件中配置它。

    <service android:label="承香墨影的輔助工具"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"android:name=".WeForwardServer"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService"/></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/accessibility_config"/> </service>

    這就是一個(gè)標(biāo)準(zhǔn)的 Service,其中 label 會(huì)被解析在系統(tǒng)設(shè)置的“輔助模式中顯示”,而 intent-filter 和 meta-data 按照格式寫(xiě)就好了,沒(méi)什么原因。

    meta-data 中,通過(guò) android:resource 屬性指定的就是我們?cè)诘诙骄庉嫷呐渲梦募窂?#xff0c;指定它就好了。

    2.4 開(kāi)啟輔助模式

    以上步驟都完成之后,你就可以在系統(tǒng)的“無(wú)障礙”設(shè)置里,看到你編寫(xiě)的輔助模式的開(kāi)關(guān)了。

    默認(rèn)為關(guān)閉狀態(tài),打開(kāi)它的時(shí)候,你會(huì)收到一個(gè)警告彈窗,說(shuō)明當(dāng)前你正在開(kāi)啟一個(gè)無(wú)障礙的服務(wù),它有哪些權(quán)限,這個(gè)對(duì)話框,我們是控制不了的。

    注意這里的 Title 就是清單文件里配置的 android:label ,而描述就是 XML 配置文件里的 android:description 信息。

    當(dāng)你在系統(tǒng)設(shè)置里,能看到此開(kāi)關(guān)的時(shí)候,就說(shuō)明你的輔助模式的服務(wù),配置的沒(méi)問(wèn)題了,接下來(lái)就要思考如何使用它。

    三、編寫(xiě)邏輯代碼

    前面提到,在 AccessibilityService 里,我們最需要關(guān)注的就是 onAccessibilityEvent() 方法,它會(huì)在我們監(jiān)聽(tīng)的事件發(fā)生的時(shí)候,被系統(tǒng)回調(diào),并傳遞過(guò)來(lái)該事件相關(guān)的信息。

    接下來(lái)我們看看如何在 onAccessibilityEvent() 回調(diào)方法里,編寫(xiě)具體的邏輯。

    接下來(lái) "程序員思維" 要上線了,把大象關(guān)冰箱,需要幾步。我們接下來(lái)來(lái)拆分輔助模式的步驟。

  • 判斷事件,onAccessibilityEvent() 會(huì)被回調(diào)多次,而我們只需要處理我們關(guān)心的事件,其他的忽略過(guò)濾掉即可。
  • 找到需要控制的關(guān)鍵節(jié)點(diǎn)(Node),以便之后進(jìn)行控制。
  • 對(duì)關(guān)鍵節(jié)點(diǎn),發(fā)送對(duì)于的操作事件,以便完成我們的步驟。
  • 回收資源,防止資源泄露。
  • 很簡(jiǎn)單對(duì)不對(duì),接下來(lái)我們細(xì)細(xì)的說(shuō)下,這些步驟相關(guān)的方法和屬性。

    3.1 判斷事件

    當(dāng) onAccessibilityEvent() 被系統(tǒng)回調(diào)的時(shí)候,同時(shí)也會(huì)傳遞過(guò)來(lái)一個(gè) AccessibilityEvent 對(duì)象,它其中包含了很多與當(dāng)前事件相關(guān)的信息,有興趣可以看看源碼,我們這里只關(guān)注最需要的幾個(gè)屬性。

    1、eventType 判斷事件類(lèi)型

    通過(guò) eventType 來(lái)判斷事件的類(lèi)型,我們可以利用 getEventType() 方法獲取到它。

    這些事件都很好辨認(rèn),例如:TYPE_NOTIFICATION_STATE_CHANGED 是一個(gè)窗口 View 發(fā)生了變化,TYPE_VIEW_CLICKED 是某個(gè) View 發(fā)生了一次點(diǎn)擊事件等等。

    2、packageName 判斷事件發(fā)生的 App

    通過(guò) getPackageName() 方法,判斷出事件發(fā)生在那個(gè) App 里的。

    3、className 判斷當(dāng)前發(fā)生事件的是那個(gè)類(lèi)

    通過(guò) getClassName() 判斷當(dāng)前發(fā)生事件的是那個(gè)類(lèi),例如 頁(yè)面的顯示,className 可能指向一個(gè) Activity,一個(gè)按鈕的點(diǎn)擊,className 可能指向的是一個(gè) Button,這些都是根據(jù)實(shí)際場(chǎng)景區(qū)分的。

    4、text 判斷當(dāng)前事件觸發(fā)源上的 Text

    通過(guò) getText() 獲取當(dāng)前事件源的 text 屬性,可能是 TextView 的 Text,也可能是 Activity 的 Label 屬性,依然是根據(jù)實(shí)際情況區(qū)分。

    一般我們可以通過(guò)以上幾種方式,猜測(cè)是否是我們需要監(jiān)聽(tīng)的事件,下一步就是我們找到我們要操作的源。

    3.2 找到待控制的關(guān)鍵節(jié)點(diǎn)(Node)

    通常我們是使用輔助模式去操作頁(yè)面上的某個(gè)元素,那這一步,就是為了找到它。

    在輔助模式下,頁(yè)面上的每個(gè)元素,其實(shí)都是一個(gè)個(gè) AccessibilityNodeInfo 節(jié)點(diǎn),它是一個(gè)類(lèi)似樹(shù)形的結(jié)構(gòu),其內(nèi)和我們真實(shí) App 內(nèi)的布局層級(jí)是一致的,但是并不能將它單純的理解成一個(gè) ViewTree。

    既然是樹(shù)形結(jié)構(gòu),我們首先要獲取到根節(jié)點(diǎn)的 NodeInfo,可以通過(guò)以下兩個(gè)方式獲取:

    • event.getSource()
    • getRootInActiveWindow()

    這兩個(gè)方法都會(huì)返回一個(gè) AccessibilityNodeInfo 對(duì)象。getSource() 是AccessibilityEvent 的方法,它可用的前提是前面配置 android:canRetrieveWindowContent 的時(shí)候,被設(shè)置為 True。所以我推薦使用 getRootInActiveWindow() 方法來(lái)獲取。這兩個(gè)方法還是略微有些差異,有興趣可以打斷點(diǎn)看看信息,但是大多數(shù)情況下,對(duì)我們使用者來(lái)說(shuō)是一致的。

    獲得根節(jié)點(diǎn)的 AccessibilityNodeInfo 之后,就可以通過(guò)它找到我們想操作的關(guān)鍵節(jié)點(diǎn),在 AccessibilityNodeInfo 中,提供了以下兩個(gè)方法來(lái)找到關(guān)鍵節(jié)點(diǎn)。

    • findAccessibilityNodeInfosByViewId(String viewId)
    • findAccessibilityNodeInfosByText(String text)

    一個(gè)是依賴(lài) ViewId,另外一個(gè)是依賴(lài) Text 信息。

    使用 ViewId 查找關(guān)鍵節(jié)點(diǎn)是穩(wěn)妥的方案,而使用 Text 去查找,可能會(huì)找不到。

    無(wú)論通過(guò)哪種方式查找 關(guān)鍵節(jié)點(diǎn) ,都是存在能找到多個(gè) NodeInfo 的可能的,所以這兩個(gè)方法干脆的都返回了一個(gè) List<AccessibilityNodeInfo> ,所以需要我們通過(guò)其他條件再過(guò)濾一遍,通常就是通過(guò) Text 信息過(guò)濾。

    var mNodeInfo = rootInActiveWindow var listItem = mNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/lp") for (item in listItem) {if (item.text.toString().equals("承香墨影")){nodeClick(item)} }

    如果是使用 findXxxByText() 的方法的話,還需要注意它實(shí)際上不是通過(guò)類(lèi)似 == 或者 equals() 的方法來(lái)查找子節(jié)點(diǎn)的,而是通過(guò)類(lèi)似 contain() 的方式,所以只要節(jié)點(diǎn)的 text 屬性包含查找的內(nèi)容,都會(huì)被找到,這個(gè)我們額外還需要增加判斷條件。

    如果這些方法都試過(guò),還是找不到關(guān)鍵節(jié)點(diǎn),可以通過(guò)遍歷的方式查找。

    AccessibilityNodeInfo 既然是一個(gè)樹(shù)狀結(jié)構(gòu),也提供了我們遍歷樹(shù)的方法。

    • getParent():查找父節(jié)點(diǎn)。
    • getChild():返回子節(jié)點(diǎn)。
    • getChildCount():當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)個(gè)數(shù)。

    通過(guò) getChild() 和 getChildCount() 兩個(gè)方法,我們是可以對(duì)整個(gè) ViewNodeTree 進(jìn)行遍歷,來(lái)找到我們關(guān)注的關(guān)鍵節(jié)點(diǎn),這是一個(gè)最后的方案,并不推薦使用。

    3.3 觸發(fā)事件

    輔助模式一般都是幫助我們響應(yīng)一些事件,而這些事件大體上,可以分為兩類(lèi)。

    • 全局系統(tǒng)事件。
    • View 事件。

    對(duì)于全局系統(tǒng)事件,其實(shí)我們并不需要第二步找到的關(guān)鍵節(jié)點(diǎn)。AccessibilityService 提供了一個(gè) performGlobalAction() 方法,我們可以通過(guò)該方法,操作一些全局的系統(tǒng)事件,例如:模擬返回鍵點(diǎn)擊、模擬 HOME 鍵點(diǎn)擊、鎖屏等等。

    // 返回鍵 performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK); // HOME鍵 performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);

    這些事件被封裝在 AccessibilityService 中,以 GLOBAL_ 為前綴,看看屬性說(shuō)明就懂了。

    除了全局系統(tǒng)事件之外,通常我們就是想操作第二步拿到的關(guān)鍵節(jié)點(diǎn)。

    在 AccessibilityNodeInfo 中,提供了一個(gè) performAction() 的方法,可以通過(guò)該方法,對(duì)關(guān)鍵節(jié)點(diǎn)傳遞一個(gè)我們需要的事件。

    這些事件都被定義在 AccessibilityNodeInfo 中,以 ACTION_ 為前綴定義。例如:ACTION_CLICK 是一個(gè)點(diǎn)擊事件,ACTION_SET_TEXT 設(shè)置一個(gè)輸入。

    這里僅介紹一些比較常見(jiàn)的操作,更多的操作也是類(lèi)似的使用方式。

    1. View 的點(diǎn)擊

    找到關(guān)鍵節(jié)點(diǎn)之后,就可以發(fā)送 AccessibilityNodeInfo.ACTION_CLICK 模擬對(duì)這個(gè) View 的點(diǎn)擊操作。

    但是有時(shí)候它是不生效的,主要原因是因?yàn)槟阏业降倪@個(gè)關(guān)鍵節(jié)點(diǎn),它的 isClickable() 為 false。

    例如微信的這個(gè)公眾號(hào)分享彈窗,如果我們想要查找“發(fā)送給朋友”,其實(shí)最好的辦法是找到這個(gè) TextView 控件所代表的關(guān)鍵節(jié)點(diǎn)(NodeInfo),然后對(duì)它進(jìn)行點(diǎn)擊。而實(shí)際上這個(gè) TextView 是不具有點(diǎn)擊效果的,它的 isClickable() 為 false。

    這個(gè)時(shí)候可以想一個(gè)折中的方案,去找關(guān)鍵節(jié)點(diǎn)(NodeInfo)的父節(jié)點(diǎn),再去判斷它是否可點(diǎn)擊,可點(diǎn)擊則點(diǎn)擊它,否則繼續(xù)向上找。

    private fun nodeClick(node : AccessibilityNodeInfo?){var clickNode = node;while (clickNode!=null){if(clickNode.isClickable){clickNode.performAction(AccessibilityNodeInfo.ACTION_CLICK)break;}clickNode = node?.parent} }

    雖然 AccessibilityNodeInfo 其實(shí)也開(kāi)放了 setClickable() 方法,但是我不建議操作它,有些時(shí)候會(huì)拋出一個(gè)異常,不太穩(wěn)定。

    2. EditText 輸入文字

    對(duì) EditText 輸入文字,最少需要兩個(gè)參數(shù),關(guān)鍵節(jié)點(diǎn)和輸入的文字。這就需要用到 performAction() 的另外一個(gè)重載方法,它允許額外在傳遞一個(gè) Bundle 來(lái)指定參數(shù)。

    private fun nodeSetText(node : AccessibilityNodeInfo?,text:String){var argument = Bundle()argument.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,text)node?.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT,argument) }

    所有支持定義的額外參數(shù),都被定義在 AccessibilityNodeInfo 中,并以 ACTION_ARGUMENT_ 為前綴定義。

    3. ListView 的滾動(dòng)

    AccessibilityNodeInfo 其實(shí)只能操作當(dāng)前屏幕下可見(jiàn)的 節(jié)點(diǎn),所以碰上 ListView 或者 RecycleView 這種列表,就需要對(duì)它進(jìn)行滾動(dòng)。

    滾動(dòng)的事件有兩種:

    • ACTION_SCROLL_FORWARD
    • ACTION_SCROLL_BACKWARD
    private fun nodeScrollList(node : AccessibilityNodeInfo?){node?.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) }

    一個(gè)前進(jìn)一個(gè)后退,足夠使用了。

    3.4 回收資源

    在使用完 AccessibilityNodeInfo 之后,別忘了還需要調(diào)用 recycle() 方法,釋放資源。

    nodeInfo.recycle();

    四、小結(jié)

    輔助模式如何使用,到現(xiàn)在已經(jīng)講解的非常清楚了,后面基本上就是靠自己的想象力來(lái)做小功能了。

    利用輔助模式,發(fā)揮想象力,你也可以做出很多有意思的功能。


    公眾號(hào)后臺(tái)回復(fù)成長(zhǎng)『成長(zhǎng)』,將會(huì)得到我準(zhǔn)備的學(xué)習(xí)資料,也能回復(fù)『加群』,一起學(xué)習(xí)進(jìn)步;你還能回復(fù)『提問(wèn)』,向我發(fā)起提問(wèn)。

    推薦閱讀:

    • 小程序 UI 布局指南(一)
    • 程序員的密碼管理之道
    • 手動(dòng)刷新 MediaStore,保存的圖片立即出現(xiàn)在相冊(cè)中
    • 偽代碼、幽默和 Google 的藝術(shù)!
    • 漫畫(huà):App 防止 Fiddler 抓包小技巧!

    總結(jié)

    以上是生活随笔為你收集整理的辅助模式最终考验的是想象力,先来看看怎么用!| Accessibility的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。