I would like to create a notification icon view that looks similar to the Google+ app's notification. The difference will be that I need to be able to change the color at runtime where as the Google+ icons gray or red so I'm assuming they are using a StateListDrawable.
What is the best approach for this? I'd prefer to have the rounded clipped corners and have the option to have a drawable inside. This custom view will be placed in the Action Bar as well. I still need the view to respond to android:background state list drawables so I can have the click and selected accordance working.
This custom view will be placed in the action bar as well.
I solved this by doing the following.
Created this to make the rounded corner shape with a solid color. This also adds a translucent black to give it a pressed look against a blackground.
res/drawable/shape_notification.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:color="#33000000" android:width="2dp"/>
<corners android:radius="4dp" />
<solid android:color="#99333333"/>
</shape>
The layer drawable will be used as the actual drawable on the action bar item. It has the background (written above) overlayed with the wrench icon.
res/drawable/layer_customizer.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/shape_notification" />
<item android:drawable="#drawable/ic_menu_preferences" />
</layer-list>
Java code to change the color. The target view is the object that is assigned the layer_customizer drawable. The color passed in will change the shape_notification.xml's solid tag color.
public static void setCustomizerDrawableColor(final View target, final int color) {
final Drawable d = target.getDrawable();
LayerDrawable layer = (LayerDrawable)d;
GradientDrawable gradient = (GradientDrawable)layer.getDrawable(0);
gradient.setColor(color);
gradient.invalidateSelf();
layer.invalidateSelf();
target.invalidate();
}
Create a layout using these layers.
res/layout/actionview_customizer.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/ActionViewCustomizer"
android:src="#drawable/layer_customizer"
android:contentDescription="#string/customize"
style="#style/ActionBarButton" />
To get the custom layout to put into the ActionBar add this menu item into it:
res/menu/actionbar_main.xml
<item android:id="#+id/MenuItemCustomize"
android:icon="#drawable/layer_customizer"
android:title="#string/customize"
android:showAsAction="always"
android:actionLayout="#layout/actionview_customizer"
/>
Then after loading the Action Bar use this code to get the handle to the button. This happens in your Activity.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.actionbar_main, menu);
final ActionBar actionBar = getActionBar();
final MenuItem customizerItem = menu.findItem(R.id.MenuItemCustomize);
View v = customizerItem.getActionView();
customizerActionView = (ImageButton) v;
customizerActionView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
onOptionsItemSelected(customizerItem);
}
});
}
If you want to see the full source working together look at the app source code I use this in. http://code.google.com/p/motivatormaker-android/source/browse/MakeMotivator/src/com/futonredemption/makemotivator/activities/MainActivity.java
Related
I have a problem in my Android project.
I can't change the color of the bottombar.
This is how I want my bottombar to look:
This is my code
menu > tabhost_bottom.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
>
<item
android:id="#+id/home_item"
android:icon="#drawable/ic_home"
android:color="#color/colorPrimary"
android:title="Home"
/>
<item
android:id="#+id/setting_item"
android:icon="#drawable/ic_setting"
android:color="#color/colorPrimary"
android:title="Setting" />
HomeActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.tabhost_activity);
BottomBar bottomBar = BottomBar.attach(this, savedInstanceState);
bottomBar.setItemsFromMenu(R.menu.tabhost_bottom, new OnMenuTabSelectedListener() {
#Override
public void onMenuItemSelected(int itemId) {
}
});
// Set the color for the active tab. Ignored on mobile when there are more than three tabs.
bottomBar.setActiveTabColor("#55a8e5");
// Use the dark theme. Ignored on mobile when there are more than three tabs.
bottomBar.setBackgroundColor(Color.parseColor("#55a8e5"));
// Use custom text appearance in tab titles.
//bottomBar.setTextAppearance(R.style.MyTextAppearance);
// Use custom typeface that's located at the "/src/main/assets" directory. If using with
// custom text appearance, set the text appearance first.
//bottomBar.setTypeFace("MyFont.ttf");
}
and this my reference
http://androidgifts.com/build-android-material-design-bottom-navigation/
I've finally achieved to change it with the following code (Xamarin C#)
var bottomBarBackground = FindViewById(Resource.Id.bb_bottom_bar_background_view);
bottomBarBackground.SetBackgroundResource(Resource.Drawable.tabbar_background);
tabbar_background.axml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="#color/YourColor"/>
</shape>
</item>
</layer-list>
Found also here, though the final solution did not work for me with the Xamarin version: Question about background color
Is this the library?
Other Option:
seems like you need to set the Background color a different way:
// Setting colors for different tabs when there's more than three of them.
// You can set colors for tabs in three different ways as shown below.
mBottomBar.mapColorForTab(0, ContextCompat.getColor(this, R.color.colorAccent));
mBottomBar.mapColorForTab(1, 0xFF5D4037);
mBottomBar.mapColorForTab(2, "#7B1FA2");
mBottomBar.mapColorForTab(3, "#FF5252");
mBottomBar.mapColorForTab(4, "#FF9800");
For more inforation:
Android new Bottom Navigation bar
For all Kotlin fans: To set background color for all items in bottom bavigation bar, just add this lines in class MainActivity function onCreate:
// finds view in bottom_nav_menu.xml
val navView: BottomNavigationView = findViewById(R.id.nav_view)
// sets background color for the whole bar
navView.setBackgroundColor(ContextCompat.getColor(this, R.color.yourColor))
When you are using this library (roughike's bottombar) you can try this.
You can set the backgroundcolor of a specific tab by using the following line:
bottomBar.getTabAtPosition(0).setBackgroundColor(backgroundColorInt);
When you use this line multiple times for each tab, you can change the backgroundcolor of the whole tab.
Hi, I am working on custom keyboard tool in android it is somewhat
same as our default android device keyboard. Below shows the format of
my keyboard.
So, here i am setting backgorund color to button but it is looking
very clumsy as shown below,
i need to set background color as red same as shown in above screenshot which is default color of button.It changes the dimension of button when i set background color.
Code i have used to set background color is,
int mColor = 0xFFFF0000;
b.setBackgroundColor(mColor);
v.setBackgroundColor(mColor);
So where i am going wrong.
enter code hereYour normal button got a design from the system. If you change the color the design will be changed to standard.
You should create you own style for a button with a shape
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:angle="270"
android:endColor="#aaaaaa"
android:startColor="#555555" />
<stroke
android:width="1dp"
android:color="#000000" />
<corners
android:bottomLeftRadius="10sp"
android:bottomRightRadius="10sp"
android:topLeftRadius="10sp"
android:topRightRadius="10sp" />
</shape>
create a xml file in your drawable and insert the code above.
When did you want to change the color of your button? If you want to change the color by a click, you should use a selector, like this
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/shapeButtonRed" android:state_focused="true"/>
<item android:drawable="#drawable/shapeButtonRed" android:state_pressed="true"/>
<item android:drawable="#drawable/shapeButton"/>
</selector>
now you have to give you button the android:backgroud"#drawable/selector" the it will change the color by click
You can use a color filter to achieve the red coloring of the two buttons:
int mColor = 0xFFFF0000;
b.getBackground().setColorFilter(mColor, PorterDuff.Mode.MULTIPLY);
v.getBackground().setColorFilter(mColor, PorterDuff.Mode.MULTIPLY);
while using this import statement:
import android.graphics.PorterDuff;
This will preserve the default design of the button.
I'm trying to change the drawable that sits in the Android actionbar searchview widget.
Currently it looks like this:
but I need to change the blue background drawable to a red colour.
I've tried many things short of rolling my own search widget, but nothing seems to work.
Can somebody point me in the right direction to changing this?
Intro
Unfortunately there's no way to set SearchView text field style using themes, styles and inheritance in XML as you can do with background of items in ActionBar dropdown. This is because selectableItemBackground is listed as styleable in R.stylable, whereas searchViewTextField (theme attribute that we're interested in) is not. Thus, we cannot access it easily from within XML resources (you'll get a No resource found that matches the given name: attr 'android:searchViewTextField' error).
Setting SearchView text field background from code
So, the only way to properly substitute background of SearchView text field is to get into it's internals, acquire access to view that has background set based on searchViewTextField and set our own.
NOTE: Solution below depends only on id (android:id/search_plate) of element within SearchView, so it's more SDK-version independent than children traversal (e.g. using searchView.getChildAt(0) to get to the right view within SearchView), but it's not bullet-proof. Especially if some manufacturer decides to reimplement internals of SearchView and element with above-mentioned id is not present - the code won't work.
In SDK, the background for text field in SearchView is declared through nine-patches, so we'll do it the same way. You can find original png images in drawable-mdpi directory of Android git repository. We're interested in two image. One for state when text field is selected (named textfield_search_selected_holo_light.9.png) and one for where it's not (named textfield_search_default_holo_light.9.png).
Unfortunately, you'll have to create local copies of both images, even if you want to customize only focused state. This is because textfield_search_default_holo_light is not present in R.drawable. Thus it's not easily accessible through #android:drawable/textfield_search_default_holo_light, which could be used in selector shown below, instead of referencing local drawable.
NOTE: I was using Holo Light theme as base, but you can do the same with Holo Dark. It seems that there's no real difference in selected state 9-patches between Light and Dark themes. However, there's a difference in 9-patches for default state (see Light vs Dark). So, probably there's no need to make local copies of 9-patches for selected state, for both Dark and Light themes (assuming that you want to handle both, and make them both look the same as in Holo Theme). Simply make one local copy and use it in selector drawable for both themes.
Now, you'll need to edit downloaded nine-patches to your need (i.e. changing blue color to red one). You can take a look at file using draw 9-patch tool to check if it is correctly defined after your edit.
I've edited files using GIMP with one-pixel pencil tool (pretty easy) but you'll probably use the tool of your own. Here's my customized 9-patch for focused state:
NOTE: For simplicity, I've used only images for mdpi density. You'll have to create 9-patches for multiple screen densities if, you want the best result on any device. Images for Holo SearchView can be found in mdpi, hdpi and xhdpi drawable.
Now, we'll need to create drawable selector, so that proper image is displayed based on view state. Create file res/drawable/texfield_searchview_holo_light.xml with following content:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
android:drawable="#drawable/textfield_search_selected_holo_light" />
<item android:drawable="#drawable/textfield_search_default_holo_light" />
</selector>
We'll use the above created drawable to set background for LinearLayout view that holds text field within SearchView - its id is android:id/search_plate. So here's how to do this quickly in code, when creating options menu:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Getting SearchView from XML layout by id defined there - my_search_view in this case
SearchView searchView = (SearchView) menu.findItem(R.id.my_search_view).getActionView();
// Getting id for 'search_plate' - the id is part of generate R file,
// so we have to get id on runtime.
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
// Getting the 'search_plate' LinearLayout.
View searchPlate = searchView.findViewById(searchPlateId);
// Setting background of 'search_plate' to earlier defined drawable.
searchPlate.setBackgroundResource(R.drawable.textfield_searchview_holo_light);
return super.onCreateOptionsMenu(menu);
}
}
Final effect
Here's the screenshot of the final result:
How I got to this
I think it's worth metioning how I got to this, so that this approach can be used when customizing other views.
Checking out view layout
I've checked how SearchView layout looks like. In SearchView contructor one can find a line that inflates layout:
inflater.inflate(R.layout.search_view, this, true);
Now we know that SearchView layout is in file named res/layout/search_view.xml. Looking into search_view.xml we can find an inner LinearLayout element (with id search_plate) that has android.widget.SearchView$SearchAutoComplete inside it (looks like ours search view text field):
<LinearLayout
android:id="#+id/search_plate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:background="?android:attr/searchViewTextField">
Now, we now that the background is set based on current theme's searchViewTextField attribute.
Investigating attribute (is it easily settable?)
To check how searchViewTextField attribute is set, we investigate res/values/themes.xml. There's a group of attributes related to SearchView in default Theme:
<style name="Theme">
<!-- (...other attributes present here...) -->
<!-- SearchView attributes -->
<item name="searchDropdownBackground">#android:drawable/spinner_dropdown_background</item>
<item name="searchViewTextField">#drawable/textfield_searchview_holo_dark</item>
<item name="searchViewTextFieldRight">#drawable/textfield_searchview_right_holo_dark</item>
<item name="searchViewCloseIcon">#android:drawable/ic_clear</item>
<item name="searchViewSearchIcon">#android:drawable/ic_search</item>
<item name="searchViewGoIcon">#android:drawable/ic_go</item>
<item name="searchViewVoiceIcon">#android:drawable/ic_voice_search</item>
<item name="searchViewEditQuery">#android:drawable/ic_commit_search_api_holo_dark</item>
<item name="searchViewEditQueryBackground">?attr/selectableItemBackground</item>
We see that for default theme the value is #drawable/textfield_searchview_holo_dark. For Theme.Light value is also set in that file.
Now, it would be great if this attribute was accessible through R.styleable, but, unfortunately it's not. For comparison, see other theme attributes which are present both in themes.xml and R.attr like textAppearance or selectableItemBackground. If searchViewTextField was present in R.attr (and R.stylable) we could simply use our drawable selector when defining theme for our whole application in XML. For example:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:searchViewTextField">#drawable/textfield_searchview_holo_light</item>
</style>
</resources>
What should be modified?
Now we know, that we'll have to access search_plate through code. However, we still don't know how it should look like. In short, we search for drawables used as values in default themes: textfield_searchview_holo_dark.xml and textfield_searchview_holo_light.xml. Looking at content we see that the drawable is selector which reference two other drawables (which occur to be 9-patches later on) based on view state. You can find aggregated 9-patch drawables from (almost) all version of Android on androiddrawables.com
Customizing
We recognize the blue line in one of the 9-patches, so we create local copy of it and change colors as desired.
The above solutions may not work if you are using appcompat library. You may have to modify the code to make it work for appcompat library.
Here is the working solution for appcompat library.
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
SearchView.SearchAutoComplete searchAutoComplete = (SearchView.SearchAutoComplete)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchAutoComplete.setHintTextColor(Color.WHITE);
searchAutoComplete.setTextColor(Color.WHITE);
View searchplate = (View)searchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
searchplate.setBackgroundResource(R.drawable.texfield_searchview_holo_light);
ImageView searchCloseIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn);
searchCloseIcon.setImageResource(R.drawable.abc_ic_clear_normal);
ImageView voiceIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_voice_btn);
voiceIcon.setImageResource(R.drawable.abc_ic_voice_search);
ImageView searchIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_mag_icon);
searchIcon.setImageResource(R.drawable.abc_ic_search);
return super.onCreateOptionsMenu(menu);
}
Your onCreateOptionsMenu method must be:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.option, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
int linlayId = getResources().getIdentifier("android:id/search_plate", null, null);
ViewGroup v = (ViewGroup) searchView.findViewById(linlayId);
v.setBackgroundResource(R.drawable.searchviewredversion);
return super.onCreateOptionsMenu(menu);
}
where your search item is menu_search off course
and here is the searchviewredversion (this one is the xhdpi version): http://img836.imageshack.us/img836/5964/searchviewredversion.png
The solution above doesn't work with ActionBarSherlock 4.2 and therefore it's not backward compatible to Android 2.x. Here is working code which setups SearchView background and hint text on ActionBarSherlock 4.2:
public static void styleSearchView(SearchView searchView, Context context) {
View searchPlate = searchView.findViewById(R.id.abs__search_plate);
searchPlate.setBackgroundResource(R.drawable.your_custom_drawable);
AutoCompleteTextView searchText = (AutoCompleteTextView) searchView.findViewById(R.id.abs__search_src_text);
searchText.setHintTextColor(context.getResources().getColor(R.color.your_custom_color));
}
I've tired to do this as well and I'm using v7.
The application was crashed when I tried to grab the searchPlate via the getIdentifier() so I done it this way:
View searchPlate = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
Update
If you are using AndroidX then you can do it like this
View searchPlate = svSearch. findViewById(androidx.appcompat.R.id.search_plate);
if (searchPlate != null) {
AutoCompleteTextView searchText = searchPlate.findViewById(androidx.appcompat.R.id.search_src_text);
if (searchText != null){
searchText.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.edittext_text_size));
searchText.setMaxLines(1);
searchText.setSingleLine(true);
searchText.setTextColor(getResources().getColor(R.color.etTextColor));
searchText.setHintTextColor(getResources().getColor(R.color.etHintColor));
searchText.setBackground(null);
}
}
I also faced same problem.I used appcompat v7 library and defined custom style for it.
In drawable folder put bottom_border.xml file which looks like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape >
<solid android:color="#color/blue_color" />
</shape>
</item>
<item android:bottom="0.8dp"
android:left="0.8dp"
android:right="0.8dp">
<shape >
<solid android:color="#color/background_color" />
</shape>
</item>
<!-- draw another block to cut-off the left and right bars -->
<item android:bottom="2.0dp">
<shape >
<solid android:color="#color/main_accent" />
</shape>
</item>
</layer-list>
In values folder styles_myactionbartheme.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppnewTheme" parent="Theme.AppCompat.Light">
<item name="android:windowBackground">#color/background</item>
<item name="android:actionBarStyle">#style/ActionBar</item>
<item name="android:actionBarWidgetTheme">#style/ActionBarWidget</item>
</style>
<!-- Actionbar Theme -->
<style name="ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">#color/main_accent</item>
<!-- <item name="android:icon">#drawable/abc_ic_ab_back_holo_light</item> -->
</style>
<style name="ActionBarWidget" parent="Theme.AppCompat.Light">
<!-- SearchView customization-->
<!-- Changing the small search icon when the view is expanded -->
<!-- <item name="searchViewSearchIcon">#drawable/ic_action_search</item> -->
<!-- Changing the cross icon to erase typed text -->
<!-- <item name="searchViewCloseIcon">#drawable/ic_action_remove</item> -->
<!-- Styling the background of the text field, i.e. blue bracket -->
<item name="searchViewTextField">#drawable/bottom_border</item>
<!-- Styling the text view that displays the typed text query -->
<item name="searchViewAutoCompleteTextView">#style/AutoCompleteTextView</item>
</style>
<style name="AutoCompleteTextView" parent="Widget.AppCompat.Light.AutoCompleteTextView">
<item name="android:textColor">#color/text_color</item>
<!-- <item name="android:textCursorDrawable">#null</item> -->
<!-- <item name="android:textColorHighlight">#color/search_view_selected_text</item> -->
</style>
</resources>
I defined custommenu.xml file for displaying menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:com.example.actionbartheme="http://schemas.android.com/apk/res-auto" >
<item android:id="#+id/search"
android:title="#string/search_title"
android:icon="#drawable/search_buttonn"
com.example.actionbartheme:showAsAction="ifRoom|collapseActionView"
com.example.actionbartheme:actionViewClass="android.support.v7.widget.SearchView"/>
Your activity should extend ActionBarActivity instead of Activity.
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.custommenu, menu);
}
In manifest file:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppnewTheme" >
For more information see here:
Here http://www.jayway.com/2014/06/02/android-theming-the-actionbar/
First, let's create an XML file called search_widget_background.xml, to be used as a drawable, i.e. under drawable directory.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#color/red" />
</shape>
This drawable will be used as the background for our search widget. I set the color to red because that's what you asked for, but you can set it to any color defined by #color tag. You can even modify it further using the attributes defined for shape tag (make rounded corners, do an oval background, etc.).
Next step is to set the background of our search widget to this one. This can be accomplished by the following:
public boolean onCreateOptionsMenu(Menu menu) {
SearchView searchView = (SearchView)menu.findItem(R.id.my_search_view).getActionView();
Drawable d = getResources().getDrawable(R.drawable.search_widget_background);
searchView.setBackground(d);
...
}
public boolean onCreateOptionsMenu(Menu menu) {
........
// Set the search plate color
int linlayId = getResources().getIdentifier("android:id/search_plate", null, null);
View view = searchView.findViewById(linlayId);
Drawable drawColor = getResources().getDrawable(R.drawable.searchcolor);
view.setBackground( drawColor );
........
}
and this is the searchablecolor.xml file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape >
<solid android:color="#ffffff" />
</shape>
</item>
<!-- main color -->
<item android:bottom="1.5dp"
android:left="1.5dp"
android:right="1.5dp">
<shape >
<solid android:color="#2c4d8e" />
</shape>
</item>
<!-- draw another block to cut-off the left and right bars -->
<item android:bottom="18.0dp">
<shape >
<solid android:color="#2c4d8e" />
</shape>
</item>
</layer-list>
I was digging about that a lot and finally I found this solution and it works for me!
You can use this
If you use appcompat try this:
ImageView searchIconView = (ImageView) searchView.findViewById(android.support.v7.appcompat.R.id.search_button);
searchIconView.setImageResource(R.drawable.yourIcon);
If you use androidx try this:
ImageView searchIconView = (ImageView) searchView.findViewById(androidx.appcompat.R.id.search_button);
searchIconView.setImageResource(R.drawable.yourIcon);
It will change the default serchview icon.
Hope it helps!
I explained in the end of this post with images
this is apply for xamarin forms. But i think you can understand it, because it is based on the source code of searchview of android
How to change searchbar cancel button image in xamarin forms
If you are inflating Searchview like this "getMenuInflater().inflate(R.menu.search_menu, menu);". Then you can customize this searchview via style.xml like below.
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="searchViewStyle">#style/SearchView.ActionBar</item>
</style>
<style name="SearchView.ActionBar" parent="Widget.AppCompat.SearchView.ActionBar">
<item name="queryBackground">#drawable/drw_search_view_bg</item>
<item name="searchHintIcon">#null</item>
<item name="submitBackground">#null</item>
<item name="closeIcon">#drawable/vd_cancel</item>
<item name="searchIcon">#drawable/vd_search</item>
</style>
I have a ListView that sits on the left side of a tablet-size screen. My goal was to give it a solid background with a border on the right, then apply an overlapping background on the list element to break that border so that it appears to be a part of the view on the right.
The ListView Background
I achieved the right border using a <layer-list> drawable as suggested by Emile in another question:
rightborder.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/black" />
</shape>
</item>
<item android:right="2dp">
<shape android:shape="rectangle">
<solid android:color="#color/white" />
</shape>
</item>
</layer-list>
...and here's the ListView definition for good measure:
<ListView
android:id="#+id/msglist"
android:layout_width="300dp"
android:layout_height="match_parent"
android:divider="#color/black"
android:dividerHeight="1dp"
android:background="#drawable/rightborder"
android:paddingRight="0dip">
</ListView>
<!-- I added the android:paddingRight after reading something
about shape drawables and padding, don't think it actually
did anything. -->
Attempting to override it with a color
In order to achieve the desired effect, I placed the following in the getView function of my adapter:
//If it's selected, highlight the background
if(position == mSelectedIndex)
convertView.setBackgroundColor(R.color.light_gray);
else
convertView.setBackgroundResource(0);
However, using this method, the black border of the ListView's drawable remained visible, and only the white part of the background was replaced by gray. Here's a screen capture:
Fixing it with a drawable
On a hunch, I replaced the color I was assigning with a shape drawable:
selectedmessage.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/light_gray" />
</shape>
getView snippet:
//If it's selected, highlight the background
if(position == mSelectedIndex)
convertView.setBackgroundResource(R.drawable.selectedmessage);
else
convertView.setBackgroundResource(0);
This achieves the desired result, as shown below:
The question:
Why does assigning a rectangle as the background for my ListView element cover the entire view, while assigning the color allows the black border to show through? I'm happy it's working, but I'd like to know why Android is rendering the view this way so I can learn more about how Android renders Views.
Other notes:
I'm running the project in the stock Android 3.2 emulator, if that makes any
difference.
One clue may be that the light_gray color background seems to render darker than the light_gray shape resource.
I doubt it makes a difference, but light_gray is:
<color name="light_gray">#FFCCCCCC</color>
You can't do this:
convertView.setBackgroundColor(R.color.light_gray);
setBackgroundColor does not take a resource id : http://developer.android.com/reference/android/view/View.html#setBackgroundColor(int)
So your getting some incidental behaviour that isn't doing what your expecting.
You would have to do:
convertView.setBackgroundColor(getResources().getColor(R.color.light_gray);
http://developer.android.com/reference/android/content/res/Resources.html#getColor(int)
I try to implement a hover effect (effect when button is pressed) through putting a semi transparent PNG file on top of the button background and the button icon. Unfortunatly the button background file is a 9-PATCH-PNG which causes some trouble here: It "swallows" everything on top of its layer and doesnt allow to cover the stretchable areas (the fine light line around) of the nine-patch-png. In other words, the black lines the top and left edge of the 9 PATCH PNG cause not only stretching, but also padding behaviour.
Removing the 9-Patch-Information is not a good solution.
Here u can see my Button. The blue background is a 9 PATCH PNG. The thin light line around the button is unwanted.
This layer-list is assigned to the button attribute "background":
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/home_btn_bg_blue_without_padding" />
<item>
<bitmap
android:src="#drawable/home_icon_test"
android:gravity="center" />
</item>
<item
android:drawable="#drawable/layer_black_50" />
</layer-list>
Setting the offsets of the layer to "-1" on each border is not valid. Have u guys suggestions?
Update
I tried following, which shall avoid scaling, suggested from here. But didn't work either:
<!-- To avoid scaling, the following example uses a <bitmap> element with centered gravity: -->
<item>
<bitmap android:src="#drawable/image"
android:gravity="center" />
</item>
My version (There are still the stretchable areas of the 9-patch-png uncovered):
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/home_btn_bg_blue_hover_without_padding" />
<item>
<bitmap
android:src="#drawable/home_icon_test"
android:gravity="center" />
</item>
<item>
<bitmap android:src="#drawable/layer_black_100"
android:height="100dp"
android:width="100dp"/></item>
</layer-list>
Update 2
Could that work for me? Making Overlaid image transparent on touch in Android?
[NeverMind]
The internal comments for LayerDrawable.getPadding claim that it takes the padding from the first drawable in the list. If this comment is telling the truth, you could get the behavior you want by putting an arbitrary (perhaps empty) image before your 9 patch in the list.
A quick reading of the code, however, implies that it actually uses the sum of all the item's paddings, which means that there's no way to eliminate your problem using the default LayerDrawable. The statement implies the solution: implement a subclass of LayerDrawable which overrides "getPadding" to return {0, 0, 0, 0}. You may have to initialize your subclass in code rather than by loading an XML layout, but this isn't particularly difficult.
[/NeverMind]
Update:
The solution above doesn't work, because the problem isn't the padding itself, it's the fact that the default implementation sets the bounds of each image to be the sum of the paddings of the preceding images. In other words, it enforces nesting, which is what most people will want. The proper solution is still to override LayerDrawable, but you replace "onBoundsChange" instead. A complete, tested demo follows:
package com.beekeeper.ninepatchcover;
import android.app.Activity;
import android.graphics.*;
import android.graphics.drawable.*;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.ImageButton;
public class NinePatchCover extends Activity {
private Drawable mCover0;
private Drawable mCover1;
/** Called when the activity is first created. */
#Override public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Drawable button =
getResources().getDrawable(android.R.drawable.btn_default);
final Bitmap iconBitmap =
BitmapFactory.decodeResource(getResources(),
android.R.drawable.ic_menu_mylocation);
final BitmapDrawable icon = new BitmapDrawable(iconBitmap);
icon.setGravity(Gravity.CENTER);
mCover0 =
getResources().getDrawable(android.R.drawable.title_bar);
mCover1 =
getResources().getDrawable(android.R.drawable.title_bar);
final LayerDrawable unsolved =
new LayerDrawable(new Drawable[]{button, icon, mCover0});
final LayerDrawable solved =
new MyLayerDrawable(new Drawable[]{button, icon, mCover1,}, mCover1);
((ImageButton)findViewById(R.id.uncovered)).setBackgroundDrawable(unsolved);
((ImageButton)findViewById(R.id.covered)).setBackgroundDrawable(solved);
}
class MyLayerDrawable extends LayerDrawable {
Drawable mCover;
public MyLayerDrawable(final Drawable[] layers, final Drawable cover) {
super(layers);
mCover = cover;
}
#Override protected void onBoundsChange(final Rect bounds) {
super.onBoundsChange(bounds);
mCover.setBounds(bounds);
}
}
}
using the following layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageButton android:id="#+id/uncovered"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<ImageButton android:id="#+id/covered"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
A sample screenshot follows:
Update 2:
As requested, here's how you can modify it to initialize a Selector within the code. Replace the initialization of "mCover1" with the following code:
final StateListDrawable sld = new StateListDrawable();
sld.addState(new int[]{android.R.attr.state_pressed},
new ColorDrawable(0xffff0000));
sld.addState(new int[]{android.R.attr.state_window_focused},
new ColorDrawable(0xff00ff00));
sld.addState(new int[]{},
getResources().getDrawable(android.R.drawable.title_bar));
mCover1 = sld;
This will show green in the normal case where the window is focused but the button isn't pressed, red when the button is pressed, and the default drawable (grey) when the window isn't focused. (Try dragging down the "windowshade" notification bar to see the window in it's unfocused state.)
I got it working just fine :
res/layout/main.xml
...
<ImageButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="#drawable/button"
/>
...
res/drawable/button.xml
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/frame" />
<item>
<bitmap
android:src="#drawable/tomato"
android:gravity="center"
/>
</item>
</layer-list>
frame.9.png is my nine-patch-png. Tomato is a basic png with transparency around it.
Here is the result :
Removing the transparent part around the tomato (filling up with pink) :
Edit 2:
This will make the tomato cover completely the patch-9-png :
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:src="#drawable/frame"
/>
</item>
<item>
<bitmap
android:src="#drawable/tomato"
/>
</item>
</layer-list>
Another way, with using an ImageButton is that you can use the patch-9-png as the background and the "content" as the src of the button. In that case, you need to set the padding to 0 for that src
I got a full overlay to work by manipulating the nine-patch. Instead of leaving the bottom and right sides (content) empty, try filling them in completely with black pixels.
I think there are two solutions to this issue.
Solution 1:
When you say "hover effect", do you mean while the button is being pressed down? If that's the case, then what you want to do use use a selector a.k.a. state list for the button background, where the selected state is different than your normal image:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#android:color/black" /> <!-- pressed -->
<item android:drawable="#drawable/home_btn_bg_blue_hover_without_padding" /> <!-- default -->
</selector>
Then set the button background to that state list drawable XML.
Solution 2:
While you haven't posted your raw nine patch PNG, I suspect that you can remove the right and bottom markings denoting the "padding box", while keeping the left and top markings, denoting the "Stretchable area" as documented in the 2D Graphics Doc. This will retain the image's current stretching behavior, but remove any padding that is intrinsic to the image. You can then add or remove padding as desired to the inner views to get the desired display.