I use several tiled drawables that are used as backgrounds for various layouts. For the most part the tiles work correctly but occasionally (once on every 4..5 runs) in some (but not all) of the backgrounds a single tile image gets stretched to fill in the background rather than repeat it (resulting in a very "fuzzy" background).
Tiles are declared in an xml drawable like this:
`bitmap android:src="#drawable/bg_tile_dark" android:tileMode="repeat"
xmlns:android="http://schemas.android.com/apk/res/android" />`
The tile drawable is used as a background image like this:
` RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/my_background_tile" >
`
....
/RelativeLayout>
This issue happens across multiple versions of Android and on different devices so there must be a trick to how to use tiles. Does anyone have experience using tile backgrounds or knows a workaround to force tiles to always repeat?
Related
I have an activity that includes a striped background image. Click to enlarge – this is the original image I'm using. There's also a version with a logo for another activity.
It looks fine as is. I set it as a background in the activity through XML, something like this.
I need the hack as an ImageView to be able to properly centerCrop a logo in the background, but this is irrelevant to the issue, as it persists when setting the background for the RelativeLayout and removing the ImageView.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="#drawable/background_striped" />
Note that since there has to be a logo inside the image, I can't stretch it artificially or have it repeat.
In the layout preview screen, it looks like this:
In the emulator, it looks like this:
As you can see, it looks quite bad, compared to how I'd expect it:
Naturally, I've created versions of the striped background for all display resolutions (from ldpi to xhdpi), but they always seem to be scaled in a pretty bad way.
Is there any way to get the background scaled in a higher quality? Just using the xhdpi version won't result in better quality—it will just make the scale result worse and more washed out.
For scalable drawables it is better to use a 9-patch. You can create one with your small striped background image using the android 9-patch tool:
http://developer.android.com/tools/help/draw9patch.html
Try using repeat. I tested it and it seems to look fine.
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/background_striped"
android:tileMode="repeat" />
I am having trouble removing anti-aliasing on a 9-patch png and a normal drawable that is tiled to make a background. I am using the 9-patch as a background for my EditText controls and the tiled drawable is used as a background for an ImageView to create the 'divider'.
Here is some enlarged versions of my 9 patch png (it's hard to show white graphics so I filled in the transparent areas in blue):
And my tiled background image along with the xml that defines the tiled pattern:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/border_diagonal_lines"
android:tileMode="repeat"
/>
Here is the whole thing put together:
The screenshot on the left is what I currently get and the screenshot on the right is what I want it to look like. What could I do to achieve the desired effect?
I also would like the imageview with the tiled background to always be 3 pixels tall regardless of screen resolution but using 'pixels' as units is generally a bad idea. Is there a way round this?
It isn't anti-aliasing your graphics, it's probably scaling them (which, granted, may also perform anti-aliasing, but it's not the cause). Are you placing them in the correct density-specific folder? (e.g. drawable-hdpi, drawable-xhdpi, etc.) If you are doing that, also make sure you are not using the android:anyDensity="true" tag in your manifest.
I also would like the imageview with the tiled background to always be
3 pixels tall regardless of screen resolution but using 'pixels' as
units is generally a bad idea. Is there a way round this?
It's discouraged in general cases, when the system should be handling scaling for multiple densities (using DP instead), but if you specifically need something 3 pixels tall, then there's nothing "bad" about specifying a pixel height.
I am wondering as a new Android developer (10+ years C# OOP) which would be the better way to create a simple repeating background. The background will be consistent no matter the screen size, density, or orientation. I've read the Android Developers Dev Guide about things such as supporting multiple screens, nine patch drawables etc. I have seen tutorials such as this one (http://androidforbeginners.blogspot.com/2010/06/how-to-tile-background-image-in-android.html) telling you how you can use an image and get it to repeat.
Of course using an image then you have to provide multiple images for multiple densities or risk bitmap scaling and pixelation. For a complex background pattern I can see how this might be the way to go. But my pattern is a simple grid pattern so isn't there a better way using just xml?
I looked at GridView and TableLayout and both allowed me to set a background color, specify cell width / height, but I did not see a way to specify the grid line color.
For now I am using the slightly older 2.3.3 api as that is the largest version currently in use.
I don't suspect I'll need much hand holdong just some good solid advise from those who know better than I.
Thank You
JB
You can create a drawable like this:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="AndroidPuzzlesSolver/#drawable/bg_tile"
android:tileMode="repeat"
android:dither="true" />
Place the above in a "background.xml" file at the drawable folder. Then you can use it in your layout like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/background">
You can use a background with all Layouts.
I don't think there is an out-of-the-box way to do an alternate repeat, e.g. show one image at some places and another one in some others. If you want something like this, then you would probably need to implement your own View and override the onDraw method. You could use a FrameLayout to combine this background View with any other elements.
I want to create a bookshelf that tiles horizontally and vertically. I have three images, ShelfLeft, ShelfMid, and ShelfRight. ShelfLeft starts each row/shelf, followed by X ShelfMids across the screen, capped off by ShelfRight at the end of each row.
There will be a default of 5 rows, and if more are needed, they shall be able to be added dynamically.
What is the best way to go about doing this?
Thanks.
I'd use a TableLayout. Use a cell for each of the "ends", and then another single cell for the tiled background.
To make a background repeat, create res/drawable/my_background.xml:
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/back"
android:tileMode="repeat" />
Then reference this as the background in your layout by specifying `android:background="#drawable/my_background".
(Source: http://androidblogger.blogspot.com/2009/01/how-to-have-tiled-background-cont.html)
Also worth noting: You might find the NinePatch class useful when creating your "ends".
NinePatch:
Screenshot:
Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#ffffff">
<LinearLayout
android:id="#+id/edit_tray"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<View
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/trash"/>
</LinearLayout>
</RelativeLayout>
Desired Results:
The "edit_tray" represents a UI element that will be toggleable. When edit mode is off, the "edit_tray" (and therefore the trash can icon) are "gone". When edit mode is on the "edit_tray" is visible and overlaid over the ScrollView contents.
There are two elements to the trash can icon: The icon itself and the linear gradient behind it. The NinePatch image contains three stretchable areas and one static area to accommodate these elements. The trash can icon in the middle of the graphic is static and should appear directly in the horizontal center and on the bottom of the screen. The gradient should stretch across the bottom of the screen from one side to the other.
The Bug?
The NinePatch image contains only one pixel of stretchable area on either side of the image horizontally. The effect of which should be that the trash can icon appears directly in the center (1 pixel on left side == 1 pixel on right side). However, as you can see in the screenshot above that is not the case. Note: this screenshot was taken from my test phone, a T-Mobile G2. The same effect can be seen in the emulator. However, in the draw9patch preview and the eclipse Graphical Layout view the image is perfectly distributed.
I've tried several different methods to try to find out where the bug is and to try to fix it or work around it. Including: using ImageViews instead of Views (same effect), using android:scaleType="fitXY" (same issue), checking at runtime that the width of the screen and the width of the "edit_tray" are the same (they are), using two different images for gradient (as edit_tray background) and icon (as ImageView src) (create another problem where the two images were not overlayed on each other. Fixed by setting an absolute height on both), etc.
The Answer, the Workaround, and the Real Question
I did some testing using some simple NinePatch images with up to six stretchable areas per side. I noticed there were some issues displaying them in at least one of the testing cases (phone, emulator, draw9patch, Graphical Layout in eclipse).
I decided to try to expand the image horizontally so that there was more of the linear gradient showing on the edges of the trash can icon. I made the image 128x64 (previously 64x64). I made more of the edges part of the stretchable part to try to curb any bad math (?) that was happening to the image. Draw9patch reported bad sections so I put it back to just the two pixels, one on either side. It worked! The icon is directly in the center of the screen now! I don't know why, but without changing the actual stretchable portion of the image, only changing the width of the image to 128, it works now.
I tried resizing the image back down to around 100px wide to remove some of the redundant pixels and the error came back! Not only did it come back, but the icon was placed at exactly the same spot offset from the center of the screen. I can't figure out why this would happen this way.
Anyone have any ideas? Is this a bug?
I currently have this working given the workarounds I described above, but if anyone has any suggestions I'm listening.
Make your 9 Patch image with using 4 points as I have done in this..and it will work.
Tips for Creating 9 Patch Image.(not a designer,telling you my funda)
Put points on Left and Top
If you have some text or image in between ..then put point on left
and right of image and top and bottom of that image or text.
Always see the no of space left and no of points on both sides(left-right and top-bottom) are equal.
Always check once the preview or right side before using check in 2x
to 6x
From my experience with the draw 9-patch tool there is an automatic 1px offset on each side of the image. Given this information if you were using just this one pixel offset your image was actually not being stretch the way you would imagine.
This can be seen by the fact that when you used a 2px offset it worked perfect.
Also the 9-patch images have a tendency of showing up in eclipse exactly how you would think... but then appearing different on the phone/emulator.
Learning the 9-patch tool is def a great thing as it allows greater customization. Another tip, if you want to do something like replace any android 9-patch with your own alterations - then just copy the 9patch that exists in the SDK and alter it. For some reason 9patch images in the SDK have weird offsets. Doing this will guarantee you don't get weird responses from your 9-patches. An example of this - I outline an editText in red when bad input is given.
The SDK images can be found in SDK->platforms->[plateform-you-want]->data->res-drawable-[you-choice]
You can also look at the SDK 9-patch images to help understand how the 9-patch-tool works.
Hope this give a little more insight.
Here are some good links:
http://developer.android.com/guide/developing/tools/draw9patch.html
http://android10.org/index.php/articlesother/279-draw-9-patch-tutorial
http://jaanus.com/post/7878186745/how-does-androids-nine-patch-tool-work-from-a
Maybe it's bug in nine-patch drawing, or just error resulting from rounding.
However, I don't like your approach of drawing this icon. You try to position your screen element using something that is not designed for this task.
You should draw it other way: create some container view (FrameLayout) with gradiend background. Then on top of that position ImageView with trash can. Neither of these 2 images need to be nine-patch, gradiend would fill entire view, trash can would be drawn without scaling.
Although there's overdraw in area of trash view, CPU time is not wasted in nine-patch areas computations.
You would use layout system for exact positioning of your trash icon. Certainly you would get expected result, since UI layouts are well tuned, and made for purpose of positioning screen elements. Nine-patch images are used for other purpose (where pixels shifted here or there a bit should not matter).
As #jjNford said - it's bad practice to work with images in this way.
For this task the best solution is to create "trash" icon with transparent background, and create shape drawable with gradient. So, you can remove unnecessary LinearLayout and use only ImageView:
<ImageView
android:id="#+id/edit_tray"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:src="#drawable/trash"
android:background="#drawable/gradient_background"/>
Docs for shape drawable.
EDIT
Just check your image - it starches fine on SE Xperia 2.3.3