Android SearchView + Toolbar 的語音搜索功能
searchView的語音搜索功能
Google的官方組件越來越豐富,功能也越來越多但是由於Google服務沒有入華的原因導致一係列的服務不可用,今天就踩了Google語音的坑
我的效果圖
前幾天看到無聊看設計的時候看到了Google 官方的設計圖
覺得還不錯,真好我要做一版blog的Anndroid 端,於是就采用了這個非常常見的ToolBar的,我接觸ToolBar也不是第一次了,對他的印象就是輕便好用,二話不說,先上代碼(Java部分采用kotlin語言)
首先在activity的layout文件上將toolbar放入AppBarLayout
<android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:
app:title="首頁"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
然後在res文件下的menu目錄下(沒有的話自己創建一個)新建menu.xml
<menu xmlns:andro
xmlns:app="https://schemas.android.com/apk/res-auto">
<item
android:
android:imeOptions="actionSearch"
android:title="@string/search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom" />
<item
android:
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
最後重寫Activity的onCreateOptionsMenu()方法
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main, menu)
return true
}
來看看效果
然後就是語音按鈕了,習慣性百度,但是卻沒有相關資料,隻能去看看Google 官方文檔了
https://developer.android.google.cn/guide/topics/search/search-dialog.html
我這這裏找到了相關的說明
原來SearchView依賴一個叫Searchable類作為配置類,不過這個類是final修飾的不能夠new 可以通過xml文件來寫配置,總體來說分為以下幾步
第一步
在res/xml/ 路徑下新建一個searchable.xml 文件
內容
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:andro
android:label="@string/search"
android:hint="請輸入內容"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
>
</searchable>
其中 android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" 這句話就是顯示語音按鈕,官網也給了解釋
第二步
在manifests的activity加一個 action 和一個meta-data,將我們剛才創建的xml引入 具體如下
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
</activity>
第三步
修改代碼讓SearchView 加載 searchable
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main, menu)
val searchMenuItem = menu.findItem(R.id.action_search)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchView = searchMenuItem.actionView as SearchView
val searchView = menu.findItem(R.id.action_search).actionView as SearchView
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
return true
}
大功告成,於是立馬去運行下看看效果,然後並沒卵用,語音按鈕還是沒出來,百思不得其解,還是老老實實去看看SearchView的源碼吧,不懂原理始終是被人牽著走呀
Google的源碼還是很規範的
......
final ImageView mSearchButton;
final ImageView mGoButton;
final ImageView mCloseButton;
final ImageView mVoiceButton;
......
顧名思義 mVoiceButton就是語音按鈕
private boolean mVoiceButtonEnabled;
又發現個boolean參數,猜的沒錯的話這個就是控製語音按鈕顯示的吧,接著看源碼,找到了這段
private void updateVoiceButton(boolean empty) {
int visibility = GONE;
if (mVoiceButtonEnabled && !isIconified() && empty) {
visibility = VISIBLE;
mGoButton.setVisibility(GONE);
}
mVoiceButton.setVisibility(visibility);
}
果然是這樣的,不過voice不僅僅受限製於它,還有其他的參數限製,看到這裏我突然想到,是不是我沒安裝Google搜索服務導致的,立馬打開我的GooglePlay
安裝了這貨然後
語音圖標就出來了,如果要完整的實現語音功能還是要在Activity解析Google語音返回回來的消息還是要在Activity裏解析的,所以完整的第三步是這樣的
### 完整的第三步
private lateinit var searchView: SearchView
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main, menu)
val searchMenuItem = menu.findItem(R.id.action_search)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
searchView = searchMenuItem.actionView as SearchView
val searchView = menu.findItem(R.id.action_search).actionView as SearchView
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
return true
}
override fun onNewIntent(intent: Intent) {
setIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
if (Intent.ACTION_SEARCH == intent.action) {
val query = intent.getStringExtra(SearchManager.QUERY)
searchView.setQuery(query,false)
searchView.setIconifiedByDefault(true)
}
}
Activity 的啟動模式要設置為singleTop 否則會無限次打開
終於知道為什麼百度都找不到方案了,原來這貨需要Google服務的支持,
所以忙活了半天也是瞎忙活,好在阿裏雲提供了免費的語音解析服務(好歹也是用的雲棲社區,肯定要給阿裏個麵子),看來要手動造輪子了下周見,源碼見附件,完整blog上線我會提供github地址
最後更新:2017-10-12 15:33:31