Android Bottom Sheet with Dimmed Background

So, I was developing a new budget feature for Monitor for EnergyHive and Engage and needed a way to display the data without obstructing the current user interface.

I am going to do a complete redesign of the app sometime soon, but for now, this is how it looks:



As you can see, the design I have used doesn’t leave much space for extra features. I’m in desperate need of a good UI designer.


Anyway. As always, the Google Material Design Spec is a godsend for us developers who have no sense of style. I wanted to achieve something like the first image on the bottom sheet spec with nice animations.


Essentially, a modal bottom sheet that contains normal interactive elements rather then a list. I was glad to see that official bottom sheet support was added to the Android Support Library 23.2 but after looking further into the implementation, what I wanted didn’t look as simple as I thought it would be.

You see, the support library offered two options - the ability to create a bottom sheet out of any view inside a CoordinatorLayout & a BottomSheetDialog / BottomSheetDialogFragment.

At a glance, the BottomSheetDialogFragment is just what I wanted as it hosts a fragment in a bottom sheet, and dims the existing activity. But nope, instead of a smooth upward animation, I got a jarring activity transition exactly like the native sharing “animation” in stock android.

Ugly!
I started playing with FrameLayouts, and TouchEvents to try and get the animation you see below. I’ll go through the steps I went through, and explain briefly.


Creating the Fragment

I have ommitted most of the code, as it is unnecessary. I tend to use custom AsyncTaskLoaders to fetch data from the server. Here, I have inflated the views from the associated layout and created a public method that will allow me to communicate visibility from the MainActivity to the Fragment.
This may seem all very random but trust me, it will make sense later on.

Adding the Bottom Sheet Fragment to the Main Activity

As you can see above, I wrapped the main fragment which contains the app (you could wrap your views) in a FrameLayout with it’s foreground set to a drawable that is simply a black rectangle.

shape_window_dim.xml:

So that’s the layouts done. Awesome. Now we need to build in the functionality. Here is a code snippet from my MainActivity.java. I’ll explain it through comments.

setScrim()

So, let’s go through this step by step.
  1. I’m grabbing the the Primary Dark colour to use as the status bar background. I am only applying this on Android Lollipop and above. Over 70% of my users are on API 21 and above, so I haven’t bothered to check before grabbing the colour.
  2. Call the setScrim() method. I am calling it a scrim as that’s what Google calls them, although it seems to be a North American word. Anyway. This method takes the FrameLayout, and cahnges the alpha of the foreground drawable. As the slide offset is between 0 and 1, we can multiply this to get an alpha value - 0 to 255. By changing the factor, we can change the darkest it will become - I have chosen 150, which is about 60% transparency.
  3. I also have a Utility method which darkens a colour by a value.
This post is still a work in progress so stay tuned for more. I’m not the best at writing and explaining, but I hope to improve over time :D

Comments

Popular

Custom Error Handling with RxJava & Retrofit 2

Graphing Energy Consumption with TP Link HS100 Smart Plug