閱讀515 返回首頁    go 微軟 go windows


Android SearchView + Toolbar 的語音搜索功能

searchView的語音搜索功能

Google的官方組件越來越豐富,功能也越來越多但是由於Google服務沒有入華的原因導致一係列的服務不可用,今天就踩了Google語音的坑

我的效果圖

giphy_1_

前幾天看到無聊看設計的時候看到了Google 官方的設計圖

image
image

覺得還不錯,真好我要做一版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
    }

來看看效果

200w_d

然後就是語音按鈕了,習慣性百度,但是卻沒有相關資料,隻能去看看Google 官方文檔了

https://developer.android.google.cn/guide/topics/search/search-dialog.html
我這這裏找到了相關的說明
原來SearchView依賴一個叫Searchable類作為配置類,不過這個類是final修飾的不能夠new 可以通過xml文件來寫配置,總體來說分為以下幾步

第一步

在res/xml/ 路徑下新建一個searchable.xml 文件
image
內容

<?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" 這句話就是顯示語音按鈕,官網也給了解釋
image

第二步

在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
WechatIMG157_jpeg
安裝了這貨然後
語音圖標就出來了,如果要完整的實現語音功能還是要在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

  上一篇:go  調查顯示:企業掙紮於攻擊檢測和分析中
  下一篇:go 雲棲大會現場潮媽為女征婚,點名隻要程序員!