Android - cannot set button border as expected - android

I just started learning Android a few days ago. When I am playing around with Button today, I noticed that I am not able to set border as expected.
xml files below:
Button partin activity_main.xml:
<Button
android:layout_width="200sp"
android:layout_height="100dp"
android:background="#drawable/start_button_selector"
app:backgroundTint="#color/start_button_color_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias=".4" />
start_button_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/arrow_button">
<shape android:shape="rectangle">
<solid android:color="#color/transparent" />
<corners android:radius="12sp" />
<stroke android:width="10sp" android:color="#color/start_button_color_selector"/>
</shape>
</item>
</selector>
start_button_color_selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/black" android:state_pressed="true"/>
<item android:color="#color/gray"/>
</selector>
however, neither the preview nor the emulator gives the expected result.
the preview does not show any border, and the emulator shows a purple border\
expected (and all color becomes black when clicked):
but here is the preview in xml Design mode:
and here is what it is showing in the emulator (API 30):
also tried:
changing Button to androidx.appcompat.widget.AppCompatButton
removing color inside stroke tag
Any help would be great!
Edit: Sorry if I didn't make it clear. The problem is not changing color when pressed, with the above xml file, the button is already able to change its color when pressed. The problem I have is that the border is transparent in preview and purple in emulator, which is not gray/black as I expected.

You can achieve this using a Material Button. There is a lot of useful attributes you can use to make the button based on your needs, like app:strokeWidth, app:strokeColor, app:cornerRadius, app:backgroundTint, app:icon, app:iconSize and much more where you can find them in the above link.
Below is a sample of your Button using the above Material Button attributes:
<com.google.android.material.button.MaterialButton
android:id="#+id/button"
android:layout_width="200dp"
android:layout_height="100dp"
android:padding="0dp"
android:insetLeft="0dp"
android:insetTop="0dp"
android:insetRight="0dp"
android:insetBottom="0dp"
app:cornerRadius="12dp"
app:strokeWidth="10dp"
app:strokeColor="#color/start_button_color_selector"
app:backgroundTint="#android:color/white"
app:icon="#drawable/button_selector"
app:iconTint="#null"
app:iconSize="80dp"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
where #color/start_button_color_selector.xml will be like below to set the stroke color based on selected/unselected state:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#android:color/black" android:state_pressed="true"/>
<item android:color="#969292"/>
</selector>
and #drawable/button_selector will be like below to set the correct vector icon based on selected/unselected state:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_arrow_black_right_24dp" android:state_pressed="true"/>
<item android:drawable="#drawable/ic_arrow_gray_right_24dp"/>
</selector>
and #drawable/ic_arrow_black_right_24dp is a sample black selected arrow:
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#android:color/black" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#android:color/black" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
</vector>
and #drawable/ic_arrow_gray_right_24dp is a sample gray unselected arrow:
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#969292" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#969292" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
</vector>
Final result for unselected state will be:
and final result for selected/clicked state will be:

You shoul remove this line from your code.
app:backgroundTint="#color/start_button_color_selector"

You can create a vector of expected result and apply as background to
button, then apply a android:state_pressed on it

Related

Change Tint Image Button after pressed

I am trying to create an ImageButton able to change the icon color after pressing. I want to do that in my XML file. I have the following code:
...
<ImageButton
android:id="#+id/stop_button"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#drawable/stop_icon"
android:background="#drawable/stop_button"
android:tint="#color/ship_cove"
app:layout_constraintBottom_toTopOf="#id/bottom_icon_guideline"
app:layout_constraintLeft_toRightOf="#id/start_icon_guideline"
app:layout_constraintRight_toLeftOf="#id/end_icon_guideline"
app:layout_constraintTop_toBottomOf="#id/mediatop_icon_guideline" />
And here is my #drawable/stop_button.xml file content:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/cornflower_blue">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/oxford_blue" />
<corners android:radius="8dp" />
</shape>
</item>
</ripple>
As I stated before, my purpose is to change my stop_icon tint after pressing my stop_button, but I do not know how I can do that. Can anyone help me?
Note: if my button is not pressed, I want my stop_icon with the color #color/ship_cove. If it is, I want the color #color/mirage.
Instead of color create a color selector with a pressed state.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:color="pressed_color" android:state_pressed="true" />
<item android:color="default_color" />
</selector>
And use this selector for the color of the icon. The rest should be taken by the system.

Android automirrored not working for Button Selector Drawable

I want a language support that is Right to Left. I have a button that has a text at start and arrow drawable at end. Arrow direction should be changed according to Locale selected. It works fine if i dont use selector as drawableEnd.
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/btn_send_otp"
android:layout_width="0dp"
android:layout_height="50dp"
android:gravity="center_vertical"
android:text="#string/get_started"
android:drawableEnd="#drawable/sl_right_arrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
Button has following selector set as drawableEnd attribute
Selector Drawable (sl_right_arrow):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/orange_right" android:state_enabled="true" />
<item android:drawable="#drawable/arrow_right_grey" android:state_enabled="false" />
</selector>
Drawables has android:autoMirrored="true". So if I use these drawables without selector like following
android:drawableEnd="#drawable/arrow_right_grey"
it works fine and arrow changes its direction according to Locale selected. But it does not work with selector.
Following are drawables:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="#dimen/sdp_15"
android:height="#dimen/sdp_12"
android:autoMirrored="true"
android:viewportWidth="18"
android:viewportHeight="14">
<path
android:fillColor="#00000000"
android:pathData="M1.5,7L16.5,7"
android:strokeWidth="1.5"
android:strokeColor="#A8A8A8"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M10.7623,1L16.5,7L10.7623,13"
android:strokeWidth="1.5"
android:strokeColor="#A8A8A8"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector>
change your selector file to the following
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true">
<item android:drawable="#drawable/orange_right" android:state_enabled="true" />
<item android:drawable="#drawable/arrow_right_grey" android:state_enabled="false" />
</selector>

Bottom Navigation Not showing original color

I have designed a bottom navigation view for my application. The idea is simple, green colored bottom bar will have white colored icons. I wrote a selector for this
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:color="#android:color/white" />
<item android:color="#android:color/holo_blue_dark" />
</selector>
And it works, it changes the icon colors, but it does not make it completely white, the color looks gray-ish.
I have also tried the <item android:state_selected="true" android:color="#android:color/white" /> but it also doesn't work. I have added the images below for you to see the difference.
Please help
If you want your icon to have same default color use this in your activiy.
bottomNavigation.setItemIconTintList(null);
Here is what worked for me:
theme.xml
<item name="elevationOverlayEnabled">false</item>
It appears that for anything that has elevation set, there will be an overlay. In my case my BottomNavigationView had elevation manually set and thus received a dark overlay.
You should use state_selected
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:color="#color/color1" />
<item android:color="#color/color2" />
</selector>
app:itemIconTint="#color/navigate_state"
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#android:color/holo_blue_dark" />
<item android:color="#android:color/darker_gray" />
</selector>
and kind of
add it on android.support.design.widget.BottomNavigationView app:itemIconTint="#drawable/nav_item_color_state" app:itemTextColor="#drawable/nav_item_color_state"
If you using BottomNavigationView from com.google.android.material, you should specified colors especially for icon and text, for example:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background"
app:itemIconTint="#color/bottom_bar_icon_tint"
app:itemTextColor="#color/bottom_bar_icon_tint"
app:menu="#menu/navigation_menu" />
and bottom_bar_icon_tint.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#color/white" />
<item android:color="#color/cool_grey" />
</selector>
also pay attention to: android:state_checked="true"
Your xml files seems to have an alpha channel/transparency
You need to change the "android:alpha" parameter to "1.0" or remove it in your icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#color/white"
android:alpha="0.8">
<path
android:fillColor="#color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM6.5,17.5l7.51,-3.49L17.5,6.5 9.99,9.99 6.5,17.5zM12,10.9c0.61,0 1.1,0.49 1.1,1.1s-0.49,1.1 -1.1,1.1 -1.1,-0.49 -1.1,-1.1 0.49,-1.1 1.1,-1.1z"/>

How to add space between bitmap of spinner selector and items of drop down list

I have following spinner:
<Spinner
android:id="#+id/safe_network_time_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="#drawable/spinner_selector"
android:entries="#array/schedule_edit_days_repeat"
android:popupBackground="#drawable/custom_dropdown_white_background"
android:spinnerMode="dropdown"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/divider4"
tool:listitem="#layout/custom_dropdown_spinner_button" />
The spinner_selector is:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:gravity="right|center_vertical" android:src="#drawable/down_red_arrow" />
</item>
</selector>
The dropdown list appears like this:
When I select an item of the dropdown list, if it is too long it overlaps the arrov bitmap. how can I avoid this?
Try using a layer-list
bg_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<!-- This is the actual spinner background -->
<selector >
<!-- Feel free to use your own drawable for these states -->
<item android:state_window_focused="false" android:drawable="#drawable/bg_border_accent_thin"/>
<item android:state_pressed="true" android:drawable="#drawable/bg_border_accent_thin"/>
<item android:state_window_focused="true" android:state_pressed="false" android:drawable="#drawable/bg_border_grey_thin"/>
</selector>
</item>
<!-- This is the spinner drawable, use your custom drawable aswell. android:right does the magin to separate this drawable from the spinner content-->
<item android:drawable="#drawable/ic_ripple_arrow"
android:gravity="center_vertical|right"
android:right="16dp"/>
</layer-list>
Edit 02/02/2020
My apologies for a weekend-long lunch.
If you are using the androidx dependencies (which I suggest you do) here's the code that I use to properly add spacing between the text and the selected item in the spinner.
On your layout.xml
<!-- The line I think you need is the one giving padding to the right -->
<androidx.appcompat.widget.AppCompatSpinner
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingRight="36dp"
android:background="#drawable/bg_spinner"
android:popupBackground="#drawable/bg_spinner_popup"/>
The bg_spinner.xml is the one provided a couple of lines above.
And the popup one doesn't really matter, since it gives some directives on how to paint a background, nothing important but here it is either way...
bg_spinner_popup.xml
<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android
android:shape="rectangle">
<corners android:radius="3dp"/>
<solid android:color ="#android:color/white"/>
<stroke android:width="5px" android:color="#color/primaryColor"/>
</shape>

Android: How to change android:fillcolor with selector in one Vector Drawable xml

Tab Icons: My current method is to create two files (ic_list_selected_24dp.xml and ic_list_unselected_24dp.xml; they are basically the same but only the android:fillColor='Color HEX CODE' are different), and then create a selector (selector_tabitem_list.xml) to change the drawable color when the state is changed.
// #drawable/selector_tabitem_list.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:drawable="#drawable/ic_list_selected_24dp"
android:state_selected="true" />
<item android:drawable="#drawable/ic_list_unselected_24dp"
android:state_selected="false" />
</selector>
It's kind of duplicated because two drawables are the same.
Selector cannot be used in vector drawable.
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#drawable/selector"
android:pathData="M19,3...."
</vector>
--
// #drawable/selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<color android:color="#color/itemSelected" />
</item>
<item android:state_selected="false">
<color android:color="#color/itemUnselected" />
</item>
</selector>
, and android:fillColor="#color/state" either.
// #color/state
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#android:color/white" android:state_selected="true" />
<item android:color="#android:color/black" android:state_selected="false" />
</selector>
Is there any way to use one drawable and change its color dynamically?
Using hard hex code is better?
Thanks.
Here is the complete list of steps to use a vector asset as tinted icon in a TabItem (which is part of the support design lib). All parts are present in the original question and linked answer, but are easy to miss.
Create the selector. Note that it has to switch the color for state_selected (as included in the question, but not in the answer linked by #cmingmai. There it only states android:state_enabled which is not relevant for tabs):
res/color/selector_navigation.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="false" android:color="#android:color/black" />
<item android:state_selected="true" android:color="#android:color/white" />
</selector>
Adjust the vector drawable by adding android:tintMode and android:tint to the vector tag.
In addition for the tinting to work with multiply, the fillColor of the path needs to be set to white!
res/drawable/ic_tab_list:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:tintMode="multiply"
android:tint="#color/selector_navigation">
<path
android:fillColor="#android:color/white"
android:pathData="..." />
</vector>
Use vector drawable in Layout – or use to create the tabs in code as shown in the developer guide on Tabs. Note that I also modified the tab indicator color to match the active icon color to follow the material design guidelines.
Relevant part of the layout:
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#android:color/white">
<android.support.design.widget.TabItem
android:id="#+id/tabItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/ic_tab_list" />
<!-- More Tabs -->
</android.support.design.widget.TabLayout>
Adjust build.gradle with following to activate vector support for old Android versions (in case it was not already previously added):
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Upgrade to Support Library 28.0.0+ (presumably same for androidx.. didn't test).
On Support Library 28.0.0 using a selector color xml resource seems to work now when used as vector's android:fillColor.
In fact the previous solution (using vector's android:tintMode, android:tint and white for android:fillColor) no longer works for me on Support Library 28.0.0.
Tested on API 21 and 27 Emulators.
Try replacing the AppTheme in style.xml with a different parent like so:
style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar"

Categories

Resources