I want to create a single pixel stroke rectangle, but android is rendering two pixels.
Here is my xml code:
<item>
<shape android:shape="rectangle">
<solid android:color="#FFF" />
<stroke android:width="1px" android:color="#000" />
</shape>
</item>
Here is the top left corner of what is rendered:
My only guess is that this background is not lining up with the device pixels.
So, essentially a line? You could try using something like
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line">
<solid android:color="#FFF" />
<stroke android:width="1px" android:color="#000"/>
</shape>
EDIT: whoops, think I misunderstood. You could always just draw a rectangle using lines though I guess.
px has different meanings on different screen sizes. I'm guessing this is on a bigger screen? Try changing the unit to dp and the anti-aliasing affect should disappear
edit: actually this wont solve your issue if you just want the physical thickness of the line on your screen to be half its current size. It will make it look equivalent on all types of screen though and keep a solid appearance, if that's your complaint
This was caused by the bi-linear filtration introduced in honeycomb and later. There are two solutions:
Disable all hardware acceleration in the manifest (bad idea) with this tag
android:hardwareAccelerated="false"
Use the xml attribute on affected views to render with software only
android:layerType="software"
I found the solution here:
Blurred 1dip shape lines (borders) on Android
Related
How can a achieve a curve like this:
The easiest solution would be to use a VectorDrawable. Create a new drawable
custom_ring.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="700"
android:viewportWidth="700">
<path
android:pathData="M0,0Q350,150,700,0L700,200Q400,300,0,200"
android:strokeColor="#color/colorPrimary"
android:strokeWidth="1"
android:fillColor="#color/colorYellow"/>
</vector>
And then add it as the background for the required view
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/custom_ring" />
Details on VectorDrawables
VectorDrawables are easy enough to understand and it is possible to get simple shapes created within Android Studio itself. For more complex shapes you'd have to resort to other tools to generate SVG files which can later be converted to VectorDrawables in AS.
For details refer to this post to get an idea on how to work with VectorDrawables.
I'll try to give a line by line explanation for the custom_ring.xml file I have used. It is correct to the best of my knowledge though I am open to suggestions and corrections.
Height and Width
Vector drawables are immune to scaling as far as I have observed. The only condition is that the aspect ratio needs to be maintained (I could be wrong here).
When familiarising myself with drawables for the first time, I used to wonder why height and width were required fields. I used to change the values to different values and never observed any change in the preview. It took me longer than truly necessary to realise that this value is required to give the correct dimensions to the view which contains it. For example, if you have an ImageView and set its height and width to wrap_content the ImageView will assume a height and width equal to the value set in the Vector height and width property respectively.
Viewport height and width
I cannot explain better than this image
Setting the viewport as I have in the post makes it possible to actually draw (almost like you'd do with Logo) on a coordinate plane with it's coordinates ranging from (0,0) in the top left corner to (700,700) at the bottom right.
The path
Stroke width: Specifies the width of the outline.
Fill color: Fills the area between the first and last point in the path data with color.
Path data: Probably the most important element and least understood. Please read the post I had linked above. It gives a pretty good explanation.
M0,0 (Moveto instruction) moves the cursor to the coordinate 0,0 without drawing.
Q350,150,700,0 creates a quadratic curve from the current cursor location (which we got by (M0,0)) to (700,0) which is the last 2 parameters of the Q instruction. The first 2 parameters of the Q instruction (350,150) dictate the shape and size of the curve. For example,
<path
android:pathData="M0,0Q350,750,700,0"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
would generate this curve
while
<path
android:pathData="M0,0Q50,750,700,0"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
would render the curve like this. Notice the change caused by changing Q350,700,700,0 to Q50,750,700,0
Changing the 2nd parameter will define the amplitude of the curve.
<path
android:pathData="M0,0Q350,350,700,0"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
will give
L350,350 (Lineto instruction) would draw a line from the current cursor position to the coordinates (350,350)
<path
android:pathData="M0,0L350,350"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
will draw the below line
That's about all the info you need to figure out how I've written the path data for the curve in the question.
First set a shape in xml like this in white color
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="150dp"
android:bottomRightRadius="150dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
<stroke
android:width="0.6dp"
android:color="#color/prefered_color" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="#color/white" />
</shape>
which will produce a shape like this
Again make shape in orange which will be placed under the white shape which will be like
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="150dp"
android:bottomRightRadius="150dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
<stroke
android:width="0.6dp"
android:color="#color/prefered_color" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="#color/orange" />
</shape>
Place Orange shape under the first layout having background in white with some negative MarginTop.
Why is it so difficult to make this little thing work? : /
I want to create something like android's lock screen.
I have an XML:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<stroke
android:width="#dimen/dp_5"
android:color="#color/black" />
<gradient
android:type="radial"
android:startColor="#color/green"
android:endColor="#color/red"
android:gradientRadius="#dimen/dp_50" />
</shape>
This circle is a background of a TextView, so the following happens:
1. wrap_content creates a little circle in the center of the screen
2. fill_parent creates an elipse taking the whole screen, instead of a circle
In addition I would like to change the startColor and endColor programmatically - Didn't find any documentations\threads which solved this SIMPLE issue.
I have a screen with a label on top. This label is done with a TextView.
As a background I'd like to have a vertical gradient, starting with color1, changing to color2 and back to color1.
At the moment I have:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="1px" android:color="#000000" />
<gradient
android:startColor="#FFFFFFFF"
android:centerColor="#FF8800"
android:endColor="#FFFFFFFF"
android:type="linear"
android:angle="270"
/>
<corners android:radius="10dp"/>
</shape>
My problem is that the centerColor line is too thin. I want it to ocupy all the letters space.
I can't find any way to make the gradient to be faster.
I've already tried to use a layout-list but with no success.
Any idea?
This is a much more different track to follow but have you considered working with 9-patch image files? This will allow you to stretch the parts of the gradient that you wish to and make the centre line as big as needed by segmenting up the background properly.
Here are some great tutorials I have used to learn about them:
draw 9 patch tutorial
And from Google's own Android mouth:
Android 9 patch
All Drawable resources for Android
Im trying to achieve a component to make custom shadows to buttons or other components, i know that it will be easier with a 9patch or a png with the shadow, but i want to change it color and size programmatically also in its states (pressed,etc), so i decided to try with 9 images, all in XML so the shadow shades start its gradient from the side of the component.
<!-- Left Shadow layer -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="0"
android:endColor="#FFFF0000"
android:startColor="#00FF0000" />
</shape>
</item>
It looks good, the problem is on the corners and with the android:gradientRadius parameter now its set to a fixed size, but in the contextual help is said that can be set in a percentage of the base size 10% or parent size 10%p, what i want its to set a 100%p radius so the gradient will always go from the main color and disappear in the edge of the square.
-- EDIT --
The android doc about gradientRadius gradientRadius
<shape android:shape="rectangle" >
<gradient
android:endColor="#00FF0000"
android:startColor="#FFFF0000"
android:gradientRadius="18"
android:centerX="100%"
android:centerY="100%"
android:type="radial" />
</shape>
And thats where im now :( i do not know how can i set this size to fit its parent view.
Any help will be appreciated, when im finished with the component i will put the code in an answer :) so typical buttons can have customizable shadows in xml.
An image of the deserved component.
--Edit--
Im still interested in this :) no one has a clue?
I think you should give up with xml and implement drawable in code.
When you extend Drawable class you can get size as rectangle with getBounds(). Also you can dynamicaly recalculate in onBoundsChange method.
You can also easily construct gradients and use them in Paint object (setShader method)
I added a full border around a view but I need to add just the corner as shown image below :
I mean the red corner only .
I tried to adjust the below border xml , but it didn't work :
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="10dp" android:height="10dp" android:color="#B22222" />
<solid android:color="#FCE6C9" />
<corners android:radius="20dp" />
</shape>
Any help will be appreciated
I don't think it's possible to do this using a ShapeDrawable, as it would require you to use some sort of margin or padding on the drawable itself. There actually is a padding attribute, but unfortunately that only has effect on the content of the View, and not the drawable itself.
That being said, an easy solution would be to create a 9-patch in stead and apply that as background to the TextView. Just for demonstration purposes: make the 9-patch look somewhat like this:
Edit:
On second thought, there's actually another option that relies on using a LayerDrawable to create the desired effect. It's a bit tedious to create and I have my doubts it'll be more efficient than using a 9-patch, but at least you don't have to render out images, which means that if you need to make e.g. a change in colours, it's more straightforward.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/rounded" />
<item android:drawable="#android:color/white" android:left="30dp"
android:right="30dp" />
<item android:bottom="30dp" android:drawable="#android:color/white"
android:top="30dp" />
<item android:bottom="30dp" android:left="10dp" android:right="10dp"
android:drawable="#color/pink" android:top="30dp" />
<item android:bottom="10dp" android:left="30dp" android:right="30dp"
android:drawable="#color/pink" android:top="10dp" />
</layer-list>
Some details: #drawable/rounded is the code snippet you posted yourself. The following two items are simply white rectangles with an offset, to create the white edges. Now, since these will also overlay the pink surface, we need two more pink rectangles (again with specific offsets) to counter that. The result is a background that looks exactly like what you're showing in your question.
Note that you might want to see if you can optimise this a bit. At the least I'd recommend not hardcoding the offsets (like I did for simplicity), but store them in a dimens.xml file so you can keep these values centralized and consistent by referencing them from both the ShapeDrawable and LayerDrawable.
Addendum: On pre-ICS (or perhaps pre-Honeycomb) devices, there appears to be an issue with directly referencing colours with the android:drawable attribute. You can however easily get around this by setting up another drawable (be it either a 9-patch or ShapeDrawable) to represent this colour. For example, in the snippet above, you would replace android:drawable="#color/pink" with android:drawable="#drawable/color_pink", where color_pink can simply be an xml file containing:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FCE6C9" />
</shape>
Obviously you will need to do the same for all other colours referenced in the LayerDrawable. Tested on Gingerbread 2.3.7.
I would create a 9-patch file and set it to be the background of the main container. The steps to do that would be.
You create the background you would like roughly in fireworks, illustrator, or whatever image editing software you prefer.
Then crop the artwork so that there is only a 1 pixel border around the artwork. Save it as a png.
Open the draw9patch.bat file in your android sdk folder on your computer C:\Program Files (x86)\Android\android-sdk\tools.
Open your png file. You can then use your mouse to click on the outer 1 pixel border which will turn the clicked pixels black. The areas that you have black pixels on both the top and bottom or on the left and right will be the area that is stretched. In your case you just want to have the middle area where there is no red stretched.
My personal preference is to just open the file above and save it as a 9 patch file. Then open it in my photo editing software to create a 1 pixel thick line in the same fashion as above. It is quicker and more precise.
Finally add the file to your drawable folder. Then set the background of your main view container to the drawable.
That should be it. Hope that helps.