0

While developing my app I'd created a RecyclerView with expandable CardViews inside and then mentioned "hey, why does the elevation is changing a bit while I'm animating only vertical size of card and opacity of extension?".

And then I've found what it's not an elevation who chages -- it's only a shadow changed.

Does anybody heard smth about it? Is it just an undescribed thing of interface drawing? I have no objections for cool feature, but it just a bit confused me (I've even spend about an hour to find out something about it on Google's guidelines)

I've shared the code that proves the idea of "height affects shadow drawing" but share some information if theres' something more behind this.

Cœur
  • 37,241
  • 25
  • 195
  • 267
AlpenDitrix
  • 322
  • 2
  • 8

2 Answers2

6

In Material Design there are 2 light sources:

  • key light - a sharp light source ~45° above the screen (over your head)
  • ambient light - softer and weaker light source perpendicular to the screen (behind your head)

The shadow of the key light dominates.

This model is implemented in Android UI. Now, the light from the key light is hitting elements close to the top of the screen under a different angle than elements at the bottom, so the shadow is cast under a different angle accordingly, just as in reality - the intention behind Material Design.

Practically: the closer the element to the bottom, the stronger the shadow at the element's bottom edge and lighter at the top edge.

See Material Design: Environment: Light and shadows: Light

Image linked from: https://touchlab.co/2016-1-consistent-lighting-in-material-design/

0

activity_main.xml

<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent" android:layout_height="match_parent">
    <android.support.v7.widget.CardView android:id="@+id/dumb_card"
                                        android:layout_margin="16dp"
                                        tools:cardCornerRadius="4dp"
                                        android:layout_width="match_parent" android:layout_height="wrap_content">
        <LinearLayout android:orientation="vertical"
                      android:layout_width="match_parent" android:layout_height="match_parent">

            <SeekBar android:id="@+id/heighter"
                     android:layout_margin="16dp"
                     android:layout_width="match_parent" android:layout_height="wrap_content"/>

            <SeekBar android:id="@+id/elevator"
                     android:layout_margin="16dp"
                     android:layout_width="match_parent" android:layout_height="wrap_content"/>

        </LinearLayout>
    </android.support.v7.widget.CardView>
</FrameLayout>

MainActivity.java

public class MainActivity extends Activity {
    CardView card;
    SeekBar  heighter;
    SeekBar  elevator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //card
        card = (CardView) findViewById(R.id.dumb_card);

        //card height
        heighter = (SeekBar) findViewById(R.id.heighter);
        heighter.setMax(2500);
        heighter.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                ViewGroup.LayoutParams lp = card.getLayoutParams();
                lp.height = progress;
                card.setLayoutParams(lp);
            }
            public void onStartTrackingTouch(SeekBar seekBar) {}
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });

        //card elevation
        elevator = (SeekBar) findViewById(R.id.elevator);
        elevator.setMax(250);
        elevator.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                card.setCardElevation(progress);
            }
            public void onStartTrackingTouch(SeekBar seekBar) {}
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }
}

AndroidManifest.xml

<application
    android:label="DumbCardElevation"
    android:theme="@android:style/Theme.Holo.Light" >
    <activity
        android:name=".MainActivity" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

AlpenDitrix
  • 322
  • 2
  • 8