9

Two screens, aside from the density, almost same size:

Left screen is an emulator 768x1280 160dpi (MDPI). Right screen is an emulator 720x1280 320dpi (XHDPI).

enter image description here

I am using width 300dp and height 300dp. XML:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/picture"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:src="@drawable/picture"
        android:layout_centerInParent="true"/>
</RelativeLayout>

Regardless of the cripsness/image quality, should not both images fill the same space in both (and others) screens? There is an answer that confirms this statement here

EDIT: I have seen users saying that you must duplicate the same XML for different screens so you can change the DP values of elements. If this is true, I think I misunderstood the DP unit purpose. I thought it was intented to have the image with exactly same size across different screens using the same DP values. Can you please clarify it?

Community
  • 1
  • 1
AndroidDev
  • 831
  • 5
  • 17
  • 36
  • 2
    Excuse me, did you check if you don't have different dimension images at the drawable folders (mdpi and xhdpi) of your project? – statosdotcom Jul 10 '16 at 14:50
  • Yes. Currently, I have only one version of the image for testing. But I have already tested by including all buckets and still, no luck. – AndroidDev Jul 10 '16 at 15:02

3 Answers3

15

I think the fact that emulators are being used is causing a bit of confusion here.

Specifying dp units as you have done here, should mean that the image is roughly the same physical size on different devices. In your question you have said that we are comparing two screens of almost the same size, but that is not the case!

Given the resolutions you have stated in the question, we are actually looking at (approximately) a 9 inch tablet on the left and a 4.5 inch phone on the right. As these are virtual devices and can be resized on screen they can be made to appear the same size but they represent very different things in reality.

On the left we can see from the status bar and system buttons that this indeed looks like a tablet, and I've used the icons in the status bar as a rough measure of scale here:

enter image description here

This backs up the expectation that if you actually had a tablet and phone in front of you(or if the emulators were in correct proportion), the image would be the same physical size on both.

Edit-additional detail in response to the comments on this answer:

The purpose of describing sizes in dp is that they will be the same physical size on devices with different pixel densities. This is what you've done above. If the element is, for example, 2 inches on each side, then it will be 2 inches on a high-res or low-res phone, and it will be 2 inches on a high-res or low-res tablet.

If what you want is not for the element to be the same actual size, but to always be the same proportion of the screen(like always 90% the width of the screen say) then there are a few types of layout you might choose from.

LinearLayout uses the concept of Weight to allocate different proportions of the space.

The support library includes PercentRelativeLayout and PercentFrameLayout which work like the regular layouts but allow you to specify sizes using percentages.

The new ConstraintLayout is currently only available in Android Studio 2.2 Preview edition. I have not yet used it myself, but it seems as though it includes it's own proportion and percentage based concepts which would enable this also.

Lewis McGeary
  • 7,692
  • 2
  • 40
  • 46
2

you can do this in programming also, so for different screen sizes(also for different densities) you can set the image size in percentage by getting the screen dimensions and then calculating the number of pixels(in terms of percentage) required for both width and height like this.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout_xml);

    DisplayMetrics metrics = getResources().getDisplayMetrics();
    int screenWidthInPixels = metrics.widthPixels;
    int screenHeightInPixels = metrics.heightPixels;

    int imageWidth = Math.round (screenWidthInPixels * (58.57/100)); //58.57 is the percentage value for image width
    int imageHeight = Math.round (screenHeightInPixels * (58.57/100)); //58.57 is the percentage value for image height

    ImageView picture= (ImageView)findViewById(R.id.your_image_id);
    picture.setLayoutParams(new RelativeLayout.LayoutParams((int) imageWidth , (int) imageHeight ));


    }
sunil kushwah
  • 495
  • 1
  • 6
  • 20
0

Simple Clarification:

First screen with 160 [MDPI]:

Here 1 dp[Used by you in xml's ImageView width] = 1 pixel[px]. As it is specification by Android. So, image is displayed in complete 300 pixels in both width and height.

Second Screen with 320 [XHDPI]:

Here 1 dp[Used by you in xml's ImageView width] = 2 pixels[px].

And as you have used "300dp" in width and height, means you are asking Android to use "density pixels" [dp] rather than physical pixels [px].

So, 300 dp = 600 pixels[px]

That's why ImageView is of double size in 2nd Emulator.

Hope , it clears doubt.

Solution:

If you want your ImageView to be of same width and height, then you can use android:weight attribute in both android:width and android:height. Which will allocate equal space on both sides of your imageview.

Sample code for finding density at runtime:

private static String getDensityName(Context context){
    float density = getResources().getDisplayMetrics().density;

    if(density >= 4.0){
        return “xxxhdpi”;
    }
    if(density >= 3.0){
        return “xxhdpi”;
    }
    if(density >= 2.0){
       return “xhdpi”;
    }
    if(density >= 1.5){
       return “hdpi”;
    }
    if(density >= 1){
       return “mdpi”;
    }
    return “ldpi”;

}
Anish Mittal
  • 1,157
  • 12
  • 29
  • Hi Anish, I get your explanation and it makes sense. But then what I do not understand is the term "density-independent pixel". It makes no sense to me.. If it is independent, then displaying the same image with same dp values in different densities should not generate differente results, right? – AndroidDev Jul 20 '16 at 11:51
  • 1
    @LevySchiavetti : Hi, Actually, "density independent pixel" concept comes in picture when "Screen size is same, but number of pixels are different." In that case, your code will display the image on both screens properly. In Your case, it is opposite. So, you need 2 images : 1 for mdpi density and another for xhdpi density. Just put these 2 diff. images in these separate folders and you are done. – Anish Mittal Jul 20 '16 at 12:34
  • Try to find density of both emulators. And check Do they match with the one , you specified above? I put the code for finding density in my above answer. – Anish Mittal Jul 20 '16 at 13:03