Android(二)

實(shí)現(xiàn)輔助(外掛)
參考地址:http://developer.android.com/training/accessibility/index.html我們?cè)O(shè)計(jì)開(kāi)發(fā)的App需要給更廣泛的人群使用,有一部分的在視力、手腳等方面可能有殘障睁蕾,這時(shí)為了提高他們這部分人的用戶(hù)體驗(yàn),我們需要使用輔助服務(wù)來(lái)幫助他們來(lái)完成交互卵迂。也就是Android Framework中定義的Accessibility Services底扳。
設(shè)計(jì)輔助程序
添加android:contentDescription屬性
利用Google基于聲音的TalkBack服務(wù) 寂嘉,在UI元素上加 android:contentDescription屬性顾复,可以使用這個(gè)服務(wù)將其讀出來(lái)班挖,使得視力障礙者可以通過(guò)聲音訪問(wèn)這些元素。例如:

有一些有狀態(tài)的UI(比如ToggleButton捕透,CheckBox)聪姿,就不能通過(guò)在布局中設(shè)置android:contentDescription來(lái)實(shí)現(xiàn)碴萧,這時(shí)可以在代碼中動(dòng)態(tài)設(shè)置:
String contentDescription = "Select " + strValues[position];label.setContentDescription(contentDescription);

代碼很簡(jiǎn)單乙嘀,但是卻很有用末购。下載TalkBack服務(wù),然后在 Settings > Accessibility > TalkBack中開(kāi)啟服務(wù)即可使用虎谢。
Android不僅僅提供了觸摸屏的導(dǎo)航方式盟榴,還可以通過(guò)D-Pad、方向鍵或軌跡球來(lái)操作婴噩。后來(lái)Android還提供了通過(guò)USB或藍(lán)牙連接的外置鍵盤(pán)來(lái)操作擎场。要使用這種形式的操作方式,必須讓設(shè)置操作的元素處于獲取焦點(diǎn)狀態(tài)(Focus)几莽,使用View.setFocusable()或在XML布局中設(shè)置 android:focusable屬性迅办。另外,每個(gè)UI控件都有四個(gè)屬性android:nextFocusUp, android:nextFocusDown, android:nextFocusLeft和android:nextFocusRight章蚣,你可以用這些屬性定義在某個(gè)方向哪個(gè)控件將獲取焦點(diǎn)站欺,因?yàn)橄到y(tǒng)默認(rèn)是采用布局臨近原則來(lái)自動(dòng)決定順序的,采用這四個(gè)屬性可以人工干預(yù)纤垂。例如:有一個(gè)Button和一個(gè)TextView矾策,都可以focus,當(dāng)按下方向鍵的時(shí)候焦點(diǎn)從button跳到TextView峭沦,按上焦點(diǎn)返回到button:

最好的驗(yàn)證方式是在模擬器上贾虽,操作上下方向鍵,來(lái)查看控件的焦點(diǎn)情況吼鱼。
發(fā)送輔助事件
如果你使用AndroidFramework中的控件蓬豁,那么不管何時(shí)它的選中狀態(tài)或焦點(diǎn)狀態(tài)發(fā)生變化,都可以發(fā)送AccessibilityEvent菇肃。這個(gè)事件是由accessibility service檢查的庆尘,可以提供像TTS那樣的功能。如果你寫(xiě)一個(gè)自定義的View巷送,要保證在適當(dāng)?shù)臅r(shí)候發(fā)送accessibility event驶忌。通過(guò)調(diào)用sendAccessibilityEvent(int)方法,其中參數(shù)代表發(fā)生的事件類(lèi)笑跛,來(lái)創(chuàng)建一個(gè)事件付魔。AccessibilityEvent提供了完整的事件類(lèi)型列表。例如飞蹂,你想繼承imageview以致于在它獲取焦點(diǎn)時(shí)可以通過(guò)鍵盤(pán)輸入標(biāo)題上去几苍,這時(shí)需要發(fā)生一個(gè) TYPE_VIEW_TEXT_CHANGED事件,盡管這個(gè)事件一般沒(méi)有在內(nèi)置定義在imageview中陈哑。代碼如下:
public void onTextChanged(String before, String after) { ... if (AccessibilityManager.getInstance(mContext).isEnabled()) { sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); } ...}

開(kāi)發(fā)一個(gè)Accessibility Service
創(chuàng)建一個(gè)Accessibility Service
package com.example.android.apis.accessibility;import android.accessibilityservice.AccessibilityService;public class MyAccessibilityService extends AccessibilityService {... @Override public void onAccessibilityEvent(AccessibilityEvent event) { } @Override public void onInterrupt() { }...}

在Manifest中注冊(cè)Service妻坝,要特別指定android.accessibilityservice伸眶,當(dāng)應(yīng)用程序發(fā)出一個(gè)AccessibilityEvent時(shí)可以接收到。
...

. . .
...

配置Accessibility Service
配置Accessibility Service有兩種方式刽宪,兼容的方式是在代碼中配置厘贼。在onServiceConnected()中調(diào)用setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)來(lái)配置輔助服務(wù):
@Overridepublic void onServiceConnected() { // Set the type of events that this service wants to listen to. Others // won't be passed to this service. info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED; // If you only want this service to work with specific applications, set their // package names here. Otherwise, when the service is activated, it will listen // to events from all applications. info.packageNames = new String[] {"com.example.android.myFirstApp", "com.example.android.mySecondApp"}; // Set the type of feedback your service will provide. info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; // Default services are invoked only if no package-specific ones are present // for the type of AccessibilityEvent generated. This service is // application-specific, so the flag isn't necessary. If this was a // general-purpose service, it would be worth considering setting the // DEFAULT flag. // info.flags = AccessibilityServiceInfo.DEFAULT; info.notificationTimeout = 100; this.setServiceInfo(info);}

從Android4.0開(kāi)始,我們可以將配置寫(xiě)在一個(gè)XML文件中圣拄,一些配置選項(xiàng)比如canRetrieveWindowContent只能在XML中配置嘴秸。和上面代碼同樣的配置選項(xiàng)的XML配置如下:

如果使用XML配置,還需要在Manifest文件中配置 屬性庇谆,指定輔助服務(wù)的resource為上面的XML配置文件:

響應(yīng)AccessibilityEvents
覆蓋onAccessibilityEvent(AccessibilityEvent)方法來(lái)處理AccessibilityEvents事件:
@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) { final int eventType = event.getEventType(); String eventText = null; switch(eventType) { case AccessibilityEvent.TYPE_VIEW_CLICKED: eventText = "Focused: "; break; case AccessibilityEvent.TYPE_VIEW_FOCUSED: eventText = "Focused: "; break; } eventText = eventText + event.getContentDescription(); // Do something nifty with this text, like speak the composed string // back to the user. speakToUser(eventText); ...}

查詢(xún)View Heirarchy獲取的Context
這個(gè)是 Android 4.0 (API Level 14) 上AccessibilityService 才有的能力岳掐,這種能力非常有用!我們需要在XML的配置中配置android:canRetrieveWindowContent=”true”饭耳。通過(guò)getSource()獲得AccessibilityNodeInfo對(duì)象串述,如果事件源的窗口仍然是活動(dòng)窗口,則這個(gè)調(diào)用返回一個(gè)對(duì)象寞肖;否則返回null纲酗。下面的例子是一個(gè)代碼片段,它接收到一個(gè)事件時(shí),作如下事情:1、直接抓住事件源View的父視圖2逝淹、在父View里耕姊,尋找一個(gè)label和checkbox作為子View3、如果找到了栅葡,創(chuàng)建一個(gè)string發(fā)給用戶(hù)茉兰,標(biāo)識(shí)checkbox是否被選中4、如果遍歷了整個(gè)view hierarchy返回null欣簇,則默默的放棄
// Alternative onAccessibilityEvent, that uses AccessibilityNodeInfo@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) { AccessibilityNodeInfo source = event.getSource(); if (source == null) { return; } // Grab the parent of the view that fired the event. AccessibilityNodeInfo rowNode = getListItemNodeInfo(source); if (rowNode == null) { return; } // Using this parent, get references to both child nodes, the label and the checkbox. AccessibilityNodeInfo labelNode = rowNode.getChild(0); if (labelNode == null) { rowNode.recycle(); return; } AccessibilityNodeInfo completeNode = rowNode.getChild(1); if (completeNode == null) { rowNode.recycle(); return; } // Determine what the task is and whether or not it's complete, based on // the text inside the label, and the state of the check-box. if (rowNode.getChildCount() < 2 || !rowNode.getChild(1).isCheckable()) { rowNode.recycle(); return; } CharSequence taskLabel = labelNode.getText(); final boolean isComplete = completeNode.isChecked(); String completeStr = null; if (isComplete) { completeStr = getString(R.string.checked); } else { completeStr = getString(R.string.not_checked); } String reportStr = taskLabel + completeStr; speakToUser(reportStr);}

現(xiàn)在规脸,你有一個(gè)功能完整的accessibility servicel了。試著配置TTS引擎來(lái)更好的與用戶(hù)交互熊咽,或者使用振動(dòng)提供觸摸反饋莫鸭。
系統(tǒng)狀態(tài)欄和導(dǎo)航欄
參考地址:http://developer.android.com/training/system-ui/index.html
變暗系統(tǒng)狀態(tài)欄
在Android 4.0(API14)及以上可以使用SYSTEM_UI_FLAG_LOW_PROFILE這個(gè)Flag很容易的變暗狀態(tài)欄。Android早期版本系統(tǒng)不提供一個(gè)內(nèi)置的API變暗狀態(tài)欄横殴。
// This example uses decor view, but you can use any visible view.View decorView = getActivity().getWindow().getDecorView();int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;decorView.setSystemUiVisibility(uiOptions);

當(dāng)用戶(hù)觸摸狀態(tài)或?qū)Ш綑诒灰颍@個(gè)flag就消失了,就恢復(fù)了明亮衫仑。如果想再次變暗它梨与,就需要重新設(shè)置它。如果你要通過(guò)代碼清除flag文狱,使用setSystemUiVisibility():
View decorView = getActivity().getWindow().getDecorView();// Calling setSystemUiVisibility() with a value of 0 clears// all flags.decorView.setSystemUiVisibility(0);

隱藏狀態(tài)欄
![](http://upload-images.jianshu.io/upload_images/2761423-5647e863f436313f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)注意:狀態(tài)欄不可見(jiàn)時(shí)粥鞋,永遠(yuǎn)不要顯示action bar 。![](http://upload-images.jianshu.io/upload_images/2761423-757753de83ded631.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在Android 4.0及以下版本上隱藏狀態(tài)欄
...

或者
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // If the Android version is lower than Jellybean, use this call to hide // the status bar. if (Build.VERSION.SDK_INT < 16) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } setContentView(R.layout.activity_main); } ...}

可以使用FLAG_LAYOUT_IN_SCREEN這個(gè)flag設(shè)置你的Activity使用相同的屏幕區(qū)域瞄崇,這樣就不會(huì)使?fàn)顟B(tài)欄不停的隱藏和顯示了呻粹。
在Android 4.1隱藏狀態(tài)欄
View decorView = getWindow().getDecorView();// Hide the status bar.int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;decorView.setSystemUiVisibility(uiOptions);// Remember that you should never show the action bar if the// status bar is hidden, so hide that too if necessary.ActionBar actionBar = getActionBar();actionBar.hide();

注意:設(shè)置UI的flag只是當(dāng)時(shí)生效壕曼。比如你在onCreate()中設(shè)置隱藏狀態(tài)欄,點(diǎn)擊home回到桌面狀態(tài)欄顯示等浊,再次進(jìn)入之后onCreate()不會(huì)再執(zhí)行腮郊,狀態(tài)欄就一直顯示,就會(huì)有問(wèn)題了凿掂。解決方法是:在onResume()或onWindowFocusChanged()中設(shè)置flag使其消失伴榔。setSystemUiVisibility()方法只對(duì)可見(jiàn)的View有效設(shè)置過(guò)setSystemUiVisibility()的View再導(dǎo)航離開(kāi)后纹蝴,flag會(huì)消失庄萎。

讓界面內(nèi)容顯示在狀態(tài)欄的后面
在Android 4.1及以后,可以設(shè)置界面內(nèi)容在狀態(tài)欄的后面塘安,這樣界面就不會(huì)因?yàn)闋顟B(tài)欄顯示和隱藏而resize了糠涛。使用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN這個(gè)flag就可以了,還可以使用SYSTEM_UI_FLAG_LAYOUT_STABLE這個(gè)flag幫助app維持一個(gè)穩(wěn)定的布局兼犯。當(dāng)你使用這種方法時(shí)忍捡,你就要對(duì)它負(fù)責(zé),來(lái)確保你的某些UI(比如地圖的內(nèi)置控件)不會(huì)被遮住而影響使用切黔。多數(shù)情況下你可以在XML布局中設(shè)置android:fitsSystemWindows屬性為true來(lái)處理這種情況砸脊,這對(duì)大多數(shù)應(yīng)用都適用。某些情況下纬霞,可能你需要修改默認(rèn)的padding值來(lái)得到想要的合理布局凌埂。要直接操作內(nèi)容布局相對(duì)于狀態(tài)欄的位置(占據(jù)的那部分空間稱(chēng)content insets),需要覆蓋fitSystemWindows(Rect insets)方法诗芜。fitSystemWindows方法在content insets發(fā)生變化被 view hierarchy時(shí)調(diào)用瞳抓,允許window調(diào)整它的content。通過(guò)覆蓋這個(gè)方法伏恐,不管你想不想孩哑,你都可以處理這個(gè)insets 。
讓Actionbar和狀態(tài)欄同步
在Android 4.1及以上版本中翠桦,為避免在actionbar隱藏和顯示時(shí)resize你的布局横蜒,你可以為actionbar開(kāi)啟覆蓋(overlay)模式。在覆蓋模式中销凑,你的Activity使用盡可能大的空間好像Actionbar不在那兒一樣丛晌,其實(shí)actionbar是在布局的上面,只是布局頂部有一部分變模糊了闻鉴,但現(xiàn)在actionbar不管顯示和隱藏茵乱,都不會(huì)resize布局了。打開(kāi)覆蓋模式孟岛,需要?jiǎng)?chuàng)建一個(gè)自定義的主題瓶竭,繼承一個(gè)帶有actionbar的主題督勺,設(shè)置 android:windowActionBarOverlay=true。然后使用上面提到的SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN Flag斤贰,設(shè)置你的Activity在打開(kāi)SYSTEM_UI_FLAG_FULLSCREEN flag時(shí)使用相同的屏幕區(qū)域智哀。當(dāng)你要隱藏SystemUI時(shí),使用SYSTEM_UI_FLAG_FULLSCREEN的flag荧恍。這個(gè)也會(huì)隱藏action bar(因?yàn)閍ndroid:windowActionBarOverlay=true)瓷叫,而且在隱藏和顯示時(shí)有一個(gè)和諧的動(dòng)畫(huà)。
隱藏導(dǎo)航欄


navigation-bar

vcC4oaM8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> View decorView = getWindow().getDecorView(); // Hide both the navigation bar and the status bar. // SYSTEM_UI_FLAG_FULLSCREEN is only available on Android 4.1 and higher, but as // a general rule, you should design your app to hide the status bar whenever you // hide the navigation bar. int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions);

使用這個(gè)方法送巡,用戶(hù)點(diǎn)擊屏幕任何地方將導(dǎo)致導(dǎo)航欄(和狀態(tài)欄)都重新顯示并保持摹菠。這個(gè)flag被清除后,需要重新設(shè)置它進(jìn)行隱藏導(dǎo)航欄其他部分都和狀態(tài)欄的注意部分一樣

讓界面內(nèi)容顯示在導(dǎo)航欄下面
在Android4.1及以上版本骗爆,使用SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION的flag使界面布局顯示在導(dǎo)航欄的下面次氨,并使用SYSTEM_UI_FLAG_LAYOUT_STABLE保持布局。其他部分和狀態(tài)欄部分注意部分相同
使用沉浸式的全屏模式
在Android 4.4 (API Level 19)中為setSystemUiVisibility()新介紹了SYSTEM_UI_FLAG_LAYOUT_STABLE的flag摘投,它讓你的app真實(shí)的進(jìn)入“全屏”模式煮寡,和SYSTEM_UI_FLAG_HIDE_NAVIGATION以及SYSTEM_UI_FLAG_FULLSCREEN結(jié)合起來(lái)時(shí),隱藏狀態(tài)欄和導(dǎo)航欄犀呼,app將捕獲全屏的觸摸事件幸撕。當(dāng)沉浸式全屏模式開(kāi)啟后宪拥,你的Activity持續(xù)的接收全屏的觸摸事件约啊。當(dāng)用戶(hù)沿著system bar一般顯示的地方向內(nèi)滑動(dòng)時(shí)會(huì)讓system bar顯示出來(lái)段审。這個(gè)動(dòng)作清除了SYSTEM_UI_FLAG_HIDE_NAVIGATION flag (以及 SYSTEM_UI_FLAG_FULLSCREEN淘太,如果應(yīng)用的話(huà))锌妻,于是system bar變得可見(jiàn)勾邦,這會(huì)觸發(fā)View.OnSystemUiVisibilityChangeListener序六。然而糕非,你希望system bar一會(huì)兒后再自動(dòng)隱藏跃须,你可以使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY的flag站叼。注意這個(gè)粘性(”sticky” )的版本不會(huì)觸發(fā)任何監(jiān)聽(tīng)事件,因?yàn)閟ystem bar在這種模式下只是暫時(shí)性的顯示菇民。![](http://upload-images.jianshu.io/upload_images/2761423-6b390d66e11494cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
非沉浸式模式尽楔。在app進(jìn)入沉浸式模式前的狀態(tài)。它也表示如果你使用沉浸式flag第练,當(dāng)用戶(hù)滑動(dòng)時(shí)清除了SYSTEM_UI_FLAG_HIDE_NAVIGATION 和 SYSTEM_UI_FLAG_FULLSCREEN顯示system bar的情況阔馋。這是保持UI控件和system bar同步的最好實(shí)踐,它最小化了屏幕的狀態(tài)數(shù)娇掏。這個(gè)提供了更加無(wú)縫的用戶(hù)體驗(yàn)呕寝,所以這里所有的UI控件和狀態(tài)欄一起顯示。一旦進(jìn)入沉浸模式婴梧,UI控件將隨著system bar的隱藏而隱藏下梢。為確保你的UI和system bar保持可見(jiàn)客蹋,使用View.OnSystemUiVisibilityChangeListener監(jiān)聽(tīng)可見(jiàn)性的變化。 提示氣泡孽江。當(dāng)用戶(hù)第一次進(jìn)入沉浸模式時(shí)讶坯,系統(tǒng)將顯示一個(gè)提示氣泡。這個(gè)氣泡提示用戶(hù)將怎樣顯示system bar岗屏。注意:如果你想強(qiáng)制性的顯示提示氣泡用作測(cè)試意圖辆琅,你可以將app進(jìn)入沉浸模式,然后關(guān)閉屏幕这刷,然后在5秒內(nèi)點(diǎn)亮屏幕婉烟。 沉浸模式。app進(jìn)入沉浸模式崭歧,system bars和其他UI控件都隱藏隅很。 粘性Flag撞牢。這個(gè)UI是你使用IMMERSIVE_STICKY的Flag率碾,然后用戶(hù)滑動(dòng)使system bar顯示的。半透明的bar臨時(shí)顯示然后會(huì)再隱藏屋彪∷祝滑動(dòng)行為不會(huì)清除任何flag,所以也不會(huì)觸發(fā)system UI可見(jiàn)性變化的監(jiān)聽(tīng)畜挥。注意:沉浸的FLag只有你使用SYSTEM_UI_FLAG_HIDE_NAVIGATION, SYSTEM_UI_FLAG_FULLSCREEN的Flag或兩者都有的時(shí)候才會(huì)生效仔粥。通常情況下當(dāng)你使用“全屏沉浸”模式會(huì)隱藏狀態(tài)欄和導(dǎo)航欄。

SYSTEM_UI_FLAG_IMMERSIVE 和SYSTEM_UI_FLAG_IMMERSIVE_STICKY可以提供一個(gè)差異化的沉浸式的體驗(yàn)蟹但。下面是一些情況躯泰,你需要使用其中一個(gè),而不是另一個(gè):
當(dāng)你開(kāi)發(fā)一個(gè)閱讀app华糖,新聞app或雜志app時(shí)麦向,使用沉浸flag需要和SYSTEM_UI_FLAG_FULLSCREEN、 SYSTEM_UI_FLAG_HIDE_NAVIGATION兩者結(jié)合起來(lái)用客叉。 當(dāng)你開(kāi)發(fā)一個(gè)完全沉浸模式的app诵竭,期望用戶(hù)和屏幕的邊緣進(jìn)行交互而不期望用戶(hù)頻繁的和system UI交互,使用粘性沉浸的flag兼搏,結(jié)合SYSTEM_UI_FLAG_FULLSCREEN 和SYSTEM_UI_FLAG_HIDE_NAVIGATION使用卵慰。 如果你開(kāi)發(fā)一個(gè)視頻播放器或其他很少需要用戶(hù)交互的app,你可能需要老一點(diǎn)版本的方法了( Android 4.0 (API Level 14)及以上)佛呻。因?yàn)閷?duì)于這類(lèi)app裳朋,簡(jiǎn)單的使用SYSTEM_UI_FLAG_FULLSCREEN和會(huì)SYSTEM_UI_FLAG_HIDE_NAVIGATION的Flag就足夠了,不需要沉浸的flag吓著。使用非粘性沉浸
這段代碼演示了如何隱藏和顯示狀態(tài)欄和導(dǎo)航欄鲤嫡,而不用resize界面的內(nèi)容氧苍。
// This snippet hides the system bars.private void hideSystemUI() { // Set the IMMERSIVE flag. // Set the content to appear under the system bars so that the content // doesn't resize when the system bars hide and show. mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar | View.SYSTEM_UI_FLAG_IMMERSIVE);}// This snippet shows the system bars. It does this by removing all the flags// except for the ones that make the content appear under the system bars.private void showSystemUI() { mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);}

1、注冊(cè)一個(gè)監(jiān)聽(tīng)讓你的app得到system UI可見(jiàn)性變化的通知泛范。2让虐、實(shí)現(xiàn)onWindowFocusChanged()方法。如果你獲得window的焦點(diǎn)罢荡,你可能想重新隱藏system bar赡突。如果你失去了window的焦點(diǎn),例如一個(gè)對(duì)話(huà)框或彈出菜單区赵,你可能想取消之前的Handler.postDelayed()或類(lèi)似方法安排的隱藏操作惭缰。3、實(shí)現(xiàn)一個(gè)GestureDetector 笼才,讓它監(jiān)測(cè)onSingleTapUp(MotionEvent)漱受,讓用戶(hù)可以通過(guò)觸摸content手動(dòng)控制system bar的可見(jiàn)性。簡(jiǎn)單的click監(jiān)聽(tīng)不是最好的解決方案因?yàn)楫?dāng)用戶(hù)在屏幕滑動(dòng)手指都可以觸發(fā)骡送。
使用粘性沉浸
當(dāng)你使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY的flag昂羡,在system bar內(nèi)部區(qū)域的滑動(dòng)會(huì)導(dǎo)致其半透明狀態(tài)并暫時(shí)性的顯示但沒(méi)有flag被清除,你的system UI的可見(jiàn)性監(jiān)聽(tīng)沒(méi)有被觸發(fā)摔踱。system bar會(huì)在一會(huì)兒以后再次隱藏或用戶(hù)在content交互下虐先。下圖展示了當(dāng)使用IMMERSIVE_STICKY的flag時(shí)半透明的system bar短暫的顯示然后隱藏![](http://upload-images.jianshu.io/upload_images/2761423-ddcb0092bb30c425.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)下面是一個(gè)簡(jiǎn)單的方法來(lái)使用這個(gè)flag:
@Overridepublic void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}}

如果你喜歡IMMERSIVE_STICKY的flag的自動(dòng)隱藏行為,但是需要同時(shí)顯示你自己的UI控件派敷,使用 IMMERSIVE和Handler.postDelayed()或者其它一些類(lèi)似的在一會(huì)兒之后可以重新進(jìn)入沉浸模式的方式蛹批。

響應(yīng)UI可見(jiàn)性的變化
要獲得UI可見(jiàn)性變化的通知,需要為你的View注冊(cè)View.OnSystemUiVisibilityChangeListener篮愉,例如在你的Activity中的onCreate()中:
View decorView = getWindow().getDecorView();decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { // Note that system bars will only be "visible" if none of the // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set. if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { // TODO: The system bars are visible. Make any desired // adjustments to your UI, such as showing the action bar or // other navigational controls. } else { // TODO: The system bars are NOT visible. Make any desired // adjustments to your UI, such as hiding the action bar or // other navigational controls. } }});

通常保持UI與system bar可見(jiàn)性變化的一致性是不錯(cuò)的實(shí)踐腐芍。例如,你可以通過(guò)這種方式讓action bar和狀態(tài)欄保持一致的變化狀態(tài)试躏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末猪勇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子冗酿,更是在濱河造成了極大的恐慌埠对,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裁替,死亡現(xiàn)場(chǎng)離奇詭異项玛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)弱判,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)襟沮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事开伏“虻” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵固灵,是天一觀的道長(zhǎng)捅伤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)巫玻,這世上最難降的妖魔是什么丛忆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮仍秤,結(jié)果婚禮上熄诡,老公的妹妹穿的比我還像新娘。我一直安慰自己诗力,他們只是感情好凰浮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著苇本,像睡著了一般袜茧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上圈澈,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天惫周,我揣著相機(jī)與錄音,去河邊找鬼康栈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛喷橙,可吹牛的內(nèi)容都是我干的啥么。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贰逾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悬荣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起疙剑,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤氯迂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后言缤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體嚼蚀,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年管挟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轿曙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖导帝,靈堂內(nèi)的尸體忽然破棺而出守谓,到底是詐尸還是另有隱情,我是刑警寧澤您单,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布斋荞,位于F島的核電站,受9級(jí)特大地震影響虐秦,放射性物質(zhì)發(fā)生泄漏譬猫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一羡疗、第九天 我趴在偏房一處隱蔽的房頂上張望染服。 院中可真熱鬧,春花似錦叨恨、人聲如沸柳刮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秉颗。三九已至,卻和暖如春送矩,著一層夾襖步出監(jiān)牢的瞬間蚕甥,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工栋荸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菇怀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓晌块,卻偏偏與公主長(zhǎng)得像爱沟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匆背,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容