0

I'm developing a kind of a instructions app. It uses fragments with ScrollvView, vertical LinearLayout and some TextViews / ImageViews in it to explain how a product works.

The images are just simple vector graphics which I save as png due to the lack of vector image support on Android. Here's an example:

Example of the images

The images are always filling the the screen using android:scaleType="fitXY" (portait and landscape) and the scrollviewer takes care of the rest (using android:adjustViewBounds="true"in the image view to prefent from scrolling over the original size of the image).

I read the guidelines of Google to use different versions for the different resolutions and densities but this seems to be overengineered for my purpose. My idea was to just supply one high-res (2000px width) image of the images in the drawable folder and let Android auto scaling do the rest.

The only issue I can think of is memory. But I'm not quite sure how the internals work here. If an OutOfMemory only occurs when displaying an image it shouldn't be a problem as the autoscaling hits in first.

If the scaler can run into memory issues I'm thinking using 3 versions of the image with different widths (i.e. 800pixel, 1500pixel and 2200pixel) and put them in different resource directories. This seems not possible though... The Android Studio wizard for Resource directories has an option for "smallest screen width" but its only for dp (density-independent pixels)! I want a resource file for real device pixels. I hope Android takes the closest fitting and don't fall back to the default one if it can't find an exact match. My images don't care about density as they are always filling the screen.

So in a nutshell:

  • Is supplying just one large pixel image with a small file size an issue?

  • If yes how can I setup device pixel resource directories?

The nature of the app already has an huge amount of images. That's why I don't want to duplicate each a couple of times which x-folds the number of images to deal with. The app is for API 11 onward.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Soko
  • 774
  • 1
  • 7
  • 20

1 Answers1

1

I finally found a solution to proportionally scale one image to device width with no memory issues.

  1. First you have to draw up your image (my_image.png) in a rather high resolution
  2. Put this image ONLY into the drawable-xxhdpi folder.
  3. Extend the Android ImageView class using this awesome answer.
  4. Use it in your layout as shown below:

Here is layout that works for me:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:fillViewport="true">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/main_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />

        <my.package.name.DynamicImageView
            android:id="@+id/main_image"
            android:adjustViewBounds="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/main_text_view"
            android:src="@drawable/my_image"
            android:scaleType="fitXY"/>

        <my.package.name.DynamicImageView
            android:id="@+id/main_image2"
            android:adjustViewBounds="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/main_image"
            android:src="@drawable/my_image"
            android:scaleType="fitXY"/>

        <TextView
            android:id="@+id/main_text_view2"
            android:layout_below="@id/main_image2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />

    </RelativeLayout>
</ScrollView>

Some more final information: I did a lot of testing with point 2 (which folder to put the image in) before I found the solution of point 3.

If you put the image in the standard drawable folder the scaling works without point 3 but you might run into OutOfMemory exceptions on older devices as android tries to scale up the already large image (Android thinks in drawable are only small images without checking their size).

When the image is in the drawable-xxhdpi folder Android knows its high-res and does only a down scaling if necessary. But it doesn't scale the image to width on density fitting devices! For example in a Nexus 10 the image gets drawn in its original size and scale - doesn't matter what you set for scaleType (I reckon it has something to do with inTargetDensity as explained in the inScaled description).

One important thing to keep in mind here is that I have to use a ScollView around the whole content. You may find some other solutions when no ScrollView is involved.

Finally, you could also use the drawable-xxxhdpi folder but it was introduced with API 19. I tried it and it worked on lower APIs as well. Apparently Android build tool 19.1.0 and higher takes care of lower API versions.

I hope this helps someone...

Community
  • 1
  • 1
Soko
  • 774
  • 1
  • 7
  • 20