Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android進階:動態修改android內置搜索對話框(浮動搜索)的Icon

Android進階:動態修改android內置搜索對話框(浮動搜索)的Icon

編輯:Android開發實例

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

 

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


 

 

 


 

 

效果如圖

 

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

 

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

 

這個配置就在 /res/layout/search_bar.xml 文件中 可以自己看一下布局 如下:

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <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" 
  3.   xmlns:android="http://schemas.android.com/apk/res/android"> 
  4.     <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"> 
  5.         <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" /> 
  6.         <LinearLayout android:orientation="horizontal" android:id="@id/search_edit_frame" android:layout_width="fill_parent" android:layout_height="wrap_content"> 
  7.             <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" /> 
  8.             <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" /> 
  9.             <Button android:id="@id/search_go_btn" android:background="@drawable/btn_search_dialog" android:layout_width="wrap_content" android:layout_height="fill_parent" /> 
  10.             <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" /> 
  11.         </LinearLayout> 
  12.     </LinearLayout> 
  13. </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()方法顯示搜索框之後

  1. try {  
  2.             //通過反射修改搜索框的圖標  
  3.             Class activityClass = Class.forName("android.app.Activity");  
  4.             Field activityClassf = activityClass.getDeclaredField("mSearchManager");  
  5.             activityClassf.setAccessible(true);  
  6.             Object mSearchManager = activityClassf.get(this);  
  7.               
  8.             Class searchClass = Class.forName("android.app.SearchManager");  
  9.             Field mSearchDialogf = searchClass.getDeclaredField("mSearchDialog");  
  10.             mSearchDialogf.setAccessible(true);  
  11.             Object mSearchDialog = mSearchDialogf.get(mSearchManager);  
  12.               
  13.             Class searchDialog = Class.forName("android.app.SearchDialog");  
  14.             Field mAppIcon = searchDialog.getDeclaredField("mAppIcon");  
  15.             mAppIcon.setAccessible(true);  
  16.             ImageView imageView = (ImageView) mAppIcon.get(mSearchDialog);  
  17.             Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);  
  18.             imageView.setImageDrawable(new BitmapDrawable(bitmap));  
  19.               
  20.         } catch (Exception e) {  
  21.             e.printStackTrace();  
  22.         } 

 

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

 

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

  1. Field mGoButtonf = searchDialog.getDeclaredField("mGoButton");  
  2.             mGoButtonf.setAccessible(true);  
  3.             Button mGoButton = (Button) mGoButtonf.get(mSearchDialog);  
  4.             bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.transit);  
  5.             mGoButton.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(bitmap), null, null, null); 

 

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

 

 

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

 

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

 

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

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved