问题
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.
回答1:
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/
回答2:
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>
来源:https://stackoverflow.com/questions/32534578/cardview-dynamic-shadow-depends-not-only-on-elevation