The Problem
I have an ImageView in my XML like that:
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_person_add"
android:alpha="0.87" />
The ic_person_add is the normal Material design Vectoricon.
On my Nexus 5 (Android 6), the icon scales beautiful and is really sharp:
On a Note 2 (Android 4.4) however, the icon gets really pixelated and ugly:
How do I get the ImageView (with a Vector as src) sharp on every device? Preferably with an only xml solution.
I already found:
Adding android:adjustViewBounds="true" -> did nothing
ImageView images seem pixelated and low quality -> Doesn't apply to vector
Setting BitmapFactory.inscaled=false -> doesn't work with only xml and I didn't know where to put this in a custom ImageView class.
The real problem wasn't the DPI of the Note 2, it was its Android Version.
The Link Melllvar posted states:
Once you have a vectorDrawable image in your res/drawable, the Gradle plugin will automatically generate raster PNG images for API level 20 and below during build time
So my Android 6 device really had a Vectorgraphic as source for the ImageView so it managed to scale it up flawlessly.
For the Note 2 (running on an older than Android 5 OS) Android Studio automatically converted the Vectorgraphic in my Drawables Folder to a PNG.
You can change the size of the converted PNG in the VectorXML by changing the
android:height android:width
to the size in dp your vectorgraphic needs to be displayed on pre API 20 devices. So in my Case (maximum of 100dp) I had to change the Values to:
<vector android:height="100dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="100dp">
The Nexus 5 density bucket is xxhdpi, while the Note 2's (based on this) is xhdpi. This suggests that your xxhdpi bitmap is sized properly (or is, at least, at or above the required size), while xhdpi isn't.
If you're using the automatic conversion provided by the recent versions of Android studio, you may want to try rasterizing the vector image manually to see if this fixes the issue.
If you're using raster graphics, you may want to add some visual element to each density variant to get an idea which one is actually being used.
Related
I'm new on android studio and planning to design an app for tablets and phones. Therefore my app will be mostly used on normal and large screens.
Which dpi is best for my vector icons ?
Should I make different dpi versions of the same icon for multiple screen support ?
Why only making the icons wrap_content doesnt support multiple screen sizes. I thought vector images doesnt get blurred when they are distorted.
The "dpi" for vector icons is meaningless. Vector icons are DPI independent. That's the whole point of them. It doesn't matter what size you design them at. It only makes a difference what size you draw (render) them at at run time. The bigger the size it is displayed at, the more pixels have to be calculated and drawn.
That's what the second paragraph in #muhammad-younas answer (which is from this Colt McAnlis blog) is trying to say.
I use InkScape for editing and save my SVG files (vector images). In theory, it scales well for any size. In theory...
In Android Studio I use New, Vector Asset, and I select the SVG file and it generates a XML file, below drawables folder, under res folder. But sometimes, without any explanation, the image was blurred in my phone (Not blurred in the Android Studio preview). It's crazy.
I've tried everything, and just one action has solved my problem:
I've decided to change XML file directly in Android Studio. I read something about width and height specs (image size) vs viewportWidth and viewportHeight (image real size in the cell phone)
So I've decided scaled up the first width and height pair
For instance, one blurred image has:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="6.415605dp"
android:height="5.33568dp"
android:viewportWidth="6.415605"
android:viewportHeight="5.33568">
....
</vector>
I've set in my head the width = 25dp, so I've made 25 / 6.415605 = 3.89675. So I've multiplied both numbers in the first pair by 3.89675. So I've got new values for width and height.
It's just a random guess. The important is to make width and height much bigger than viewport width and viewport height, preserving the proportions.
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="20.7915dp"
android:viewportWidth="6.415605"
android:viewportHeight="5.33568">
....
</vector>
It works like a charm ...
I have been struggling with this problem about a week and can not figure out how to make it work. I have some views on a screen. And one values\dimens.xml(sw320dp-xxhdpi) resource file. Also I have nexus 5.2 1080*1920 420dpi and nexus 5.0 1080*1920 xxhdpi. The layout appears differently on both screens. How to make it display the same on each device?
What resource file should I add (if it is any)?
How to add for example values\dimens.xml(1080*1920 420dpi)?
I think your layout is simply built as poorly scaling. Unless you have some very specific use case, you need to make sure your layout fills the area it is provided with regardless.
As for the resource folder, if you want to make sure the same layout file is used on large screens, it is enough to put it in the folder layout-sw360dp. If you have xxhdpi devices with the resolution 1080x1920, Android will select the same file for both since the smallest side will be exactly 1080 / 3 = 360 density-independent pixels.
How to make it display the same on each device?
In general it's impossible for all Android devices. I think best solution - using VectorDrawable or SVG format and scale vectors for each device.
I have a very simple activity showing an image:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/my_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/activation_background" />
</RelativeLayout>
my_image.png is only in /res/drawable-xhdpi/ and it is working fine for all the phones I've tried so far, except the Galaxy S5 with Lollipop (it is working on 4.4). On this specific phone and version, the ImageView shows instead a kind of default Android icon that is even not in my project.
To fix it, I need to put my_image.png in /res/drawable-xxhdpi/. But I don't understand this behavior. It is working fine on the Nexus 6 without the need to do that. Is it a known issue of the 5.0 version of the S5? Is there another way to do it rather than moving the image to drawable-xxhdpi?
Well, you should be creating drawables for each size screen. Android Studio has a tool to do this for you - right click on drawable and select new -> image asset
Otherwise, in Lollipop and up I believe vector graphics are supported - check here:
https://developer.android.com/training/material/drawables.html
If you are able to provide the image at the xxhdpi resolution you definitely should add it. It is best practice to have all your graphics defined in mdpi, hdpi, xhdpi, and xxhdpi folders.
Otherwise a workaround would be to simply make a copy of the image in the xhdpi folder and add it to the xxhdpi folder. That way phones at xxhdpi will still have a drawable resource to load.
Well the solution to my problem is a bit odd. I fixed it by simply renaming the drawable activation_bg to something_activation_bg. Please note that anything other than activation_bg was working, except activation_background which led to the same issue.
I don't know why this is an issue specifically on the Lollipop version of the Galaxy S5. There shouldn't be any conflicts with anything external to the app so it is really odd.
I'm trying to create a background image for my app that will look sharp on all resolutions/orientations.
I'm new to android development, but I understand the easiest way to achieve this is to use 9 patch images. I thought I understood how they worked, but I can't get it to work.
I've created a background image # 768 x 1280 which is the resolution of my Nexus 4. When I don't 9 patch it and view it on my device, it looks fine (obviously, because the resolution/orientation matches the device's):
So it looks nice and sharp.
But then I add the patches onto the image using the drawer9patch.bat file and rename the file to '.9.png' and this is the result:
Knackered!
The strange thing is: in the preview pane in the right hand side of the draw9patch tool it all looks fine....
I've also tried making the image at a smaller resolution, but the logo & text don't look sharp; they look pixelated...
I feel there must be some vital piece of the puzzle I'm missing? The area I've defined as content is being stretched?
Here is my layout code:
<?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:background="#drawable/my_background_image_patched"
android:padding="0px">
<!-- Login controls here --->
</RelativeLayout>
Here is my 9 patch image (which is located to the 'drawable' folder):
OK, I tinkered with your 9 patch.
I must say it was poorly designed (72 dpi, while it should really be 320 dpi).
So, I redesigned it (you can see I moved the black pixels) and saved it to 320 dpi (in the drawable-xhdpi folder).
It seems it scaled well at ldpi and mdpi screens (so, I guess it will also scale well at hdpi):
The patch I used is this:
Try to generate Nine-Patch using this Nine-patch Generator allows you to quickly generate simple nine-patches at different screen densities, based on the specified source artwork
Right now, i am developing Android Application using SDK 1.5 and testing application on HTC Hero, its firmware is Android 1.5.
Let me come to actual point: in application, i am having an imageview for displaying image (Image resolution is 320*480), now imageview is displaying image in full-screen perfectly, but when i am trying to test it on HTC EVO 4G (having resolution 480*800), image gets stretch.
So, what i like to do is want to display 320*480 resolution image in all screen-resolution mobile ? i means to say,if the mobile is of higher resolution(i.e. 480*800 , 480*854, or else) than the image should be displayed in "Center" portion of the screen.
So displaying image in Center in all screen (without stretching or cutting) resolution other than 320*480, what attributes i have to set ?
Simply set the scaleType attribute of your ImageView. Possible values here: ImageView.ScaleType You might want to use CENTER.
In addition you face another problem: You have to provide a hdpi image in addition to your mdpi image so your mdpi image does not get automatically scaled up to hdpi by the Android system, read more here: http://developer.android.com/guide/topics/resources/providing-resources.html
Edit: Oh, and I nearly forgot: The 'drawable-mdpi' and 'drawable-hdpi' folders are only possible if you build your project against at least Android 1.6. So you have to set your minSdkVersion to 3 and your targetSdkVersion to 4, and place your images into the normal 'drawable' folder in order for Android 1.5 to catch up. See this video from the Google I/O 2010 to learn more: Casting a wide net for all Android devices.