0

I've assigned a drawable resource to my app's loading theme. However, the bitmap within the drawable resource is being clipped and I can't figure out why. Using android:gravity="fill_horizontal" stops the horizontal clipping, but also changes the image's aspect ratio.

How can I use the image without clipping the edges and while maintaining its original aspect ratio?

styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- Launcher/splash theme. -->
    <style name="AppTheme.Launcher">
        <item name="android:windowBackground">@drawable/launch_screen</item>
        <item name="android:adjustViewBounds">true</item>
    </style>

</resources>

launch_screen.xml

<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">

    <!-- Background color-->
    <item android:drawable="@android:color/white"/>

    <!-- Splash Logo -->
    <item>
        <bitmap
            android:src="@drawable/splash_screen"
            android:gravity="center"/>
    </item>
</layer-list>

Original Bitmap

Bitmap using---android:gravity="center"

Bitmap using---android:gravity="fill_horizontal"

Temporary Solution: I've found an imperfect solution. By tweaking the item's height and width I've managed ensure the image remains within the container's boundaries. The image does not scale equally across different screen sizes. For now, this setting is the best solution I've come across.

Amended launch_screen.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Use android:opacity=”opaque” to prevent black flash during theme 
transition. -->

<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">

<!-- Background color-->
<item android:drawable="@android:color/white"/>

<!-- Splash Logo -->
<item
    android:height="400dp"
    android:width="400dp"
    android:gravity="center">
    <bitmap
        android:src="@drawable/splash_screen"
        />
</item>

</layer-list>

Amended launch_screen.xml

Samm
  • 115
  • 12
  • https://stackoverflow.com/questions/1400782/android-scale-a-drawable-or-background-image – Vince VD Mar 10 '19 at 03:37
  • @Vince I'm not sure what you want me to do with this. I tried a few of the suggested answers, but none of them worked. – Samm Mar 10 '19 at 04:13
  • Already tried using gravity="fill" ? – Vince VD Mar 10 '19 at 04:21
  • @Vince Yep. It resolves the clipping issue, but it stretches the image to fit the constraints of its container, causing a change in aspect ratio. – Samm Mar 10 '19 at 04:23
  • https://stackoverflow.com/questions/9891065/scale-image-keeping-its-aspect-ratio-in-background-drawable – Vince VD Mar 10 '19 at 04:26
  • @Vince ImageView can't be used with this resource type. – Samm Mar 10 '19 at 04:36
  • Indeed, but in the post you can see what you're trying to achieve is easier if you use an imageView. – Vince VD Mar 10 '19 at 04:38
  • It is impossible to achieve manipulating background attribute within xml-files only. (from the answer in the post i linked) – Vince VD Mar 10 '19 at 04:39
  • @Vince Wouldn't that require adding a new layout, then switching to the main layout once the background tasks are complete? I'm trying to do this with theme switching, requiring a drawable resource, not a layout.. – Samm Mar 10 '19 at 04:41
  • Yes you would need to create a new layout, but you're just trying to create a splash screen which shows an image and then goes to your mainactivity right? – Vince VD Mar 10 '19 at 04:46
  • Yes, but only while the mainactivity.java loads. Doing it with theme switching allows me to put up a splash screen before mainactivity.java calls onCreate. – Samm Mar 10 '19 at 04:50
  • You could use a runnable so that after a time it loads your mainactivity. – Vince VD Mar 10 '19 at 04:57
  • Here is a post explaining how to make a splashactivity and layout: https://stackoverflow.com/questions/5486789/how-do-i-make-a-splash-screen – Vince VD Mar 10 '19 at 04:58
  • Well i just found out it's a bad practice by using a splash screen timer and your way is actually the right way for creating a splash screen but i'm not sure how to fix your image. – Vince VD Mar 10 '19 at 05:03
  • I'll let you know if i find something. – Vince VD Mar 10 '19 at 05:03
  • The "correct" answer in that post goes against material-design guidelines, by introducing a fixed-wait time before the user can accept the app. The answer below that shows how to introduce a splash screen (via theme switching) that lasts until the app is configured. This is the process I'm using. – Samm Mar 10 '19 at 05:07
  • Just saw your response. No worries. Hopefully I'll hear from you! – Samm Mar 10 '19 at 05:08
  • Still looking for an answer? – Vince VD Mar 17 '19 at 17:54
  • I posted an answer, let me know if it works or if you need some help. – Vince VD Mar 17 '19 at 18:13

2 Answers2

0

Change your launch_screen.xml with this

<?xml version="1.0" encoding="utf-8"?>
<layer-list 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:opacity="opaque">

    <item android:width="220dp" android:height="220dp">
        <bitmap
            android:src="@drawable/splash_screen"
            android:gravity="center"/>
    </item>
</layer-list>

Edit: I updated the code, try this.

Rishabh Sagar
  • 3,877
  • 3
  • 15
  • 24
  • This didn't work. It reduced the clipping, but stretched the image to fit the screen, changing its aspect ratio. – Samm Mar 10 '19 at 04:10
  • That didn't work either. It moves the image up and to the left, moving a large part of it off screen. – Samm Mar 10 '19 at 04:35
0

In your AndroidStudioProjects folder, usually located C:\Users\username\AndroidStudioProjects you will find drawable dimension folders.

Dimensions

 - LDPI:
    - Portrait: 200x320px
    - Landscape: 320x200px
 - MDPI:
    - Portrait: 320x480px
    - Landscape: 480x320px
 - HDPI:
    - Portrait: 480x800px
    - Landscape: 800x480px
 - XHDPI:
    - Portrait: 720px1280px
    - Landscape: 1280x720px
 - XXHDPI
    - Portrait: 960x1600px
    - Landscape: 1600x960px
 - XXXHDPI 
    - Portrait: 1280x1920px
    - Landscape: 1920x1280px

Resize your original image with following dimensions and put them in the right folder. I also see that your image is a logo with a white background so you can just make your logo transparent in an image editor like photoshop.

Then create a drawable in your drawable folder

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:drawable="@color/color1"/> <-- this is the background color in your splashscreen.

    <item>
        <bitmap
            android:gravity="top"
            android:src="@drawable/splashlogo"/> <-- your transparent logo.
    </item>

</layer-list>

Then create Style in your values folder -> styles.xml

 <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/splash_screen</item>
 </style>

And finally add the theme style to your manifest

<activity
      android:name=".SplashActivity"
      android:theme="@style/SplashTheme"  <-- your splashscreen theme style.
      android:label="@string/app_name"
      android:screenOrientation="portrait">
          <intent-filter>
             <action android:name="android.intent.action.MAIN" />

             <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
</activity>

PS: make sure you created an Activity for your Splashscreen and in onCreate start an intent to open your MainActivity.

@Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

     Intent mainIntent = new Intent(SplashActivity.this, MainActivity.class);
     startActivity(mainIntent);
     finish();      
}
Vince VD
  • 1,506
  • 17
  • 38
  • I found a workaround that avoids the problem by setting the height and width of the image. The downside to specifying the size is that it doesn't scale with different screen resolutions. --- Your answer doesn't actually solve the problem. The different Drawable folders aren't for specific resolutions, they're for specific screen densities (dpi = dots per inch). For example, an 800x600 image can have a DPI of 72, 150, 300 etc. The image is still 800x600, but higher DPI holds more data in the same space and provides a higher-fidelity image. – Samm Mar 18 '19 at 00:08
  • The image is actually transparent already. Furthermore, you can see in my original post that my drawable.xml is almost identical to yours, except for the different gravity. However, setting gravity to _top_ shifts the image to the top-border of the screen, rather than placing it in the centre. --- I've already got the theme listed within styles.xml and the manifest, see original post. – Samm Mar 18 '19 at 00:09
  • Creating an activity for the Splashscreen is unnecessary and goes against design guidelines by not sending the user to MainActivity.java once app configuration has completed. Theme switching in MainActivity.java is a simpler way to achieve the same outcome. To do that, add the following code to 'protected void onCreate' _before_ calling `super.onCreate`. `setTheme(R.style.AppTheme)` with _AppTheme_ being the App's main-theme name in styles.xml – Samm Mar 18 '19 at 00:09
  • I followed a guide which indeed stated that not using an activity for the splashscreen is better, but using an activity which starts an intent to your mainActivity will have almost no downside to it. Source: https://android.jlelse.eu/the-complete-android-splash-screen-guide-c7db82bce565 – Vince VD Mar 18 '19 at 02:44
  • Except small delay when transitioning, for my app it's not that of a big deal but i guess it's personal preference. – Vince VD Mar 18 '19 at 02:49
  • For the different screen resolutions you could use a dimensions file (dimens.xml). Check out this post: https://stackoverflow.com/questions/32860815/how-to-define-dimens-xml-for-every-different-screen-size-in-android – Vince VD Mar 18 '19 at 02:51
  • Just tested it with my app if there was any difference in speed between using an activity and not and it's really minimal and i even do heavy data loading in my MainActivity, so i think it's up to you for using an activity or not. I chose an activity because i ask for permissions in my splashscreen. – Vince VD Mar 18 '19 at 03:11