I have a unique splash screen, called splash.png and sized 1280x1280, 150dpi
I use react-native-bootsplash in my React Native project, but I don't think it really matters.
My question is simple : how can I make my splash screen, in portrait mode, be full height, not less, not more, and keep its aspect ratio so that the picture fills the screen.
Like a background-size: cover in css.
Or like an easy <Image resizeMode="cover" style={{ height: '100%' }} /> in React Native.
So I have :
android/app/src/main/res/values/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:textColor">#000000</item>
</style>
<!-- BootTheme should inherit from AppTheme -->
<style name="BootTheme" parent="AppTheme">
<!-- set the generated bootsplash.xml drawable as activity background -->
<item name="android:windowBackground">#drawable/bootsplash</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
android/app/src/main/res/drawable/bootsplash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<item>
<!-- your logo, centered horizontally and vertically -->
<bitmap
android:layout_height="fill_parent"
android:src="#drawable/splash"
android:scaleType="centerInside"
android:gravity="center" />
</item>
</layer-list>
And my splash.png in android/app/src/main/res/drawable/splash.png
I tried a lot of things, a lot of combinations of android:layout_height, android:scaleType and all, and I always end-up with a splash image's height overflowing the screen height.
[EDIT]
Here is the splash original image, with the size reduced enough to have a small size for stackoverflow
and here is what it give on screen...
I think the key here is android:gravity="fill".
I had the same issue when I was implementing it in my application.
My android/app/src/main/res/values/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:textColor">#000000</item>
</style>
<style name="BootTheme" parent="AppTheme">
<!-- set bootsplash.xml as background -->
<item name="android:background">#drawable/bootsplash</item>
and my android/app/src/main/res/drawable/bootsplash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
<item>
<bitmap android:src="#mipmap/launch_screen" android:gravity="fill" />
</item>
</layer-list>
for center image with background image fillup..
step1: create a Drawable resource file inside drawable in res
step2: paste the code below replacing with background images as your image and logo
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/backgroundmapsneww"
android:gravity="fill"
/>
<item
android:height="100dp"
android:width="100dp"
android:gravity="center"
android:drawable="#drawable/logo"
>
</item>
Splash screen implemented as a launcher theme is mostly meant for showing logos and not full images. You can try to nine-patch the image for different resolutions, use this website:
http://ticons.fokkezb.nl/
Upload your image (use 3:4 aspect ratio, e.g. 1080x1920, for the best results) and select -> splashes. It will generate nine-patch images for you, which you then need to upload to your res/drawable-hdpi, res/drawalbe-mdpi, res/drawable-xhdpi, res/drawable-xxhdpi and res/drawable-xxxhdpi directories. If they do not exist yet, you can just create them.
Use it like this after uploading nine-patched images:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:src="#drawable/background"
android:gravity="fill" />
</item>
</layer-list>
I was able to achieve reasonable results using the image you provided. Let me know, if this has helped. This is the best you can get. Other option would be to create your own SplashActivity which would show that image for you for a short period of time.
The approach with Bitmap did not seem to succeed. Are you happy with an alternative?
What about using a layout for your SplashActivity/-Fragment like the following?
Pretty useful to display additional information like Appversion, Support's contact, Progress etc. - that's why I personally prefer it.
Done in Kotlin working with ViewModels, you might probably know it better for ReactNative.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_splash"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:srcCompat="#drawable/splash"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
As you can see centerCrop is key. It will cut the image, but retain its aspect ratio.
Now inflate the layout in SplashActivity, where you could also let the user sign in or so, then display the result in the layout and when done, switch to MainActivity.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
}
...or Fragment
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel = ViewModelProvider.AndroidViewModelFactory(Application())
.create(viewModel::class.java)
return inflater.inflate(R.layout.fragment_splash, container, false)
}
Alternative Solution
Using this as a layout, if you don't plan to display anything more than just the image itself in the future.
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:srcCompat="#drawable/splash"/>
Hope it helps :)
I have done this by using FrameLayout and ImageView. Write down below code in your android/app/src/main/res/drawable/bootsplash.xml:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/splash"
android:scaleType="centerCrop"
/>
</FrameLayout>
Related
My company has a single activity Android Kotlin applicaiton.
We would like to display a splashscreen on startup.
After reading a bunch of turtorial I have found a way to do it.
But when I try to display an ImageView the splashscreen, it becomes a white background.
Here is my code:
AndroidManifest.xml
<application
...
android:theme="#style/Theme.SplashScreen">
...
</application
Theme.SplashScreen in res/values/themes/themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
...
<style name="Theme.SplashScreen" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">#drawable/splash_background</item>
</style>
...
</resources>
res/drawable/splash_background.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:drawable="#color/blue" />
<item>
<!-- This works
<bitmap
android:gravity="center"
android:src="#mipmap/ic_launcher" />
-->
<!-- This doesn't work -->
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:src="#drawable/ic_somePicture"
app:tint="#color/white" />
</item>
</layer-list>
Notice I have two cases here: The bitmap and the ImageView cases.
The bitmap case work if I uncomment it.
During startup this image is displayed in the splashscreen.
The ImageView case doesn't work.
This result is a completely white splashscreen.
The ImageView "should" work, because I use the same setup in some fragments.
The #drawable/ic_somePicture is a SVG-image that I have added in the AndroidStudio project.
I cannot show it here, as it's a property of my company.
Notice I have to specify the app:tint property to show the image on whatever background color I have in either the splash_background.xml or the fragment.
What could be the problem?
Any suggestion how to fix this?
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ImageButton Selected"/>
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button"/>
This is in my activity_main.xml
and this
<item android:drawable="#drawable/round" android:state_pressed="true"/>
<item android:drawable="#drawable/round2" android:state_focused="true"/>
in my button.xml
the custom buttons are made with image button function
when I start the application It doesn't give error and shows only "imagebutton selected"
The problem can be with my image?being too large?
here are the images and they are png btw with 1000x1000..I know is big but being png I thought will be everything fine..now I have to find how to make the white background dissapear.
here are the images round and round2
I don't know what is a selector,I know that I've put them in the folder drawable and then I followed a tutorial to make custom buttons.
the images are vectors
here is how the emulator looks like emulator
Your button.xml should look like this.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- pressed -->
<item android:drawable="#drawable/round2" android:state_pressed="true"/>
<!-- focused -->
<item android:drawable="#drawable/round3" android:state_focused="true"/>
<!-- default -->
<item android:drawable="#drawable/round"/>
</selector>
Also, you should reduce the size of your PNGs, that would take up a lot of space, and a lot of memory.
My splash screen is a layer-list drawable as background in app theme. Here is it:
background_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#color/dark_blue"/>
<item android:top="100dp">
<bitmap
android:gravity="top"
android:src="#mipmap/img_logo"/>
</item>
</layer-list>
As you see, I place the logo with margin 100dp from the top. Then I try to do the same in my fragment layout:
fragment_start.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#mipmap/bg_create_account">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/img_logo"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp" />
</RelativeLayout>
But the logo in the layout appears lower than logo on the splash screen. I thought, the problem is in the default margin of Activity. But if I set:
<dimen name="activity_horizontal_margin">0dp</dimen>
<dimen name="activity_vertical_margin">0dp</dimen>
Nothing still happens. I always see the "jump" of logo from top to down about 10-20 dp. How can I avoid it?
EDIT: My activity xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</LinearLayout>
EDIT 2: I tried to pick up the distance manually and if I set <item android:top="125dp"> (or 126dp) and leave android:layout_marginTop="100dp" I see no "jump". It means the difference is 25 or 26 dp, but where are they?
EDIT 3: according to answer from Bryan the issue exists only in Android 4.4(API 19) and above. To avoid it I overrode styles.xml in folder values-19 with:
<item name="android:windowTranslucentStatus">true</item>
It seems drawable that you use for the splash screen does not take into account the size of the status bar, but the Activity does. This is the ~25dp difference you are observing, though this height of ~25dp is not guaranteed to be the same on all devices.
Maybe the problem is in the ActionBarSize, try add this to the SplashScreen :
Without AppCompat
android:paddingTop="?android:attr/actionBarSize"
With AppCompat
android:paddingTop="?attr/actionBarSize"
Or if you want, (although may be considered a bad practice), you can set a negative padding in the Activity Layout using data binding :
android:paddingTop="#{-1 * ?android:actionBarSize}"
Here is my button image file from my drawable folder called ooo.png:
And that's how it looks like on the device:
As you can see the width height proportion changed. It's a bit wider than the original.
I need it to be looking the same though.
I don't understand what causes this stretching. Here is my xml-file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
style="#style/styleBtns"
android:layout_gravity="center_horizontal"
android:layout_marginTop="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
My styleBtns-part of the styles.xml:
<style name="styleBtns" >
<item name="android:background">#drawable/btns_abc</item>
</style>
And in my btns_abc I set the background to my image resource. Currently state pressed and the normal state are the same, I want to change that as soon as it works properly:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/ooo" android:state_pressed="true"></item>
<item android:drawable="#drawable/ooo"></item>
</selector>
Thanks !
I don't know the exact reason but for a solution if u don't have any text for button ,use ImageView will show the same drawable u have added.
My imagebutton code wont respond to "fill_parent" and "wrap_content".
Instead, it just shows the middle of the image (because it is a pretty big image).
I tried setting specific values for the image but it still didn't work! Can somebody help me?
My button.xml in the res/drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">\
<item android:state_pressed="true"
android:drawable="#drawable/largishbutton" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/largerbutton2" /> <!-- focused -->
<item android:drawable="#drawable/largerbutton" /> <!-- default -->
</selector>
My main.xml in the res/layout folder:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/white">
<ImageButton
android:src="#drawable/button"
android:layout_height="fill_parent"
android:layout_width="wrap_content"
/>
</RelativeLayout>
I tried using a LinearLayout, but the app wouldnt run, and I tried replacing the imagebutton with an imageview, but then the button didn't work.
If your image is bigger than your button, you will need to use something like android:scaleType or setMaxHeight() to have it resize to fit.
Also, I recommend that you have all images in your <selector> be the same size, at least until you get things working the way you wish.