How to use different background images for different resolutions in Android?
Asked Answered
V

2

12

I'm doing an Android App for Android tablets that has a full image background but I can't use a 9-patch, so I need the background to be as close as possible as the window size.

What I have tested:

I've tested using the drawable-ldpi, drawable-mdpi, etc... folders but as I want the images to fit the window, it doesn't work that well.

Now I'm trying with the drawable-wxxxdp, folders to have images with sizes that are close to the real window size.

So I have this folder structure (each folder with a different image, i.e: images of same size are different on different folders):

drawable-w800dp-mdpi // 800x600px image
drawable-w800dp-hdpi // 800x600px image
drawable-w1024dp-mdpi // 1024x600px image
drawable-w1024dp-hdpi // 1024x600px image
drawable-w1280dp-mdpi // 1280x800 image
drawable-w1280dp-hdpi // 1280x800 image
drawable-w1280dp-xhdpi // 1280x800 image

The problem is that when I test the App on different tablets it doesn't always take the image from the expected folder.

For instance: in a 1280x800px and 160 dpis tablet, that reports (using DisplayMetrics) a window size of 1280x752, it uses the 1280x800px image from the drawable-w1280dp-mdpi folder and cuts a bit of the image from the top and the bottom. But on a 1280x800px and 213dpis tablet that reports a window size of 1280x736 it takes the image from the drawable-w800dp-hdpi... I would expect to take it from other folder like one of the drawable-w1024dp folders... but not from that one...

On the other hand if I try on the emulator with a configuration like 1024x600px and 160dpis that reports a window size of 1024x552 it gets the image from the drawable-w1024dp-hdpi folder but it scales it down and centers it on the screen so I end with very big border all around the image.

Files:

The testing layout I'm using is:

<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" >

    <ImageView
        android:id="@+id/appBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"
        android:src="@drawable/background_image"
        tools:ignore="ContentDescription" />

</RelativeLayout>      

and on my Manifest file I have:

<uses-sdk
    android:minSdkVersion="13"
    android:targetSdkVersion="15" />

<supports-screens 
android:anyDensity="true" 
android:largeScreens="true"
android:normalScreens="true" 
android:smallScreens="true"
android:resizeable="true"/>

Update: My activity code:

public class ScreenTest extends Activity {

   private int width;
   private int height;
   private int dpis;
   private String sdpis;

   @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Ask for a full screen window
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
              WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_screen_test);
  }

    /* (non-Javadoc)
    * @see android.app.Activity#onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet)
    */
   @Override
   public View onCreateView(String name, Context context, AttributeSet attrs) {
      return super.onCreateView(name, context, attrs);
   }

   /* (non-Javadoc)
    * @see android.app.Activity#onStart()
    */
   @Override
   protected void onStart() {
      // TODO Auto-generated method stub
      super.onStart();
      // Get the info about the screen
      Display display = getWindowManager().getDefaultDisplay();
      width = display.getWidth();// size.x;
      height = display.getHeight();
      DisplayMetrics outMetrics = new DisplayMetrics();
      display.getMetrics(outMetrics);
      dpis = outMetrics.densityDpi;
      sdpis = "";

      switch (dpis) {
         case DisplayMetrics.DENSITY_DEFAULT:
               sdpis = "160";
               break;
         case DisplayMetrics.DENSITY_HIGH:
            sdpis = "240";
            break;
         case DisplayMetrics.DENSITY_LOW:
            sdpis = "120";
            break;
         case DisplayMetrics.DENSITY_XHIGH:
            sdpis = "320";
            break;
         default:
            sdpis +=dpis;
            break;
      }
      Log.d("DPIs", "dpis: " + dpis + " sdpis: " + sdpis + " width: " + width + " height: " + height);

   }

   @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_screen_test, menu);
        return true;
    }
}                 

Summary:

So I don't know how to predict from which folder is the App going to take the image? and what it will do with it? (scale, crop...)

Extra Background:

I've checked all the questions on the android-resoruces tag, I've read several times the official documentation:

and some related questions:

Update: fixed typos in the folder names.

Villalba answered 7/11, 2012 at 14:2 Comment(2)
Why don't you handle in your JAVA code?Ideomotor
Added Activity Code as @Ideomotor asked.Villalba
K
1

If you want to target specific device. or all devices that are in-between two resolutions then you have to find width of device first. like this

Display display ; 
int width =0;
display = getWindowManager().getDefaultDisplay(); 
width = display.getWidth();

after that you can make if statements with width conditions and make different layouts for different screens size. this one is not recommended method but work great in some case

    if(width>=750)
      {
          setContentView(R.layout.screen_blue_heigh);
      }
   else if(width>=500&&width<750)
      {
          setContentView(R.layout.screen_blue_heigh);
      }
   else if(width<500&&width>=330)
      {
              setContentView(R.layout.screen_blue_medium);
      }
   else if(width<320)
       {
          setContentView(R.layout.screen_blue_low);
       }

Hope this will help you.

Kavita answered 20/1, 2014 at 13:19 Comment(0)
G
1

you are right it will pick resource from w800dp , coz you are running in portrait mode.

The system's corresponding value for the width changes when the screen's orientation switches between landscape and portrait to reflect the current actual width that's available for your UI.

use res/drawable-sw600dp

the device's smallestWidth does not change when the screen's orientation changes.

Gwendolin answered 7/11, 2012 at 15:18 Comment(1)
The app is runnnig in Landscape ModeVillalba
K
1

If you want to target specific device. or all devices that are in-between two resolutions then you have to find width of device first. like this

Display display ; 
int width =0;
display = getWindowManager().getDefaultDisplay(); 
width = display.getWidth();

after that you can make if statements with width conditions and make different layouts for different screens size. this one is not recommended method but work great in some case

    if(width>=750)
      {
          setContentView(R.layout.screen_blue_heigh);
      }
   else if(width>=500&&width<750)
      {
          setContentView(R.layout.screen_blue_heigh);
      }
   else if(width<500&&width>=330)
      {
              setContentView(R.layout.screen_blue_medium);
      }
   else if(width<320)
       {
          setContentView(R.layout.screen_blue_low);
       }

Hope this will help you.

Kavita answered 20/1, 2014 at 13:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.