Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use different background images for different resolutions in Android?

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:

  • Suporting Multiple Screens
  • Providing Resources: Best Match

and some related questions:

  • How to findout the best match
  • Android resources “best match” fallback logic
  • Dynamic Bitmap drawable in android
  • Why Android uses resources from the higher resource instead of a lower?

Update: fixed typos in the folder names.

like image 622
pconcepcion Avatar asked Nov 07 '12 14:11

pconcepcion


People also ask

What is Xhdpi in android?

Hdpi is a 1.5:1, and can be thought of as a HD (high-definition) display. And xhdpi is 2:1, much like Apple retina displays. . The normal mdpi is based on a 160 dpi screen, which again is the same as a single pixel unit in your graphics software.

How do you handle bitmaps in android as it takes too much memory?

Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.

Why is it problematic to define sizes using pixels on android?

Why is it problematic to define sizes using pixels on Android? Although screen pixel density varies, this does not impact the use of pixels to define sizes. Large devices always have more pixels, so your UI elements will be e=affected if you define them with pixels.


2 Answers

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.

like image 106
Umer Avatar answered Oct 09 '22 09:10

Umer


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.

like image 30
Padma Kumar Avatar answered Oct 09 '22 08:10

Padma Kumar