在 5.0 上 提供了很多动画效果方面的 优化 和 设置
在android5.0(api21)及以上,允许自定义这些动画:
1. Touch feedback 触摸反馈
2. Circular Reveal 圆形显示
3. Activity transitions 过渡动画
4. Curved motion 曲线运动
5. View state changes 视图状态变化

4. Curved motion 曲线运动

Material design中的动画依靠曲线,这个曲线适用于时间插值器和控件运动模式。

PathInterpolator类是一个基于贝塞尔曲线(Bézier curve)或路径(Path)对象上的新的插值器。这个插值器指定了一个1x1的方形运动曲线,用(0,0)点和(1,1)定位点还有控制点来作为构造方法中的参数。你还可以定义一个XML资源的路径插值器:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"android:controlX1="0.4"android:controlY1="0"android:controlX2="1"android:controlY2="1"/>

在materialdesign规范中,系统提供了三个基本的曲线:

@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml

你可以传递一个PathInterpolator对象给Animator.setInterpolator()方法。。

ObjectAnimator类有的构造方法,使你能够一次能同时使用两个或多个属性去绘制动画的路径
例如,下面的动画使用一个Path对象进行视图X和Y属性的动画绘制:

ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);

mAnimator.start();

     ObjectAnimator.ofArgbObjectAnimator.ofFloatObjectAnimator.ofIntObjectAnimator.ofMultiFloatObjectAnimator.ofObjectObjectAnimator.ofPropertyValuesHolder

4.2相关代码示例可以参考:

android-sdk-windows\samples\android-21\legacy\ApiDemos\src\com\example\android\apis\animation\PathAnimations.java

PathAnimation.java

/** This application demonstrates the use of Path animation. */
public class PathAnimations extends Activity implements  RadioGroup.OnCheckedChangeListener, View.OnLayoutChangeListener {  final static Path sTraversalPath = new Path();  final static float TRAVERSE_PATH_SIZE = 7.0f;  final static Property<PathAnimations, Point> POINT_PROPERTY  = new Property<PathAnimations, Point>(Point.class, "point") {  @Override  public Point get(PathAnimations object) {  View v = object.findViewById(R.id.moved_item);  return new Point(Math.round(v.getX()), Math.round(v.getY()));  }  @Override  public void set(PathAnimations object, Point value) {  object.setCoordinates(value.x, value.y);  }  };  static {  float inverse_sqrt8 = FloatMath.sqrt(0.125f);  RectF bounds = new RectF(1, 1, 3, 3);  sTraversalPath.addArc(bounds, 45, 180);  sTraversalPath.addArc(bounds, 225, 180);  bounds.set(1.5f + inverse_sqrt8, 1.5f + inverse_sqrt8, 2.5f + inverse_sqrt8,  2.5f + inverse_sqrt8);  sTraversalPath.addArc(bounds, 45, 180);  sTraversalPath.addArc(bounds, 225, 180);  bounds.set(4, 1, 6, 3);  sTraversalPath.addArc(bounds, 135, -180);  sTraversalPath.addArc(bounds, -45, -180);  bounds.set(4.5f - inverse_sqrt8, 1.5f + inverse_sqrt8, 5.5f - inverse_sqrt8, 2.5f + inverse_sqrt8);  sTraversalPath.addArc(bounds, 135, -180);  sTraversalPath.addArc(bounds, -45, -180);  sTraversalPath.addCircle(3.5f, 3.5f, 0.5f, Path.Direction.CCW);  sTraversalPath.addArc(new RectF(1, 2, 6, 6), 0, 180);  }  private CanvasView mCanvasView;  private ObjectAnimator mAnimator;  /** Called when the activity is first created. */  @Override  public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.path_animations);  mCanvasView = (CanvasView) findViewById(R.id.canvas);  mCanvasView.addOnLayoutChangeListener(this);  ((RadioGroup) findViewById(R.id.path_animation_type)).setOnCheckedChangeListener(this);  }  public void setCoordinates(int x, int y) {  changeCoordinates((float) x, (float) y);  }  public void changeCoordinates(float x, float y) {  View v = findViewById(R.id.moved_item);  v.setX(x);  v.setY(y);  }  public void setPoint(PointF point) {  changeCoordinates(point.x, point.y);  }  @Override  public void onCheckedChanged(RadioGroup group, int checkedId) {  startAnimator(checkedId);  }  @Override  public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,  int oldTop, int oldRight, int oldBottom) {  int checkedId = ((RadioGroup)findViewById(R.id.path_animation_type)).getCheckedRadioButtonId();  if (checkedId != RadioGroup.NO_ID) {  startAnimator(checkedId);  }  }  private void startAnimator(int checkedId) {  if (mAnimator != null) {  mAnimator.cancel();  mAnimator = null;  }  View view = findViewById(R.id.moved_item);  Path path = mCanvasView.getPath();  if (path.isEmpty()) {  return;  }  switch (checkedId) {  case R.id.named_components:  // Use the named "x" and "y" properties for individual (x, y)  // coordinates of the Path and set them on the view object.  // The setX(float) and setY(float) methods are called on view.  // An int version of this method also exists for animating  // int Properties.  mAnimator = ObjectAnimator.ofFloat(view, "x", "y", path);  break;  case R.id.property_components:  // Use two Properties for individual (x, y) coordinates of the Path  // and set them on the view object.  // An int version of this method also exists for animating  // int Properties.  mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);  break;  case R.id.multi_int:  // Use a multi-int setter to animate along a Path. The method  // setCoordinates(int x, int y) is called on this during the animation.  // Either "setCoordinates" or "coordinates" are acceptable parameters  // because the "set" can be implied.  mAnimator = ObjectAnimator.ofMultiInt(this, "setCoordinates", path);  break;  case R.id.multi_float:  // Use a multi-float setter to animate along a Path. The method  // changeCoordinates(float x, float y) is called on this during the animation.  mAnimator = ObjectAnimator.ofMultiFloat(this, "changeCoordinates", path);  break;  case R.id.named_setter:  // Use the named "point" property to animate along the Path.  // There must be a method setPoint(PointF) on the animated object.  // Because setPoint takes a PointF parameter, no TypeConverter is necessary.  // In this case, the animated object is PathAnimations.  mAnimator = ObjectAnimator.ofObject(this, "point", null, path);  break;  case R.id.property_setter:  // Use the POINT_PROPERTY property to animate along the Path.  // POINT_PROPERTY takes a Point, not a PointF, so the TypeConverter  // PointFToPointConverter is necessary.  mAnimator = ObjectAnimator.ofObject(this, POINT_PROPERTY,  new PointFToPointConverter(), path);  break;  }  mAnimator.setDuration(10000);  mAnimator.setRepeatMode(Animation.RESTART);  mAnimator.setRepeatCount(ValueAnimator.INFINITE);  mAnimator.setInterpolator(new LinearInterpolator());  mAnimator.start();  }  public static class CanvasView extends FrameLayout {  Path mPath = new Path();  Paint mPathPaint = new Paint();  public CanvasView(Context context) {  super(context);  init();  }  public CanvasView(Context context, AttributeSet attrs) {  super(context, attrs);  init();  }  public CanvasView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle);  init();  }  private void init() {  setWillNotDraw(false);  mPathPaint.setColor(0xFFFF0000);  mPathPaint.setStrokeWidth(2.0f);  mPathPaint.setStyle(Paint.Style.STROKE);  }  @Override  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  super.onLayout(changed, left, top, right, bottom);  if (changed) {  Matrix scale = new Matrix();  float scaleWidth = (right-left)/TRAVERSE_PATH_SIZE;  float scaleHeight= (bottom-top)/TRAVERSE_PATH_SIZE;  scale.setScale(scaleWidth, scaleHeight);  sTraversalPath.transform(scale, mPath);  }  }  public Path getPath() {  return mPath;  }  @Override  public void draw(Canvas canvas) {  canvas.drawPath(mPath, mPathPaint);  super.draw(canvas);  }  }  private static class PointFToPointConverter extends TypeConverter<PointF, Point> {  Point mPoint = new Point();  public PointFToPointConverter() {  super(PointF.class, Point.class);  }  @Override  public Point convert(PointF value) {  mPoint.set(Math.round(value.x), Math.round(value.y));  return mPoint;  }  }
}  

path_animations.xml

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical"  android:layout_width="match_parent"  android:layout_height="match_parent">  <ScrollView android:layout_width="match_parent"  android:layout_height="wrap_content">  <RadioGroup android:orientation="horizontal"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:id="@+id/path_animation_type"  >  <RadioButton android:id="@+id/named_components"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Named Components"/>  <RadioButton android:id="@+id/property_components"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Property Components"/>  <RadioButton android:id="@+id/multi_int"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Multi-int"/>  <RadioButton android:id="@+id/multi_float"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Multi-float"/>  <RadioButton android:id="@+id/named_setter"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Named Property"/>  <RadioButton android:id="@+id/property_setter"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Property"/>  </RadioGroup>  </ScrollView>  <view class="com.example.android.apis.animation.PathAnimations$CanvasView"  android:id="@+id/canvas"  android:layout_width="match_parent"  android:layout_height="0px"  android:layout_weight="1">  <ImageView android:id="@+id/moved_item"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:src="@drawable/frog"/>  </view>
</LinearLayout>  

Material Design - Curved motion相关推荐

  1. Android Material Design动画 Curved motion | 曲线运动

    Material Design动画 Curved motion | 曲线运动 在materialDesign中,动画是依赖于时间插值器和空间运动模式的.但是在Android5.0或者5.0以后的版本, ...

  2. ANDROID L——Material Design详解(动画篇)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...

  3. AndroidMaterialDesign动画之Curved Motion

    1,Material Design简介 2,MaterialDesign主题Theme 3,android:elevation的使用 4,AndroidMaterialDesign动画之RippleD ...

  4. Android Material Design动画

    最近在看一些关于Material Design的东西,还记得在博客<你所不知道的Activity转场动画--ActivityOptions>中,我们介绍了一种优雅的activity过度动画 ...

  5. Android(Lollipop/5.0) Material Design(七) 自定义动画

    Material Design系列 Android(Lollipop/5.0) Material Design(一) 简介 Android(Lollipop/5.0) Material Design( ...

  6. android6.0进入Material Design时代

    Material Design 官方Material Design详细介绍文档:http://www.google.com/design/spec/material-design/introducti ...

  7. 【Android】进入Material Design时代

    由于本文引用了大量官方文档.图片资源,以及开源社区的Lib和相关图片资源,因此在转载的时候,务必注明来源,如果使用资源请注明资源的出处,尊重版权,尊重别人的劳动成果,谢谢! Material Desi ...

  8. Flutter OpenContainer 容器转换过渡 Material Design 设计风格的实践

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,优美的应用体验 来自于细节的处理,更源自于码农的自我要求与努力 Flutter是谷歌推出的最新的移动开发框架. [x1]微信公众号的每日 ...

  9. Material Design设计规范

    作为技术开发者需不需要了解设计规范?个人认为非常需要,一个交流的需要,另一就是了解相关的设计才能储备相应地知识,知道UI开发的方向.这问题非常希望读者能留言讨论. **Android**的设计风格变迁 ...

最新文章

  1. 心路历程:「双非」研究生数据分析春招
  2. Shell(4)——测试test、[]、逻辑、||文件-f、-d、-x、-eq、-gt、-ge、-lt、-le、-ne
  3. .h .dll .lib
  4. 【CodeForces - 264A】Escape from Stones (模拟,卡精度的处理)
  5. WinForm 清空界面控件值的小技巧
  6. JPA + EclipseLink + SAP云平台 = 运行在云端的数据库应用 1
  7. Java 算法 身份证排序
  8. require()与 require_once()、 include与include_once()
  9. 教你如何快速查询快递物流,并自动识别已签收单号
  10. 极课大数据:培养超级学生,不如打造超级教师
  11. 评卷系统-答题卡制作参考网站
  12. python实现whois查询_Python 工具whois查询
  13. At least one JAR was scanned for TLDs yet contained no TLDs.问题解决方式
  14. FreeRTOS 任务调度 系统节拍
  15. html5统计在线人数,html的统计访客人数的代码?
  16. 一文解决关于建立时间和保持时间的困惑
  17. 工银亚洲见证开户详细过程和攻略
  18. Robot framework模拟打开浏览器问题
  19. 锂电池电量百分比计算_锂电池充放电理论及电量计算方法详解
  20. 北京可视化暑期学校日志——Day1

热门文章

  1. 学习opencv3 pdf_如何提取PDF页面?实用方法就在这里了!
  2. 【SSL1502】校门外的树
  3. MPICH编译及MPI分布式设计基础(案例展示)
  4. linux内核笔记之SMMU代码分析
  5. python:获取摄像头照片
  6. 软件测试专业社会现状,软件测试行业现状如何?是青春饭吗?
  7. 2021年TWS蓝牙耳机哪个好?tws蓝牙耳机排名!
  8. 灵格斯词霸能否替代金山词霸?
  9. 163VIP邮箱怎么设置邮件签名?如何群发邮件?
  10. Linux实训课笔记内容