Android drawable rotate inside button - android

I need to have a button series with inside text and icon.
The icon inside the 4 buttons must rotate to cover every poly.
Follow an example with two buttons where the top is create with the original (vector drawable) icon and the "left" button rotating the vector.
<Button
style="#style/Buttons.Small"
android:drawableLeft="#drawable/ic_vertical_align_top_white_12dp"
android:text="#string/optional" />
<Button
style="#style/Buttons.Small"
android:drawableLeft="#drawable/arrow_left"
android:text="#string/optional" />
The vector drawable:
ic_vertical_align_top_white_12dp
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M8,11h3v10h2V11h3l-4,-4 -4,4zM4,3v2h16V3H4z" />
</vector>
The rotate drawable:
arrow_left.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="-90"
android:toDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:drawable="#drawable/ic_vertical_align_top_white_12dp">
</rotate>
The style
<style name="Buttons.Small">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">#color/buttonSmallBackground</item>
<item name="android:layout_margin">2dp</item>
<item name="android:minHeight">0dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:textSize">12sp</item>
<item name="android:drawablePadding">4dp</item>
<item name="android:paddingLeft">4dp</item>
<item name="android:paddingRight">4dp</item>
</style>
And following the result
Nougat (PERFECT)
Marshmallow (WRONG)
I already tried to play with the vector viewport without success.
Thanks

I solved with a trick.
Appling directly the rotation inside the vector.
Now arrow_left.xml become
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<group android:rotation="-90"
android:pivotX="12"
android:pivotY="12">
<path
android:fillColor="#FFFFFF"
android:pathData="M8,11h3v10h2V11h3l-4,-4 -4,4zM4,3v2h16V3H4z" />
</group>
</vector>
I don't know why in Marshmallow the rotation not work properly but this solve my case.
Thanks

Related

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 replicate Google photos scrolling thumb for RecyclerView

I'm trying to replicate the google photos scrolling behavior in our app and failing miserably.
Desired outcome:
I have a simple recyclerview where right now I'm using the fastscroller line and thumb.
The problem with that it redefines the height of the thumb drawable based on the content size.
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:id="#+id/pages"
app:fastScrollEnabled="true"
app:fastScrollHorizontalThumbDrawable="#drawable/thumb_drawable"
app:fastScrollHorizontalTrackDrawable="#drawable/line_drawable"
app:fastScrollVerticalThumbDrawable="#drawable/thumb_drawable"
app:fastScrollVerticalTrackDrawable="#drawable/line_drawable">
</androidx.recyclerview.widget.RecyclerView>
you can do it by defining height and width for thumb
here is how I have done it
ic_scroll.png
thumb.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_scroll" android:width="44dp" android:height="40dp"/>
</layer-list>
thumb_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/thumb" android:state_pressed="true" />
<item android:drawable="#drawable/thumb" />
</selector>
This is an easy and customizable option
Create an ic_asset_1.xml drawable /* This is a Vector */
Customize the background and arrows color according to your needs
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22.94dp"
android:height="38.3dp"
android:viewportWidth="22.94"
android:viewportHeight="38.3">
<path
android:pathData="M22.94,37.2a15.65,15.65 0,0 1,-5.76 1.1C7.69,38.3
0,29.72 0,19.15S7.69,0 17.18,0a15.56,15.56 0,0 1,5.54 1"
android:fillColor="#4298f5"/>
<path android:pathData="M8.02,21.06l7.31,0l-3.65,5.45l-3.66,-5.45z"
android:fillColor="#fff"
/>
<path
android:pathData="M15.23,16.02l-7.11,0l3.56,-5.55l3.55,5.55z"
android:fillColor="#fff"
/>
</vector>
Create an scrollbar_thumb.xml drawable
Customize height and width according to your needs
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_asset_1"
android:width="30dp"
android:height="40dp"
/>
</layer-list>
Create a new style in styles.xml
<style name="scrollbar_style">
<item name="android:scrollbarAlwaysDrawVerticalTrack">true</item>
<item name="android:scrollbarStyle">outsideOverlay</item>
<item name="android:scrollbars">vertical</item>
<item name="android:fadeScrollbars">true</item>
<item
name="android:scrollbarThumbVertical">#drawable/scrollbar_thumb</item>
<item name="android:scrollbarFadeDuration">800</item>
<item name="android:scrollbarDefaultDelayBeforeFade">500</item>
</style>
Add this style in recyler view like this
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="#style/scrollbar_style"
android:scrollbars="vertical"
/>

Crash on custom Animation Vector Drawable for Indeterminate ProgressBar

I wanna customize a progressbar, however the app crashed.
This is usage:
<ProgressBar
android:id="#+id/search_button_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true"
style="#style/ProgressBar.Customized"
/>
This is style:
<style name="ProgressBar" parent="android:Widget.ProgressBar">
<item name="android:indeterminateBehavior">repeat</item>
<item name="android:indeterminateDuration">#android:integer/config_longAnimTime</item>
</style>
<style name="ProgressBar.Customized">
<item name="android:src">#drawable/ic_loading_pb_group</item>
<item name="android:indeterminateDrawable">#drawable/ic_animated_loading_pb</item>
<item name="android:indeterminateBehavior">cycle</item>
</style>
This is drawable/ic_loading_pb_group:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<group
android:name="rotation_group"
android:pivotX="12"
android:pivotY="12"
android:rotation="0" >
<path
android:fillColor="#color/new_blue"
android:pathData="M13,2.05v3.03c3.39,0.49 6,3.39 6,6.92 0,0.9 -0.18,1.75 -0.48,2.54l2.6,1.53c0.56,-1.24 0.88,-2.62 0.88,-4.07 0,-5.18 -3.95,-9.45 -9,-9.95zM12,19c-3.87,0 -7,-3.13 -7,-7 0,-3.53 2.61,-6.43 6,-6.92V2.05c-5.06,0.5 -9,4.76 -9,9.95 0,5.52 4.47,10 9.99,10 3.31,0 6.24,-1.61 8.06,-4.09l-2.6,-1.53C16.17,17.98 14.21,19 12,19z"/>
</group>
This drawable/ic_animated_loading_pb:
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/ic_loading_pb_group" >
<target
android:name="rotation_group"
android:animation="#animator/rotation" />
</animated-vector>

Is it possible to rotate a drawable in the xml description?

I am creating an app, with resources that can be reused (because buttons are always the same, but mirrored or rotated). I do want to use the same resource so I don't have to add 3 more resources that are exactly like the original but rotated. But I also don't want to mix the code with things that can be declared in the XML or make transformations with a matrix that will cost processing time.
I've got a two state button declared in an XML.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/and_card_details_button_down_left_onclick" /> <!-- pressed -->
<item android:drawable="#drawable/and_card_details_button_down_left" /> <!-- default -->
</selector>
and I want to reuse the drawable because it will be the same but rotated 90º and 45º and I assign to the button as a drawable.
<Button android:id="#+id/Details_Buttons_Top_Left_Button"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/details_menu_large_button" />
I know that I can rotate it with a RotateDrawable or with a Matrix but as I already explained I don't like that approach.
Is it possible to achieve that directly on the XML or what do you think that will be the best way to do it? Put all resources but rotated, rotate them in the code?
--- EDIT ---
The answer of #dmaxi works great, this is how to combine it with an item list :)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<rotate
android:fromDegrees="90"
android:toDegrees="90"
android:pivotX="50%"
android:pivotY="50%"
android:drawable="#drawable/and_card_details_button_up_onclick"/>
</item>
<item>
<rotate
android:fromDegrees="90"
android:toDegrees="90"
android:pivotX="50%"
android:pivotY="50%"
android:drawable="#drawable/and_card_details_button_up_onclick"/>
</item>
</selector>
I could rotate in XML:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="90"
android:toDegrees="90"
android:pivotX="50%"
android:pivotY="50%"
android:drawable="#drawable/mainmenu_background">
</rotate>
The fromDegrees is important.
Basically this is a rotate animation defined in XML. With fromDegrees you define the initial rotated state. The toDegrees is the final rotated state of the drawable in the animation sequence but can be anything if you don't want to use animation.
I don't think it allocates resources for animation as it doesn't have to be loaded as animation. As a drawable it is rendered as it's initial state and should be put in the drawable resource folder.
To use it as an animation you should put it in anim resource folder and can start the animation like this (just an example):
Animation rotation = AnimationUtils.loadAnimation(this, R.anim.rotation);
rotation.setRepeatCount(Animation.INFINITE);
myView.startAnimation(rotation);
I could rotate left arrow right in XML as:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="180"
android:toDegrees="0"
android:drawable="#drawable/left">
</rotate>
Attached image for reference.
If vector based drawables are used, in conjunction with an ImageView, style, and color state list, your button can be refactored as follows:
Note: Vector drawables are significantly smaller than images, so extra, explicit definitions don't incur much overhead, and makes for clear, explicit code (although I've read that hand modifying vector assets should be avoided, I'd rather deal with the overhead of updating a couple of files than having transformations on one):
Note: Android Studio is a great source for vector assets.
res\values\styles.xml
<!--ImageView-->
<style name="Details_Buttons_Top_Left_Button">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:tint">#color/button_csl</item>
</style>
res\color\button_csl.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="#color/grey_disabled"/>
<item android:state_pressed="true" android:color="#color/orange_hilite"/>
<item android:color="#color/black"/>
</selector>
details_menu_large_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/and_card_details_button_down_left_onclick" /> <!-- pressed -->
<item android:drawable="#drawable/and_card_details_button_down_left" /> <!-- default -->
</selector>
Details_Buttons_Top_Left_Button
<ImageView android:id="#+id/Details_Buttons_Top_Left_Button"
style="#style/Details_Buttons_Top_Left_Button"
android:src="#drawable/details_menu_large_button" />
and_card_details_button_down_left.xml (ic_play_arrow_black_24dp.xml)
<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="#FF000000"
android:pathData="M8,5v14l11,-7z"/>
</vector>
and_card_details_button_down_left_onclick.xml (ic_play_arrow_black_24dp.xml modified)
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<group android:name="rotationGroup"
android:pivotX="12"
android:pivotY="12"
android:rotation="90" >
<path
android:fillColor="#FF000000"
android:pathData="M8,5v14l11,-7z"/>
</group>
</vector>
If you want to rotation drawable in xml file then simple add android:rotation="180" in ImageView
<ImageView
android:id="#+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_dropdown"
android:rotation="180"/>
Programatically
val image = findViewById(R.id.imageview)
image.rotation = 180f

Categories

Resources