How to auto mirror a shape in Android XML - android

I have a custom card like shape as below.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?attr/colorListItemBackground" />
<corners
android:bottomLeftRadius="16dp"
android:topLeftRadius="16dp" />
</shape>
My app also supports RTL languages, thus changing to RTL, this shape does not change(Auto Mirror).
What changes can I do to make it an auto mirror?
Notice the rounded corners near the circle.
LTR_Image
The rounded corners still in the same place.
RTL_Image

You can have define custom shape inside
res/
drawable
drawable-ldltr
drawable-ldrtl
Now put the mirrored custom shape inside drawable-ldrtl and it should work.
Your custom shape xml should be exactly opposite i.e.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?attr/colorListItemBackground" />
<corners
android:bottomRightRadius="16dp"
android:topRightRadius="16dp" />
</shape>
You can alternatively add android:autoMirrored="true" to your vector drawable which should auto mirror it. But this requires you to have a vector image as per documentation : https://developer.android.com/reference/android/graphics/drawable/VectorDrawable
Hence a shortcut is to wrap your shape around with a vector drawable
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/your_shape"
android:autoMirrored="true"/>
Let me know if this works for you.

Related

How to create shapes on drawable layout android

I need to create a layout that will be with rounded corners, but in which there will be various shapes.
I have a sample (in the screenshot below). I created a layout with rounded corners and the right color, but I don’t know if I can create a few more shapes on it (these shapes are dark in the screenshot) and if I can place them where I want?
My code for background shape:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/purple_light" />
<corners android:radius="16dp" />
</shape>
You can use android layer list drawable. You can refer the docs here.
You have 2 choices:
1- Export the complete shape as a vector (SVG) and import it into Android Studio.
Then you can use this shape wherever you want.
(Whole purple background with triangle shaped inside of it)
2- Trying to draw that shape on Android Studio.
You have to do something like this:
<?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/purple_200" />
<corners android:radius="1dp" />
</shape>
</item>
<item android:drawable="#drawable/ic_baseline_square_24"/>
<item android:drawable="#drawable/ic_baseline_triangle"/>
</layer-list>
But you need to completely design shapes with the drawable.
I tried quickly just for showing you the result:
Sample output

Creating Android Shape with rounded corners and shadow and custom image

I'm trying to create a shape for ImageView that would have round corners, the actual image and a shadow. When I created a shape and set the following variables then I got myself a rounded image with some shadow:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#42000000" />
<corners android:radius="5dp" />
</shape>
Now when I tried to add my custom image (like many people suggested I used Layer-list I got the image but the rounded corners and shadow was gone :
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#42000000" />
<corners android:radius="5dp" />
</shape>
</item>
<item android:drawable="#drawable/no_cover_art" />
</layer-list>
Also I will be changing``Images` programatically so maybe that is also something that needs to be mentioned.
What am I doing wrong and how do I get the rounded corners with shadows and custom image?
EDIT
I have tried using only the shape as a drawable, but I get a result where it applies the corners to something behind it and does not change the ImageView itself.
<ImageView
android:id="#+id/song_album_cover"
android:layout_width="64dp"
android:layout_height="68dp"
android:layout_marginStart="8dp"
android:layout_marginTop="6dp"
android:elevation="18dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/no_cover_art"
android:background="#drawable/artist_cover_image"/>
On the left side is a picture of what Android Studio shows me and on the right side is the image from when I actually run the app.
Use the drawable as the background for the image view and then set the src to whatever image you want.
/use need to use this below thing in the imageview and put your code in the drawable file and then add in the below way/
android:background="#drawable/nameofdrawablefile"

Apply ripple effect on click of a relative layout which already has a background XML

I am trying to implement a ripple effect on click of a relative layout which already has a background XML. But how can I do this? If I want to add the ripple effect to the relative layout then I must change the tag in the background XML to <ripple></ripple>, but when I do this I lose the corner radius and solid color that I had given for the relative layout.
Below is the code of the relative layout:
<RelativeLayout
android:layout_width="400dp"
android:layout_height="100dp"
android:background="#drawable/roundedcorners">
</RelativeLayout>
Below is the code in the background XML "roundedcorners"
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#000000"/>
<corners
android:radius="25dp"/>
</shape>
I looked out for posts for the same but did not find one, as the posts had just the information on how to achieve the ripple effect, but not on how to merge and use the ripple effect, scale, or shape tags together.
The solution for this lies in the special mask layer of the RippleDrawable. You specify the mask layer via the android:id value set to #android:id/mask.
For the example below, you can set the mask to the same size/shape as the view you’re masking, and then the ripple will only show for that area. Do something like this:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="#android:id/mask">
<shape
android:shape="rectangle">
<solid android:color="#000000"/>
<corners
android:radius="25dp"/>
</shape>
</item>
<item android:drawable="#drawable/rounded_corners" />
</ripple>
now you can set it as your android:background

How to layout view correctly after stroke of background drawable changed?

What I have:
I have a LinearLayout which contains Views with a background Drawable (rectangular shape with rounded corners and a stroke). They act as color selection buttons. Initially the first button has a background with a thicker stroke (4px instead of 1px). Everything is nice (see left side of picture below).
What I want:
However, when I press such a button, I want to remove the thick stroke from the previously selected button and apply it to the actual button. I try it the following way (only a snippet):
// get layout
LinearLayout favoriteColorsLayout = (LinearLayout) findViewById(R.id.favoriteColorsLayout);
// get view at old position, update stroke, invalidate
View view = favoriteColorsLayout.getChildAt(selectedColorButton);
GradientDrawable drawable = (GradientDrawable) view.getBackground();
drawable.setStroke(1, Color.parseColor("#bbbbbb"));
view.invalidate(); // do I need this?
// also update stroke of new view
..
// re-layout
favoriteColorsLayout.requestLayout(); // do I need this?
What I see:
And indeed the thicker stroke is moved but unfortunately the layout is wrong afterwards! The colored background of buttons 2-4 should become thinner when the stroke surrounding them gets thicker so that they are still fitting into the containing layout but this does not happen (see right side of picture below). Instead the stroke is partially cut off (because otherwise it would be drawn outside the bounds of the View). This is not a desired effect.
What do I have to do to get the desired effect instead?
I know how many buttons of which color I have only at runtime, so I would prefer a programmatic solution.
Actually I'm beginning to think it could be an Android bug since drawing the stroke outside the borders per default is surely not desired behavior. I see the effect on the emulator and API level 23 as well as my old phone with API level 11.
A bit of layout xml. The linear layout (Views are added programmatically):
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:id="#+id/favoriteColorsLayout"></LinearLayout>
The button Views:
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="#dimen/color_selection_button_size"
android:layout_height="#dimen/color_selection_button_size"
android:layout_margin="#dimen/color_selection_button_margin"
android:layout_gravity="center"
android:background="#drawable/color_selection_cell_background">
</View>
The buttons background drawable (color_selection_cell_background.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<stroke
android:width="1px"
android:color="#bbbbbb"/>
<corners
android:radius="5px" />
<gradient
android:angle="90"
android:centerX="0.5"
android:centerY="0.5"
android:startColor="#aaaaaa"
android:endColor="#bbbbbb"
android:type="linear" />
</shape>
Not sure why you are doing it in code but why not have two drawables and change those?
button_blue_selected.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/blue_500" />
<stroke android:width="4dp" android:color="#color/grey_500" />
<corners android:radius="5dp" />
</shape>
button_blue_unselected.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/blue_500" />
<stroke android:width="1dp" android:color="#color/grey_500" />
<corners android:radius="5dp" />
</shape>
Then update the background drawable in your code:
View view = favoriteColorsLayout.getChildAt(selectedColorButton);
view.setBackgroundResource(R.drawable.button_blue_selected);
Or even better you could use a third drawable with state so you didn't need to update it directly in code:
button_blue.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#drawable/button_blue_selected" />
<item android:drawable="#drawable/button_blue_unselected" />
</selector>
And then:
view.setSelected(true);

Layerlist not showing items correctly Android

I've got two shape drawable xml files that I am using on imagebuttons. One contains a ring, the other contains an oval small enough to fit into the larger ring, similar to a radiobutton. In this image http://imgur.com/mYPALoT you can see (from left to right) the ring, the smaller middle oval, and the combined image showing the layerlist view of both together. This doesn't work and instead shows a complete filled in oval.
Here is the ring xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="3"
android:thickness="1dp"
android:useLevel="false">
<solid android:color="#1976D2" />
<size
android:height="20dp"
android:width="20dp" />
</shape>
Here is the oval xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#1976D2" />
<size
android:height="7dp"
android:width="7dp" />
</shape>
Here is the layerlist xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ring_select" />
<item android:drawable="#drawable/ring_center" />
</layer-list>
I'm not familiar with layerlists as I am new to android. What am I doing wrong?
In case another person descends upon this page by the guiding of the knowledegable Google...
I have a workaround that may or may not work for you: instead of using <scale> , try <inset>. You can use a combination of the <item>'s android:top / android:bottom / android:left / android:right and the <inset>'s android:insetXXX to size the image
You can do things like set the sides of each inset value relative to your source image's dimensions. For example, if you have a 64 pixel-wide image and want to cut it down by 50%, you can do (64 / 4 = 16) for each side
I finally found the answer. Basically, the oval in front needs to have this added to it's line:
<item android:top="10dp" android:bottom="10dp" android:left="10dp" android:right="10dp">
The dimensions need to be the same since this is an oval. I'm still not sure why the oval stretched to the entire size of the ring, especially since the size was defined. If anyone has any idea why the top oval stretched like that, please let me know.

Categories

Resources