親愛的同窗們我又來了,搬好小板凳準備開車了。。。android
不知道你們平時都用什麼聽音樂,我我的比較喜歡網易雲音樂 (不是作廣告,可是我這是幹啥呢?),不過如今網易雲音樂不能停周董的歌了,實在有些。。。那天忽然想起最近研究的MaterialDesign,就想到的網易雲音樂的標題欄是怎麼實現的。後來我就各類百度,中於功夫不負有心人,總算是被我刨出來了!其實網易雲音樂使用的就是標題上面說的SearchView,其實就是一個搜索的View。那麼怎麼實現的呢?請聽下回分解!bash
開個玩笑,同窗們準備好,立刻開車了。。。app
先簡單說明一下,這裏主要是講解SearchView怎麼實現網易雲音樂的標題欄,可是都是以來Toolbar的,若是你對Toolbar和menu不是很瞭解的話!ide
請看我公衆號的這兩篇文章(強勢輸出一波)佈局
上面很詳細的講解了關於Toolbar和menu的使用方法和注意事項!!!this
SearchView是和Toolbar聯動,經過menu進行設置的搜索的控件(不知道我這麼歸納你能不能懂)。會在Toolbar的右側出現一個搜索的按鈕(系統自帶的,也能夠進行替換)。當你點擊搜索按鈕的時候,會出現相應的編輯框進行搜索。當你點擊叉號的時候,本次搜索取消,還原成搜索按鈕。google
這裏針對menu作了一些修改,因此可能和你出現的基本效果不太同樣,可是我會把相應的內容貼出來,這樣便於像我同樣的懶癌患者,能很快的實現效果。畢竟開發項目緊的時候我是不會管是怎麼實現的!!!先看一下基本功能的效果圖spa
相信你看了以前的那兩篇文章的話,很快就能寫出下面這個標題欄的。
<?xml version="1.0" encoding="utf-8"?>
<!--仿網易雲音樂的menu實現-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:icon="@drawable/ic_search_black_24dp"
android:title="搜索"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
<item
android:id="@+id/other"
android:title="其餘內容"
app:showAsAction="never" />
</menu>
複製代碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.jinlong.newmaterialdesign.toolbar.YunActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#ff0000"
app:popupTheme="@style/ToolbarTheme"
app:navigationIcon="@mipmap/back_icon">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="雲Toolbar的實現"
android:textColor="@android:color/white"
android:textSize="18sp" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
複製代碼
public class YunActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_yun);
initToolbar();
}
private void initToolbar() {
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle("");
setSupportActionBar(toolbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_yun,menu);
return super.onCreateOptionsMenu(menu);
}
}
複製代碼
上面代碼跑一下,緊接着就能夠看見上面的內容了!
由於在初始化SearcheView,須要對相應的menu進行操做,因此通常都會在
onCreateOptionsMenu(Menu menu)
中進行獲取。具體代碼以下:
//獲取SearchView對象
MenuItem searchItem = menu.findItem(R.id.search);
mSearchView = (SearchView) searchItem.getActionView();
複製代碼
這裏注意一點,就是在初始化SearchView的時候,也可使用MenuItemCompat.getActionView(searchItem);
進行獲取的,只不過是過期了。。。因此見到了不要說不知道就行
setOnQueryTextListener(OnQueryTextListener listener)
setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//在文字改變的時候回調,query是改變以後的文字
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
//文字提交的時候哦回調,newText是最後提交搜索的文字
return false;
}
});
複製代碼
上面的內容能夠實現簡單的搜索了?其實我我的以爲這一個監聽還不夠?爲何這麼說呢?由於你想要控制Fragment的切換,沒有相應的時間點,或者說是沒找到時機進行Fragment的切換問題,當時我想了很久,後來看見源碼的時候,我才發現,其實這種時機google工程是早就替咱們想好了,其實我以爲咱們能想到的,google工程師會替咱們實現的!
這樣就存在相應的時間點了,你在進來的時候開啓一個事物,放進去一個Fragment(這裏若是你想加動畫效果的話,你可使用ViewPager,而後經過設置顯示那個的方法進行切換.其實事物也是能夠設置動畫的,看你怎麼選擇吧)。當你點擊關閉的時候。再將以前的Fragment替換掉就能夠了。這裏爲了你們能更好的理解,我仍是用代碼實現一下吧!先看下效果(虛擬機錄得有點渣!)
public class YunActivity extends AppCompatActivity {
private static final String TAG = YunActivity.class.getSimpleName();
private SearchView mSearchView;
private ViewPager mVpContent;
private SearchFragment mSearchFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_yun);
Log.e(TAG, "onCreate: ");
initToolbar();
initViewPager();
}
private void initToolbar() {
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle("");
setSupportActionBar(toolbar);
}
private void initViewPager() {
mVpContent = findViewById(R.id.vp_content);
List<Fragment> list = new ArrayList<>();
DefaultFragment defaultFragment = new DefaultFragment();
list.add(defaultFragment);
mSearchFragment = new SearchFragment();
list.add(mSearchFragment);
MainVPAdapter adapter = new MainVPAdapter(getSupportFragmentManager(), list);
mVpContent.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.e(TAG, "onCreateOptionsMenu: ");
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_yun, menu);
//獲取SearchView對象
MenuItem searchItem = menu.findItem(R.id.search);
mSearchView = (SearchView) searchItem.getActionView();
//設置相應的監聽,文字變化的監聽
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//在文字改變的時候回調,query是改變以後的文字
mSearchFragment.setSearchStr(query);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
//文字提交的時候哦回調,newText是最後提交搜索的文字
return false;
}
});
mSearchView.setOnSearchClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//開始搜索的時候,設置顯示搜索頁面
mVpContent.setCurrentItem(1);
}
});
mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
//關閉搜索按鈕的時候,設置顯示默認頁面
mVpContent.setCurrentItem(0);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}
複製代碼
這裏最主要的就是那幾個監聽,只要你理解了那幾個監聽的話基本上就沒有問題了。
public class SearchFragment extends Fragment {
private TextView mTvSearch;
public SearchFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_search, container, false);
mTvSearch = rootView.findViewById(R.id.tv_search);
return rootView;
}
/**
* 搜索的內容
*/
public void setSearchStr(String query) {
if (!TextUtils.isEmpty(query))
mTvSearch.setText("搜索的內容是" + query);
}
}
複製代碼
這樣就能實現相應的效果了。怎麼樣?不錯吧!!!
上面的圖是沒有提示文字時候顯示的樣子,怎麼添加提示文字呢?
searchView.setQueryHint("相應的提示內容");
複製代碼
經過上面的代碼就能夠添加搜索的提示文字了。
這個搜索按鈕是在輸入框的內部,當你設置內容的時候,搜索按鈕會消失。這個我感受我描述的不太正確,管他呢?大家理解就好。。。
有的產品經理總會有奇葩的需求,想要去掉那個搜索後面的叉號。說不人性。。。只能默默的改了。。。其實個人心裏是崩潰的。。。
雖然你能關閉這個圖標,可是這樣就存在一個問題了,以前寫好的關閉切換Fragment的操做在這裏就會失效了。怎麼解決呢?想了半天,只有處理返回事件了,要不我根本就沒有辦法知道用戶真麼時候搜索完成啊?那就只有何時執行返回操做何時算他結束了唄!
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSearchAutoComplete.isShown()) {
try {
mSearchAutoComplete.setText("");//清除文本
//利用反射調用收起SearchView的onCloseClicked()方法
Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
method.setAccessible(true);
method.invoke(mSearchView);
} catch (Exception e) {
e.printStackTrace();
}
} else {
finish();
}
}
});
複製代碼
加上這段代碼的話,經過反射拿到SearchView的onDloseClicked(),調用一下就能夠了
產品又說了,進到這個頁面,默認應該是顯示搜索對話框的,用戶少操做一步,用戶體驗好,當時我就說了。那用戶就要那樣呢?產品說那樣的奇葩用戶不用管。。。(當時的我啊!滿腦殼黑線)
老根產品過不去也不行吧!這裏本身看了看搜索圖標以爲小了,想更改一下!怎麼辦呢?
就是在頁面的Activity的主題中,添加相應的searchViewStyle屬性,這個屬性能夠本身設置的。
<!--SearchView的主題設置-->
<item name="searchViewStyle">@style/SearchViewStyle</item>
<!--SearchView的主題設置-->
<style name="SearchViewStyle" parent="Widget.AppCompat.SearchView">
<!--修改圖標的圖片-->
<item name="searchIcon">@mipmap/ic_directions_bike_white_24dp</item>
<!--去掉圖標-->
<!--<item name="searchHintIcon">@null</item>-->
</style>
複製代碼
這裏的圖片就看你發揮了。。。
當你以爲輸入框的文字或者提示的文字是黑色比較難看的時候,那麼你能夠像下面這樣修改
//修改searchView的文字顏色
SearchView.SearchAutoComplete mSearchAutoComplete = mSearchView.findViewById(R.id.search_src_text);
//設置輸入框內提示文字樣式
mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.white));//設置提示文字顏色
mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.white));//設置內容文字顏色
複製代碼
不知道還有沒有什麼其餘的了,我感受有了這些對付大家產品經理就已經足夠了,不行桌子上放把刀、要不放個二維碼啥的就能夠了。。。
但願個人文章對你有幫助!但願咱們共同進步。。。see you!
若是你感興趣,請關注個人二維碼