I implemented a custom RatingBar in an application on my ListView items.
Custom style ratingbar_red.xml:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background" android:drawable="#drawable/star_off" />
<item android:id="#android:id/secondaryProgress" android:drawable="#drawable/star_on" />
<item android:id="#android:id/progress" android:drawable="#drawable/star_on" />
</layer-list>
Here's part of ListItem layout:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="15dp" >
<RatingBar
android:id="#+id/li_company_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="1dp"
android:isIndicator="true"
android:numStars="5"
android:progressDrawable="#drawable/ratingbar_red"
android:stepSize="1" />
<Button
android:id="#+id/li_company_callbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginLeft="40dp"
android:contentDescription="#string/ContentDescription"
android:drawableLeft="#drawable/phone_icon"
android:drawablePadding="5dp"
android:onClick="callbtn_Click"
android:text="#string/CallButton"
android:focusable="false"
android:focusableInTouchMode="false" >
</Button>
</LinearLayout>
It works, but when the rating is set, I get some strange image artifacts; 2 vertical lines below the pink stars appear on my view:
Here is star_on.png
star_off.png looks okay, and if rating == 0, the lines don't appear.
I'm android beginner, and can't understand what the problem is.
Try giving height to RatingBar in xml layout like this:
android:layout_height="30dp"
30dp or whatever suits you..
Check out why is this happening ??
I had this issue to, looked like the bottom edge of custom star image being stretched. You don't have to set the layout_height of rating bar tag. You can set the min/max height on the rating bar (to same as image height).
Example from my styles xml.
<style name="GoldRatingBar" parent="#android:style/Widget.RatingBar">
<item name="android:minHeight">#dimen/rating_bar_height</item>
<item name="android:maxHeight">#dimen/rating_bar_height</item>
</style>
Dimens.xml
<dimen name="rating_bar_height">11dp</dimen>
The value should match that of the drawable used. 11 pixel high image, so the rating_bar_height was set to 11dp.
Another simple solution woud be to leave a row of empty pixels in the star image using an image editor like photoshop. Then the repeated or stretched row of pixels in the ratingbar would be empty. This aproach solved my issue.
I solved this problem in another way. I take my custom star png's, and in image editor add transparent line to the bottom of the image. The problem with vertical lines disappeared on all screens!
Its a Icon design issue. The Problem here is the padding around the icon. If you are creating a custom star icon make sure you leave some padding space between the star and the page boundary on which it lies.
If you are not sure how to do it try Android Asset Studio. You can see something like "Padding around Optical Icon" do not keep it to 0 dip.
Every body is suggesting something but no body is trying to explain why this happen. I am gonna try to explain it now. Of course this will happen only when you are trying to customise the rating bar images.
Imagine that we have custom image with size 72x72 pixels and this is our resource for XXXHDPI -(it is 4x).
Same image need to have copy inside XXHDPI, XHDPI, HDPI, MDPI and LDPI as well. I will miss last one resource directory for now.
Inside different directories this image need to be as follow:
for XXHDPI size copy image need to be 54x54 (this is 3x)
for XHDPI size copy image need to be 36x36 (this is 2x)
for HDPI size copy image need to be 27x27 (this is 1.5x)
for MDPI size copy image need to be 18x18 (this is 1x)
So now in this scenario if your Rating bar has height bigger then 18 dp for example 30 dp, you will see this bad image artefacts below every star image, BECAUSE obviously RatingBar is trying to fill the rest of it's height with something (your Image is 18 dp but the height of the bar is 30dp), so rest 12dp will be filled with this artefacts.
That's why if you set the rating bar height to be fixed size everything COULD be OK but also COULDN'T be OK. All this depends about your custom image size.
I think there has one solution which will work in all possible scenarios and this is :
Create image asset for all devices screens that your app will support XXXHDPI, XXHDPI or what ever you want.
Make sure that if your (MDPI which is 1x) image has for example height 20 pixels, your RatingBar height will not be bigger then 20 dp and everything will be OK.
NOTE: In this whole conversation we talk about dp (density pixels) not in px because if we provide all those image resources in every single res folder we will have chance to work with dp not with px. I hope the last sentence is clear and make sense.
EDIT: The other possible way is to leave some small padding (empty space) , maybe 1px or 2px at the bottom of your custom image. In that case RatingBar view will NOT display those artefacts pixels, because they will be taken from the padding part of your custom image, which actually is just empty (transparent) pixels. I personally think, that this is not the best way, because the image padding will create some space (padding) between RatingBar and the rest Views inside the layout. In that case you will not have absolutely full control of Views space, because some small part has been hard coded inside the custom image (those 2 px padding).
Just 2 pixel padding in image star in photoshop.
padding in xml not work, just padding star image in photoshop.
it's work very good.
I fixed my same problem by reducing "layout_height" since my image's height was less than the height that I had in layout_height.
Same issue. In my case
Put custom star images in /Drawable folder
and set "android:layout_height="30dip"
work fine!!
I was observing the issue due to vector drawable.
Once I added respective png images it started working.
Added this as answer as it may helpful to someone facing the same issue.
Related
Is it possible to create a splash screen with a logo that maintains its aspect ratio while the background image can be resized independently? I'm currently using several .png files for different resolutions and they look great on most devices. However, there are a few phones that distort my logo severely (i.e. the Samsung S8, with move vertical screen space).
I can deal with some distortion for my splash screen background, but the skinny/squashed logo is unacceptable. Does anyone know how to do this? And would a vector drawable logo be better than a .png for the new layout?
Rendering a splash view in a layout.xml instead of as a theme background (like other answers here recommend) takes longer to load. This is because the app's theme is loaded first, then the Activity is constructed and the layout inflated last. Since the purpose of a splash screen is to display something while the app loads, having a ~0.5s delay in loading the splash screen itself results in a noticeable delay. Loading a splash as a theme windowBackground performs better (renders almost instantly after tapping the launcher icon), but has some restrictions to work around. Your current method of defining multiple logo sizes depending on the screen width is the correct way to handle this situation. Here is an example configuration, which handles differences between pre and post Android v21:
values/themes.xml:
<style name="SplashThemeCommon" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowBackground">#drawable/splash_logo_theme</item>
</style>
<style name="SplashTheme" parent="SplashThemeCommon">
<item name="android:windowFullscreen">true</item>
</style>
values-v21/themes.xml:
<style name="SplashTheme" parent="SplashThemeCommon">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
drawable/splash_logo_theme.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:gravity="center"
android:src="#drawable/splash_logo"/>
</item>
</layer-list>
Next you can include a copy of "splash_logo.png" for different screen configurations. You have a couple reasonable options here. An exhaustive approach might include different logos for each screen size:
drawable-sw320dp-xxxhdpi/splash_logo.png
drawable-sw400dp-xxxhdpi/splash_logo.png
drawable-sw480dp-xxxhdpi/splash_logo.png
drawable-sw600dp-xxxhdpi/splash_logo.png
drawable-sw720dp-xxxhdpi/splash_logo.png
drawable-sw820dp-xxxhdpi/splash_logo.png
The "swXXXdp" means that XXX is the smallest screen dimension (width or height) in dp. 820dp is going to be a huge tablet, 320dp will be an old small device, and most flagship devices today will be in the 400dp category. A 450dp wide device would use the 400dp image.
Why did I define xxxhdpi here? Because if you don't specify, Android will assume it is an mdpi image and try to upscale/resize for higher dpi devices (most flagship phones today are xxhdpi). This upscaling will result in your image being blocky, and larger than the original. By specifying xxxhdpi here, Android will only try to downscale the image ensuring that the image never goes blocky; this is a optimization so we don't also need to define separate images for ldpi, mdpi, hdpi, xhdpi etc.
Having 6 images in the APK is kind of a waste though. We can futher optimize this approach in order to include less images in the app and ensure a smaller APK size. Instead, let's include only the following two images:
drawable-sw600dp-xxxhdpi/splash_logo.png
drawable-xxxhdpi/splash_logo.png
Any devices 600dp and larger (tablets) have a larger copy of the image to take advantage of the larger screen real estate, while all other phones use a smaller copy located in the bin with no screen width qualifier. The drawback here is since each bin covers such a large range of screen widths, the logo on a 4" device will take up a larger portion of the screen than on a 6" devices. This is a compromise to cut down the APK size, and most users won't notice so long as the image never gets cut off even on the smallest device.
So what size png's should we include? They need to be a particular size to be displayed in a theme, since unlike in a layout.xml we cannot specify a width/height in the XML (drawable width/height support was only added in API 23). This means if you include a non-optimal png size, it will appear too small or two big; if its too big it will actually get cut off. A good plan to get the right size is:
Create an layout/test.xml file with just the default LinearLayout and no visible content
Open it in Android Studio and select the Design tab in the layout editor's bottom left corner
Change the theme to SplashTheme in the layout editor's top bar
Change the device to "Pixel XL"
Place an image under drawable-sw400dp/splash_logo.png
Open the image in an external image editor such as Photoshop or Gimp, change the size, save, then check the layout in Android Studio (you may need to close and reopen the editor for the change to take effect). Repeat until the image looks the correct size in the layout
Generate images for the other screen widths proportionately; for example the sw320dp image should be 320/400 or 67% of the 400dp image size, while the 720dp image should be 720/400 or 180% of the 400dp image size. Remember not to upscale your 400dp image for the larger images as you will lose quality. Instead, generate all the images based on your high quality original copy
Place the generated images in the different drawable directories as specified above
Select devices of different screen sizes (including tablets) in the layout editor and make sure they logo is large enough, but not cut off, for all screen sizes
How do you know which device screen resolution belongs to which swXXXdp category? This requires a simple calculation. Lets look at the Pixel XL:
The screen size is 1440x2560
The smallest dimension is therefore 1440
The screen dpi is 534
The screen width in inches is 1440/534=2.69"
Open the website: http://angrytools.com/android/pixelcalc/
Enter 2.69 in the inches ("in") box
One of the green boxes on the left will display the dp, in this case 431
With a 431 dp wide screen, the Pixel XL will use the drawable-sw400dp/splash_logo.png image if you have all 6 image categories, or the drawable-xxxhdpi/splash_logo.png image if you only have the two image categories
If you only have a portrait image for your splash screen, here's a solution which is full screen on portrait, and centred but not cropped on edit:
portrait landscape:
splash_screen.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layoutSplash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/splash_screen_background">
<ImageView
android:contentDescription="#string/splash_screen_description"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
style="#style/SplashScreen" />
</LinearLayout>
values/styles.xml
<style name="SplashScreen">
<item name="android:src">#drawable/splash</item>
<item name="android:adjustViewBounds">true</item>
<item name="android:scaleType">fitCenter</item>
</style>
values-port/styles.xml
<style name="SplashScreen">
<item name="android:src">#drawable/splash</item>
<item name="android:adjustViewBounds">true</item>
<item name="android:scaleType">centerCrop</item>
</style>
Have you looked into maintaining the aspect ratio for the ImageView? Here is a relevant question that should point you in the right direction: How to scale an Image in ImageView to keep the aspect ratio
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/logo"/>
</RelativeLayout>
This will do this
This is on a nexus 10
No need to use layouts at all, use a LayeredList, and set it as the background. Here is an example;
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/gray"/>
<item>
<bitmap android:gravity="center" android:src="#drawable/splash_image"/>
</item>
</layer-list>
In Android resources/res folder, create a folder "drawable-xxxhdpi" and "drawable-sw600dp"
In "drawable-sw600dp" folder, add 'splash_logo.png' with resolution 4096x4096 pixels. This should cover tablets.
In "drawable-xxxhdpi" folder, add another 'splash_logo.png" with resolution 1440x2560 pixels. This should cover smart phones.
That's how to solve all distortions!
I'm strugling while creating designs for Android.
According to some information that I've found, an MDPI screen has a 1 scale factor, So I create an image of 48dp = 48px and save it in the mdpi folder and then with the correct scaling factor, I'm saving it across the various places.
Now, I want to have a button that's the same height as my image, off course, in my layout I can declare a button of 48dp height, but then, when being used on other screens (say XXHDPI) the image and the button are not the same in height anymore.
Edit: Added the layout of the button
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp">
<Button
android:id="#+id/btnCamera"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#drawable/logon_camera_button"
android:text="#string/logon_scanQrCode"
android:textColor="#ffffff"
android:textSize="20sp"
android:layout_marginLeft="48dp"
android:layout_marginRight="25dp"
android:gravity="center" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/btnCamera"
android:layout_alignLeft="#+id/btnCamera"
android:id="#+id/imgCamera"
android:src="#drawable/camera" />
</RelativeLayout>
Anyone who has some advice on this topic?
Kind regards
you can add a res/values-xlarge/styles.xml
<style name="height">
<item name="android:height">50dp</item>
</style>
with varies device screen values-xxlarge, values-small, etc., values
and add this style to your button
style="#style/height"
Always start with highest resolution you are going to support. xxhdpi has a scaling factor of 3, so your xxhdpi version of the image should be 144px.
Nowadays, there are quite a few xxxhdpi devices, so you should probably go with 48 * 4 = 192px. Just place the highest res images into the -xxxhdpi folder (leaving mdpi and others empty) and let autoscaling do it's thing. And keep in mind the x4 multiplier when you assign sizes in dp.
E.g. if you want to maintain the 1:1 ratio of button height and image height, and your image is 192px in xxxhdpi bucket -- button should be 48dp.
In that scenario, say, on xxhdpi the image will get scaled by 3/4 to be 144xpx and 48dp button height will be scaled by 3 and also be 144px. For xhdpi that'll be 1/2 and 2, respectively, both resulting in 96px.
If you notice that autoscaled graphics look bad on some density, then provide hand-tuned resources for that density.
No need to provide custom styles/dimensions for different densities -- that is for when your [proportionally resized] UI doesn't look good on some densities and you decide to cope with this by using different proportions. For example if baseline (aka mdpi) size of some element is 24px, on ldpi that becomes 12px which may be too small, so for ldpi you set it to be 36dp=18px (using custom version of style, or, preferrably, dimension) which probably breaks UI proportions a bit but may look better nevertheless.
If your button background is of shapes supported by ShapeDrawable then you can create one by creating xml in drawable folder and setting that as your button background. See the ShapeDrawable example below
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f0600000"/>
<stroke android:width="3dp" android:color="#ffff8080"/>
<corners android:radius="3dp" />
<padding android:left="10dp" android:top="10dp"
android:right="10dp" android:bottom="10dp" />
</shape>
If its of any other shape or with text you can create a NinePatch image of it in such a way that text do not stretch only the portion without text stretch as per screen resolution. It is advisable to add the text using android:text property and give text size using android:textSize in sp. So you can add a image without text and set patch as that only the line portion is stretched and not the curves in the images if any.
First of all remove the image what you want to set on view. Then download this software. And set Input Density on that software xxhdpi. and check all options. Then 9patch resize the image. and put them inside drawable and set to view. That's it.
I'm working with an emulator screen set at 320x480 MDPI. I created a background image in fireworks with the exact size of 320x480 pixels, placed it in the drawable MDPI folder, and set it as an ImageView in hopes it would fill the entire background of the emulator. The problem is the background only fills vertically, but seems to leave empty space equally on the left and right horizontally.
Any idea what I'm doing wrong?
Any reason why you don't just setBackground on your root view?
Either way, filling the background in Android is a troublesome business. I suggest reading this question: Handling different screen resolutions for background images in Android
<ImageView android:layout_width="fill_parent"
android:layout_height ="fill_parent"
android:scaleType="fillXY" />
Note that this will cause it to scale in the X direction to fill the space, which will slightly distort the image.
please don't use a ImageView, just set the android:background property of the root layout in your xml. Look at this example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/your_image_here" >
.....
</RelativeLayout>
I hope this helps you. Best Regards
I create combobox_normal_m.9.png in draw9patch.exe. It looks very good in draw9patch.exe, but in Eclipse/device it's not so clear. Why edges are blurred?
from layout:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/selector_cbutton_m" />
from selector:
<item
android:drawable="#drawable/combobox_normal_m"
android:state_selected="false"
android:state_pressed="false"/>
You've inverted the top and bottom 9 patch data. The top 1 pixel defines the area that can be stretched. The bottom 1 pixel defines the area that can be covered with content. Unless, I guess, you intended there to be a buffer between the right edge of the text and the vertical separator. I could be misunderstanding what you are trying to do.
You will also notice that you still have to create versions of the 9 patch for different densities if there are non-scalable features that you want to look right at the different pixel densities. In eclipse you are also seeing a enlarged (typically) version of the screen resolution so it may not be representative of the device.
I'm using such layout:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/logo"
android:orientation="horizontal" >
The drawable/logo.xml:
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/login_logo"
android:gravity="center" />
The drawable/login_logo.png has 280 pixels width, my Galaxy Tab screen width is 600px but in launched app I see the image takes almost all screen width and it is about 500px
Where did I make mistake?
SOLVED
By setting
<uses-sdk android:minSdkVersion="4" />
and putting image to drawable-hdpi
As you are saying it is for galaxy tab so it is coming under drawable-hdpi.So change the resolution of image with photoshop or something and put it inside drawable-hdpi.
and try to use android:layout_width="wrap_content". instead of android:layout_width="fil_parent"
You are setting your picture in background, and the android:background tag uses 9 patch images. So your background always stretches to the width and height of the view. Your layout width is set to fill_parent, so the image width is fill_parent too.
The solution could be to make a 9 patch image of the png you are using with .9.png extension.
Read here for drawing 9 patch images - developer.android.com/guide/developing/tools/draw9patch.html
I suggest that you have a good read of the documentation. If you have placed your image in the drawable-mdpi folder, then in high density screens the image will appear to be 1.5x in size. You will have to provide different resolutions of your image for different screen densities.