Android Dropdown меню на всю ширину Action Bar

Android: добавить Dropdown меню на всю ширину Action Bar

Android Dropdown меню на всю ширину Action Bar

Android Dropdown меню на всю ширину Action Bar

Как же установить выпадающее меню на всю ширину Action Bar? Использовать меню с переопределённым слоем. И да, делать будем на базе элемента Spiner.

Ну, во-первых, можно, конечно, добавить напрямую в Action Bar элемент как-то так:

    // установка типа навигации
    getActionBar().setNavigationMode( ActionBar.NAVIGATION_MODE_LIST);
    // листенер на клики по элементам меню
    OnNavigationListener mOnNavigationListener = new OnNavigationListener() {

        @Override
        public boolean onNavigationItemSelected(int position, long itemId) {
	    return true;
	}
    };  
    // кастомный адаптер для Spinner'а
    ArrayAdapter<CharSequence> barAdapter = new ArrayAdapter<CharSequence>(mContext, R.layout.projects_filter_item, 
			    android.R.id.text1, mContext.getResources().getStringArray( R.array.projects_filteres));
    barAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item);
    getActionBar().setListNavigationCallbacks(barAdapter, mOnNavigationListener);
    // скрываем Title
    getActionBar().setDisplayShowTitleEnabled(false);

Это хорошо, если у вас этот элемент на всех экранах/фрагментах нужен. Но если на разных фрагментах Action Bar должен выглядеть абсолютно по-разному, что делать? Разумным будет использовать меню и переопределять onCreateOptionsMenu по надобности. Вот только меню всегда будет по ширине элемента и прибито к правому краю Action Bar’а. Что же делать? Свой кастомый слой для Spinner‘а писать. Для начала, сам код меню:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" >

   <item
        android:title="Фильтр"
        android:visible="false"
        android:id="@+id/context_menu_filter"
        app:actionViewClass="android.widget.Spinner"
        android:orderInCategory="1"
        app:showAsAction="always"
        /> 
</menu>

Тут самое важное — строка, указывающая View для отображения элемента app:actionViewClass="android.widget.LinearLayout". onCreateOptionsMenu во фрагменте:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
	super.onCreateOptionsMenu(menu, inflater);
	menu.clear();
	// создаём меню из xml
	inflater.inflate(R.menu.action_bar_context_menu, menu);
	// находим нужный элемент
	android.view.MenuItem filter = menu.findItem(R.id.context_menu_filter);
	// получаем ActionView. В данном случае через MenuItemCompat, 
	// так как Support Library используется.
	// Иначе надо писать просто filter.getActionView()
	mFilterSpinner = (Spinner) MenuItemCompat.getActionView( filter)

	filter.setVisible(true);
	// адаптер для элементов создаём, где projects_filter_item - наш собственный слой,
	// а R.array.projects_filteres - просто массив из ресурсов
	ArrayAdapter<CharSequence> adapter =  new ArrayAdapter<CharSequence>(getActivity(), R.layout.projects_filter_item, 
		    android.R.id.text1, getActivity().getResources().getStringArray( R.array.projects_filteres));
	adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item);
	mFilterSpinner.setAdapter(adapter);

	mFilterSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {

		@Override
		public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long pos) {
		}

		@Override
		public void onNothingSelected(AdapterView<?> arg0) {
		}
	});
}

Небольшое дополнение. Поясню про MenuItemCompat.getActionView(). Так надо писать если вы используете AppCompat. Иначе же пишите сразу filter.getActionView(). Так же, если вы используете AppCompat, то в меню пишите некоторые атрибуты с префиксом app:

app:actionViewClass="android.widget.Spinner"
app:showAsAction="always"

Иначе же используйте префикс android:

android:actionViewClass="android.widget.Spinner"
android:showAsAction="always"

Остаётся только создать тот самый слой res/layout/projects_filter_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="fill_horizontal"
    android:orientation="vertical" >

    <TextView
        android:textColor="#000"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"   
        android:textAppearance= "?android:attr/textAppearanceMedium" />


</RelativeLayout>

Всё, теперь в нужном нам фрагменте будет отображаться наше меню в Action Bar на всю ширину, как на пикче.