Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Center ImageView relative to screen(ignore status bar and navigation bar)

Tags:

android

layout

I am using the react native splash screen package(https://github.com/crazycodeboy/react-native-splash-screen), and am trying to implement a proper splash screen in Android, where a logo is displayed.

I originally found this article on it, which covered it pretty well: https://medium.com/handlebar-labs/how-to-add-a-splash-screen-to-a-react-native-app-ios-and-android-30a3cec835ae - however, i have the "jumping issue" the article explains, but in a way the author probably didn't expect.

Let explain: When the app first opens, a layer-list based splash screen is displayed on the launch activity, which transfers to the react-native-splash-screen activity(defined by launch_screen.xml) when the app has loaded in memory. The problem is that while the theme on the startup activity fills the entire screen, the second stage of the splash screen defined in launch_screen.xmldoes care about layout. Because of this, the "centered logo" is offset either 24dp up, or down, depending on if the android device has soft navigation buttons or not.

If it was a constant offset, i'd just use margin to offset the logo, but because of the navigation buttons, i'd need some kind of conditional in the xml, which can detect and react to the navigation bar existing.

Therefore, i would like to align an ImageView in the center of the screen, not its parent container. That, or have the parent container somehow exist underneath the navigation bar when present.

Or, in other words, the issue is that the first-stage of the splash centers relative to the screen, while the second-stage centers relative to the usable space of the screen, and i'd like to match the two, in some way that works regardless of navigation bar existence

Is this possible?

Code

launch_screen.xml (layout of the second stage of the splash)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:background="@color/background">

    <TextView android:text="App"
         android:layout_alignParentBottom="true"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:paddingBottom="20dp"
         android:gravity="center"/>



    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">

        <ImageView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:src="@mipmap/logo"/>

    </LinearLayout>
</RelativeLayout>

background_splash.xml (Theme used in the first stage of the splash)

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

    <item
        android:drawable="@color/background"/>

    <item
        android:width="200dp"
        android:height="200dp"
        android:drawable="@mipmap/logo"
        android:gravity="center"
         />

</layer-list>
like image 437
Liam S. Crouch Avatar asked Jun 19 '18 07:06

Liam S. Crouch


1 Answers

You can offset the launch screen programmatically with something like the following

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    ImageView image = view.findViewById(R.id.image_logo);
    image.setTranslationY((getNavBarHeight() - getStatusBarHeight()) / 2.0f);

}

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public int getNavBarHeight(){
    Resources resources = getResources();
    int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        return resources.getDimensionPixelSize(resourceId);
    }
    return 0;
}
like image 178
Zates Avatar answered Sep 30 '22 20:09

Zates