AndroidDev
AndroidDev

Reputation: 691

Two screens, same size with different density

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?

Upvotes: 9

Views: 3264

Answers (3)

Anish Mittal
Anish Mittal

Reputation: 1182

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”;

}

Upvotes: 0

sunil kushwah
sunil kushwah

Reputation: 505

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 ));


    }

Upvotes: 2

Lewis McGeary
Lewis McGeary

Reputation: 7922

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.

Upvotes: 15

Related Questions