Android(安卓)5.0学习之定义阴影
16lz
2021-01-26
前言
Material Design 规范指导里面特别提出了阴影的重要性和如何正确使用的方法(点击传送),那我们就更加不能忽视这一点了,本篇文章就要教大家如何设置阴影,做出一个有层次感的界面。
设置方法: android:elevation 分别设置不同数值的elevation效果如下:layout: [html] view plain copy print ?
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <TextViewandroid:layout_width="100dp"
- android:layout_margin="2dp"
- android:layout_height="100dp"
- android:text="test"
- android:background="@android:color/white"
- android:gravity="center"
- android:elevation="1dip"
- />
- <TextViewandroid:layout_width="100dp"
- android:layout_margin="2dp"
- android:layout_height="100dp"
- android:text="test"
- android:background="@android:color/white"
- android:gravity="center"
- android:elevation="4dip"/>
- <TextViewandroid:layout_width="100dp"
- android:layout_margin="2dp"
- android:layout_height="100dp"
- android:text="test"
- android:background="@android:color/white"
- android:gravity="center"
- android:elevation="8dip"
- />
- </LinearLayout>
View的z值由两部分组成,elevation和translationZ.
eleavation是静态的成员,translationZ是用来做动画。
Z = elevation + translationZ
在布局中使用android:elevation属性去定义
在代码中使用View.setElevation方法去定义
设置视图的translation,可以使用View.setTranslationZ方法
新的ViewPropertyAnimator.z和ViewPropertyAnimator.translationZ方法可以设置视图的elevation值
在5.0 的API Demos中 Graphics-》Shadow Card Drag 和 Shadow Card stack 这两个例子就很好的使用translationZ和eleavation
Shadow Card Drag 源码:
[java] view plain copy print ?
- /*
- *Copyright(C)2014TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packagecom.example.android.apis.graphics;
- importandroid.animation.ObjectAnimator;
- importandroid.app.Activity;
- importandroid.graphics.Canvas;
- importandroid.graphics.Color;
- importandroid.graphics.Outline;
- importandroid.graphics.Paint;
- importandroid.graphics.Path;
- importandroid.graphics.PorterDuff;
- importandroid.graphics.drawable.ShapeDrawable;
- importandroid.graphics.drawable.shapes.OvalShape;
- importandroid.graphics.drawable.shapes.RectShape;
- importandroid.graphics.drawable.shapes.RoundRectShape;
- importandroid.graphics.drawable.shapes.Shape;
- importandroid.os.Bundle;
- importandroid.view.MotionEvent;
- importandroid.view.View;
- importandroid.view.animation.AccelerateInterpolator;
- importandroid.view.animation.DecelerateInterpolator;
- importandroid.widget.Button;
- importandroid.widget.CheckBox;
- importandroid.widget.CompoundButton;
- importcom.example.android.apis.R;
- importjava.util.ArrayList;
- publicclassShadowCardDragextendsActivity{
- privatestaticfinalfloatMAX_Z_DP=10;
- privatestaticfinalfloatMOMENTUM_SCALE=10;
- privatestaticfinalintMAX_ANGLE=10;
- privateclassCardDragState{
- longlastEventTime;
- floatlastX;
- floatlastY;
- floatmomentumX;
- floatmomentumY;
- publicvoidonDown(longeventTime,floatx,floaty){
- lastEventTime=eventTime;
- lastX=x;
- lastY=y;
- momentumX=0;
- momentumY=0;
- }
- publicvoidonMove(longeventTime,floatx,floaty){
- finallongdeltaT=eventTime-lastEventTime;
- if(deltaT!=0){
- floatnewMomentumX=(x-lastX)/(mDensity*deltaT);
- floatnewMomentumY=(y-lastY)/(mDensity*deltaT);
- momentumX=0.9f*momentumX+0.1f*(newMomentumX*MOMENTUM_SCALE);
- momentumY=0.9f*momentumY+0.1f*(newMomentumY*MOMENTUM_SCALE);
- momentumX=Math.max(Math.min((momentumX),MAX_ANGLE),-MAX_ANGLE);
- momentumY=Math.max(Math.min((momentumY),MAX_ANGLE),-MAX_ANGLE);
- //noinspectionSuspiciousNameCombination
- mCard.setRotationX(-momentumY);
- //noinspectionSuspiciousNameCombination
- mCard.setRotationY(momentumX);
- if(mShadingEnabled){
- floatalphaDarkening=(momentumX*momentumX+momentumY*momentumY)/(90*90);
- alphaDarkening/=2;
- intalphaByte=0xff-((int)(alphaDarkening*255)&0xff);
- intcolor=Color.rgb(alphaByte,alphaByte,alphaByte);
- mCardBackground.setColorFilter(color,PorterDuff.Mode.MULTIPLY);
- }
- }
- lastX=x;
- lastY=y;
- lastEventTime=eventTime;
- }
- publicvoidonUp(){
- ObjectAnimatorflattenX=ObjectAnimator.ofFloat(mCard,"rotationX",0);
- flattenX.setDuration(100);
- flattenX.setInterpolator(newAccelerateInterpolator());
- flattenX.start();
- ObjectAnimatorflattenY=ObjectAnimator.ofFloat(mCard,"rotationY",0);
- flattenY.setDuration(100);
- flattenY.setInterpolator(newAccelerateInterpolator());
- flattenY.start();
- mCardBackground.setColorFilter(null);
- }
- }
- /**
- *Simpleshapeexamplethatgeneratesashadowcastingoutline.
- */
- privatestaticclassTriangleShapeextendsShape{
- privatefinalPathmPath=newPath();
- @Override
- protectedvoidonResize(floatwidth,floatheight){
- mPath.reset();
- mPath.moveTo(0,0);
- mPath.lineTo(width,0);
- mPath.lineTo(width/2,height);
- mPath.lineTo(0,0);
- mPath.close();
- }
- @Override
- publicvoiddraw(Canvascanvas,Paintpaint){
- canvas.drawPath(mPath,paint);
- }
- @Override
- publicvoidgetOutline(Outlineoutline){
- outline.setConvexPath(mPath);
- }
- }
- privatefinalShapeDrawablemCardBackground=newShapeDrawable();
- privatefinalArrayList<Shape>mShapes=newArrayList<Shape>();
- privatefloatmDensity;
- privateViewmCard;
- privatefinalCardDragStatemDragState=newCardDragState();
- privatebooleanmTiltEnabled;
- privatebooleanmShadingEnabled;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.shadow_card_drag);
- mDensity=getResources().getDisplayMetrics().density;
- mShapes.add(newRectShape());
- mShapes.add(newOvalShape());
- floatr=10*mDensity;
- floatradii[]=newfloat[]{r,r,r,r,r,r,r,r};
- mShapes.add(newRoundRectShape(radii,null,null));
- mShapes.add(newTriangleShape());
- mCardBackground.getPaint().setColor(Color.WHITE);
- mCardBackground.setShape(mShapes.get(0));
- finalViewcardParent=findViewById(R.id.card_parent);
- mCard=findViewById(R.id.card);
- mCard.setBackground(mCardBackground);
- finalCheckBoxtiltCheck=(CheckBox)findViewById(R.id.tilt_check);
- tiltCheck.setOnCheckedChangeListener(newCompoundButton.OnCheckedChangeListener(){
- @Override
- publicvoidonCheckedChanged(CompoundButtonbuttonView,booleanisChecked){
- mTiltEnabled=isChecked;
- if(!mTiltEnabled){
- mDragState.onUp();
- }
- }
- });
- finalCheckBoxshadingCheck=(CheckBox)findViewById(R.id.shading_check);
- shadingCheck.setOnCheckedChangeListener(newCompoundButton.OnCheckedChangeListener(){
- @Override
- publicvoidonCheckedChanged(CompoundButtonbuttonView,booleanisChecked){
- mShadingEnabled=isChecked;
- if(!mShadingEnabled){
- mCardBackground.setColorFilter(null);
- }
- }
- });
- finalButtonshapeButton=(Button)findViewById(R.id.shape_select);
- shapeButton.setOnClickListener(newView.OnClickListener(){
- intindex=0;
- @Override
- publicvoidonClick(Viewv){
- index=(index+1)%mShapes.size();
- mCardBackground.setShape(mShapes.get(index));
- }
- });
- /**
- *Enableanytouchontheparenttodragthecard.Notethatthisdoesn'tdoaproperhit
- *test,soanydrag(includingoffofthecard)willwork.
- *
- *Thisenablestheusertoseetheeffectmoreclearlyforthepurposeofthisdemo.
- */
- cardParent.setOnTouchListener(newView.OnTouchListener(){
- floatdownX;
- floatdownY;
- longdownTime;
- @Override
- publicbooleanonTouch(Viewv,MotionEventevent){
- switch(event.getAction()){
- caseMotionEvent.ACTION_DOWN:
- downX=event.getX()-mCard.getTranslationX();
- downY=event.getY()-mCard.getTranslationY();
- downTime=event.getDownTime();
- ObjectAnimatorupAnim=ObjectAnimator.ofFloat(mCard,"translationZ",
- MAX_Z_DP*mDensity);
- upAnim.setDuration(100);
- upAnim.setInterpolator(newDecelerateInterpolator());
- upAnim.start();
- if(mTiltEnabled){
- mDragState.onDown(event.getDownTime(),event.getX(),event.getY());
- }
- break;
- caseMotionEvent.ACTION_MOVE:
- mCard.setTranslationX(event.getX()-downX);
- mCard.setTranslationY(event.getY()-downY);
- if(mTiltEnabled){
- mDragState.onMove(event.getEventTime(),event.getX(),event.getY());
- }
- break;
- caseMotionEvent.ACTION_UP:
- ObjectAnimatordownAnim=ObjectAnimator.ofFloat(mCard,"translationZ",0);
- downAnim.setDuration(100);
- downAnim.setInterpolator(newAccelerateInterpolator());
- downAnim.start();
- if(mTiltEnabled){
- mDragState.onUp();
- }
- break;
- }
- returntrue;
- }
- });
- }
- }
- <?xmlversion="1.0"encoding="utf-8"?>
- <!--Copyright(C)2014TheAndroidOpenSourceProject
- LicensedundertheApacheLicense,Version2.0(the"License");
- youmaynotusethisfileexceptincompliancewiththeLicense.
- YoumayobtainacopyoftheLicenseat
- http://www.apache.org/licenses/LICENSE-2.0
- Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- SeetheLicenseforthespecificlanguagegoverningpermissionsand
- limitationsundertheLicense.
- -->
- <FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/card_parent"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <CheckBox
- android:id="@+id/tilt_check"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:checked="false"
- android:text="@string/enable_tilt"/>
- <CheckBox
- android:id="@+id/shading_check"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:checked="false"
- android:text="@string/enable_shading"/>
- <Button
- android:id="@+id/shape_select"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/select_shape"/>
- </LinearLayout>
- <TextView
- android:id="@+id/card"
- android:layout_width="150dp"
- android:layout_height="150dp"
- android:background="@drawable/round_rect"
- android:clipToPadding="false"
- android:gravity="center"
- android:padding="20dp"
- android:text="@string/draggable_card"
- android:textSize="20sp"
- android:elevation="2dp"/>
- </FrameLayout>
Shadow Card stack 源码: [java] view plain copy print ?
- /*
- *Copyright(C)2014TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packagecom.example.android.apis.graphics;
- importandroid.animation.Animator;
- importandroid.animation.AnimatorSet;
- importandroid.animation.ObjectAnimator;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.view.ViewGroup;
- importandroid.widget.TextView;
- importcom.example.android.apis.R;
- importjava.util.ArrayList;
- publicclassShadowCardStackextendsActivity{
- privatestaticfinalfloatX_SHIFT_DP=1000;
- privatestaticfinalfloatY_SHIFT_DP=50;
- privatestaticfinalfloatZ_LIFT_DP=8;
- privatestaticfinalfloatROTATE_DEGREES=15;
- publicAnimatorSetcreateSet(ArrayList<Animator>items,longstartDelay){
- AnimatorSetset=newAnimatorSet();
- set.playTogether(items);
- set.setStartDelay(startDelay);
- returnset;
- }
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.shadow_card_stack);
- floatdensity=getResources().getDisplayMetrics().density;
- finalViewGroupcardParent=(ViewGroup)findViewById(R.id.card_parent);
- finalfloatX=X_SHIFT_DP*density;
- finalfloatY=Y_SHIFT_DP*density;
- finalfloatZ=Z_LIFT_DP*density;
- ArrayList<Animator>towardAnimators=newArrayList<Animator>();
- ArrayList<Animator>expandAnimators=newArrayList<Animator>();
- ArrayList<Animator>moveAwayAnimators=newArrayList<Animator>();
- ArrayList<Animator>moveBackAnimators=newArrayList<Animator>();
- ArrayList<Animator>awayAnimators=newArrayList<Animator>();
- ArrayList<Animator>collapseAnimators=newArrayList<Animator>();
- finalintmax=cardParent.getChildCount();
- for(inti=0;i<max;i++){
- TextViewcard=(TextView)cardParent.getChildAt(i);
- card.setText("Cardnumber"+i);
- floattargetY=(i-(max-1)/2.0f)*Y;
- Animatorexpand=ObjectAnimator.ofFloat(card,"translationY",targetY);
- expandAnimators.add(expand);
- Animatortoward=ObjectAnimator.ofFloat(card,"translationZ",i*Z);
- toward.setStartDelay(200*((max)-i));
- towardAnimators.add(toward);
- card.setPivotX(X_SHIFT_DP);
- AnimatorrotateAway=ObjectAnimator.ofFloat(card,"rotationY",
- i==0?0:ROTATE_DEGREES);
- rotateAway.setStartDelay(200*((max)-i));
- rotateAway.setDuration(100);
- moveAwayAnimators.add(rotateAway);
- AnimatorslideAway=ObjectAnimator.ofFloat(card,"translationX",
- i==0?0:X);
- slideAway.setStartDelay(200*((max)-i));
- slideAway.setDuration(100);
- moveAwayAnimators.add(slideAway);
- AnimatorrotateBack=ObjectAnimator.ofFloat(card,"rotationY",0);
- rotateBack.setStartDelay(200*i);
- moveBackAnimators.add(rotateBack);
- AnimatorslideBack=ObjectAnimator.ofFloat(card,"translationX",0);
- slideBack.setStartDelay(200*i);
- moveBackAnimators.add(slideBack);
- Animatoraway=ObjectAnimator.ofFloat(card,"translationZ",0);
- away.setStartDelay(200*i);
- awayAnimators.add(away);
- Animatorcollapse=ObjectAnimator.ofFloat(card,"translationY",0);
- collapseAnimators.add(collapse);
- }
- AnimatorSettotalSet=newAnimatorSet();
- totalSet.playSequentially(
- createSet(expandAnimators,250),
- createSet(towardAnimators,0),
- createSet(moveAwayAnimators,250),
- createSet(moveBackAnimators,0),
- createSet(awayAnimators,250),
- createSet(collapseAnimators,0));
- totalSet.start();
- totalSet.addListener(newRepeatListener(totalSet));
- }
- publicstaticclassRepeatListenerimplementsAnimator.AnimatorListener{
- finalAnimatormRepeatAnimator;
- publicRepeatListener(AnimatorrepeatAnimator){
- mRepeatAnimator=repeatAnimator;
- }
- @Override
- publicvoidonAnimationStart(Animatoranimation){}
- @Override
- publicvoidonAnimationEnd(Animatoranimation){
- if(animation==mRepeatAnimator){
- mRepeatAnimator.start();
- }
- }
- @Override
- publicvoidonAnimationCancel(Animatoranimation){}
- @Override
- publicvoidonAnimationRepeat(Animatoranimation){}
- }
- }
- <?xmlversion="1.0"encoding="utf-8"?>
- <!--Copyright(C)2014TheAndroidOpenSourceProject
- LicensedundertheApacheLicense,Version2.0(the"License");
- youmaynotusethisfileexceptincompliancewiththeLicense.
- YoumayobtainacopyoftheLicenseat
- http://www.apache.org/licenses/LICENSE-2.0
- Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- SeetheLicenseforthespecificlanguagegoverningpermissionsand
- limitationsundertheLicense.
- -->
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/card_parent"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:gravity="center">
- <TextView
- android:layout_width="250dp"
- android:layout_height="150dp"
- android:background="@drawable/round_rect"
- android:padding="20dp"
- android:textSize="20sp"/>
- <TextView
- android:layout_width="250dp"
- android:layout_height="150dp"
- android:background="@drawable/round_rect"
- android:padding="20dp"
- android:textSize="20sp"/>
- <TextView
- android:layout_width="250dp"
- android:layout_height="150dp"
- android:background="@drawable/round_rect"
- android:padding="20dp"
- android:textSize="20sp"/>
- <TextView
- android:layout_width="250dp"
- android:layout_height="150dp"
- android:background="@drawable/round_rect"
- android:padding="20dp"
- android:textSize="20sp"/>
- <TextView
- android:layout_width="250dp"
- android:layout_height="150dp"
- android:background="@drawable/round_rect"
- android:padding="20dp"
- android:textSize="20sp"/>
- </RelativeLayout>
更多相关文章
- android linux 休眠 深度睡眠 查看 方法 调试
- Activity伪造Dialog的时候不能全屏显示
- Android(安卓)Binder Mechanism (4) -- 如何使用已注册的系统Ser
- Android对View的onMeasure方法理解
- 编写高效Android代码
- Android开发环境的搭建方法
- android email 邮件转发 附件不能转发问题的解决
- android中onClick事件的实现
- Android中TextView文字设置不同的颜色