After collapse SearchView disappear from toolbar - android

I create small example to show my issue.
Main layout with SearchView in toolbar and 3 buttons:
1) Set text - expand search view and set query
2) Expand - expand search view
3) Collapse - collapse search view
activity_main.xml
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context="com.porn.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="368dp"
android:layout_height="wrap_content"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="0dp">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStartWithNavigation="0dp">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<Button
android:id="#+id/setTextBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Set text" />
<Button
android:id="#+id/expandBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Expand" />
<Button
android:id="#+id/collapseBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Collapse" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private MenuItem toolbarSearchMenuItem;
private SearchView toolbarSearchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
findViewById(R.id.expandBtn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toolbarSearchMenuItem.expandActionView();
}
});
findViewById(R.id.collapseBtn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toolbarSearchMenuItem.collapseActionView();
}
});
findViewById(R.id.setTextBtn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setToolbarSearchQuery("Text2");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toobar, menu);
toolbarSearchMenuItem = menu.findItem(R.id.toolbar_action_search);
toolbarSearchView = (SearchView) menu.findItem(R.id.toolbar_action_search).getActionView();
init();
return true;
}
public void init() {
//In real app i get searchQuery from extra
//String searchQuery = getIntent().getStringExtra(INTENT_EXTRA_SEARCH_QUERY_KEY);
setToolbarSearchQuery("Text from intent");
}
private void setToolbarSearchQuery(String searchQuery) {
if (!searchQuery.equals("")) {
toolbarSearchMenuItem.expandActionView();
toolbarSearchView.setQuery(searchQuery, false);
toolbarSearchView.clearFocus();
} else {
toolbarSearchMenuItem.collapseActionView();
}
}
}
My problem appears when i call method init() from onCreateOptionsMenu (In real app i init SearchView with text from intent extra). If i call setToolbarSearchQuery method from init and after i click collapse button SearchView collapsed and search icon disappear.
But if i will not call init method and will call same method setToolbarSearchQuery with set text button it works correctly (SearchView is collapsed and search icon shown in toolbar).
How i can solve this problem? And why icon disappear after collapse?
I understood that it happens when i expand SearchView from onCreateOptionsMenu. But how i can correct init SearchView from intent extra?
Screenshot how it looks after collapse
Screenshot how it must looks after collapse

The "anton111111" answer works perfectly, but just for those who don't want to use delay, I recommend change search menu item showAsAction property as below:
android:showAsAction="always|collapseActionView"
instead of
android:showAsAction="ifRoom|collapseActionView"
See original answer here.

I found only one solution. Set text in init method delayed.
public void init() {
//setToolbarSearchQuery("Text from intent");
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toolbarSearchMenuItem.expandActionView();
toolbarSearchView.setQuery("Text from intent", false);
}
}, 1000);
}
But i don't like this solution. It looks like trick.

Related

Issue with setting android's appBar/toolbar title multiple times

I'm developing an android app and I'm stuck in organizing the layout in a input form activity. I would like to organize the layout of my activity like this sample (found in google android's docs): https://material-design.storage.googleapis.com/publish/material_v_4/material_ext_publish/0Bzhp5Z4wHba3Skg2b19UVS1LSmc/components_textfields_labels2.png . So a big app bar will contain one or two text field, referencing the name and the description of a user's activity, and within the activity layout's content the rest of input controls.
The behaviour I would reach is:
the activity title is initially empty and toolbar collapsed
when I get down the toolbar the text input appear and the user insert some text
when the user collapse the toolbar, the activity title (that is, the toolbar title) must be set to the input text value
The problem is that only one time this mechanism works: once set value and collapse the toolbar, when I get down again the toolbar, set the text input value and collapse the toolbar, the title is not setted, that is, setTitle has no effect over the first time.
I will now list my code: I tried to use a custom app bar layout, a collapsing tool bar layout, a toolbar and a text input in the following way:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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="wrap_content"
android:orientation="vertical"
tools:context="com.example.davide.inputformapp.MainActivity">
<com.example.davide.inputformapp.MyAppBarLayout.MyAppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="400dp"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="#dimen/activity_horizontal_margin"
app:expandedTitleMarginStart="#dimen/activity_horizontal_margin"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="parallax"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TextInputEditText
android:id="#+id/textInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.design.widget.CollapsingToolbarLayout>
</com.example.davide.inputformapp.MyAppBarLayout.MyAppBarLayout>
</android.support.design.widget.CoordinatorLayout>
where MyAppBarLayout is the class defined in this way(the code is not mine, I found here in a stackoverflow discussion):
public class MyAppBarLayout extends AppBarLayout
implements AppBarLayout.OnOffsetChangedListener {
private State state;
private OnStateChangeListener onStateChangeListener;
public MyAppBarLayout(Context context) {
super(context);
}
public MyAppBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!(getLayoutParams() instanceof CoordinatorLayout.LayoutParams)
|| !(getParent() instanceof CoordinatorLayout)) {
throw new IllegalStateException(
"MyAppBarLayout must be a direct child of CoordinatorLayout.");
}
addOnOffsetChangedListener(this);
}
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (verticalOffset == 0) {
if (onStateChangeListener != null && state != State.EXPANDED) {
Log.d("MYAPP","---> EXPANDED");
onStateChangeListener.onStateChange(State.EXPANDED);
}
state = State.EXPANDED;
} else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
if (onStateChangeListener != null && state != State.COLLAPSED) {
Log.d("MYAPP","---> COLLAPSED");
onStateChangeListener.onStateChange(State.COLLAPSED);
}
state = State.COLLAPSED;
} else {
if (onStateChangeListener != null && state != State.IDLE) {
Log.d("MYAPP","---> IDLE");
onStateChangeListener.onStateChange(State.IDLE);
}
state = State.IDLE;
}
}
public void setOnStateChangeListener(OnStateChangeListener listener) {
this.onStateChangeListener = listener;
}
public interface OnStateChangeListener {
void onStateChange(State toolbarChange);
}
public enum State {
COLLAPSED,
EXPANDED,
IDLE
}
}
The code in the main activity's onCreate() method is:
toolbar = (Toolbar) findViewById(R.id.toolbar);
textInput = (TextInputEditText) findViewById(R.id.textInput);
final MyAppBarLayout collapsableAppBar = (MyAppBarLayout) findViewById(R.id.appbar);
setSupportActionBar(toolbar);
setTitle(null);
collapsableAppBar.setOnStateChangeListener(new MyAppBarLayout.OnStateChangeListener() {
#Override
public void onStateChange(MyAppBarLayout.State toolbarChange) {
String value = textInput.getText().toString();
toolbar.setTitle(value);
}
});
Any suggestion?
Thanks,
davide
set "android:id" to CollapsingToolbarLayout. find it in activity and set title to it.
I have tried many answers but only setting title to CollapsingToolbarLayout worked.
Please try to replace
toolbar.setTitle(value)
with
getSupportActionBar().setTitle(value)
as mentioned in this answer
You have to change title like this :
instead of
toolbar.setTitle(value);
do
getSupportActionBar.setTitle(value);
on
setOnStateChangeListener
it may not be a good solution but one way to get every thing working is by creating custom action Bar
custom_actionbar.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="100dp"
android:background="#drawable/yourcolorforactionbar" >
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#fff"
android:textStyle="bold" />
<ImageView
android:id="#+id/myimage"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:src="#drawable/yourimagetoset" />
<ImageButton
android:id="#+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:background="#null"
android:src="#android:drawable/menubutoon" />
</RelativeLayout>
mainactivity.class
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar mActionBar = getActionBar();
mActionBar.setDisplayShowHomeEnabled(false);
mActionBar.setDisplayShowTitleEnabled(false);
LayoutInflater mInflater = LayoutInflater.from(this);
View mCustomView = mInflater.inflate(R.layout.custom_actionbar, null);
TextView mTitleTextView = (TextView) mCustomView.findViewById(R.id.title_text);
mTitleTextView.setText("My Own Title");
ImageButton imageButton = (ImageButton) mCustomView
.findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "Refresh Clicked!",
Toast.LENGTH_LONG).show();
}
});
mActionBar.setCustomView(mCustomView);
mActionBar.setDisplayShowCustomEnabled(true);
}
}

Android - Make whole search bar clickable

I am using a search-view element in my fragment to implement search feature.
<SearchView
android:id="#+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="7dp"
android:layout_marginLeft="7dp"
android:layout_marginRight="7dp"
android:layout_marginBottom="7dp"
android:background="#color/white" />
The problem is only the search icon is clickable other area in the search bar is not clickable, when i click the icon only i can able to search.
Can you please help me to make the whole search area clickable.
This can be simply done by setting Iconified to false on OnClick of SearchView.
searchBar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchBar.setIconified(false);
}
});
Reference: Eric Lui's answer
Hopefully it will help.
UPDATE:
You can also use it directly in your XML
app:iconifiedByDefault="false"
search_bar.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
search_bar.onActionViewExpanded();
}
});
The trick isn't so much to make the entire area clickable as much as it is to expand it and then hide the keyboard.
First, your layout in the XML is fine, leave it as is, in your Java, you want to have the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
//Define your Searchview
SearchView searchView = (SearchView) findViewById(R.id.search_bar);
//Turn iconified to false:
searchView.setIconified(false);
//The above line will expand it to fit the area as well as throw up the keyboard
//To remove the keyboard, but make sure you keep the expanded version:
searchView.clearFocus();
}
What this accomplishes is it expands the keyboard to the entire length of the area, it focuses on it, which allows the entire area to be clickable, and then it removes the keyboard so that it looks to the user like they are able to click that field and bring up a keyboard.
Should accomplish what you are looking for.
-Sil
add this to your xml android:iconifiedByDefault="false" it will keep
open your searchview.
and to clear it add clearfocus to your searchview object.
What is the clickable mean? trigger search action or just make the edit area focused? If it is the first, you can just make the icon clickable=false. and make the whole layout clickable and implement a event listener.
<SearchView
android:id="#+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:click="onClick"
android:layout_marginTop="7dp"
android:layout_marginLeft="7dp"
android:layout_marginRight="7dp"
android:layout_marginBottom="7dp"
android:background="#color/white" />
The onClick method should be
public void onClick(View v) {
  InputMethodManager im = ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE));
im.showSoftInput(editText, 0);
}
For latest versions of android -
Try:
app:iconifiedByDefault="false"
Example -
<android.support.v7.widget.SearchView
android:id="#+id/source_location_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:layout_marginRight="20dp"
app:iconifiedByDefault="false"
app:queryHint="Your hint text" />
searchView.setIconified(false);
Just write it in xml
android:iconifiedByDefault="false"
Worked for me
Write the lines of code given below in your Java file:
SearchView searchView = (SearchView) findViewById(R.id.searchView);
searchView.setQueryHint("Enter your address");
searchView.setIconified(false);
searchView.clearFocus();
After that, don't forget to write android:focusable="true" in your XML file inside SearchView tag.
For example:
<SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true" />
Use This
searchView.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
searchView.onActionViewExpanded();
OR
searchView.setIconified(false);
}
});
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener()
{
#Override
public void onFocusChange(View view, boolean b)
{
if(!b)
{
if(searchView.getQuery().toString().length() < 1)
{
searchView.setIconified(true); //close the search editor and make search icon again
OR
searchView.onActionViewCollapsed();
}
searchView.clearFocus();
}
}
});
in code:
private void initSearchView(View layout) {
// Locate the EditText in listview_main.xml
searchInput = (SearchView) layout.findViewById(R.id.search);
//searchInput.onActionViewExpanded();//force show keyboard at start
//==>region to enable search after click in input-text(not only at magnifier icon)
searchInput.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchInput.onActionViewExpanded();
}
});
searchInput.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
if (!b) {
if (searchInput.getQuery().toString().length() < 1) {
searchInput.setIconified(true);
}
searchInput.clearFocus();
}
}
});
//endregion
}
and in my layout:
<androidx.appcompat.widget.SearchView
android:id="#+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar_main"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="2dp"
android:background="#drawable/search_border"
android:inputType="text"
android:layoutDirection="ltr"
android:searchSuggestThreshold="2"
app:queryHint="#string/search"
app:searchHintIcon="#null" />
Use the below code.
<androidx.appcompat.widget.SearchView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/earningSearchView"
app:queryHint="Search"
app:iconifiedByDefault="false"
app:queryBackground="#android:color/transparent"/>
So recently I've had to do this and I tried all the answers provided but each had some dodgy behaviour - for example the x close/erase all button would only show up if you'd clicked on the search icon, otherwise you'd be able to edit etc. but you would only see the x as an erase all button.
Looking at the SearchView's code I noticed that clicking the mSearchButton calls onSearchClicked() and not the suggested onActionViewExpanded(), but the former is a package private function so it can't be called directly. So I came up with this:
private val searchButton by lazy { searchView.findViewById<ImageView>(R.id.search_button) }
searchView.setOnClickListener { searchButton.callOnClick() }
This way you get the same behaviour no matter where you click and you don't need to manually set the iconified property in either the xml or programatically.
What you ask can be done as follows
For the first click in the bar we use the method onClick of the SearchView to expand it.
public void onClick(View v) {
SearchView searchView = (SearchView) v;
searchView.setIconified(false);
}
When it doesn't have the focus then we collapse the SearchView.
Also for the next clicks on the bar, onClick just doesn't work, so we used onFocusChange to expand SearcView too.
final SearchView searchView = findViewById(R.id.searchView);
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
if (b) {
searchView.setIconified(false);
}
if (!b) { // Not have focus
if (searchView.getQuery().toString().length() < 1) {
searchView.setIconified(true);
}
searchView.clearFocus();
}
}
});

Implementing SearchView as per the material design guidelines

I have been looking for ways to implement a searchview in the activity toolbar (actionbar) as per the material design guidelines.
On clicking on the search icon, the entire toolbar animates to have only the search EditText with white background with suggestions appearing in the main view instead of a drop down.
Here is a screenshot from the guidelines:
Here is a gif from the Gmail Inbox implementation:
I have been looking for code examples and tutorials but so far I have been unsuccesful. How do I go about doing this?
I tried several material SearchView libraries, but none of them worked good as the one from the support library, so I decided to redesign it, after a lot of work, I am pleased with the result:
Here is how you can do it:
1) Add SearchView item to your menu
<item
android:id="#+id/m_search"
android:icon="#drawable/ic_action_search"
android:title="#string/search_title"
app:actionLayout="#layout/search_view_layout"
app:showAsAction="ifRoom|collapseActionView" />
Notice that I'm declaring actionLayout instead of actionViewClass, I figured that this is the only way to set SearchView theme separately from Toolbar theme.
search_view_layout.xml:
<android.support.v7.widget.SearchView
android:id="#+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/SearchViewTheme" />
2) Add the custom SearchView theme to your styles, declare SearchView theme in your Toolbar theme as well:
<style name="SearchViewTheme" parent="Widget.AppCompat.SearchView.ActionBar">
<item name="layout">#layout/toolbar_search_view</item>
<item name="commitIcon">#drawable/ic_search_commit</item>
<item name="colorControlNormal">#color/material_light_active_icon</item>
<item name="colorControlHighlight">#color/material_ripple_light</item>
<item name="autoCompleteTextViewStyle">#style/AutoCompleteTextViewStyle</item>
<item name="suggestionRowLayout">#layout/search_view_suggestion_row</item>
<item name="android:maxWidth">9999dp</item>
</style>
<style name="AutoCompleteTextViewStyle" parent="Widget.AppCompat.Light.AutoCompleteTextView">
<item name="android:popupBackground">#drawable/search_suggestions_bg</item>
<item name="android:popupElevation">0dp</item>
</style>
<style name="ToolbarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="searchViewStyle">#style/SearchViewTheme</item>
</style>
toolbar_search_view.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingEnd="8dp">
<!-- This is actually used for the badge icon *or* the badge label (or neither) -->
<TextView
android:id="#+id/search_badge"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginBottom="2dp"
android:drawablePadding="0dp"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
android:visibility="gone" />
<ImageView
android:id="#+id/search_button"
style="?attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:contentDescription="#string/abc_searchview_description_search"
android:focusable="true" />
<LinearLayout
android:id="#+id/search_edit_frame"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layoutDirection="locale"
android:orientation="horizontal">
<ImageView
android:id="#+id/search_mag_icon"
style="#style/RtlOverlay.Widget.AppCompat.SearchView.MagIcon"
android:layout_width="#dimen/abc_dropdownitem_icon_width"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:visibility="gone" />
<!-- Inner layout contains the app icon, button(s) and EditText -->
<LinearLayout
android:id="#+id/search_plate"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal">
<view
android:id="#+id/search_src_text"
class="android.support.v7.widget.SearchView$SearchAutoComplete"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginEnd="#dimen/item_list_horizontal_margin"
android:layout_marginStart="#dimen/item_list_horizontal_margin"
android:layout_weight="1"
android:background="#null"
android:dropDownAnchor="#id/anchor_dropdown"
android:dropDownHeight="wrap_content"
android:dropDownHorizontalOffset="0dp"
android:dropDownVerticalOffset="0dp"
android:ellipsize="end"
android:imeOptions="actionSearch"
android:inputType="text|textAutoComplete|textNoSuggestions"
android:maxLines="1"
android:paddingEnd="8dp"
android:textColor="#android:color/black"
android:textColorHint="#color/material_light_hint_text"
android:textSize="20sp" />
<ImageView
android:id="#+id/search_close_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="#string/abc_searchview_description_clear"
android:focusable="true"
android:paddingEnd="8dp"
android:paddingStart="8dp" />
</LinearLayout>
<LinearLayout
android:id="#+id/submit_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/search_go_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="#string/abc_searchview_description_submit"
android:focusable="true"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:visibility="gone" />
<ImageView
android:id="#+id/search_voice_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="#string/abc_searchview_description_voice"
android:focusable="true"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
Notice that I added anchor dropdown view under the Toolbar view, so suggestions will get full screen width.
<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:collapseIcon="#drawable/ic_search_collapse"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:theme="#style/ToolbarTheme" />
<View
android:id="#+id/anchor_dropdown"
android:layout_width="match_parent"
android:layout_height="0dp" />
</android.support.design.widget.AppBarLayout>
search_view_suggestion_row.xml:
(change suggestion_divider visibility if you want divider between suggestions):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="58dp"
android:theme="#style/Theme.AppCompat.DayNight">
<!-- Icons come first in the layout, since their placement doesn't depend on
the placement of the text views. -->
<ImageView
android:id="#android:id/icon1"
style="#style/RtlOverlay.Widget.AppCompat.Search.DropDown.Icon1"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:scaleType="centerInside"
android:visibility="invisible" />
<ImageView
android:id="#+id/edit_query"
style="#style/RtlOverlay.Widget.AppCompat.Search.DropDown.Query"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:background="?attr/selectableItemBackground"
android:scaleType="centerInside"
android:visibility="gone" />
<ImageView
android:id="#id/android:icon2"
style="#style/RtlOverlay.Widget.AppCompat.Search.DropDown.Icon2"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:scaleType="centerInside"
android:visibility="gone" />
<!-- The subtitle comes before the title, since the height of the title depends on whether the
subtitle is visible or gone. -->
<TextView
android:id="#android:id/text2"
style="?android:attr/dropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="29dp"
android:layout_alignParentBottom="true"
android:layout_alignWithParentIfMissing="true"
android:gravity="top"
android:maxLines="1"
android:paddingBottom="4dp"
android:textColor="?android:textColorSecondary"
android:textSize="12sp"
android:visibility="gone" />
<!-- The title is placed above the subtitle, if there is one. If there is no
subtitle, it fills the parent. -->
<TextView
android:id="#android:id/text1"
style="?android:attr/dropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#android:id/text2"
android:layout_centerVertical="true"
android:ellipsize="end"
android:maxLines="1"
android:scrollHorizontally="false"
android:textColor="?android:textColorPrimary"
android:textSize="16sp" />
<View
android:id="#+id/suggestion_divider"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_alignParentBottom="true"
android:layout_alignStart="#android:id/text1"
android:layout_marginStart="8dp"
android:background="#color/divider_color"
android:visibility="gone" />
The suggestions background and the commit icon are custom made, the rest of the icons I used can be found at: https://material.io/icons/
ic_search_commit.xml:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#color/active_icon_color"
android:pathData="m18.364,16.95l-8.605,-8.605l7.905,-0l-0.007,-2.001l-11.314,0l0,11.314l1.994,-0l0.007,-7.898l8.605,8.605l1.414,-1.414z" />
search_suggestions_bg.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<padding android:top="0.5dp" />
<stroke
android:width="0.5dp"
android:color="#color/divider_color" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#color/cards_and_dialogs_color" />
</shape>
</item>
</layer-list>
Add following values to your colors.xml (add values-night only if you are using DayNight theme):
values/colors.xml
<color name="material_light_primary_text">#DE000000</color>
<color name="material_light_hint_text">#61000000</color>
<color name="material_light_active_icon">#8A000000</color>
<color name="material_ripple_light">#1F000000</color>
<color name="divider_color">#1F000000</color>
<color name="active_icon_color">#8A000000</color>
<color name="cards_and_dialogs_color">#android:color/white</color>
<color name="quantum_grey_600">#757575</color>
values-night/colors.xml:
<color name="divider_color">#1FFFFFFF</color>
<color name="active_icon_color">#android:color/white</color>
<color name="cards_and_dialogs_color">#424242</color>
3) Last part, make the magic happen in code:
Setup and initialize SearchView in your desired activity
private MenuItem mSearchItem;
private Toolbar mToolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
mSearchItem = menu.findItem(R.id.m_search);
MenuItemCompat.setOnActionExpandListener(mSearchItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Called when SearchView is collapsing
if (mSearchItem.isActionViewExpanded()) {
animateSearchToolbar(1, false, false);
}
return true;
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Called when SearchView is expanding
animateSearchToolbar(1, true, true);
return true;
}
});
return true;
}
public void animateSearchToolbar(int numberOfMenuIcon, boolean containsOverflow, boolean show) {
mToolbar.setBackgroundColor(ContextCompat.getColor(this, android.R.color.white));
mDrawerLayout.setStatusBarBackgroundColor(ContextCompat.getColor(this, R.color.quantum_grey_600));
if (show) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int width = mToolbar.getWidth() -
(containsOverflow ? getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_overflow_material) : 0) -
((getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material) * numberOfMenuIcon) / 2);
Animator createCircularReveal = ViewAnimationUtils.createCircularReveal(mToolbar,
isRtl(getResources()) ? mToolbar.getWidth() - width : width, mToolbar.getHeight() / 2, 0.0f, (float) width);
createCircularReveal.setDuration(250);
createCircularReveal.start();
} else {
TranslateAnimation translateAnimation = new TranslateAnimation(0.0f, 0.0f, (float) (-mToolbar.getHeight()), 0.0f);
translateAnimation.setDuration(220);
mToolbar.clearAnimation();
mToolbar.startAnimation(translateAnimation);
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int width = mToolbar.getWidth() -
(containsOverflow ? getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_overflow_material) : 0) -
((getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material) * numberOfMenuIcon) / 2);
Animator createCircularReveal = ViewAnimationUtils.createCircularReveal(mToolbar,
isRtl(getResources()) ? mToolbar.getWidth() - width : width, mToolbar.getHeight() / 2, (float) width, 0.0f);
createCircularReveal.setDuration(250);
createCircularReveal.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mToolbar.setBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimary));
mDrawerLayout.setStatusBarBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimaryDark));
}
});
createCircularReveal.start();
} else {
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
Animation translateAnimation = new TranslateAnimation(0.0f, 0.0f, 0.0f, (float) (-mToolbar.getHeight()));
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(translateAnimation);
animationSet.setDuration(220);
animationSet.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mToolbar.setBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimary));
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
mToolbar.startAnimation(animationSet);
}
mDrawerLayout.setStatusBarBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimaryDark));
}
}
private boolean isRtl(Resources resources) {
return resources.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}
private static int getThemeColor(Context context, int id) {
Resources.Theme theme = context.getTheme();
TypedArray a = theme.obtainStyledAttributes(new int[]{id});
int result = a.getColor(0, 0);
a.recycle();
return result;
}
Few things to notice about the code:
1) The animation will adjust it's start point based on your set of number of menu items and if the toolbar has overflow icon, it will detect if layout is LTR or RTL automatically.
2) I'm using navigation drawer activity, so I set StatusBar color to mDrawerLayout, if you are using regular activity, you can set StatusBar color this way:
getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.quantum_grey_600));
3) The circular reveal animation will only work on KitKat and above.
It is actually quite easy to do this, if you are using android.support.v7 library.
Step - 1
Declare a menu item
<item android:id="#+id/action_search"
android:title="Search"
android:icon="#drawable/abc_ic_search_api_mtrl_alpha"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />
Step - 2
Extend AppCompatActivity and in the onCreateOptionsMenu setup the SearchView.
import android.support.v7.widget.SearchView;
public class YourActivity extends AppCompatActivity {
...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_home, menu);
// Retrieve the SearchView and plug it into SearchManager
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
return true;
}
...
}
The idea is very simple - you have to write your own AutoCompleteTextView using EditText, TextWatcher and RecyclerView with Filterable adapter.
EditText gives you a text field with ability to input characters
TextWatcher allows you to watch for text changes
RecyclerView can be placed anywhere, so you can show the search results just like on your screenshot
Filterable adapter helps to present data filtered with the entered text
So:
make a layout with EditText on the top, with RecyclerView filling the remaining space. Add the icon, shadow, etc.
add a TextWatcher and update the adapter on each text change
If you'd like to see my solution in action, check out my project on github:
https://github.com/ZieIony/Carbon
The Auto complete demo can be sound in the sample app in 'Demos' section.
Taking a hint from #Zielony's answer I did the following:
1) Instead if using an ActionBar or ToolBar I built my own layout (basically a RelativeLayout with burger menu, search and other menu buttons and a EditText for search)
2) Used a theme without an ActionBar, placed my custom layout at the top of the activity so that it appeared like an ActionBar.
3) In the search button's OnClickListener I do 2 things:
Hide the menu buttons and show the 'search' EditText.
Add a fragment to display search suggestions and search
Show the soft keyboard input
3) Added OnClickListeners for the other menu buttons.
4) Added a TextWatcher on the 'search' EditText to display search hints and results from the server.
This is how it appears now:
I think I've figured it out.
I'm now using just an EditText inside of the Toolbar.
I now have this:
First inside onCreate() of my activity I added the EditText with an image view on the right hand side to the Toolbar like this:
// Setup search container view
searchContainer = new LinearLayout(this);
Toolbar.LayoutParams containerParams = new Toolbar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
containerParams.gravity = Gravity.CENTER_VERTICAL;
searchContainer.setLayoutParams(containerParams);
// Setup search view
toolbarSearchView = new EditText(this);
// Set width / height / gravity
int[] textSizeAttr = new int[]{android.R.attr.actionBarSize};
int indexOfAttrTextSize = 0;
TypedArray a = obtainStyledAttributes(new TypedValue().data, textSizeAttr);
int actionBarHeight = a.getDimensionPixelSize(indexOfAttrTextSize, -1);
a.recycle();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, actionBarHeight);
params.gravity = Gravity.CENTER_VERTICAL;
params.weight = 1;
toolbarSearchView.setLayoutParams(params);
// Setup display
toolbarSearchView.setBackgroundColor(Color.TRANSPARENT);
toolbarSearchView.setPadding(2, 0, 0, 0);
toolbarSearchView.setTextColor(Color.WHITE);
toolbarSearchView.setGravity(Gravity.CENTER_VERTICAL);
toolbarSearchView.setSingleLine(true);
toolbarSearchView.setImeActionLabel("Search", EditorInfo.IME_ACTION_UNSPECIFIED);
toolbarSearchView.setHint("Search");
toolbarSearchView.setHintTextColor(Color.parseColor("#b3ffffff"));
try {
// Set cursor colour to white
// http://stackoverflow.com/a/26544231/1692770
// https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(toolbarSearchView, R.drawable.edittext_whitecursor);
} catch (Exception ignored) {
}
// Search text changed listener
toolbarSearchView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Fragment mainFragment = getFragmentManager().findFragmentById(R.id.container);
if (mainFragment != null && mainFragment instanceof MainListFragment) {
((MainListFragment) mainFragment).search(s.toString());
}
}
#Override
public void afterTextChanged(Editable s) {
// http://stackoverflow.com/a/6438918/1692770
if (s.toString().length() <= 0) {
toolbarSearchView.setHintTextColor(Color.parseColor("#b3ffffff"));
}
}
});
((LinearLayout) searchContainer).addView(toolbarSearchView);
// Setup the clear button
searchClearButton = new ImageView(this);
Resources r = getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, r.getDisplayMetrics());
LinearLayout.LayoutParams clearParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
clearParams.gravity = Gravity.CENTER;
searchClearButton.setLayoutParams(clearParams);
searchClearButton.setImageResource(R.drawable.ic_close_white_24dp); // TODO: Get this image from here: https://github.com/google/material-design-icons
searchClearButton.setPadding(px, 0, px, 0);
searchClearButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toolbarSearchView.setText("");
}
});
((LinearLayout) searchContainer).addView(searchClearButton);
// Add search view to toolbar and hide it
searchContainer.setVisibility(View.GONE);
toolbar.addView(searchContainer);
This worked, but then I came across an issue where onOptionsItemSelected() wasn't being called when I tapped on the home button. So I wasn't able to cancel the search by pressing the home button. I tried a few different ways of registering the click listener on the home button but they didn't work.
Eventually I found out that the ActionBarDrawerToggle I had was interfering with things, so I removed it. This listener then started working:
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// toolbarHomeButtonAnimating is a boolean that is initialized as false. It's used to stop the user pressing the home button while it is animating and breaking things.
if (!toolbarHomeButtonAnimating) {
// Here you'll want to check if you have a search query set, if you don't then hide the search box.
// My main fragment handles this stuff, so I call its methods.
FragmentManager fragmentManager = getFragmentManager();
final Fragment fragment = fragmentManager.findFragmentById(R.id.container);
if (fragment != null && fragment instanceof MainListFragment) {
if (((MainListFragment) fragment).hasSearchQuery() || searchContainer.getVisibility() == View.VISIBLE) {
displaySearchView(false);
return;
}
}
}
if (mDrawerLayout.isDrawerOpen(findViewById(R.id.navigation_drawer)))
mDrawerLayout.closeDrawer(findViewById(R.id.navigation_drawer));
else
mDrawerLayout.openDrawer(findViewById(R.id.navigation_drawer));
}
});
So I can now cancel the search with the home button, but I can't press the back button to cancel it yet. So I added this to onBackPressed():
FragmentManager fragmentManager = getFragmentManager();
final Fragment mainFragment = fragmentManager.findFragmentById(R.id.container);
if (mainFragment != null && mainFragment instanceof MainListFragment) {
if (((MainListFragment) mainFragment).hasSearchQuery() || searchContainer.getVisibility() == View.VISIBLE) {
displaySearchView(false);
return;
}
}
I created this method to toggle visibility of the EditText and menu item:
public void displaySearchView(boolean visible) {
if (visible) {
// Stops user from being able to open drawer while searching
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
// Hide search button, display EditText
menu.findItem(R.id.action_search).setVisible(false);
searchContainer.setVisibility(View.VISIBLE);
// Animate the home icon to the back arrow
toggleActionBarIcon(ActionDrawableState.ARROW, mDrawerToggle, true);
// Shift focus to the search EditText
toolbarSearchView.requestFocus();
// Pop up the soft keyboard
new Handler().postDelayed(new Runnable() {
public void run() {
toolbarSearchView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
toolbarSearchView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
}
}, 200);
} else {
// Allows user to open drawer again
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
// Hide the EditText and put the search button back on the Toolbar.
// This sometimes fails when it isn't postDelayed(), don't know why.
toolbarSearchView.postDelayed(new Runnable() {
#Override
public void run() {
toolbarSearchView.setText("");
searchContainer.setVisibility(View.GONE);
menu.findItem(R.id.action_search).setVisible(true);
}
}, 200);
// Turn the home button back into a drawer icon
toggleActionBarIcon(ActionDrawableState.BURGER, mDrawerToggle, true);
// Hide the keyboard because the search box has been hidden
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(toolbarSearchView.getWindowToken(), 0);
}
}
I needed a way to toggle the home button on the toolbar between the drawer icon and the back button. I eventually found the method below in this SO answer. Though I modified it slightly to made more sense to me:
private enum ActionDrawableState
{
BURGER, ARROW
}
private void toggleActionBarIcon(final ActionDrawableState state, final ActionBarDrawerToggle toggle, boolean animate) {
if (animate) {
float start = state == ActionDrawableState.BURGER ? 1.0f : 0f;
float end = Math.abs(start - 1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
offsetAnimator.setDuration(300);
offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float offset = (Float) animation.getAnimatedValue();
toggle.onDrawerSlide(null, offset);
}
});
offsetAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
toolbarHomeButtonAnimating = false;
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
toolbarHomeButtonAnimating = true;
offsetAnimator.start();
}
} else {
if (state == ActionDrawableState.BURGER) {
toggle.onDrawerClosed(null);
} else {
toggle.onDrawerOpened(null);
}
}
}
This works, I've managed to work out a few bugs that I found along the way. I don't think it's 100% but it works well enough for me.
EDIT: If you want to add the search view in XML instead of Java do this:
toolbar.xml:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
contentInsetLeft="72dp"
contentInsetStart="72dp"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
app:contentInsetLeft="72dp"
app:contentInsetStart="72dp"
app:popupTheme="#style/ActionBarPopupThemeOverlay"
app:theme="#style/ActionBarThemeOverlay">
<LinearLayout
android:id="#+id/search_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="#+id/search_view"
android:layout_width="0dp"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:background="#android:color/transparent"
android:gravity="center_vertical"
android:hint="Search"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:paddingLeft="2dp"
android:singleLine="true"
android:textColor="#ffffff"
android:textColorHint="#b3ffffff" />
<ImageView
android:id="#+id/search_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:src="#drawable/ic_close_white_24dp" />
</LinearLayout>
onCreate() of your Activity:
searchContainer = findViewById(R.id.search_container);
toolbarSearchView = (EditText) findViewById(R.id.search_view);
searchClearButton = (ImageView) findViewById(R.id.search_clear);
// Setup search container view
try {
// Set cursor colour to white
// http://stackoverflow.com/a/26544231/1692770
// https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(toolbarSearchView, R.drawable.edittext_whitecursor);
} catch (Exception ignored) {
}
// Search text changed listener
toolbarSearchView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Fragment mainFragment = getFragmentManager().findFragmentById(R.id.container);
if (mainFragment != null && mainFragment instanceof MainListFragment) {
((MainListFragment) mainFragment).search(s.toString());
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
// Clear search text when clear button is tapped
searchClearButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toolbarSearchView.setText("");
}
});
// Hide the search view
searchContainer.setVisibility(View.GONE);
Here is how I tried to implement it, please check this out.
https://github.com/Shahroz16/material-searchview
You can use AutoCompleteTextView to achieve this, Follow the link below
How to build Gmail like search box in the action bar?

Create a panel that slides up and out of the screen in Android

i need some guidance. I need to make a custom view that touched and drag up the screen slides out of the screen. I have tried this cool library: here but this is dependend to exactly 2 layouts. The one that is slided out and the one that remains after that. What i have now is buggy and ugly.
public class DemoActivity extends Activity {
private SlidingUpPanelLayout mLayout;
private RelativeLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
layout = (RelativeLayout) findViewById(R.id.panel);
final int defaulttop = layout.getTop();
final int defaultbottom = layout.getBottom();
RelativeLayout dragView = (RelativeLayout) findViewById(R.id.dragView);
mLayout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
mLayout.setDragView(dragView);
mLayout.setPanelSlideListener(new PanelSlideListener() {
#Override
public void onPanelSlide(View panel, float slideOffset) {
}
#Override
public void onPanelExpanded(View panel) {
System.out.println("panel expanded");
}
#Override
public void onPanelCollapsed(View panel) {
System.out.println("panel collapsed");
}
#Override
public void onPanelAnchored(View panel) {
System.out.println("anchored");
}
#Override
public void onPanelHidden(View panel) {
System.out.println("panel is hidden now");
}
});
}
#Override
public void onBackPressed() {
if (mLayout != null && mLayout.isPanelExpanded()) {
mLayout.collapsePanel();
} else {
super.onBackPressed();
}
}
}
The layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DemoActivity" >
<com.sothree.slidinguppanel.SlidingUpPanelLayout
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:id="#+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:gravity="bottom"
sothree:dragView="#+id/dragView"
sothree:panelHeight="60dp"
sothree:paralaxOffset="60dp"
sothree:shadowHeight="0dp" >
<RelativeLayout
android:id="#+id/panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/unt"
android:orientation="vertical" >
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:text="Sleep" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/dragView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:clickable="true"
android:focusable="false" >
</RelativeLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
</RelativeLayout>
it slides up but leaves a white background in the back. If i touch the screen then it slides. So, i need a new path. Did anyone confrunted with something similar? I need a hint, not code. Thanks.
I have used the library you mentioned here and it worked out fine for me. You might have not set the drag view/layout
Do use mSlidingPanelLayout.setDragView(YourLayout) to set the layout that can be dragged
I have done something like this previously but with a button.
I did it using Animation class when moving it by OnTouchListener. While you have to be careful while using it and control the X and Y values of the layout.

Accessing a view inside ActionBar

I'm trying to add an Horizontal Progress bar to my view like so:
res/menu.xml
<item android:id="#+id/menuItemProgress"
android:title="Progress"
android:actionLayout="#layout/component_cancellable_progressbar"
android:showAsAction="always"/>
component_cancellable_progressbar.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/searchProgressWrapper"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<ProgressBar android:id="#+id/searchProgress"
android:layout_height="30dp"
android:layout_width="150dp"
style="#style/Custom.Widget.ProgressBar.Horizontal"
android:max="100" />
<ImageView android:id="#+id/cancelSearch"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="8dp"
android:layout_gravity="right|center_vertical"
android:src="#android:drawable/ic_notification_clear_all"
android:scaleType="fitXY" />
</FrameLayout>
How do I access this ProgressBar from within an Action (To make it Visisble / Invisible / Progress) ?
it is possible to get the view of the action item.
however, do note that sometimes action items get to be inside the overflow menu so you might get a null instead.
so, how can you do it?
here's a sample code:
public boolean onCreateOptionsMenu(final Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View syncItemView = findViewById(R.id.action_search);
...
this was tested when using actionBarSherlock library, on android 4.1.2 and android 2.3.5 .
another alternative is to use a more extensive way , used on the showcaseView library, here .
onCreate() and after you can simply access it via findViewById() like normal. Problem was caused by something else.
You can override onCreateOptionsMenu and catch your view there:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.getItem(0).getActionView();
...
or by searching the id
View v = (View) menu.findItem(R.id.search).getActionView();
I inserted a custom drop down menu in the action bar and was able to gain control of it this way.
Following is a very helpful link for actionBar.Hope you will able to implement what you want.
http://thiranjith.wordpress.com/2011/07/15/actionbar-design-pattern-example-for-android/
public class ActionBar extends FrameLayout {
private ProgressBar mProgress;
public ActionBar(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
FrameLayout barView = (RelativeLayout) mInflater.inflate(R.layout.actionbar, null);
addView(barView);
mProgress = (ProgressBar) barView.findViewById(R.id.actionbar_progress);
public void showProgressBar() { ... }
public void hideProgressBar() { ... }
public boolean isProgressBarVisible() { ... }
}
Then from your activity control your progressbar like following.
public class MainActivity extends Activity {
private ActionBar mActionBar;
#Override
public void onCreate(Bundle savedInstanceState) {
mActionBar = (ActionBar) findViewById(R.id.actionBar);
mActionBar.showProgressbar()
}
}

Categories

Resources