Currently I'm developing a Android application. I want to make a text (a header) with a background that looks like this:
_______
/______/
I have the following code:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#color/jaarkleur"
android:centerColor="#color/jaarkleur"
android:endColor="#E66C2C00"
android:angle="0" />
<stroke android:width="1dp"
android:color="#ff000000"
/>
</shape>
</item>
<item>
<bitmap android:src="#drawable/overlay_left" android:gravity="left" />
</item>
<item>
<bitmap android:src="#drawable/overlay_right" android:gravity="right" />
</item>
</layer-list>
So I made to images so with a transparant triangle which are placed at both ends.
This works fine for headers with only one line, but when a header takes up two lines it looks like this:
So my question is: Is it possible to resize both images so looks correctly?
Thank you!
I solved it using two (half-transparant) images which represent the corners.
The XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#color/jaarkleur"
android:centerColor="#color/jaarkleur"
android:endColor="#E66C2C00"
android:angle="0" />
<stroke android:width="1dp"
android:color="#ff000000"
/>
</shape>
</item>
<item>
<bitmap android:src="#drawable/overlay_left" android:gravity="left|top" />
</item>
<item>
<bitmap android:src="#drawable/overlay_right" android:gravity="right|bottom" />
</item>
</layer-list>
Instead of using a layer-list with gradient / border stroke and a custom image, consider using a NinePatchDrawable.
There is also a handy 9-patch creater that comes with the android SDK.
Related
I googled a lot and spent many hours trying to figure out how to create custom Android UI widgets (in code and xml). But there are some limitations I don't know how to bypass. Therefore I mocked up an imaginary button and would like to know how to implement it.
This would help me a lot and I'm sure that I'm not the only one that has problems creating custom Android widgets.
About the multi-colored background, I was successful at these using shape drawables.
For example to define a grey solid zone, then a gradient transitioning to black, and a black solid zone:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<corners android:radius="10px" />
<solid android:color="#FF444444"/>
</shape>
</item>
<item
android:left="45dp">
<shape android:shape="rectangle">
<gradient
android:angle="0"
android:centerX="15%"
android:startColor="#FF444444"
android:centerColor="#FF000000"
android:endColor="#FF000000"
android:type="linear"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<corners android:radius="10px" />
<stroke
android:width="2px"
android:color="#FF444444" />
<solid android:color="#00000000"/>
</shape>
</item>
</layer-list>
The cool thing here is the layered shapes (items). It should allow you to define a yellow triangle, a red triangle, and a green rectangle.
The above layout renders into the following:
(the icons and text not being rendered by the above layout)
If you choose to create a custom widget I recommend to check out a most similar standard widget from the android sources and modify them
Create a shape for background:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/GREEN"/>
<stroke
android:width="2dp"
android:color="#color/GREEN"/>
</shape>
Then Create a shape with layer-list that show your image:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/GREEN"/>
</shape>
</item>
<item
android:left="15dp"
android:top="15dp"
android:right="15dp"
android:bottom="15dp"
android:drawable="#drawable/ic_image" />
</layer-list>
Finally, you can use above shapes in a button:
<Button
android:id="#+id/btnFavorite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_below="#id/btnWorkout"
android:background="#drawable/selector_main_button"
android:drawableRight="#drawable/shape_favorite"
android:gravity="center"
android:text="#string/favorite"
android:textSize="#dimen/font_7"
android:textColor="#color/ORANGE"
android:textStyle="bold"
android:onClick="onClick"/>
Even, it should mentioned that you can use first shape as a selector.
I have a simple aim. I want a light grey background on my FrameLayout with a black dividing line underneath it (only undernearth, not all around). So far I have this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" android:gravity="center">
<solid android:color="#EEEEEE" />
</shape>
</item>
<item>
<shape android:shape="line" android:gravity="bottom" >
<stroke android:width="1dip" android:color="#010101"/>
</shape>
</item>
</layer-list>
But it draws the line through the centre, i.e. ignores the gravity='bottom' bit. How can I fix this?
EDIT: This question is very old. The selected answer may or may not be in-line with current APIs, etc. You are encouraged to start your own question rather than add to this one, which is no longer monitored.
I've struggled a lot with this as well. Basically, to create a border at the bottom, you have to think in opposite direction from what you expect. You start with a rectangle with your Border color. On top of that, you draw the actual color, with an offset from the bottom.
I use this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- CREATE A RECTANGLE WITH YOUR BORDER COLOR -->
<item>
<shape android:shape="rectangle" >
<solid android:color="#fff"/>
</shape>
</item>
<!-- NOW DEFINE THE NORMAL COLOR-->
<item android:bottom="BOTTOM_BORDER_THICKNESS E.G. 4dp">
<shape android:shape="rectangle" >
<solid android:color="#ccc"/>
</shape>
</item>
</layer-list>
Or, as Juan Pablo Saraceno suggested :
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<color android:color="YOUR_BORDER_COLOR" />
</item>
<item android:top="YOUR_BORDER_THICKNESS">
<color android:color="YOUR_BG_COLOR" />
</item>
</layer-list>
Unfortunately I have not found a way to get the gravity working for drawables, but I found how you can achieve what you want with pure xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-2dp"
android:left="-2dp"
android:right="0dp"
android:bottom="1dp"
>
<shape android:shape="rectangle">
<solid android:color="#EEEEEE"/>
<stroke android:width="1dp" android:color="#010101"/>
</shape>
</item>
</layer-list>
Good luck:)
I'd recommend using a nine-patch image for this - here's an example that should do the job:
(It's only tiny but it is there!)
If you place this in your drawable folder and set your FrameLayout's background to it then you should get the desired result. The content will go in the grey area and the #010101 pixel will be stretched horizontally to form a line at the bottom. Just make sure to keep the .9.png extension to ensure it gets loaded as a nine-patch.
Hope that helps you
This works!
<item>
<bitmap
android:gravity="left|bottom"
android:src="#drawable/myDrawable" />
</item>
I know it's pretty old question but given answers didn't work for me. Turns out in order to gravity property work you just need to add size tag in drawable item.
So following will work as expected:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:gravity="center">
<shape android:shape="rectangle">
<solid android:color="#EEEEEE" />
</shape>
</item>
<item
android:gravity="bottom">
<shape android:shape="line">
<size android:height="2dp"/>
<stroke android:width="1dip" android:color="#010101"/>
</shape>
</item>
</layer-list>
ps. this feature added in api level 23
https://developer.android.com/reference/android/graphics/drawable/LayerDrawable#setLayerGravity%28int,%20int%29
<?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:bottom="5dp">
<shape android:shape="rectangle" >
<solid android:color="#color/White" />
</shape>
</item>
</layer-list>
Well, it's pretty old question, but none of the answers seem to answer the actual question (how to make gravity working) so here's a working example:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="#2196F3"/> <!-- Background color -->
</item>
<item android:gravity="bottom">
<shape>
<size android:height="10dp" /> <!-- I would suggest 1dp -->
<solid android:color="#F50057" /> <!-- Line color -->
</shape>
</item>
</layer-list>
By analogy, if you want to use gravity left or right change attribute height to width
I’m attempting to create a layout border with corners that are square on the outside and round on the inside. I’ve gathered that I need to create an .xml drawable definition composed of two shapes: one with a stroke width and corner radius and another with a stroke width only:
The drawables
round_border.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="4dp" android:color="#FF000000" />
<padding android:left="7dp" android:top="7dp"
android:right="7dp" android:bottom="7dp" />
<corners android:radius="4dp" />
<solid android:color="#FFC0C0C0" />
</shape>
square_border.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp" android:color="#FF000000" />
<solid android:color="#FFC0C0C0" />
</shape>
Each of these works independantly as a border when appliedby itself like so:
android:background="#drawable/round_border"
but when they either or both are added to an item-list drawable like so:
composite_border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<layer-list>
<item android:drawable="#drawable/round_border"/>
<!-- <item android:drawable="#drawable/square_border"/> -->
</layer-list>
</shape>
and:
android:background="#drawable/composite_border"
The layout's background is completely black instead of just a black border.
Does anyone know how to make the layer list work for this task?
From Shape Drawable Doc you can see that shape can't have layer-list inside so you should define your composite_border.xml like this
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/square_border"/>
<item android:drawable="#drawable/round_border"/>
</layer-list>
note that I changed the order of your items inside the layer-list as stated in the documentation of layer-list
Each drawable in the list is drawn in the order of the list—the last drawable in the list is drawn on top and you want it to be squared from outside
Try this will work fine enough:
solid is background color
stroke is border
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#color/white"/>
<stroke android:width="1dp" android:color="#ffaaaaaa" />
<size
android:width="15dp"
android:height="15dp"/>
</shape>
Create a xml file like round_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#CCCC33"/>
<size
android:width="35dp"
android:height="35dp"/>
</shape>
In the layout set as background
<LinearLayout
android:id="#+id/layout_wellbeing"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:background="#drawable/rounded_corner_leuvan"
android:orientation="horizontal" >
</LinearLayout>
square_border.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp"
android:color="#FF000000"
/>
<solid android:color="#FFC0C0C0" />
</shape>
composite_border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<layer-list>
<item android:drawable="#drawable/round_border"/>
<!-- <item android:drawable="#drawable/square_border"/> -->
</layer-list>
</shape>
watch out the comments and the quotation marks! =]
What I'm trying to do is define a common background for use in a LinearLayout which frequents my application on many of its Activitys. This particular layout is a header that shows on the top of each activity.
What I'm trying to do is create a drawable that fills the linearlayout with a gradient and has a horizontal line below the gradient.
Does anyone know if this is possible or do I have to do this sort of thing only with nested layouts.
My attemptat the drawable xml is
<selector 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:startColor="#AA000000" android:endColor="#AA333333"
android:angle="270" />
</shape>
</item>
<item>
<shape android:shape="line">
<stroke android:width="3dp" android:color="#FFFFFFFF"
android:dashWidth="1dp" android:dashGap="2dp" />
<size android:height="5dp" />
</shape>
</item>
</selector>
Drawable accepts multiple shapes, (defined always in others files) if i understand your question maybe you can do a Layer drawable (this draws multiple underlying drawables on top of each other)
i write this here, so, i dont tested, but try this and read this fantastic documentation.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/shape_7"/>
<item android:drawable="#drawable/shape_1"/>
</layer-list>
the android complete xml resources
cheers
Use gravity to set your items in layer-list.
for vertical orientation use:
android:gravity="top"
android:gravity="center"
android:gravity="bottom"
for horizontal orientation use:
android:gravity="left"
android:gravity="center"
android:gravity="right"
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:src="#drawable/top_img"
android:gravity="top"/>
</item>
<item>
<bitmap
android:src="#drawable/center_img"
android:gravity="center"/>
</item>
<item>
<bitmap
android:src="#drawable/bottom_img"
android:gravity="bottom"/>
</item>
</layer-list>
Be sure that the parent element has enough space to hold all the items!
Otherwise they will overlap each other
I'm creating a custom progress bar (positioned under a WebView) and what I would like to draw is a 1dp-wide line between the WebView and the ProgressBar. I'm modifying existing drawable, namely progress_horizontal.xml, and tried 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="line">
<stroke android:width="1dp" android:color="#FF000000" />
</shape>
</item>
</layer-list>
This line however is vertically centered but I want it to be drawn on top of the drawable. The only idea I could come up with is to use this "hacky" gradient below:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
(...)
<item>
<shape>
<gradient
android:startColor="#FF000000"
android:centerColor="#00000000"
android:centerY="0.01"
android:endColor="#00000000"
android:angle="270"
/>
</shape>
</item>
</layer-list>
Do you have better ideas how to draw a single line shape aligned to the top of the drawable defined with layer-list?
I spent a while trying to figure this out as well. Hopefully there is a better way to do it but here is the method I used, which is also kind of hackish, but in case it helps someone, I thought I would share.
The first item in your layer list should be a solid of whatever color you want to be your border. Following that would be the thing(s) you want to have the border, with padding on whatever side you want the border to be on.
For example:
<?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="YOUR BORDER COLOR" />
</shape>
</item>
<item android:top="YOUR TOP BORDER THICKNESS">
THE THING YOU WANT A BORDER ON
</item>
</layer-list>
The idea is that the padding on the item reveals the solid shape behind it, giving the border appearance. You could add padding to any side to add a border. I imagine you could get more complicated and have different colored borders this way as well.
Seems like a hack but it worked for me.
EDIT: I said "padding" but in layer-lists it's more of an offset.
i was going through all related topics but no one could solve my problem. But some of them were very useful to understand how the layer-list or shape parameters work.
My problem was to define a button with a linear gradient and draw a top and a bottom line in different colors. After all I hacked this solution. I saved the file unter res/drawable/blue_btn.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<solid android:color="#color/blue_end" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
<stroke
android:width="1dp"
android:color="#color/bottomline_btn" />
</shape>
</item>
<item>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="#color/blue" />
<gradient
android:startColor="#color/blue"
android:endColor="#color/blue_end"
android:angle="270" />
</shape>
</item>
<item android:top="0dp" android:bottom="-1dp" android:left="-1dp" android:right="-1dp">
<shape android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/topline_btn" />
<solid android:color="#00000000" />
<corners android:radius="0dp" />
</shape>
</item>
<item android:top="-1dp" android:bottom="0dp" android:left="-1dp" android:right="-1dp">
<shape android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/bottomline_btn" />
<solid android:color="#00000000" />
<corners android:radius="0dp" />
</shape>
</item>
</layer-list>
</item>
</selector>
<color name="topline_btn">#31ffffff</color>
<color name="bottomline_btn">#31000000</color>
<color name="blue">#449def</color>
<color name="blue_end">#2f6699</color>
Did you try offsetting it by something like this
http://android.amberfog.com/?p=9
My solution is to add 9-patch as the last layer item :
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<solid android:color="#color/tab_button_active_layer2" />
</shape>
</item>
<item android:bottom="#dimen/tab_button_active_bottom_bar_width">
<shape>
<solid android:color="#color/tab_button_active_layer1" />
</shape>
</item>
<!-- 9-patch drawable -->
<item android:drawable="#drawable/tab_button_border_top"/>
</layer-list>