日韩性视频-久久久蜜桃-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无障碍宝典的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国内精品嫩模av私拍在线观看 | 自拍偷在线精品自拍偷无码专区 | 亚洲天堂手机在线观看 | 日韩欧美国产亚洲 | 欧美综合激情网 | 国产成人观看 | 在线美女av | 天天干狠狠爱 | 日本特黄特色aaa大片免费 | 午夜婷婷 | www.男人的天堂 | 性色av免费观看 | 色爱AV综合网国产精品 | 久久99国产精品成人 | 黄色小视频免费网站 | 国产91免费| www.青青草 | 欧美精产国品一二三 | 国产免费无码XXXXX视频 | 精品久久久久久亚洲综合网站 | 男人懂的网站 | a级黄色网址 | 91精品中文字幕 | 91免费视频 | 美女脱衣服一干二净 | 精品无码av一区二区三区不卡 | 亚洲色吧 | 成年人免费在线 | 天堂av资源在线观看 | 人妻熟女一区二区aⅴ水 | 会喷水的亲姐姐 | eeuss鲁丝片一区二区三区 | 国产麻豆精品久久一二三 | 男人撒尿视频xvideos | 91网页入口| 女人高潮被爽到呻吟在线观看 | 亚洲精品无码久久久久久久 | 91成人在线观看喷潮动漫 | 6080午夜伦理 | 国内精品国产成人国产三级 | 日韩逼| 精品国产理论 | 国产乱码精品一区二三赶尸艳谈 | 久久久久久国产免费a片 | 福利在线一区 | 欧美成人动态图 | 在线视频欧美亚洲 | 香蕉毛片| 欧美日韩国产综合网 | 爱爱一区 | 成人久久久精品国产乱码一区二区 | 麻豆成人av | 成人免费久久 | 七仙女欲春2一级裸体片 | 欧美色婷婷 | 午夜激情福利视频 | 乱lun合集小可的奶水 | 久久作爱视频 | 男女黄色又爽大片 | 岛国精品在线播放 | 久久最新免费视频 | 四虎三级| 国产欧美激情在线观看 | 亚洲视频二区 | 香蕉网站在线 | 日韩电影一二三区 | 91极品美女 | 99久久一区 | 国产青青视频 | 久久精品亚洲精品国产欧美 | 黑人狂躁日本妞hd | 日本亚洲一区二区 | 亚洲国产精品国自产拍av | 九九在线观看高清免费 | 少妇脚交调教玩男人的视频 | 用力使劲高潮了888av | 黑丝一区二区三区 | 日韩精品啪啪 | 成人av资源站 | 快射视频网 | 欧美自拍区 | 久久高清国产 | 天堂中文8 | 欧美日韩中文字幕在线播放 | 让人下面流水的视频 | 国产精品国产三级国产aⅴ无密码 | 欧美一区亚洲 | 少妇特殊按摩高潮惨叫无码 | 亚洲咪咪 | 久久综合精品国产二区无码不卡 | 天天综合网天天综合 | 岛国大片在线 | 在线视频久| 日韩一区二区三区不卡视频 | 国产精品二区一区二区aⅴ污介绍 | 57pao成人国产永久免费视频 | 人人草在线 | 国产精品不卡一区 | 国产宾馆自拍 |