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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android accessibility 模拟返回_Android无障碍宝典

發布時間:2024/1/23 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android accessibility 模拟返回_Android无障碍宝典 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android江湖上一直流傳著一部秘籍——Android無障礙寶典。傳聞練成這部寶典,可在Android無障礙模式下,飛檐走壁,能人所不能。寶典分為三篇,分別是入門、進階和高級,由淺入深,全面展示無障礙的基本方法及擴展應用。

Android應用無障礙化,目的是為視覺障礙或其他有障礙的用戶提供更好的服務。在無障礙模式下,用戶的操作方式與平常不同,比如:

  • 選擇(Hover)一個元素:單擊
  • 點擊(Click)一個元素:雙擊
  • 滾動:雙指往上、下、左、右
  • 選擇上或下一個項目:單指往上、下、左、右
  • 快速回到主畫面:單指上滑+左滑
  • 返回鍵:單指下滑+左滑
  • 最近畫面鍵:單指左滑+上滑
  • 通知欄:單指右滑+下滑

此外,還需要理解在無障礙模式下“無障礙焦點”這個概念。如圖1所示,界面上以綠色方框來表示目前獲得無障礙焦點的View。擁有無障礙焦點的View,會被TalkBack服務識別,TalkBack會從View中取出相關的無障礙內容,然后提示給用戶。

圖1 無障礙焦點

有了對無障礙模式初步的了解,就可以正式開始學習如何為應用無障礙化。

入門篇

為View添加ContentDescription

UI上的可操作元素都應該添加上ContentDescription, 當此元素獲得無障礙焦點時,TalkBack服務就取出View的提示語(contentDescription),并朗讀出來。

添加ContentDescription有兩種方法,第一種是通過在XML布局中設置android:contentDescripton屬性,如:

但是很多情況下,View的內容描述會根據不同情景需要而改變,比如CheckBox按鈕是否被選中,以及ListView中item的內容描述等。這種則需要在代碼中使用setContentDescription方法,如:

String contentDescription = "已選中 " + strValues[position];

label.setContentDescription(contentDescription);

設置無障礙焦點

UI上的元素,有的默認帶有無障礙焦點,如Button、CheckBox等標準控件,有的如果不設置contentDescription是默認沒有無障礙焦點。在開發應用過程中,還會遇到一些UI元素,是不希望它獲取無障礙焦點的。以下方法可以改變元素的無障礙焦點:

public void setAccessibilityFocusable(View view, boolean focused){

if(android.os.Build.VERSION.SDK_INT >= 16){

if(focused){

ViewCompat.setImportantForAccessibility(view, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);

}else{

ViewCompat.setImportantForAccessibility(view, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);

}

}

}

IMPORTANT_FOR_ACCESSIBILITY_YES表示這個元素應該有無障礙焦點,會被TalkBack服務讀出描述內容;IMPORTANT_FOR_ACCESSIBILITY_NO表示屏蔽元素的無障礙焦點,手指滑動遍歷及觸摸此元素,都不會獲得無障礙焦點,TalkBack服務也不會讀出其描述內容。

發出無障礙事件

IMPORTANT_FOR_ACCESSIBILITY_YES表示這個元素應該有無障礙焦點,會被TalkBack服務讀出描述內容;IMPORTANT_FOR_ACCESSIBILITY_NO表示屏蔽元素的無障礙焦點,手指滑動遍歷及觸摸此元素,都不會獲得無障礙焦點,TalkBack服務也不會讀出其描述內容。

view.postDelayed(new Runnable() {

@Override

public void run() {

if(android.os.Build.VERSION.SDK_INT >= 14){

view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);

}

}

},100);

這個方法是讓View來自動發出被單擊選中的無障礙事件,發出后,UI上的無障礙焦點則會馬上賦給這個View,從而達到搶無障礙焦點的效果。再比如:

if(android.os.Build.VERSION.SDK_INT >= 16){

AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT);

event.setPackageName(view.getContext().getPackageName());

event.setClassName(view.getClass().getName());

event.setSource(view);

event.getText().add(desc);

view.getParent().requestSendAccessibilityEvent(view, event);

}

AccessibilityEvent.TYPE_ANNOUNCEMENT是代表元素需要TalkBack服務來讀出描述內容。其中desc是描述內容,將它放到event的getText()中,然后請求View的父類來發出事件。

進階篇

介紹AccessibilityDelegate

Android中View含有AccessibilityDelegate這個子類,它可被注冊進View中,主要作用是為了增強對無障礙化的支持。

查看View的源碼可發現,注冊Accessibility Delegate方法很簡單:

Public void setAccessibilityDelegate(AccessibilityDelegate delegate) {

mAccessibilityDelegate = delegate;

}

注冊后,View對無障礙的處理,則會交給AccessibilityDelegate,如:

public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {

if (mAccessibilityDelegate != null) {

mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);

} else {

onInitializeAccessibilityNodeInfoInternal(info);

}

}

onInitializeAccessibilityNodeInfo是View源碼中初始化無障礙節點信息的方法,從上面代碼看出,當mAccessibilityDelegate是開發注冊的AccessiblityDelegate時,則會執行AccessiblityDelegate中的onInitializeAccessibilityNodeInfo方法。再看看AccessibilityDelegate類中的onInitializeAccessibilityNodeInfo:

public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {

host.onInitializeAccessibilityNodeInfoInternal(info);

}

Host是被注冊AccessibilityDelegate的View,onInitializeAccessibilityNodeInfoInternal是View中真正初始化無障礙節點信息的方法。即是說,注冊了AccessibilityDelegate并沒有改變View原來對無障礙的操作,而是在這個操作之后增加了處理。

AccessibilityDelegate的應用

下面介紹下AccessibilityDelegate可以提供哪些無障礙應用,注冊AccessibilityDelegate是在API 14以上才開放的接口,API 14以下如需使用,可以接入support v4包中的AccessibilityDelegateCompt。注冊方法如下:

if (Build.VERSION.SDK_INT >= 14) {

View view = findViewById(R.id.view_id);

view.setAccessibilityDelegate(new AccessibilityDelegate() {

public void onInitializeAccessibilityNodeInfo(View host,

AccessibilityNodeInfo info) {

super.onInitializeAccessibilityNodeInfo(host, info);

// 對info做出擴展性支持

});

}

要對info做出擴展支持,還得先了解AccessibilityNodeInfo這個類。Android開發都知道,UI上的元素是通過View來實現,而AccessibilityNodeInfo則是存儲View的無障礙信息(如contentDescription)及無障礙狀態(如focusable、visiable、clickable等),同時它還肩負著TalkBack服務和View之間通訊的橋梁作用。如果要修改View的無障礙提示,比如修改View的類型提示,可以這樣做:

if(android.os.Build.VERSION.SDK_INT >= 14){

view.setAccessibilityDelegate(new AccessibilityDelegate(){

@Override

public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {

super.onInitializeAccessibilityNodeInfo(host, info);

if(contentDesc != null) {

info.setContentDescription(contentDesc);

}

info.setClassName(className);

}

});

}

className是類型名稱,這里如果是Button.class.getName(),則TalkBack會對這個View讀“XXX 按鈕”,“XXX”是contentDescription,而“按鈕”則是TalkBack服務添加的(如果是英文環境,則是“XXX button”)。使用上面的方法,可以為非按鈕控件加上“按鈕”的提示,方便無障礙用戶識別UI上元素的作用,同時又不必把“按鈕”提示強加入contentDescription中。除了修改AccessibilityNodeInfo外,使用AccessibilityDelegate還可以影響無障礙事件,如:

if (android.os.Build.VERSION.SDK_INT >= 14) {

view.setAccessibilityDelegate(new AccessibilityDelegate() {

@Override

public void sendAccessibilityEvent(View host, int eventType) {

// 彈出Popup后,不自動讀各項內容

if (eventType != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {

super.sendAccessibilityEvent(host, eventType);

}

}

});

}

無障礙模式下,彈出Dialog,則會把Dialog中的所有元素都讀一遍。這個方法可以把彈起窗口的無障礙事件攔截,Dialog彈起就不會再自動讀各項內容。

高級篇

有了AccessibilityDelegate這把利器之后,開發可以輕松對應Android中大部分的無障礙化,但是如果想要做到游刃有余,還得深造更高級的功夫——自定義View無障礙化。

應用開發過程中,總會需要自定義View來實現特殊的UI效果,當一個自定義View中包含多種UI元素時,無障礙模式下并不能區分包含的多種UI元素,而只為自定義View添加一個大無障礙焦點。如圖2所示。

圖2 自定義View只有一個大無障礙焦點

圖中只有一個大無障礙焦點,因為這是一個View,里面的文字及藍色的矩形都是繪制出來的。

@Override

public void onDraw(Canvas c) {

super.onDraw(c);

if (mTitle != null) {

drawTitle(c);

}

for (int i = 0; i < mSize; i++) {

drawBarAtIndex(c, i);

}

drawAxisY(c);

}

代碼中繪制出來的元素不可被TalkBack識別出來,所以開發需要多做一步,對自定義View無障礙化。這里將介紹如何通過官方提供的ExploreByTouchHelper來實現。

圖3 自定義View內元素獲得無障礙焦點

圖3是使用ExploreByTouchHelper實現的最終效果,每一個小矩形都能獲取到無障礙焦點,且可以進行選中高亮。實現ExploreByTouchHelper需要五步。

第一步,委托處理無障礙。

public class BarGraphView extends View {

private final BarGraphAccessHelper mBarGraphAccessHelper;

public BarGraphView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

...

mBarGraphAccessHelper = new BarGraphAccessHelper(this);

ViewCompat.setAccessibilityDelegate(this, mBarGraphAccessHelper);

}

@Override

public boolean dispatchHoverEvent(MotionEvent event) {

if ((mBarGraphAccessHelper != null)

&& mBarGraphAccessHelper.dispatchHoverEvent(event)) {

return true;

}

return super.dispatchHoverEvent(event);

}

}

mBarGraphAccessHelper繼承ExploreBy TouchHelper,可通過注冊AccessibilityDelegate的方式來注冊給自定義BarGraphView,同時讓mBarGraphAccessHelper來處理Hover事件(無障礙模式下的點擊)的分發。

第二步,標記無障礙虛擬節點ID。

private class BarGraphAccessHelper extends ExploreByTouchHelper {

private final Rect mTempParentBounds = new Rect();

public BarGraphAccessHelper(View parentView) {

super(parentView);

}

@Override

protected int getVirtualViewIdAt(float x, float y) {

final int index = getBarIndexAt(x, y);

if (index >= 0) {

return index;

}

return ExploreByTouchHelper.INVALID_ID;

}

@Override

protected void getVisibleVirtualViewIds(List virtualViewIds) {

final int count = getBarCount();

for (int index = 0; index < count; index++) {

virtualViewIds.add(index);

}

}

}

getVirtualViewIdAt和getVisibleVirtualViewIds都是ExploreByTouchHelper類需要實現的方法,分別代表獲取虛擬無障礙節點的id以及設置虛擬無障礙節點的id。由于自定義View里的元素非繼承于View,如要在無障礙模式下被識別,則需要構造一個虛擬無障礙節點。構造方法已封裝到ExploreByTouchHelper里,開發只需要告訴ExploreByTouchHelper有哪些虛擬無障礙節點的id即可。無障礙節點id需要滿足以下條件:id是一個接一個的,穩定且為非負整數。設置好無障礙虛擬節點id后,根據用戶操作UI上的xy坐標,取得對應的無障礙虛擬節點id,通過getVirtualViewIdAt方法告訴ExploreByTouchHelper類。

第三步,填充無障礙節點的屬性。

private class BarGraphAccessHelper extends ExploreByTouchHelper {

...

private CharSequence getDescriptionForIndex(int index) {

final int value = getBarValue(index);

final int templateRes = ((mHighlightedIndex == index) ?

R.string.bar_desc_highlight : R.string.bar_desc);

return getContext().getString(templateRes, index, value);

}

@Override

protected void populateEventForVirtualViewId(int virtualViewId, AccessibilityEvent event) {

final CharSequence desc = getDescriptionForIndex(virtualViewId);

event.setContentDescription(desc);

}

@Override

protected void populateNodeForVirtualViewId(

int virtualViewId, AccessibilityNodeInfoCompat node) {

final CharSequence desc = getDescriptionForIndex(virtualViewId);

node.setContentDescription(desc);

node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);

final Rect bounds = getBoundsForIndex(virtualViewId, mTempParentBounds);

node.setBoundsInParent(bounds);

}

}

構造了虛擬無障礙節點后,便可以往節點里塞無障礙信息。populateEventForVirtualViewId是將無障礙信息填入無障礙事件中。populateNodeForVirtualViewId是初始化每個虛擬無障礙節點,設置contentDescription,注冊所需要處理的Action,以及設置無障礙焦點的邊框。setBoundsInParent一定要設置有效的邊框,否則會導致虛擬無障礙節點無法獲取無障礙焦點。

第四步,提供用戶無障礙交互支持。

private class BarGraphAccessHelper extends ExploreByTouchHelper {

...

@Override

protected boolean performActionForVirtualViewId(

int virtualViewId, int action, Bundle arguments) {

switch (action) {

case AccessibilityNodeInfoCompat.ACTION_CLICK:

onBarClicked(virtualViewId);

return true;

}

return false;

}

}

private void onBarClicked(int index) {

setSelection(index);

if (mBarGraphAccessHelper != null) {

mBarGraphAccessHelper.sendEventForVirtualViewId(

index, AccessibilityEvent.TYPE_VIEW_CLICKED);

}

}

小矩形點擊后是會被選中且高亮的,在performActionForVirtualViewId中實現對應的點擊事件處理。經過這四步,自定義View就可以完美支持無障礙化了!

可以看出,ExploreByTouchHelper簡化了虛擬節點層次結構的構造,封裝AccessibilityNodeProvider的實現,更完善的控制Hover事件、無障礙事件。有了它,Android無障礙化再也不是難題。

Android無障礙化寶典的內容就介紹到此,在實際開發中,遇到的無障礙化問題都比較細小和瑣碎,希望以上介紹能提供一點幫助。很多Android開發以為無障礙化就是為控件加上ContentDescription,其實還有空描述、混亂焦點、焦點順序、描述準確性等地方需要注意和優化。只有用心、持續地改進和優化,才能做出真正無障礙的產品。

總結

以上是生活随笔為你收集整理的android accessibility 模拟返回_Android无障碍宝典的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 老湿机69福利 | 日韩精品在线一区二区三区 | 国产做受91| 黄片毛片 | 全部免费毛片 | 国产精品久久久久久久久借妻 | 亚洲制服av| 久久久久久久久久久久久久国产 | 一本大道东京热无码aⅴ | 在线观看污网站 | 灌满闺乖女h高h调教尿h | 国产一区二区三区黄片 | 99国产精品视频免费观看一公开 | 久久乐av | 麻豆久久久久 | 亚洲av无码乱码在线观看性色 | 精人妻一区二区三区 | 久久国产精品无码一级毛片 | 欧美丰满艳妇bbwbbw | 国产视频资源 | 国产男男gay体育生白袜 | 新红楼梦2005锦江版高清在线观看 | 亚洲精品www久久久 一级aaa毛片 | 欧美人性生活视频 | 亚洲图片一区二区 | 成人国产片女人爽到高潮 | 特级av片 | 91抖音成人 | 日韩一区在线视频 | 日韩电影中文字幕在线观看 | 中文字幕一区在线播放 | 日日夜夜综合 | 黑人与日本少妇高潮 | 亚洲成人系列 | 91无打码| 96精品在线 | 91精产品一区观看 | 久久综合桃花网 | 亚洲成人一区二区三区 | 国产伦精品一区二区三区照片91 | 日本少妇一级 | 黑丝国产在线 | 一区二区视频网站 | 操碰在线观看 | 一区二区三区久久精品 | 瑟瑟综合网| 探花视频在线观看 | 色噜噜综合 | 天天狠天天插 | 朋友人妻少妇精品系列 | 欧美黑人粗大 | 男裸体无遮挡网站 | 亚洲乱码国产乱码精品精大量 | 精品成人18 | 韩国明星乱淫(高h)小说 | 欧美精品一区二区三区在线播放 | 第一页综合 | 91麻豆精品视频 | 成人污网站 | 另类激情综合 | 日本孰妇毛茸茸xxxx | 欧美女同视频 | 国产一级久久久久毛片精品 | 久久99久久98精品免观看软件 | 色播基地 | 久久av网站 | 欧美大片免费在线观看 | 国产一区二区女内射 | 国产精品无码人妻一区二区在线 | 日韩精品人妻中文字幕 | 国产66页 | 免费香蕉视频 | 成人欧美视频 | 亚洲欧美福利 | free性欧美hd精品4k | 麻豆成人91精品二区三区 | 伊人伊人网 | 亚洲自拍偷拍色图 | 中文字幕在线观看av | 99视频免费 | 国产一区资源 | 欧美一级大片在线观看 | 日本激情视频一区二区三区 | 精人妻无码一区二区三区 | 日本免费a级片 | 99精品在线观看视频 | 国产区视频 | 日韩成人一区二区视频 | 国产情侣呻吟对白高潮 | 一区二区免费在线观看 | 欧美天堂在线 | 九九午夜 | 小香蕉影院 | 无码日韩人妻精品久久蜜桃 | 日韩视频在线观看视频 | 亚洲视频a | 免费看一区二区三区 | 国产乱淫av片杨贵妃 | 青娱乐在线视频观看 |