22

I'm trying to take advantage of the new KitKat translucent system bars, to get a full screen image in the background of my app.

I'm having problems figuring out the right settings to get the behaviour I want. Right now I have a ViewPager with three Fragments each one composed of a RelativeLayout containing an ImageView (for the background image) and a TextView for the content.

What I'm after is to have the content fit fully in the portion of the screen available for interactions, and the image to take the whole visible portion of the screen.

If I just use android:Theme.Holo.Light.NoActionBar.TranslucentDecor as my theme it looks fine in portrait, but the navigation bar overlaps the content in landscape (see the screenshots below).

First attempt - portrait. Looks good.First attempt - landscape. nav bar overlaps the content

Following the recommendation in the docs, I added android:fitsSystemWindows = true to my theme, but that generates some weird artifacts (see below) Second attempt - portrait. Artifacts!! Second attempt - landscape. Artifacts!!

How can I make it behave like in the second example, but look good, without the visual artifacts?

Krzysztof Kozmic
  • 27,267
  • 12
  • 73
  • 115

5 Answers5

39

My solution was to disable translucent navigation in landscape mode. You still get a translucent status bar, but it fixes the issue where the nav bar is opaque and overlaps in landscape.

res/values-v19/styles.xml (these values are in my theme)

<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">@bool/translucentNavBar</item>

res/values-v19/bools.xml (enable translucent nav)

<bool name="translucentNavBar">true</bool>

res/values-land-v19/bools.xml (disable translucent nav in landscape)

<bool name="translucentNavBar">false</bool>

res/values-sw600dp-land-v19/bools.xml (enable translucent nav for tablets in landscape)

<bool name="translucentNavBar">true</bool>
Tanner Perrien
  • 3,133
  • 1
  • 28
  • 35
  • 1
    +1 for an inteligent workaround ;) Is this the best _solution_ though? For example on tablets, the navbar stays translucent, and moves the bottom of the screen in portrait, so I don't want to disable it there... – Krzysztof Kozmic Dec 28 '13 at 22:49
  • This solution only disables the nav bar in landscape, not portrait. Did I misunderstand something? From what I can tell, my issue was exactly the same as yours. For what it's worth, I had no need to use `android:fitsSystemWindows` – Tanner Perrien Dec 29 '13 at 06:21
  • No, sorry. I meant _in landscape_. In tablets, the nav bar stays transparent, and at the (logical) bottom of the screen regardless of the orientation, so the problem only occurs on phones. So it would be nice, if your workaround is indeed the least worst solution, to only apply it on phones, or more generally - devices/orientations where the navbar becomes opaque – Krzysztof Kozmic Dec 29 '13 at 08:28
  • 1
    Got it! I just edited my answer to reflect how you can keep translucent nav enabled for landscape on tablets. – Tanner Perrien Dec 29 '13 at 19:59
  • 3
    Shouldn't that be `res/values-sw600dp-land-v19/bools.xml`? – Lesik2008 Feb 22 '14 at 19:56
7

I know this is old, but I've just run into the same problem and found an easy solution, so I wanted to share it in case this was run into by anyone Google'ing around.

It seems that there is an Android bug when a ViewPager (especially an ImageSwitcher) is placed within a layout that has the attribute android:fitsSystemWindows="true". For some reason the system windows seem to be getting artifacts drawn all over them. :/

Anyway, I found a fix. For my activity, I had an XML layout as follows:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    <!-- NOT HERE! android:fitsSystemWindows="true" -->
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageSwitcher
        android:id="@+id/background_image_switcher"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="0dp"
        android:layout_margin="0dp"
        android:background="@color/background_dark_navy"
        android:inAnimation="@android:anim/fade_in"
        android:outAnimation="@android:anim/fade_out"
        >

        <ImageView
            style="@style/BlurredBackgroundImage"
            />
        <ImageView
            style="@style/BlurredBackgroundImage"
            />

    </ImageSwitcher>

    <FrameLayout
        android:fitsSystemWindows="true" <!-- Here!!! -->
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Fitted content here -->

    </FrameLayout>

The trick was to not contain the ImageSwitcher in a layout with the android:fitsSystemWindows="true" attribute, but to instead move the android:fitsSystemWindows="true" attribute to the inner FrameLayout containing the actual content I needed to fit (the title text in your case). Unfortunately, this allows for the ImageSwitcher/ViewPager's view to get slightly cut off by the system windows, but if the image is used like a background image anyway it doesn't matter too much and is a much better trade off than artifacts or maintaining all of the different dimensions/styles that may or may not have disabled navigation (such as the currently selected answer).

I hope this helps someone!

Rican7
  • 1,125
  • 2
  • 10
  • 28
  • I've filed an Android bug for this issue. Feel free to star it to get updates on its progress: https://code.google.com/p/android/issues/detail?id=73372 – Rican7 Jul 10 '14 at 20:50
3

I've run into similar problems, but I wasn't using a ViewPager, so this may not work. I solved by doing some nesting as Gabe described: only the inner ViewGroup is fitSystemWindows="true", the outer ViewGroup which displays the background is therefore allowed to extend under the translucent bars. Then I'm also calling requestFitSystemWindows() on orientation changes. Again, your ViewPager might be complicating things and my solution won't work, but I hope this helps.

danh32
  • 6,234
  • 2
  • 38
  • 39
2

Put another ViewGroup inside of the one with the image and fitsSystemWindows to true

Gabe
  • 1,239
  • 1
  • 13
  • 20
  • Hey, thanks for your help. I updated the question to mention that there's a `ViewPager` around this. Each screen has its own background too. I tried your recommendation. I added another `RelativeLayout` but it doesn't quite get me there. I still get visual artifacts, although behaving differently now. Here's the portrait and landscape screen-recording showing what's happening (notice how inconsistent it is): https://dl.dropboxusercontent.com/u/2887400/landscape_1.mp4 and https://dl.dropboxusercontent.com/u/2887400/portrait_1.mp4 – Krzysztof Kozmic Dec 26 '13 at 08:42
-3

You should wrap this inside an Linear Layout and set fitsSystemWindows to true.

Engineer2021
  • 3,288
  • 6
  • 29
  • 51
user3339439
  • 95
  • 1
  • 7