雖然使用 ObjectAnimator 很方便,但預設會沿著起點和終點之間的直線重新定位檢視畫面。Material Design 的設計仰賴曲線在螢幕上的物件空間移動,以及動畫的時間。使用彎曲動作可讓應用程式更具 Material Design 風格,同時讓動畫更生動有趣。
自行定義路徑
ObjectAnimator 類別的建構函式可讓您同時使用兩個以上的屬性以及路徑,為座標加上動畫效果。舉例來說,下列動畫工具會使用 Path 物件,為檢視畫面的 X 和 Y 屬性建立動畫:
Kotlin
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){valpath=Path().apply{arcTo(0f,0f,1000f,1000f,270f,-180f,true)}valanimator=ObjectAnimator.ofFloat(view,View.X,View.Y,path).apply{duration=2000start()}}else{// Create animator without using curved path}
Java
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){Pathpath=newPath();path.arcTo(0f,0f,1000f,1000f,270f,-180f,true);ObjectAnimatoranimator=ObjectAnimator.ofFloat(view,View.X,View.Y,path);animator.setDuration(2000);animator.start();}else{// Create animator without using curved path}
以下是弧形動畫的呈現方式:
圖 1. 曲線路徑動畫。
Interpolator 是漸變曲線的實作項目。如要進一步瞭解加/減速曲線的概念,請參閱 Material Design 說明文件。Interpolator 會定義動畫中特定值的計算方式,以時間為函式。系統會為 Material Design 規格中的三種基本曲線提供 XML 資源:
[null,null,["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Move a View with animation\n\nTry the Compose way \nJetpack Compose is the recommended UI toolkit for Android. Learn how to use Animations in Compose. \n[Animate position →](/develop/ui/compose/animation/quick-guide#animate-position) \n\n\u003cbr /\u003e\n\nObjects on screen often need to be repositioned due to user interaction or\nprocessing behind the scenes. Instead of immediately updating the object's\nposition, which causes it to blink from one area to another, use an animation to\nmove it from the starting position to its end position.\n\nOne way that Android lets you reposition your view objects on screen is by\nusing [`ObjectAnimator`](#UseObjectAnimator). You provide the end position you\nwant the object to settle in as well as the duration of the animation. You can\nalso use time interpolators to control the acceleration or deceleration of the\nanimation.\n\nChange the view position with ObjectAnimator\n--------------------------------------------\n\nThe [`ObjectAnimator`](/reference/android/animation/ObjectAnimator)\nAPI provides a way to change the properties of a view with a specified duration.\nIt contains static methods to create instances of `ObjectAnimator` depending on\nwhat type of attribute you are animating. When repositioning your views on\nscreen, use the `translationX` and `translationY` attributes.\n\nHere's an example of an `ObjectAnimator` that moves the view to a position 100\npixels from the left of the screen in 2 seconds: \n\n### Kotlin\n\n```kotlin\nObjectAnimator.ofFloat(view, \"translationX\", 100f).apply {\n duration = 2000\n start()\n}\n```\n\n### Java\n\n```java\nObjectAnimator animation = ObjectAnimator.ofFloat(view, \"translationX\", 100f);\nanimation.setDuration(2000);\nanimation.start();\n```\n\nThis example uses the\n[`ObjectAnimator.ofFloat()`](/reference/android/animation/ObjectAnimator#ofFloat(T,%20android.util.Property%3CT,%20java.lang.Float%3E,%20android.util.Property%3CT,%20java.lang.Float%3E,%20android.graphics.Path))\nmethod, because the translation values have to be floats. The first parameter is\nthe view you want to animate. The second parameter is the property you are\nanimating. Since the view needs to move horizontally, the `translationX`\nproperty is used. The last parameter is the end value of the animation. In this\nexample, the value of 100 indicates a position that many pixels from the left of\nthe screen.\n\nThe next method specifies how long the animation takes, in milliseconds. In this\nexample, the animation runs for 2 seconds (2000 milliseconds).\n\nThe last method causes the animation to run, which updates the view's position\non screen.\n\nFor more information about using `ObjectAnimator`, see [Animate using\nObjectAnimator](/guide/topics/graphics/prop-animation#object-animator).\n\nAdd curved motion\n-----------------\n\nWhile using the `ObjectAnimator` is convenient, by default it repositions the\nview along a straight line between the starting and ending points. Material\ndesign relies on curves for spatial movement of objects on the screen and the\ntiming of an animation. Using curved motion gives your app a more material feel\nwhile making your animations more interesting.\n\n### Define your own path\n\nThe `ObjectAnimator` class has constructors that let you animate coordinates\nusing two or more properties at once along with a path. For\nexample, the following animator uses a\n[`Path`](/reference/android/graphics/Path) object to animate the X and Y\nproperties of a view: \n\n### Kotlin\n\n```kotlin\nif (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n val path = Path().apply {\n arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)\n }\n val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {\n duration = 2000\n start()\n }\n} else {\n // Create animator without using curved path\n}\n```\n\n### Java\n\n```java\nif (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n Path path = new Path();\n path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);\n ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);\n animator.setDuration(2000);\n animator.start();\n} else {\n // Create animator without using curved path\n}\n```\n\nHere is what the arc animation looks like:\n\n**Figure 1.** A curved path animation.\n\nAn [`Interpolator`](/develop/ui/views/animations/prop-animation#interpolators)\nis an implementation of an easing curve. See the\n[Material Design documentation](https://m3.material.io/styles/motion/easing-and-duration/applying-easing-and-duration)\nfor more information about the concept of easing curves. An `Interpolator`\ndefines how specific values in an animation are calculated as a function of\ntime. The system provides XML resources for the three basic curves in the\nMaterial Design specification:\n\n- `@interpolator/fast_out_linear_in.xml`\n- `@interpolator/fast_out_slow_in.xml`\n- `@interpolator/linear_out_slow_in.xml`\n\n### Use PathInterpolator\n\nThe\n[`PathInterpolator`](/reference/android/view/animation/PathInterpolator)\nclass is an interpolator introduced in Android 5.0 (API 21). It is based on a\n[Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve) or a\n`Path` object. The Android examples in the [Material Design documentation for\neasing](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs#433b1153-2ea3-4fe2-9748-803a47bc97ee)\nuse `PathInterpolator`.\n\n`PathInterpolator` has constructors based on different types of Bézier curves.\nAll Bézier curves have start and end points fixed at `(0,0)` and `(1,1)`,\nrespectively. The other constructor arguments depend on the type of Bézier\ncurve being created.\n\nFor example, for a quadratic Bézier curve only the X and Y coordinates\nof one control point are needed: \n\n### Kotlin\n\n```kotlin\nval myInterpolator = if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n PathInterpolator(0.67f, 0.33f)\n} else {\n LinearInterpolator()\n}\n```\n\n### Java\n\n```java\nInterpolator myInterpolator = null;\nif (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n myInterpolator = new PathInterpolator(0.67f, 0.33f);\n} else {\n myInterpolator = new LinearInterpolator();\n}\n```\n\nThis produces an easing curve that starts quickly and decelerates as it\napproaches the end.\n\nThe cubic Bézier constructor similarly has fixed start and end points, but it\nrequires two control points: \n\n### Kotlin\n\n```kotlin\nval myInterpolator = if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)\n} else {\n LinearInterpolator()\n}\n```\n\n### Java\n\n```java\nInterpolator myInterpolator = null;\nif (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);\n} else {\n myInterpolator = new LinearInterpolator();\n}\n```\n\nThis is an implementation of the Material Design [*emphasized\ndecelerate*](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs#cbea5c6e-7b0d-47a0-98c3-767080a38d95)\neasing curve.\n\nFor greater control, an arbitrary `Path` can be used to define the curve: \n\n### Kotlin\n\n```kotlin\nval myInterpolator = if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n val path = Path().apply {\n moveTo(0.0f, 0.0f)\n cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)\n }\n PathInterpolator(path)\n} else {\n LinearInterpolator()\n}\n```\n\n### Java\n\n```java\nInterpolator myInterpolator = null;\nif (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.LOLLIPOP) {\n Path path = new Path();\n path.moveTo(0.0f, 0.0f);\n path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);\n myInterpolator = new PathInterpolator(path);\n} else {\n myInterpolator = new LinearInterpolator();\n}\n```\n\nThis produces the same easing curve as the cubic Bézier example, but it uses a\n`Path` instead.\n\nYou can also define a path interpolator as an XML resource: \n\n \u003cpathInterpolator xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:controlX1=\"0.5\"\n android:controlY1=\"0.7\"\n android:controlX2=\"0.1f\"\n android:controlY2=\"1.0f\"/\u003e\n\nOnce you create a `PathInterpolator` object, you can pass it to the\n[`Animator.setInterpolator()`](/reference/android/animation/Animator#setInterpolator(android.animation.TimeInterpolator))\nmethod. The `Animator` uses the interpolator to determine the timing or path\ncurve when it is started. \n\n### Kotlin\n\n```kotlin\nval animation = ObjectAnimator.ofFloat(view, \"translationX\", 100f).apply {\n interpolator = myInterpolator\n start()\n}\n```\n\n### Java\n\n```java\nObjectAnimator animation = ObjectAnimator.ofFloat(view, \"translationX\", 100f);\nanimation.setInterpolator(myInterpolator);\nanimation.start();\n```"]]