前言

Material Design 规范指导里面特别提出了阴影的重要性和如何正确使用的方法(点击传送),那我们就更加不能忽视这一点了,本篇文章就要教大家如何设置阴影,做出一个有层次感的界面。

设置方法: android:elevation 分别设置不同数值的elevation效果如下:
layout: [html] view plain copy print ?
  1. <LinearLayout
  2. android:layout_width="match_parent"
  3. android:layout_height="wrap_content"
  4. android:orientation="horizontal">
  5. <TextViewandroid:layout_width="100dp"
  6. android:layout_margin="2dp"
  7. android:layout_height="100dp"
  8. android:text="test"
  9. android:background="@android:color/white"
  10. android:gravity="center"
  11. android:elevation="1dip"
  12. />
  13. <TextViewandroid:layout_width="100dp"
  14. android:layout_margin="2dp"
  15. android:layout_height="100dp"
  16. android:text="test"
  17. android:background="@android:color/white"
  18. android:gravity="center"
  19. android:elevation="4dip"/>
  20. <TextViewandroid:layout_width="100dp"
  21. android:layout_margin="2dp"
  22. android:layout_height="100dp"
  23. android:text="test"
  24. android:background="@android:color/white"
  25. android:gravity="center"
  26. android:elevation="8dip"
  27. />
  28. </LinearLayout>

View的z值由两部分组成,elevation和translationZ.

eleavation是静态的成员,translationZ是用来做动画。

Z = elevation + translationZ


在布局中使用android:elevation属性去定义

在代码中使用View.setElevation方法去定义

设置视图的translation,可以使用View.setTranslationZ方法

新的ViewPropertyAnimator.zViewPropertyAnimator.translationZ方法可以设置视图的elevation


在5.0 的API Demos中 Graphics-》Shadow Card Drag 和 Shadow Card stack 这两个例子就很好的使用translationZ和eleavation

Shadow Card Drag 源码:
[java] view plain copy print ?
  1. /*
  2. *Copyright(C)2014TheAndroidOpenSourceProject
  3. *
  4. *LicensedundertheApacheLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  11. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  12. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  13. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  14. *limitationsundertheLicense.
  15. */
  16. packagecom.example.android.apis.graphics;
  17. importandroid.animation.ObjectAnimator;
  18. importandroid.app.Activity;
  19. importandroid.graphics.Canvas;
  20. importandroid.graphics.Color;
  21. importandroid.graphics.Outline;
  22. importandroid.graphics.Paint;
  23. importandroid.graphics.Path;
  24. importandroid.graphics.PorterDuff;
  25. importandroid.graphics.drawable.ShapeDrawable;
  26. importandroid.graphics.drawable.shapes.OvalShape;
  27. importandroid.graphics.drawable.shapes.RectShape;
  28. importandroid.graphics.drawable.shapes.RoundRectShape;
  29. importandroid.graphics.drawable.shapes.Shape;
  30. importandroid.os.Bundle;
  31. importandroid.view.MotionEvent;
  32. importandroid.view.View;
  33. importandroid.view.animation.AccelerateInterpolator;
  34. importandroid.view.animation.DecelerateInterpolator;
  35. importandroid.widget.Button;
  36. importandroid.widget.CheckBox;
  37. importandroid.widget.CompoundButton;
  38. importcom.example.android.apis.R;
  39. importjava.util.ArrayList;
  40. publicclassShadowCardDragextendsActivity{
  41. privatestaticfinalfloatMAX_Z_DP=10;
  42. privatestaticfinalfloatMOMENTUM_SCALE=10;
  43. privatestaticfinalintMAX_ANGLE=10;
  44. privateclassCardDragState{
  45. longlastEventTime;
  46. floatlastX;
  47. floatlastY;
  48. floatmomentumX;
  49. floatmomentumY;
  50. publicvoidonDown(longeventTime,floatx,floaty){
  51. lastEventTime=eventTime;
  52. lastX=x;
  53. lastY=y;
  54. momentumX=0;
  55. momentumY=0;
  56. }
  57. publicvoidonMove(longeventTime,floatx,floaty){
  58. finallongdeltaT=eventTime-lastEventTime;
  59. if(deltaT!=0){
  60. floatnewMomentumX=(x-lastX)/(mDensity*deltaT);
  61. floatnewMomentumY=(y-lastY)/(mDensity*deltaT);
  62. momentumX=0.9f*momentumX+0.1f*(newMomentumX*MOMENTUM_SCALE);
  63. momentumY=0.9f*momentumY+0.1f*(newMomentumY*MOMENTUM_SCALE);
  64. momentumX=Math.max(Math.min((momentumX),MAX_ANGLE),-MAX_ANGLE);
  65. momentumY=Math.max(Math.min((momentumY),MAX_ANGLE),-MAX_ANGLE);
  66. //noinspectionSuspiciousNameCombination
  67. mCard.setRotationX(-momentumY);
  68. //noinspectionSuspiciousNameCombination
  69. mCard.setRotationY(momentumX);
  70. if(mShadingEnabled){
  71. floatalphaDarkening=(momentumX*momentumX+momentumY*momentumY)/(90*90);
  72. alphaDarkening/=2;
  73. intalphaByte=0xff-((int)(alphaDarkening*255)&0xff);
  74. intcolor=Color.rgb(alphaByte,alphaByte,alphaByte);
  75. mCardBackground.setColorFilter(color,PorterDuff.Mode.MULTIPLY);
  76. }
  77. }
  78. lastX=x;
  79. lastY=y;
  80. lastEventTime=eventTime;
  81. }
  82. publicvoidonUp(){
  83. ObjectAnimatorflattenX=ObjectAnimator.ofFloat(mCard,"rotationX",0);
  84. flattenX.setDuration(100);
  85. flattenX.setInterpolator(newAccelerateInterpolator());
  86. flattenX.start();
  87. ObjectAnimatorflattenY=ObjectAnimator.ofFloat(mCard,"rotationY",0);
  88. flattenY.setDuration(100);
  89. flattenY.setInterpolator(newAccelerateInterpolator());
  90. flattenY.start();
  91. mCardBackground.setColorFilter(null);
  92. }
  93. }
  94. /**
  95. *Simpleshapeexamplethatgeneratesashadowcastingoutline.
  96. */
  97. privatestaticclassTriangleShapeextendsShape{
  98. privatefinalPathmPath=newPath();
  99. @Override
  100. protectedvoidonResize(floatwidth,floatheight){
  101. mPath.reset();
  102. mPath.moveTo(0,0);
  103. mPath.lineTo(width,0);
  104. mPath.lineTo(width/2,height);
  105. mPath.lineTo(0,0);
  106. mPath.close();
  107. }
  108. @Override
  109. publicvoiddraw(Canvascanvas,Paintpaint){
  110. canvas.drawPath(mPath,paint);
  111. }
  112. @Override
  113. publicvoidgetOutline(Outlineoutline){
  114. outline.setConvexPath(mPath);
  115. }
  116. }
  117. privatefinalShapeDrawablemCardBackground=newShapeDrawable();
  118. privatefinalArrayList<Shape>mShapes=newArrayList<Shape>();
  119. privatefloatmDensity;
  120. privateViewmCard;
  121. privatefinalCardDragStatemDragState=newCardDragState();
  122. privatebooleanmTiltEnabled;
  123. privatebooleanmShadingEnabled;
  124. @Override
  125. protectedvoidonCreate(BundlesavedInstanceState){
  126. super.onCreate(savedInstanceState);
  127. setContentView(R.layout.shadow_card_drag);
  128. mDensity=getResources().getDisplayMetrics().density;
  129. mShapes.add(newRectShape());
  130. mShapes.add(newOvalShape());
  131. floatr=10*mDensity;
  132. floatradii[]=newfloat[]{r,r,r,r,r,r,r,r};
  133. mShapes.add(newRoundRectShape(radii,null,null));
  134. mShapes.add(newTriangleShape());
  135. mCardBackground.getPaint().setColor(Color.WHITE);
  136. mCardBackground.setShape(mShapes.get(0));
  137. finalViewcardParent=findViewById(R.id.card_parent);
  138. mCard=findViewById(R.id.card);
  139. mCard.setBackground(mCardBackground);
  140. finalCheckBoxtiltCheck=(CheckBox)findViewById(R.id.tilt_check);
  141. tiltCheck.setOnCheckedChangeListener(newCompoundButton.OnCheckedChangeListener(){
  142. @Override
  143. publicvoidonCheckedChanged(CompoundButtonbuttonView,booleanisChecked){
  144. mTiltEnabled=isChecked;
  145. if(!mTiltEnabled){
  146. mDragState.onUp();
  147. }
  148. }
  149. });
  150. finalCheckBoxshadingCheck=(CheckBox)findViewById(R.id.shading_check);
  151. shadingCheck.setOnCheckedChangeListener(newCompoundButton.OnCheckedChangeListener(){
  152. @Override
  153. publicvoidonCheckedChanged(CompoundButtonbuttonView,booleanisChecked){
  154. mShadingEnabled=isChecked;
  155. if(!mShadingEnabled){
  156. mCardBackground.setColorFilter(null);
  157. }
  158. }
  159. });
  160. finalButtonshapeButton=(Button)findViewById(R.id.shape_select);
  161. shapeButton.setOnClickListener(newView.OnClickListener(){
  162. intindex=0;
  163. @Override
  164. publicvoidonClick(Viewv){
  165. index=(index+1)%mShapes.size();
  166. mCardBackground.setShape(mShapes.get(index));
  167. }
  168. });
  169. /**
  170. *Enableanytouchontheparenttodragthecard.Notethatthisdoesn'tdoaproperhit
  171. *test,soanydrag(includingoffofthecard)willwork.
  172. *
  173. *Thisenablestheusertoseetheeffectmoreclearlyforthepurposeofthisdemo.
  174. */
  175. cardParent.setOnTouchListener(newView.OnTouchListener(){
  176. floatdownX;
  177. floatdownY;
  178. longdownTime;
  179. @Override
  180. publicbooleanonTouch(Viewv,MotionEventevent){
  181. switch(event.getAction()){
  182. caseMotionEvent.ACTION_DOWN:
  183. downX=event.getX()-mCard.getTranslationX();
  184. downY=event.getY()-mCard.getTranslationY();
  185. downTime=event.getDownTime();
  186. ObjectAnimatorupAnim=ObjectAnimator.ofFloat(mCard,"translationZ",
  187. MAX_Z_DP*mDensity);
  188. upAnim.setDuration(100);
  189. upAnim.setInterpolator(newDecelerateInterpolator());
  190. upAnim.start();
  191. if(mTiltEnabled){
  192. mDragState.onDown(event.getDownTime(),event.getX(),event.getY());
  193. }
  194. break;
  195. caseMotionEvent.ACTION_MOVE:
  196. mCard.setTranslationX(event.getX()-downX);
  197. mCard.setTranslationY(event.getY()-downY);
  198. if(mTiltEnabled){
  199. mDragState.onMove(event.getEventTime(),event.getX(),event.getY());
  200. }
  201. break;
  202. caseMotionEvent.ACTION_UP:
  203. ObjectAnimatordownAnim=ObjectAnimator.ofFloat(mCard,"translationZ",0);
  204. downAnim.setDuration(100);
  205. downAnim.setInterpolator(newAccelerateInterpolator());
  206. downAnim.start();
  207. if(mTiltEnabled){
  208. mDragState.onUp();
  209. }
  210. break;
  211. }
  212. returntrue;
  213. }
  214. });
  215. }
  216. }
layout: [html] view plain copy print ?
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <!--Copyright(C)2014TheAndroidOpenSourceProject
  3. LicensedundertheApacheLicense,Version2.0(the"License");
  4. youmaynotusethisfileexceptincompliancewiththeLicense.
  5. YoumayobtainacopyoftheLicenseat
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  8. distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  9. WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  10. SeetheLicenseforthespecificlanguagegoverningpermissionsand
  11. limitationsundertheLicense.
  12. -->
  13. <FrameLayout
  14. xmlns:android="http://schemas.android.com/apk/res/android"
  15. android:id="@+id/card_parent"
  16. android:layout_width="match_parent"
  17. android:layout_height="match_parent"
  18. android:clipChildren="false"
  19. android:clipToPadding="false"
  20. android:orientation="horizontal">
  21. <LinearLayout
  22. android:layout_width="match_parent"
  23. android:layout_height="wrap_content"
  24. android:orientation="horizontal">
  25. <CheckBox
  26. android:id="@+id/tilt_check"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:checked="false"
  30. android:text="@string/enable_tilt"/>
  31. <CheckBox
  32. android:id="@+id/shading_check"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:checked="false"
  36. android:text="@string/enable_shading"/>
  37. <Button
  38. android:id="@+id/shape_select"
  39. android:layout_width="wrap_content"
  40. android:layout_height="wrap_content"
  41. android:text="@string/select_shape"/>
  42. </LinearLayout>
  43. <TextView
  44. android:id="@+id/card"
  45. android:layout_width="150dp"
  46. android:layout_height="150dp"
  47. android:background="@drawable/round_rect"
  48. android:clipToPadding="false"
  49. android:gravity="center"
  50. android:padding="20dp"
  51. android:text="@string/draggable_card"
  52. android:textSize="20sp"
  53. android:elevation="2dp"/>
  54. </FrameLayout>


Shadow Card stack 源码: [java] view plain copy print ?
  1. /*
  2. *Copyright(C)2014TheAndroidOpenSourceProject
  3. *
  4. *LicensedundertheApacheLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  11. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  12. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  13. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  14. *limitationsundertheLicense.
  15. */
  16. packagecom.example.android.apis.graphics;
  17. importandroid.animation.Animator;
  18. importandroid.animation.AnimatorSet;
  19. importandroid.animation.ObjectAnimator;
  20. importandroid.app.Activity;
  21. importandroid.os.Bundle;
  22. importandroid.view.ViewGroup;
  23. importandroid.widget.TextView;
  24. importcom.example.android.apis.R;
  25. importjava.util.ArrayList;
  26. publicclassShadowCardStackextendsActivity{
  27. privatestaticfinalfloatX_SHIFT_DP=1000;
  28. privatestaticfinalfloatY_SHIFT_DP=50;
  29. privatestaticfinalfloatZ_LIFT_DP=8;
  30. privatestaticfinalfloatROTATE_DEGREES=15;
  31. publicAnimatorSetcreateSet(ArrayList<Animator>items,longstartDelay){
  32. AnimatorSetset=newAnimatorSet();
  33. set.playTogether(items);
  34. set.setStartDelay(startDelay);
  35. returnset;
  36. }
  37. @Override
  38. protectedvoidonCreate(BundlesavedInstanceState){
  39. super.onCreate(savedInstanceState);
  40. setContentView(R.layout.shadow_card_stack);
  41. floatdensity=getResources().getDisplayMetrics().density;
  42. finalViewGroupcardParent=(ViewGroup)findViewById(R.id.card_parent);
  43. finalfloatX=X_SHIFT_DP*density;
  44. finalfloatY=Y_SHIFT_DP*density;
  45. finalfloatZ=Z_LIFT_DP*density;
  46. ArrayList<Animator>towardAnimators=newArrayList<Animator>();
  47. ArrayList<Animator>expandAnimators=newArrayList<Animator>();
  48. ArrayList<Animator>moveAwayAnimators=newArrayList<Animator>();
  49. ArrayList<Animator>moveBackAnimators=newArrayList<Animator>();
  50. ArrayList<Animator>awayAnimators=newArrayList<Animator>();
  51. ArrayList<Animator>collapseAnimators=newArrayList<Animator>();
  52. finalintmax=cardParent.getChildCount();
  53. for(inti=0;i<max;i++){
  54. TextViewcard=(TextView)cardParent.getChildAt(i);
  55. card.setText("Cardnumber"+i);
  56. floattargetY=(i-(max-1)/2.0f)*Y;
  57. Animatorexpand=ObjectAnimator.ofFloat(card,"translationY",targetY);
  58. expandAnimators.add(expand);
  59. Animatortoward=ObjectAnimator.ofFloat(card,"translationZ",i*Z);
  60. toward.setStartDelay(200*((max)-i));
  61. towardAnimators.add(toward);
  62. card.setPivotX(X_SHIFT_DP);
  63. AnimatorrotateAway=ObjectAnimator.ofFloat(card,"rotationY",
  64. i==0?0:ROTATE_DEGREES);
  65. rotateAway.setStartDelay(200*((max)-i));
  66. rotateAway.setDuration(100);
  67. moveAwayAnimators.add(rotateAway);
  68. AnimatorslideAway=ObjectAnimator.ofFloat(card,"translationX",
  69. i==0?0:X);
  70. slideAway.setStartDelay(200*((max)-i));
  71. slideAway.setDuration(100);
  72. moveAwayAnimators.add(slideAway);
  73. AnimatorrotateBack=ObjectAnimator.ofFloat(card,"rotationY",0);
  74. rotateBack.setStartDelay(200*i);
  75. moveBackAnimators.add(rotateBack);
  76. AnimatorslideBack=ObjectAnimator.ofFloat(card,"translationX",0);
  77. slideBack.setStartDelay(200*i);
  78. moveBackAnimators.add(slideBack);
  79. Animatoraway=ObjectAnimator.ofFloat(card,"translationZ",0);
  80. away.setStartDelay(200*i);
  81. awayAnimators.add(away);
  82. Animatorcollapse=ObjectAnimator.ofFloat(card,"translationY",0);
  83. collapseAnimators.add(collapse);
  84. }
  85. AnimatorSettotalSet=newAnimatorSet();
  86. totalSet.playSequentially(
  87. createSet(expandAnimators,250),
  88. createSet(towardAnimators,0),
  89. createSet(moveAwayAnimators,250),
  90. createSet(moveBackAnimators,0),
  91. createSet(awayAnimators,250),
  92. createSet(collapseAnimators,0));
  93. totalSet.start();
  94. totalSet.addListener(newRepeatListener(totalSet));
  95. }
  96. publicstaticclassRepeatListenerimplementsAnimator.AnimatorListener{
  97. finalAnimatormRepeatAnimator;
  98. publicRepeatListener(AnimatorrepeatAnimator){
  99. mRepeatAnimator=repeatAnimator;
  100. }
  101. @Override
  102. publicvoidonAnimationStart(Animatoranimation){}
  103. @Override
  104. publicvoidonAnimationEnd(Animatoranimation){
  105. if(animation==mRepeatAnimator){
  106. mRepeatAnimator.start();
  107. }
  108. }
  109. @Override
  110. publicvoidonAnimationCancel(Animatoranimation){}
  111. @Override
  112. publicvoidonAnimationRepeat(Animatoranimation){}
  113. }
  114. }
layout: [html] view plain copy print ?
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <!--Copyright(C)2014TheAndroidOpenSourceProject
  3. LicensedundertheApacheLicense,Version2.0(the"License");
  4. youmaynotusethisfileexceptincompliancewiththeLicense.
  5. YoumayobtainacopyoftheLicenseat
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  8. distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  9. WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  10. SeetheLicenseforthespecificlanguagegoverningpermissionsand
  11. limitationsundertheLicense.
  12. -->
  13. <RelativeLayout
  14. xmlns:android="http://schemas.android.com/apk/res/android"
  15. android:id="@+id/card_parent"
  16. android:orientation="vertical"
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent"
  19. android:clipChildren="false"
  20. android:clipToPadding="false"
  21. android:gravity="center">
  22. <TextView
  23. android:layout_width="250dp"
  24. android:layout_height="150dp"
  25. android:background="@drawable/round_rect"
  26. android:padding="20dp"
  27. android:textSize="20sp"/>
  28. <TextView
  29. android:layout_width="250dp"
  30. android:layout_height="150dp"
  31. android:background="@drawable/round_rect"
  32. android:padding="20dp"
  33. android:textSize="20sp"/>
  34. <TextView
  35. android:layout_width="250dp"
  36. android:layout_height="150dp"
  37. android:background="@drawable/round_rect"
  38. android:padding="20dp"
  39. android:textSize="20sp"/>
  40. <TextView
  41. android:layout_width="250dp"
  42. android:layout_height="150dp"
  43. android:background="@drawable/round_rect"
  44. android:padding="20dp"
  45. android:textSize="20sp"/>
  46. <TextView
  47. android:layout_width="250dp"
  48. android:layout_height="150dp"
  49. android:background="@drawable/round_rect"
  50. android:padding="20dp"
  51. android:textSize="20sp"/>
  52. </RelativeLayout>

更多相关文章

  1. android linux 休眠 深度睡眠 查看 方法 调试
  2. Activity伪造Dialog的时候不能全屏显示
  3. Android(安卓)Binder Mechanism (4) -- 如何使用已注册的系统Ser
  4. Android对View的onMeasure方法理解
  5. 编写高效Android代码
  6. Android开发环境的搭建方法
  7. android email 邮件转发 附件不能转发问题的解决
  8. android中onClick事件的实现
  9. Android中TextView文字设置不同的颜色

随机推荐

  1. android相关技术文档汇总
  2. Android中WebView获取网页中标题 ,内容,
  3. android 延时 不用另起线程或timertask
  4. android体系架构
  5. Android中有用的组件被选中和按下去的变
  6. Android通过RSA加密解密实现License
  7. Android的onCreateOptionsMenu()创建菜单
  8. 浅析Android的Context
  9. Android四种Activity的加载模式
  10. 【android】ORMLite框架 的使用方法---给