I recently made my first custom shape and it turned out really good accept one thing. i can't seem to set the height and with of the drawable resource in a style resource.
I do not specify a height or width in på shape because i want to use this shape in different sizes. So i set height and width in my styles.xml file. But the final result is what looks like the shape using wrap_content as both height and width which i do not want.
Any help is greatly appreciated!
SHAPE - list_item.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/list_item_background"
/>
</shape>
</item>
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="270"
android:startColor="#color/list_item_gradient_white"
android:endColor="#color/list_item_gradient_black"
android:type="linear"
/>
<stroke
android:color="#color/list_item_stroke"
android:width="1px"
/>
</shape>
</item>
STYLE
<style name="SmallListItem">
<item name="android:background">#drawable/list_item</item>
<item name="android:layout_height">69.5dip</item>
<item name="android:layout_width">fill_parent</item>
</style>
Try something like this:
<ImageView
style="#style/SmallListItem"
android:src="#drawable/list_item" />
See http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList for more information on how to use your layer-list
Related
Hi I am trying to create a background drawable for my splash screen which I'll be setting in theme itself. But the bitmap drawable used to keep in the center is getting stretched and I am not able to figure how to keep it normal. Below is my drawable code:
splash_screen_bg.xml
<?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">
<gradient
android:angle="360"
android:centerColor="#color/colorAccentXDark"
android:endColor="#color/Black"
android:gradientRadius="500dp"
android:startColor="#color/colorAccentXDark"
android:type="radial"
android:useLevel="false" />
</shape>
</item>
<item
android:bottom="50dp"
android:top="50dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="500dp"
android:innerRadiusRatio="1"
android:shape="oval">
<gradient
android:angle="360"
android:centerColor="#color/colorAccentXDark"
android:endColor="#color/colorAccentXDark"
android:gradientRadius="400dp"
android:startColor="#color/colorAccent"
android:type="radial"
android:useLevel="false" />
</shape>
</item>
<item android:gravity="center">
<bitmap android:src="#drawable/ty_logo" />
</item>
</layer-list>
Here is code where I am setting this drawable as background of an activity:
<style name="TYTheme" parent="SearchActivityTheme.NoActionBar">
<item name="colorPrimaryDark">#color/colorAccentXDark</item>
<item name="android:alertDialogTheme">#style/AlertDialogTheme</item>
<item name="android:windowBackground">#drawable/splash_screen_bg</item>
</style>
So here the bitmap drawable ty_logo is an png is getting stretched in my phone. Since there is no scaleType option with bitmapDrawable I don't know how to handle it.
Add gravity to your bitmap set to center.
<item android:gravity="center">
<bitmap android:src="#drawable/ty_logo"
android:gravity="center" />
</item>
I hope that ty_logo is of suitable pixels and you have provided different pixels image for various device screens (ldpi, mdpi, hdpi, xhdpi, etc).
If not, do go through this answer to a similar problem you find yourself in : Resize images in bitmap in xml
Otherwise, this can be easily solved if your target version is for API 23 as <item> has width,height,gravity attributes provided for them.
And if not, the following code should work, using gravity attribute for bitmap. Again, this is going by the assumption that your logo is not having more pixels than resolution of the devices.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
...
<item>
<bitmap android:src="#drawable/ty_logo"
android:gravity="center" />
</item>
...
</layer-list>
You can wrap bitmap inside ScaleDrawable <scale> and use ScaleDrawable inside LayerListDrawable.
<item android:gravity="center">
<scale android:drawable="#drawable/ty_logo"
android:scaleHeight="80%"
android:scaleWidth="80%" >
</scale>
</item>
The thumb for my Switch-button seems to get skewed(for on&off state). There were similar problems on github, but those were for people making libraries to support Switch button in API 4.0-
main contains the switch-button, and there is a thumb and track drawable applied to it
This is what is happening:
This is how its suppose to loook:
switch_track_on.png
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Switch
android:id="#+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="112dp"
android:thumb="#drawable/switch_thumb_selector"
android:track="#drawable/switch_track_selector"
android:textOn=""
android:textOff=""/>
</RelativeLayout>
switch_thumb_selector.xml
<selector>
<item android:drawable="#drawable/switch_thumb">
</item>
</selector>
switch_track_selector.xml
<selector>
<item android:drawable="#drawable/switch_track_on" android:state_checked="true"/>
<item android:drawable="#drawable/switch_track_off" android:state_checked="false"/>
</selector>
For Custom Switch (Like IOS switch) I tried below Steps:
Create a drawable track_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape android:dither="true" android:shape="rectangle" android:useLevel="false" android:visible="true">
<solid android:color="#ca120f" />
<corners android:radius="25dp" />
<size android:width="2dp" android:height="18dp" />
</shape>
</item>
<item android:state_checked="false">
<shape android:dither="true" android:shape="rectangle" android:useLevel="false" android:visible="true">
<solid android:color="#27170432" />
<corners android:radius="25dp" />
<size android:width="2dp" android:height="18dp" />
</shape>
</item>
</selector>
Create a drawable thumb_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false">
<shape android:dither="true" android:shape="rectangle" android:useLevel="false" android:visible="true">
<solid android:color="#ffffff" />
<corners android:radius="100dp" />
<size android:width="24dp" android:height="25dp" />
<stroke android:width="4dp" android:color="#0000ffff" />
</shape>
</item>
</selector>
In your layout :
<Switch
android:id="#+id/checkboxAttendanceSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:thumb="#drawable/thumb_selector"
app:track="#drawable/track_selector" />
Its working fine for me.
I had the same requirement. I checked Android code and found that
switch ignores any vertical margin/padding applied to a thumb shape drawable (thus thumb always touch the top and bottom of the track)
the width of the thumb is calculated by taking the horizontal paddings + the max width of the on and off texts.
This makes really hard to make a circle thumb.
But if you specify the thumb drawable as a layer drawable for the sole reason to be able to specify padding for the single layer of the drawable, you can get the desired effect.
Thumb selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<!--
NOTE
We want a thumb with padding around it inside the track.
Sadly, a switch draws its track and thumb with the same height ignoring
any padding of the drawable, so using a shape with padding does not work.
To overcome, we apply a trick. We create layer list because the
LayerListDrawable draws itself with taking the top, left, right, bottom
values into account.
-->
<layer-list>
<item
android:top="#dimen/switch_thumb_padding"
android:left="#dimen/switch_thumb_padding"
android:right="#dimen/switch_thumb_padding"
android:bottom="#dimen/switch_thumb_padding">
<!--
NOTE
No need to specify size because:
- The thumb fills the track in height.
- The thumb width is determined from thumb max(on, off) text +
text padding + drawable padding.
-->
<shape android:shape="oval">
<solid android:color="#color/switch_thumb"/>
<!-- NOTE did not work, had to set Switch's thumbTextPadding to the radius -->
<!--
<padding android:right="#dimen/switch_thumb_radius"
android:left="#dimen/switch_thumb_radius"/>
-->
</shape>
</item>
</layer-list>
</item>
</selector>
I set the on and off text of switch to empty (actually to "" to prevent warning about empty resource).
track:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false">
<shape android:shape="rectangle">
<size android:height="#dimen/switch_track_height"/>
<corners android:radius="#dimen/switch_thumb_radius"/>
<solid android:color="#color/switch_track_off"/>
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<size android:height="#dimen/switch_track_height"/>
<corners android:radius="#dimen/switch_thumb_radius"/>
<solid android:color="#color/switch_track_on"/>
</shape>
</item>
</selector>
Switch style:
<style name="CustomSwitch">
<!-- NOTE this way the switch will be as width as required minimally -->
<item name="android:switchMinWidth">0dp</item>
<item name="android:track">#drawable/switch_track</item>
<item name="android:thumb">#drawable/switch_thumb</item>
<item name="android:textOff">#string/switch_thumb_off</item>
<item name="android:textOn">#string/switch_thumb_on</item>
<!-- NOTE if set to 0dp, the thumb was not visible even with padding
of the thumb drawable set to -->
<item name="android:thumbTextPadding">#dimen/switch_thumb_radius</item>-->
<!--<item name="android:thumbTextPadding">0dp</item>-->
</style>
And finally, the dimens:
<dimen name="switch_track_height">30dp</dimen>
<dimen name="switch_thumb_radius">15dp</dimen>
<dimen name="switch_thumb_padding">2dp</dimen>
So the only 'tricky' thing is to keep height = radius * 2.
No clue why this happens but solved it by placing the Switch-button within a linearLayout.
There must be some propery(width) of the thumb that has a "match_parent" of some sort that must've been causing it.
Edit: It happens when I remove the default 'ON' and 'OFF' text. So to hide the text i changed its color to white.
How to change textcolor of switch in Android
main.java
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.toggle_button);
Switch sw = (Switch) findViewById(R.id.switch1);
//Both of these need to be used to change the text color to white
sw.setTextColor(Color.WHITE);
sw.setSwitchTextAppearance(this, Color.WHITE);
//Doing this would skew the circle
//sw.setTextOn(" ");
//sw.setTextOff(" ");
}
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="70dp" >
<Switch
android:id="#+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumb="#drawable/switch_thumb_selector"
android:track="#drawable/switch_track_selector" />
</LinearLayout>
You can always horizontally stretch the graphic itself (ie, "switch_thumb.png") if you can't use the other answers.
If you use the original software used to design the graphic and re-export it after stretching, it shouldn't cause blurring of the image. You'll have to eye-ball it for your dimensions, but starting at +30% stretching should get you close.
I am trying to draw border in one side only to ImageButton object,
like in CSS: border-left: 2px solid black;.
Is there any way to do that with style only? (Without inserting a blank view between them)
Thank you!
EDIT:
I used the <selector> tag with the ImageButton.
After alot of searching, I found way to do that.
Create xml file that containce the border style (border_style.xml):
<?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">
<!-- The border color -->
<solid android:color="#000" />
</shape>
</item>
<item android:left="1dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
<!-- The fill color-->
</shape>
</item>
</layer-list>
then in the selector, you write like that:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<!-- Press Event -->
</item>
<item android:state_focused="true">
<!-- Focuse Event -->
</item>
<item android:drawable="#drawable/border_style.xml" />
</selector>
You do not able to do like css. You need to create a xml and put the xml in android drable folder and send the image-button background
And rectangle drawable back.xml (put into res/drawable folder):
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#ffffff" />
<stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
I have a very simple shape that I want to set the width of:
<shape android:shape="rectangle">
<solid android:color="#color/orange"/>
<size android:width="2dp"/>
</shape>
However, when I assign this to the background of a EditText it just shows an orange background instead of a rectangle of width 2dp. Why isn't setting the size working? I want to create a transparent drawable with a orange rectangle on the left side. I also have this wrapped in a selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="#color/orange"/>
<size android:width="2dp" android:height="6dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#android:color/transparent"/>
</shape>
</item>
</selector>
I've tried adding height just to see if it would change the size. It doesn't. It's like its completely ignoring the size. WTF?
For me, setting the gravity of the item to "center" solved the issue.
For example:
<item android:id="#android:id/progress" android:gravity="center">
<clip>
<shape>
<size android:height="2dp"/>
<solid android:color="#color/my_color"/>
</shape>
</clip>
</item>
It can work with a foreground. It seems like you can't set a background's gravity. But you can on a foreground. I checked API 21, 23 and 24 (well, with the Studio design preview) and the following places a solid circle dot on the ImageView.
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/colorPrimary" />
<size android:height="8dp" android:width="8dp" />
</shape>
With the layout snippet
<ImageView
android:foreground="#drawable/list_new_dot"
android:foregroundGravity="right|center_vertical"
tools:src="#drawable/model_1_sm"
/>
UPDATE: While it appears to work in the layout design tool, it doesn't look the same in the emulator. UPDATE 2: Since this answer has a few votes, you might want to check what I actually used in order to show a new indicator dot:
https://gist.github.com/CapnSpellcheck/4d4638aefd085c703b9d990a21ddc1eb
Just to specify the user983447's answer - the size attribute does really mean a proportion. You should set the size for all shapes in your layer-list and it'll be used a as a proportion when scaling - like the layout_weight attribute of LinearLayout. So it's better to name it not a size but a weight
Below is a work-around how to implement top and bottom white lines without using the size attribute:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#fff" />
</shape>
</item>
<item android:top="1dp" android:bottom="1dp">
<shape>
<solid android:color="#888" />
</shape>
</item>
</layer-list>
I found the layer-list to be very devious for a first time Androider because of the following. At first glance most would think item top,bottom,right,left attributes are FROM the top,bottom,right,left. Where a value of the following:
<item android:top="10dp">
Would net you a starting point 10dp from the top of the respective container. This is not the case. Think of it as OFF OF the top,bottom,right,left. <item android:top="10dp"> will still net you a starting point 10dp OFF OF the top, but what happens when you want to set the bottom?
<item android:bottom="20dp">
This will not get you a bottom at 20dp from the TOP, rather a bottom of 20dp OFF OF the BOTTOM of the container.
So, for example with a 100dp container, if you wanted a rectangle with a top edge starting at 20dp and a bottom edge at 40dp:
<item android:top="20" android:bottom="60dp">
The size of a shape will be ignored when you use it as a background of a View. It will work when you show it via an ImageView:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FF7700" />
<size android:width="20dp" android:height="20dp"/>
</shape>
In your layout XML:
<!-- will have the size of 20dp x 20dp -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_shape"
/>
I had similar problem.
Documentation ( http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape ) says:
<size>
The size of the shape.
(...)
Note: The shape scales to the size of the container View proportionate to the dimensions defined here, by default. When you use the shape in an ImageView, you can restrict scaling by setting the android:scaleType to "center".
If I understand correctly, it means that "size" tag is not for setting size but for setting proportions.
shape's size attribute will provide the value for drawable.getIntrinsicWidth & getIntrinsicHeight.
if the drawable's container(e.g. ImageView, TextView) has the layout param WRAP_CONTENT, then the container dimension will change if the drawable drawingState change.
but there are a bug in android framework in ImageView drawingState implementation
ImageView only update/resize its dimension by the drawable dimension on state_selected but don't on state_activated
used this.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<stroke
android:color="#color/lgray"
android:width="1dip" />
<corners
android:bottomLeftRadius="0dip"
android:bottomRightRadius="0.1dip"
android:topLeftRadius="0dip"
android:topRightRadius="0.1dip" />
<solid android:color="#color/White" />
</shape>
put this rectangle.xml to drawable.and set your view background.
I am trying to create a background drawable for a linearlayout that has multiple gradients.
E.g. I want to have a gradient at the top and bottom, and a solid color in the middle. So basically a header and footer.
I am trying to use a layer-list like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<!--Red-->
<item>
<shape
xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#ff0000" />
</shape>
</item>
<!-- Green -->
<!-- Offsets from the top and bottom -->
<item
android:top="20dp"
android:bottom="20dp">
<shape
xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#00ff00" />
</shape>
</item>
<item
android:top="80dp">
<!--Blue -->
<shape
xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#0000ff" />
</shape>
</item>
</layer-list>
The problem is, I am unsure of the max value of density independant pixels. For this to work, the bottom item offest would need to be (max dp value-20). I have tried to assume the max is 100, and also assume the max is 160 (from the documentation), but neither of these work.
Any ideas?