First, I will explain to you what I want to do. Then, I will show you what I've already done. Finally, I will ask for your help about what I will implement.
My aim
My aim is to have a Toolbar like the Playstore:
When you click on the burger menu, it displays the menu.
When you click on the input, it displays changes the icon and it displays keyboard:
What I have for now
I followed the documentation (https://developer.android.com/training/appbar/ + https://developer.android.com/guide/topics/search/search-dialog + https://developer.android.com/training/search/setup). Thus, I have:
res/menu/action_bar_menu.xml containing my SearchView widget
<?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:id="#+id/searchView"
android:title="#string/search_title"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
</menu>
A Toolbar in my fragment's layout:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorRoyalRed"
android:theme="#style/ToolbarStyle"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
The style ToolbarStyle (see above):
<style name="ToolbarStyle">
<item name="android:background">#color/colorRoyalRed</item>
<item name="android:textColorPrimary">#color/colorRichYellow</item>
<item name="actionButtonStyle">#style/ToolbarActionButton</item>
</style>
<style name="ToolbarActionButton">
<item name="android:padding">0dp</item>
<item name="android:paddingStart">0dp</item>
<item name="android:paddingEnd">0dp</item>
</style>
In the fragment class, I make use of the toolbar:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
Toolbar toolbar = view.findViewById(R.id.toolbar);
toolbar.setTitle("");
AppCompatActivity app_compat_activity = (AppCompatActivity) getActivity();
Objects.requireNonNull(app_compat_activity).setSupportActionBar(toolbar);
app_compat_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
return view;
}
In the fragment class, I make use of the SearchView:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menu_inflater) {
menu_inflater.inflate(R.menu.action_bar_menu, menu);
super.onCreateOptionsMenu(menu,menu_inflater);
AppCompatActivity app_compat_activity = (AppCompatActivity) getActivity();
SearchView search_view = (SearchView) menu.findItem(R.id.searchView).getActionView();
search_view.setIconifiedByDefault(false);
SearchManager search_manager = (SearchManager) Objects.requireNonNull(app_compat_activity).getSystemService(Context.SEARCH_SERVICE);
search_view.setSearchableInfo(Objects.requireNonNull(search_manager).getSearchableInfo(app_compat_activity.getComponentName()));
}
Well, there are other implementations (modifications concerning the manifest, etc.) but they are not important (note all the required changements to implement a simple search bar in the toolbar... more than 5 steps...).
What I would want to do next (help please!)
I don't want to use anything other than the menu items structure (thus I don't want to actually add the SearchView in the fragment's layout).
How could I change the SearchView's icon? For now it's a magnifying glass. It must be a burger menu. I tried to modify res/menu/action_bar_menu.xml by indicating a android:icon= to the SearchView but it didn't work. I also tried to use <item name="searchIcon">#drawable/ic_baseline_menu_24px</item> in the style ToolbarActionButton but it didn't work. Here the aim is to replace the glass by a burger menu icon.
How could I handle the click on the SearchView's burger menu icon (once it will be set)? Indeed, I will call my DrawerLayout::openDrawer function to open my menu.
How could I handle the click on the SearchView's content? Indeed, I will replace the burger menu by the left arrow (and, if clicked, keyboard will disapear and the burger menu will be displayed).
Am I using the wrong things?
I just followed Google's documentation. But it seems so complicated to me to realize that I may be on the wrong path? Should I stop using the menu items structure?
You may try SearchEditTextLayout available under this Google project -
https://android.googlesource.com/platform/packages/apps/Dialer/
These libraries may also help you to achieve your desired results.
SearchView and FloatingSearchView
Related
I'm developing a material design app & I want this effect when I click on the menu option or the three dots on the side of ActionBar/Toolbar.
The effect I want is at the last of 'usage' section & just above the 'menu items' section. It is labeled as 'App bar dropdown'.
The 'three dots' is commonly called the 'overflow' menu on Android, and knowing the terminology will improve your search results.
CodePath has an example on using the Toolbar as ActionBar. It will be helpful to read the whole page, because it explains the history of both Toolbar and ActionBar. The section Using toolbar as ActionBar is particularly relevant to your question.
In your MainActivity onCreate method:
// Set a ToolBar to replace the ActionBar.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Your MainActivity will override the onCreateOptionsMenu and inflate your menu resource file:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
And you will define a menu resource file:
/res/menu/menu_main.xml
<menu 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"
tools:context=".MainActivity">
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:orderInCategory="100"
app:showAsAction="never"/>
</menu>
The 'showAsAction' attribute tells Android to only display this menu item in the overflow menu (never as an action on the toolbar).
I use this library (NavigationMaterialDrawer) for implementing drawer and managing accounts but when i add some action buttons to it,the action buttons only show in overflow menu even if considering always for showAsAction
as you see i click on overflow menu and i see this. but i want to see search icon in action bar
this is my code
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.test_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
return super.onCreateOptionsMenu(menu);
}
init method:
public void init(Bundle savedInstanceState) {
View view = LayoutInflater.from(this).inflate(R.layout.custom_drawer,null);
setDrawerHeaderCustom(view);
this.addSection(newSection("Section 1", new FragmentIndex()));
this.addSection(newSection("Section 2",new FragmentIndex()));
this.addSection(newSection("Section 3", R.drawable.ic_mic_white_24dp,new FragmentButton()).setSectionColor(Color.parseColor("#9c27b0")));
this.addSection(newSection("Section",R.drawable.ic_hotel_grey600_24dp,new FragmentButton()).setSectionColor(Color.parseColor("#03a9f4")));
this.addBottomSection(newSection("Bottom Section",R.drawable.ic_settings_black_24dp,new Intent(this,Settings.class)));
getSupportActionBar().setDisplayShowTitleEnabled(false);
setTitle("TestTitle");
}
and this is my test_menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto"
xmlns:MaterialNavigationDrawer="http://schemas.android.com/tools">
<item android:id="#+id/action_search"
android:title="Search"
android:icon="#android:drawable/ic_search_category_default"
MaterialNavigationDrawer:showAsAction="always" />
</menu>
I import library to android studio because i guess for solving this issue i have to rewrite some class or xml but i don't know where. is it right?
UPDATE
I use sample of this library(Source) for test.
maybe it because of my theme!
I read this queston(Action bar buttons showing only in overflow (not extending ActionBarActivity)) and delete theme but the sample code not working without theme.it force closed on a line of library. i move my code to another activity of sample(account light) with another theme and i have the same issue. then i delete theme from this but it force closed too :
Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
at android.support.v7.app.AppCompatDelegateImplBase.onCreate(AppCompatDelegateImplBase.java:124)
at android.support.v7.app.AppCompatDelegateImplV7.onCreate(AppCompatDelegateImplV7.java:146)
at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:59)
at it.neokree.materialnavigationdrawer.MaterialNavigationDrawer.onCreate(MaterialNavigationDrawer.java:361)
i want to use theme in future!so i can't delete theme entirely. wich element on theme must changed or deleted?
As i already mentioned in question problem is with theme!
in MaterialNavigationModule>res>values>themes.xml change parent of styles to
parent="Theme.AppCompat.NoActionBar
instead of
parent="Theme.AppCompat.Light.NoActionBar"
Background
I'm trying to theme my app to have more material design look, and as such, I have a toolbar that's being set as the actionBar of the activity.
I have a SearchView in it that allows to search items of the listView below.
The problem
Thing is, you can select the text in the SearchView (to copy, cut, etc...), yet when this happens, the toolbar gets the text-selection toolbar on top of it, making it and the text itself hidden:
Before text selection:
After text selection:
What I've tried
I tried to disable text selection using this code:
final EditText searchTextView=(EditText)searchView.findViewById(R.id.search_src_text);
if(searchTextView!=null&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB)
searchTextView.setTextIsSelectable(false);
But it didn't do anything. I've also tried to search for how to listen for the even of text selection (so that I could set the toolbar a marginTop or something), but I didn't find it.
The only thing that I have succeeded is using this code, which tells me when the text-selection toolbar appears (but not when it disappears) :
searchTextView.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
{
#Override
public void onCreateContextMenu(final ContextMenu menu,final View v,final ContextMenuInfo menuInfo)
{
Log.d("AppLog","onCreateContextMenu");
}
});
This doesn't help. I can't even close the menu. I think it can't even help, as some devices might show something else instead of a toolbar (like on LG devices, where they have a small popup).
The code
The layout is basically a vertical LinearLayout, where the first item is the toolbar:
<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">
<android.support.v7.widget.Toolbar
android:id="#+id/activity_app_list__toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:colorControlNormal="?attr/colorControlNormal"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
tools:ignore="UnusedAttribute"/>
...
The theme that's used is set to hide the normal action bar:
<style name="AppTheme" parent="#style/Theme.AppCompat.Light.DarkActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
...
The action bar menu's XML is quite basic and has 3 action items, where the first one of them is the searchView:
<item
android:id="#+id/menuItem_search"
android:icon="?attr/app_search_menu_icon"
android:title="#string/search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
Handling the SearchView is done via a special class I've made that supports even old Android versions. This is the main function that handles the searchView :
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void init(final MenuItem searchMenuItem,final int hintResId,final OnQueryTextListener onQueryTextListener,final OnActionExpandListener onActionExpandListener)
{
this._searchMenuItem=searchMenuItem;
if(_searchView==null)
{
_searchView=(SearchView)MenuItemCompat.getActionView(searchMenuItem);
if(_searchView==null)
{
MenuItemCompat.setShowAsAction(searchMenuItem,MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW|MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuItemCompat.setActionView(searchMenuItem,_searchView=new SearchView(_context));
}
_searchView.setQueryHint(_context.getString(hintResId));
if(VERSION.SDK_INT<VERSION_CODES.HONEYCOMB)
{
final EditText searchTextView=(EditText)_searchView.findViewById(R.id.search_src_text);
if(searchTextView!=null)
{
searchTextView.setScroller(new Scroller(_context));
searchTextView.setMaxLines(1);
searchTextView.setVerticalScrollBarEnabled(true);
searchTextView.setMovementMethod(new ScrollingMovementMethod());
final int searchTextColorResId=App.getResIdFromAttribute(_context,android.R.attr.textColorPrimary);
if(searchTextColorResId!=0)
searchTextView.setTextColor(_context.getResources().getColor(searchTextColorResId));
else
{
// TODO workaround for some v2.3 devices that can't get the correct color. remove this when stopping the support for v2.3
TextView searchBadge=(TextView)_searchView.findViewById(R.id.search_badge);
if(searchBadge!=null)
searchTextView.setTextColor(searchBadge.getTextColors());
}
}
}
_searchView.setOnQueryTextListener(onQueryTextListener);
MenuItemCompat.setOnActionExpandListener(searchMenuItem,onActionExpandListener);
}
}
The function is called at the end of "onCreateOptionsMenu" of any activity/fragment that is supposed to have a searchView, for example:
_searchHolder.init(menu.findItem(R.id.menuItem_search),R.string.search_for_apps,onQueryTextListener,onActionExpandListener);
The question
How can I solve this issue? Obviously this has happened because the Toolbar is just a view, so the text-selection bar is shown on top of it, but is there any way to fix this?
How do I avoid the extra toolbar become on top of the one I've used?
Is there a way to support all devices in this regard?
Looking at Google's apps, it seems that they usually don't use the official searchView, but one of their own. Only on Youtube it seems like the official one, but there it seems as if they also use the official actionBar (plus it has weird colors when selecting the text).
I found in many apps(Google messenger, Contacts etc) text selection is disabled in search view. You can do that by setting your toolbar theme as.
<style name="toolbarTheme" parent="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:autoCompleteTextViewStyle">#style/SearchViewStyle</item>
<item name="android:textColor">#android:color/white</item>
<item name="android:textColorPrimary">#android:color/white</item>
<item name="android:editTextColor">#android:color/white</item>
</style>
<style name="SearchViewStyle" parent="#android:style/Widget.Holo.Light.AutoCompleteTextView">
<item name="android:longClickable">false</item>
</style>
Or if you want it like youtube add this line in your theme
<item name="windowActionModeOverlay">false</item>
Thanks of the Max's answer, I've tried looking the AppCompat style files by clicking on references one after another, I've found Widget.AppCompat.AutoCompleteTextView. Override it in your Toolbar theme with:
<item name="android:autoCompleteTextViewStyle">#style/AppTheme.SearchViewStyle</item>
<style name="AppTheme.SearchViewStyle" parent="Widget.AppCompat.AutoCompleteTextView">
<item name="android:longClickable">false</item>
</style>
It disables the longClick in SearchView. This works on devices from API 14 (didn't try previous versions) to API 22.1.1 at least.
Firstly, my code for setting up the actionBar. (Using default system actionBar, android 4.2+)
#Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.listing_group, menu);
MenuItem listItem = menu.findItem(R.id.action_list);
ToggleButton customActionIcon = (ToggleButton) getLayoutInflater().inflate(R.layout.custom_action_bar_icon_view, null);
listItem.setActionView(customActionIcon);
customActionIcon.setTextOff("LIST");
customActionIcon.setTextOn("LIST");
customActionIcon.setTypeface(OswaldRegular());
customActionIcon= (ToggleButton)getLayoutInflater().inflate(R.layout.custom_action_bar_icon_view, null);
customActionIcon.setTextOff("MAP");
customActionIcon.setTextOn("MAP");
customActionIcon.setTypeface(OswaldRegular());
MenuItem mapItem = menu.findItem(R.id.action_map);
mapItem.setActionView(customActionIcon);
return super.onCreateOptionsMenu(menu);
}
Layout xml for Menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_list"
android:showAsAction="always"
/>
<item
android:id="#+id/action_map"
android:showAsAction="always"/>
</menu>
Layout xml for custom actionBar button:
<?xml version="1.0" encoding="utf-8"?>
<ToggleButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/action_bar_toggle_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:background="#color/transparent"
android:textColor="#drawable/listing_group_activity_actionbar_text_color_selector">
</ToggleButton>
The Problem:
When the screen with this action bar first loads, both the buttons show up in the deselected color, but they both show the default text of "Off". When I click one of them, they correctly change color AND they change the text to the one I set in onCreateOptionsMenu(). i.e. , one becomes LIST and one becomes MAP . And then they continue to stay that way and function as normal ToggleButtons would. I would like them to start with the correct text showing, and after that is fixed I want one of them to be selected by default.
Any help on the matter is much appreciated! Thanks!
Fixed. it. Had to do customActionIcon.setChecked(true) for the enabled one and setChecked(false) for the disabled one and they start with the right text and right state
I'm having a problem when I try to set one item in my actionbar as always visible and 4 more icons as dropdown items with the following layout:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/search_movies"
android:icon="#drawable/action_search"
android:showAsAction="always"
android:title="Search"/>
<item
android:id="#+id/movies"
android:icon="#drawable/action_video"
android:showAsAction="collapseActionView"
android:title="Movies"/>
<item
android:id="#+id/theaters"
android:icon="#drawable/action_location_map"
android:showAsAction="collapseActionView"
android:title="Theaters"/>
<item
android:id="#+id/preferences"
android:icon="#drawable/action_settings"
android:showAsAction="collapseActionView"
android:title="Preferences"/>
<item
android:id="#+id/contact"
android:icon="#drawable/action_about"
android:showAsAction="collapseActionView"
android:title="Contact"/>
</menu>
The result is just the first item showing and the rest are not visible, not even as a dropdown. This is using ActionBarSherlock and a 2.3 Android device.
The question is, how can I get the icons to follow this layout:
EDIT:
The problem I had was because when you are using the actionbar with a device that has a "menu" hardware button the 3-dot dropdown does not shows off, the 4 other items are only displayed if you press the menu hardware button. Does anyone knows if this behaviour can be modified?
Hmmm, maybe I misunderstood, but if you wish to places those remaining four items into the overflow action menu (the 3-dot icon) then using android:showAsAction="never" instead of "collapseActionView" should do it.
...Tried a couple ways, but this did the trick:
Force overflow menu in ABS
I've met the same problem and my solution is quite simple. (I didn't use HoloEverywhere.)
The idea comes from the ABS sample project, whose drop-down menu can be displayed on pre-4.0 devices as well by using a submenu. So, my idea is using a submenu to disguise the 3-dot icon. Here's the code:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
SubMenu sub = menu.addSubMenu("More");
sub.getItem().setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
sub.getItem().setIcon(R.drawable.ic_menu);
getSupportMenuInflater().inflate(R.menu.activity_main, sub);
return true;
}
Since the "More" menu doesn't have a MenuItem.SHOW_AS_ACTION_WITH_TEXT attribute, so the word "More"(or whatever you named) will actually not be displayed on the action bar. The only displayed icon R.drawable.ic_menu can be copied from ABS source code res/drawable-xxdpi folders named "abs__ic_menu_moreoverflow_normal_holo_dark.png", which is the so-called 3-dot icon. And the R.menu.activity_main is your menu xml.
It works!