Thoroughly understand the "shadow" in Android MD design

Thoroughly understand the "shadow" in Android MD design

[[220766]]

If we want to create better Android apps, I believe we need to follow the design specifications of Material Design. Generally speaking, Material Design is a three-dimensional environment that includes light sources, materials, and projections. If we want to follow the design principles of Material Design during the development of the App, then understanding light and shadow is particularly important.

I will try to explain the following topics in this article.

  • 3D in Android
  • Depth
  • Z axis, Elevation and Translation Z.
  • light source
  • Button states (pressed and resting)
  • Outline
  • Custom ViewOutlineProvider

Before we dive into shadows and light, what do I want to tell you about our real environment?

What is 3D?

The real material environment is a three-dimensional space, which means that all objects have X, Y and Z dimensions. The Z axis is aligned perpendicular to the plane of the display, and the positive Z axis extends towards the viewer. In the world of Material Design, each object has a thickness of 1dp.

Android Depth

Material Design is different from other design guidelines because it adds the concept of Depth. Depth has important meaning in real vision.

We can think of it as if we have a layer of paper on our table, and if we put another piece of paper on it, our eyes will feel that it has a depth.

Let’s imagine it through a screenshot of a Material Design app.

Let's take a look at the various elements on the screen.

  • Screen (surface - depth 0)
  • CardViews
  • App UI Layout
  • Floating Action Button

Here, each element is on top of another. CardView can scroll, so we can say the first layer is the scrollable content, the second layer is the AppBar layout, and the third layer (top layer) is the floating action button.

So, how do we define hierarchy? How do we give users a sense of depth? The answer is: the Z-axis.

What is Z value in Android?

The Z value of a View has two components:

  • Elevation: Height, a static value.
  • Translation Z: Z-axis change value, used for dynamic value of animation.

I always wonder what the difference is between Elevation and Translation Z.

Elevation is static, so you should never change it dynamically. If you want to animate the Z axis (like pressed or static), you need to use the Translation Z property.

Translation Z is dynamic, when you create a blank project and add a button to it, you will see the shadow get bigger when you press it. Actually, the Elevation does not change, but the Translation Z property changes. This is Android using the default state list animation, changing the Z property.

Z Vaue = Elevation + TranslationZ

If we change the Z values ​​of the two Views so that they intersect, how does Android handle the hierarchy on the screen? Let me show you with a diagram I designed.

Another question, how do we see the shadow of an object? Do we need a shadow? No, we need a light source.

What are light sources in Android?

The question is not what, but where.

In reality, if we hold a flashlight and shine it on an object on a table (from the top of it), the length of the shadow will decrease, and as you lower it, the length of the shadow will increase.

So where is the light source in Android's Material Design? At the top? Or at an angle? After some research, I found this phenomenon.

There are two light sources in Android, the top one is the key light source, and the other is the ambient light source. The shadow we see is actually the combination of these two light sources.

Let's see the display effect.

In Android, we have many widgets. Buttons, CardView, Dialogs, Drawers, etc. All of these are views. If there is a light source, we have shadows. So how do we decide the Z value in Android? How does Material Design dictate this?

There is a schematic diagram to reflect this situation.

Still or press

As I mentioned before, in Android Framework, some animations are implemented for widgets. If you place a floating action button in your layout, it will have an elevation of 6dp by default. But you will notice that when you press the button, the elevation of the FAB will increase to 12dp.

Let me tell you what happened during this process.

Actually FAB has 6dp Elevation. When you press the button, the translationZ value starts to increase. ViewPropertyAnimator animates the view by changing the translationZ value from 0dp to 6dp. If you release the button, ViewPropertyAnimator plays the animation, changing the translationZ from 6dp to 0dp. You can create a custom state list animation for your view and add it to your view.

Let's take a look at the flowchart of this process.

Secret of Shadows: Outline

Outline is a class under android.graphic. Let's see what its documentation says.

Defines a simple shape to be used for the bounding area of ​​a graphic.

Can be calculated for a View, or by a Drawable to drive the shape of a shadow cast by a view, or to clip a view's content.

Every View has a default outline to show its shadow. If we create a custom shape drawable, its outline will be calculated internally based on its shape. So, if we draw a circle, the outline will be a circle. If we draw a rectangle, the outline will be a rectangle.

To summarize, there is an Outlin that allows you to see this effect in an invisible way. But what if I want to create a custom view and change its bounds dynamically? Will Android provide an Outline for my custom view?

Of course, Android provides us with a way to customize the Outline, that is: ViewOutlineProvider.

What is ViewOutlineProvider

In my recent open source ScalingLayout library, I did not implement shadow effects for custom views. I thought it was very beautiful without shadows. But remember the basics of Material Design, 3D, Depth, Z-Value.

In this animation, we may not be able to determine which areas are clickable, and there are no shadows in the zoom layout.

Next we provide a dynamic outline for our custom view.

  1. public class ScalingLayoutOutlineProvider extends ViewOutlineProvider {
  2.  
  3. @Override
  4. public void getOutline( View   view , Outline outline) {
  5. outline.setRoundRect(0, 0, width, height, radius);
  6. }
  7. }
  8. public class ScalingLayout extends FrameLayout {
  9.  
  10. //...
  11. viewOutline = new ScalingLayoutOutlineProvider(w, h, currentRadius);
  12. setOutlineProvider(viewOutline);
  13. //..
  14.  
  15. }

In this way, we have added height support for custom View.

For more simplified basics on how to use ViewOutlineProvider, you can find details in ScalingLayout.

https://github.com/iammert/ScalingLayout

[This article is an original article by 51CTO columnist "Zhang Yang". Please contact the author through WeChat official account to obtain authorization for reprinting]

Click here to read more articles by this author

<<:  Apple will not be the first to adopt 5G technology because of these three reasons

>>:  What is the role of artificial intelligence in mobile app development and business?

Recommend

During holiday gatherings, beware of secretly elevated uric acid levels!

《Cotton Swab Medical Science Popularization》 Chin...

How good is the product manager in a programmer’s dream?

The conflicts between programmers and product man...

How to promote APP? APP promotion tips!

Mobile devices have become the most important too...

Why are instant noodles curly? Because there is a reason for them to be curly

Instant noodles are the most common but indispens...

5000 words to analyze the philosophy of planting grass when browsing Taobao!

It’s Double Eleven again this year. At 0:00 on No...

New WeChat chat function: You can add hyperlinks

On the evening of November 19, Tencent WeChat’s o...