Search code examples
androidandroid-layoutandroid-imageviewandroid-imageandroid-tablelayout

ImageView to look the same on tablet and phone


I have an imageview that is within a cardview to create a circle image. On a smart phone, I want the size of the image to be 250 and 250dp, let's say that is about 80% of my phone width.

On a tablet, I want the image to be about 80% of the width of my tablet, and the height must also match the width. What's the best way to achieve it. Thanks?

Following is the code where I manually put the width and height of 250dp, which looks fine on smartphone, but way to small for tablet.

<android.support.v7.widget.CardView
    android:id="@+id/cardView"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:elevation="12dp"
    app:cardCornerRadius="125dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:innerRadius="0dp"
    android:shape="ring"
    android:thicknessRatio="1.9"
    android:layout_marginTop="20dp">
    <ImageView
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:id="@+id/image_album_art"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true">
    </ImageView>
</android.support.v7.widget.CardView>

Solution

  • Android is designed to make this easy. If you want a resource to change depending on the device configuration (i.e. screen size), you define that resource in a specific directory:

    res/layout-sw720dp - large (9"-10") tablets
    res/layout-sw600dp - small (7"-8") tablets
    res/layout - all other devices
    

    When you append -sw600dp to the directory name, this means "smallest width 600 dp". This means that this directory is meant for devices that have a screen width of 600dp or greater. "Smallest width" means whichever side of the screen is smaller, so whether it's in portrait or landscape, a 1067dp x 600dp screen counts as having a smallest width of 600dp.

    You can make a copy of your entire layout file for each configuration and put one in each of the above directories. However, if all of the files are the same except for the View sizes, you will have a lot of duplicate code. If you need to make a change, you will have to make that change in all three files, which can lead to mistakes.

    Instead of having multiple layouts, you can define a dimension that varies according to configuration. Layouts go in res/layout/, and dimensions go in res/values/

    Create a new XML file dimensions.xml and put it in the res/values directory. Add a new dimen to it like this:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <dimen name="album_art_size">250dp</dimen>
    </resources>
    

    This will be the file that phones will see.

    Then, create two more values directories and append the smallest-width qualifier to them, so you have res/values, res/values-sw600dp and res/values-sw720dp. Copy dimensions.xml into both of those new direcories. You can then modify the album_art_size dimen in each of those files, and when your app runs on different screen sizes, it will see the appropriate dimensions.xml file.

    The last thing to do is to point your layout at the album_art_size dimension you have just created. Replace 250dp with @dimen/album_art_size:

    android:layout_width="@dimen/album_art_size"
    android:layout_height="@dimen/album_art_size"
    

    This will allow you to pick specific dimensions for each device category, which should get you close enough to your 80% screen size target. If you need exactly 80% of the screen width and a square View, you will need to fiddle with ImageView's scaleType and adjustViewBounds attributes or write some Java code.