Android進階:動態修改android內建搜尋對話方塊(浮動搜尋)的Icon

來源:互聯網
上載者:User

上次寫的是構建Android內建浮動搜尋方塊的配置,當然很簡單了,就是麻煩點而已 在我寫demo的過程中我發現一個問題 上次有提到

 



其中有個 android:icon="@drawable/menu_route" 本來以為可以設定 就搜尋Text前面那個View的 後來發現不起作用,而且文檔中都沒提到這個屬性 看來確實沒用啊 因為這屬性我可折騰好久

 

效果

 

就是這個了,看了SDK的文檔發現確實這裡沒有提供修改表徵圖的配置,那如果這裡有需求要改的情況怎麼辦呢,所以研究了下源碼 終於解決了

 

仔細看中間輸入框兩邊的那個表徵圖就可以看到 左邊那個就是Application的Icon 是個ImageView , 右邊那個是固定的 是個Button

 

這個配置就在

/res/layout/search_bar.xml 檔案中 可以自己看一下布局 如下:

 

<?xml version="1.0" encoding="UTF-8"?><br /><view android:orientation="vertical" android:id="@id/search_bar" android:focusable="true" android:descendantFocusability="afterDescendants" android:layout_width="fill_parent" android:layout_height="wrap_content" class="android.app.SearchDialog$SearchBar"<br /> xmlns:android="http://schemas.android.com/apk/res/android"><br /> <LinearLayout android:orientation="vertical" android:id="@id/search_plate" android:background="@drawable/search_plate_global" android:paddingLeft="12.0dip" android:paddingTop="7.0dip" android:paddingRight="6.0dip" android:paddingBottom="16.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content"><br /> <TextView android:textAppearance="?textAppearanceSmall" android:textColor="?textColorPrimaryInverse" android:id="@id/search_badge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="2.0dip" android:drawablePadding="0.0dip" /><br /> <LinearLayout android:orientation="horizontal" android:id="@id/search_edit_frame" android:layout_width="fill_parent" android:layout_height="wrap_content"><br /> <ImageView android:layout_gravity="center_vertical" android:id="@id/search_app_icon" android:layout_width="36.0dip" android:layout_height="36.0dip" android:layout_marginRight="7.0dip" /><br /> <view android:ellipsize="end" android:id="@id/search_src_text" android:background="@drawable/textfield_search" android:paddingLeft="8.0dip" android:paddingRight="6.0dip" android:layout_width="0.0dip" android:layout_height="wrap_content" android:singleLine="true" android:drawablePadding="2.0dip" android:popupBackground="@drawable/search_dropdown_background" android:layout_weight="1.0" android:inputType="textAutoComplete" android:dropDownWidth="fill_parent" android:dropDownAnchor="@id/search_plate" android:dropDownHeight="fill_parent" android:dropDownVerticalOffset="-9.0dip" class="android.app.SearchDialog$SearchAutoComplete" /><br /> <Button android:id="@id/search_go_btn" android:background="@drawable/btn_search_dialog" android:layout_width="wrap_content" android:layout_height="fill_parent" /><br /> <ImageButton android:id="@id/search_voice_btn" android:background="@drawable/btn_search_dialog_voice" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginLeft="0.0dip" android:layout_marginTop="-6.5dip" android:layout_marginRight="-5.0dip" android:layout_marginBottom="-7.0dip" android:src="@drawable/ic_btn_speak_now" /><br /> </LinearLayout><br /> </LinearLayout><br /></view>

 



可以看到Google還專門給訂製了一款搜尋方塊呢 android.app.SearchDialog$SearchAutoComplete 都不帶用 AutoCompleteTextView 的

 

上面就是這個搜尋方塊的布局檔案 那顯示的其實就是 SearchDialog 在android.app包裡的 剛開始在2.1裡還沒見到這個類呢 不知道咋回事

 

我們調用搜尋方塊的方法是 通過onSearchRequested

()來調用Acitvity的startSearch()

 

而在Acitivity中我們可以看到一個變數mSearchManager 真正調用的就是它的方法startSearch()

 

這樣我們就瞭解了這個搜尋方塊整個的調用過程了

 

在我的應用程式中:

 

MapActivity--》Acitvity--》SearchManager--》SearchDialog

 

這樣就清晰了 下面就可以進行操作了 然而這些類中的全域變數是private

的 而且沒有提供set方法 這樣我們就不能直接存取變數進行修改了,那隻有一個方法了 就是反射

 

首先看代碼: 在調用startSearch()方法顯示搜尋方塊之後

 

try {<br />//通過反射修改搜尋方塊的表徵圖<br /> Class activityClass = Class.forName("android.app.Activity");<br /> Field activityClassf = activityClass.getDeclaredField("mSearchManager");<br /> activityClassf.setAccessible(true);<br /> Object mSearchManager = activityClassf.get(this);</p><p> Class searchClass = Class.forName("android.app.SearchManager");<br /> Field mSearchDialogf = searchClass.getDeclaredField("mSearchDialog");<br /> mSearchDialogf.setAccessible(true);<br /> Object mSearchDialog = mSearchDialogf.get(mSearchManager);</p><p>Class searchDialog = Class.forName("android.app.SearchDialog");<br />Field mAppIcon = searchDialog.getDeclaredField("mAppIcon");<br />mAppIcon.setAccessible(true);<br />ImageView imageView = (ImageView) mAppIcon.get(mSearchDialog);<br />Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);<br />imageView.setImageDrawable(new BitmapDrawable(bitmap));</p><p>} catch (Exception e) {<br />e.printStackTrace();<br />}

 

這裡首先在當前對象Acitivity中 拿到私人變數 mSearchManager  的對象 然後通過它拿到私人變數 mSearchDialog 的SearchDialog的對象,最後拿到SearchDialog中的私人變數mAppIcon 這個ImageView 那當然就可以隨便對他進行修改了

 

上面這個是更改搜尋方塊左邊那個Icon的方法 右邊的那個同理也是可以修改的 只不過它是Button而已

 

Field mGoButtonf = searchDialog.getDeclaredField("mGoButton");<br />mGoButtonf.setAccessible(true);<br />Button mGoButton = (Button) mGoButtonf.get(mSearchDialog);<br />bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.transit);<br />mGoButton.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(bitmap), null, null, null);

 

這樣就修改完成了 下面來看看效果:

 

 

都修改完成了。。當然圖片大小可能不合適就先將就吧 demo而已

 

最後總結一下  我們開發中的大多數控制項android都是提供的 但是難免會有需求想修改一些地方 文字大小樣式 圖片位置 icon等的一些修改 一般也都是比較小的修改 但是雖然是小修改可以google可不給我們機會 這種情況下要麼照著葫蘆畫瓢重寫一個,但這樣就得花費比較長的時間了,我們還可以用java的工具反射來搞呢,這樣簡單而且有效啊

 

PS:不得不說反射真是實用啊,以前架構裡經常會用到,現在也是有用武之地啊,就是geiliable

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.