page.title=Định nghĩa Hoạt hình Tùy chỉnh @jd:body
Hoạt hình theo phong cách material design phản hồi hành động của người dùng và cung cấp tính liên tục trực quan khi người dùng tương tác với ứng dụng của bạn. Giao diện material cung cấp một số hoạt hình mặc định cho các nút và chuyển tiếp hoạt động, và Android 5.0 (API mức 21) và cao hơn cho phép bạn tùy chỉnh những hoạt hình này và tạo các hoạt hình mới:
Phản hồi chạm trong Material Design đưa ra một xác nhận trực quan tức thời tại điểm tiếp xúc khi người dùng tương tác với các phần tử UI. Hoạt hình phản hồi chạm mặc định cho nút sẽ sử dụng lớp {@link android.graphics.drawable.RippleDrawable} mới để chuyển tiếp giữa các trạng thái khác nhau bằng hiệu ứng gợn sóng.
Trong hầu hết trường hợp, bạn nên áp dụng tính năng này trong tệp XML dạng xem của mình bằng cách chỉ định nền dạng xem là:
?android:attr/selectableItemBackground
cho gợn sóng có giới hạn.?android:attr/selectableItemBackgroundBorderless
cho gợn sóng lan ra ngoài
dạng xem. Hiệu ứng sẽ được vẽ lên và được giới hạn bởi dạng xem mẹ gần nhất có nền
không rỗng.Lưu ý: selectableItemBackgroundBorderless
là một thuộc tính
mới được giới thiệu trong API mức 21.
Hoặc, bạn có thể định nghĩa {@link android.graphics.drawable.RippleDrawable}
làm tài nguyên XML bằng cách sử dụng phần tử ripple
.
Bạn có thể gán một màu cho các đối tượng {@link android.graphics.drawable.RippleDrawable}. Để thay đổi
màu phản hồi chạm mặc định, hãy sử dụng thuộc tính android:colorControlHighlight
của chủ đề.
Để biết thêm thông tin, hãy xem tài liệu tham khảo API cho lớp {@link android.graphics.drawable.RippleDrawable}.
Hoạt hình lộ ra đảm bảo tính liên tục trực quan cho người dùng khi bạn hiện hoặc ẩn một nhóm phần tử UI. Phương thức {@link android.view.ViewAnimationUtils#createCircularReveal ViewAnimationUtils.createCircularReveal()} cho phép bạn tạo hiệu ứng hoạt hình một vòng tròn cắt hình để lộ ra hoặc ẩn một dạng xem.
Để lộ ra một dạng xem ẩn trước đó bằng hiệu ứng này:
// previously invisible view View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // get the final radius for the clipping circle int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); // create the animator for this view (the start radius is zero) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); // make the view visible and start the animation myView.setVisibility(View.VISIBLE); anim.start();
Để ẩn một dạng xem hiển thị trước đó bằng hiệu ứng này:
// previously visible view final View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // get the initial radius for the clipping circle int initialRadius = myView.getWidth(); // create the animation (the final radius is zero) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); // make the view invisible when the animation is done anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); } }); // start the animation anim.start();
Hình 1 - Chuyển tiếp với những phần tử chung.
Để phát lại phim, nhấp vào màn hình thiết bịChuyển tiếp hoạt động trong các ứng dụng theo phong cách material design cung cấp kết nối trực quan giữa các trạng thái khác nhau thông qua chuyển động và chuyển đổi giữa những phần tử hay dùng. Bạn có thể quy định hoạt hình tùy chỉnh cho các chuyển tiếp ra vào và chuyển tiếp phần tử chung giữa các hoạt động.
Android 5.0 (API mức 21) hỗ trợ những chuyển tiếp ra vào sau:
Bất cứ chuyển tiếp nào mở rộng lớp {@link android.transition.Visibility} đều được hỗ trợ như một chuyển tiếp vào hoặc ra. Để biết thêm thông tin, hãy xem tài liệu tham khảo API cho lớp {@link android.transition.Transition}.
Android 5.0 (API mức 21) cũng hỗ trợ những chuyển tiếp phần tử chung này:
Khi bạn cho phép chuyển tiếp hoạt động trong ứng dụng của mình, chuyển tiếp mờ dần chéo cross-fading mặc định sẽ được kích hoạt giữa các hoạt động ra vào.
Hình 2 - Chuyển tiếp cảnh với một phần tử chung.
Trước tiên, cho phép chuyển tiếp nội dung cửa sổ bằng thuộc tính android:windowContentTransitions
khi bạn định nghĩa một kiểu kế thừa từ chủ đề material. Bạn cũng có thể quy định chuyển tiếp
ra, vào và phần tử chung trong định nghĩa kiểu của mình:
<style name="BaseAppTheme" parent="android:Theme.Material"> <!-- enable window content transitions --> <item name="android:windowContentTransitions">true</item> <!-- specify enter and exit transitions --> <item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item> <!-- specify shared element transitions --> <item name="android:windowSharedElementEnterTransition"> @transition/change_image_transform</item> <item name="android:windowSharedElementExitTransition"> @transition/change_image_transform</item> </style>
Chuyển tiếp change_image_transform
trong ví dụ này được định nghĩa như sau:
<!-- res/transition/change_image_transform.xml --> <!-- (see also Shared Transitions below) --> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeImageTransform/> </transitionSet>
Phần tử changeImageTransform
tương ứng với lớp
{@link android.transition.ChangeImageTransform}. Để biết thêm thông tin, hãy xem tài liệu tham khảo API
cho {@link android.transition.Transition}.
Thay vào đó, để cho phép chuyển tiếp nội dung cửa sổ trong mã của bạn, hãy gọi phương thức {@link android.view.Window#requestFeature Window.requestFeature()}:
// inside your activity (if you did not enable transitions in your theme) getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); // set an exit transition getWindow().setExitTransition(new Explode());
Để quy định chuyển tiếp trong mã của bạn, hãy gọi những phương thức này bằng đối tượng {@link android.transition.Transition}:
Phương thức {@link android.view.Window#setExitTransition setExitTransition()} và {@link android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} định nghĩa chuyển tiếp ra cho hoạt động gọi. Phương thức {@link android.view.Window#setEnterTransition setEnterTransition()} và {@link android.view.Window#setSharedElementEnterTransition setSharedElementEnterTransition()} định nghĩa chuyển tiếp vào cho hoạt động được gọi.
Để có đầy đủ hiệu ứng của một chuyển tiếp, bạn phải cho phép chuyển tiếp nội dung cửa sổ trên cả hoạt động gọi và được gọi. Nếu không, hoạt động gọi sẽ bắt đầu chuyển tiếp ra, nhưng khi đó bạn sẽ thấy chuyển tiếp cửa sổ (như co giãn và mờ dần).
Để bắt đầu một chuyển tiếp vào ngay khi có thể, hãy sử dụng phương thức {@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()} trên hoạt động được gọi. Nó cho phép bạn có chuyển tiếp vào ấn tượng hơn.
Nếu bạn cho phép chuyển tiếp và đặt chuyển tiếp ra cho một hoạt động, chuyển tiếp sẽ được kích hoạt khi bạn khởi chạy một hoạt động khác như sau:
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
Nếu bạn đặt một chuyển tiếp vào cho hoạt động thứ hai, chuyển tiếp này cũng được kích hoạt khi hoạt động
bắt đầu. Để vô hiệu hoá chuyển tiếp khi bạn bắt đầu một hoạt động khác, hãy cung cấp
một nhóm tùy chọn null
.
Để tạo một hoạt hình chuyển tiếp màn hình giữa hai hoạt động có một phần tử chung:
android:transitionName
.// get the element that receives the click event final View imgContainerView = findViewById(R.id.img_container); // get the common element for the transition in this activity final View androidRobotView = findViewById(R.id.image_small); // define a click listener imgContainerView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(this, Activity2.class); // create the transition animation - the images in the layouts // of both activities are defined with android:transitionName="robot" ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, androidRobotView, "robot"); // start the new activity startActivity(intent, options.toBundle()); } });
Đối với các dạng xem động dùng chung mà bạn khởi tạo trong mã của mình, hãy sử dụng phương thức {@link android.view.View#setTransitionName View.setTransitionName()} để quy định một tên phần tử chung trong cả hai hoạt động.
Để đảo ngược hoạt hình chuyển tiếp cảnh khi bạn kết thúc hoạt động thứ hai, hãy gọi phương thức {@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()} thay vì {@link android.app.Activity#finish Activity.finish()}.
Để tạo một hoạt hình chuyển tiếp cảnh giữa hai hoạt động có nhiều hơn một phần tử
chung, hãy định nghĩa các phần tử chung trong cả hai bố trí bằng thuộc tính android:transitionName
(hoặc sử dụng phương thức {@link android.view.View#setTransitionName View.setTransitionName()}
trong cả hai hoạt động), và tạo một đối tượng {@link android.app.ActivityOptions} như sau:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));
Hoạt hình theo phong cách material design phụ thuộc vào đường cong làm mẫu hình nội suy thời gian và chuyển động không gian. Với Android 5.0 (API mức 21) trở lên, bạn có thể định nghĩa đường cong định thời tùy chỉnh và mẫu hình chuyển động cong cho hoạt hình.
Lớp {@link android.view.animation.PathInterpolator} là một hàm nội suy mới dựa trên đường cong Bézier hoặc đối tượng {@link android.graphics.Path}. Hàm nội suy này quy định một đường cong chuyển động trong một hình vuông 1x1, với các điểm neo tại (0,0) và (1,1) cùng các điểm kiểm soát được quy định bằng cách sử dụng các tham đối của hàm dựng. Bạn cũng có thể định nghĩa một hàm nội suy đường dẫn dưới dạng tài nguyên XML:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.4" android:controlY1="0" android:controlX2="1" android:controlY2="1"/>
Hệ thống cung cấp tài nguyên XML cho ba đường cong cơ bản trong đặc tả material design:
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
Bạn có thể chuyển một đối tượng {@link android.view.animation.PathInterpolator} tới phương thức {@link android.animation.Animator#setInterpolator Animator.setInterpolator()}.
Lớp {@link android.animation.ObjectAnimator} có các hàm dựng mới cho phép bạn tạo hiệu ứng hoạt hình cho các tọa độ dọc theo một đường dẫn bằng hai hoặc nhiều thuộc tính đồng thời. Ví dụ, trình tạo hoạt hình sau sử dụng một đối tượng {@link android.graphics.Path} để tạo hiệu ứng hoạt hình cho thuộc tính X và Y của một dạng xem:
ObjectAnimator mAnimator; mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); ... mAnimator.start();
Lớp {@link android.animation.StateListAnimator} cho phép bạn định nghĩa trình tạo hoạt hình để chạy khi trạng thái của dạng xem thay đổi. Ví dụ sau cho biết cách định nghĩa một {@link android.animation.StateListAnimator} dưới dạng tài nguyên XML:
<!-- animate the translationZ property of a view when pressed --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="@android:integer/config_shortAnimTime" android:valueTo="2dp" android:valueType="floatType"/> <!-- you could have other objectAnimator elements here for "x" and "y", or other properties --> </set> </item> <item android:state_enabled="true" android:state_pressed="false" android:state_focused="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector>
Để gắn kèm hoạt hình trạng thái dạng xem tùy chỉnh vào một dạng xem, hãy định nghĩa một trình tạo hoạt hình bằng cách sử dụng phần tử
selector
trong một tệp tài nguyên XML như trong ví dụ này, và gán nó cho dạng xem
của bạn bằng thuộc tính android:stateListAnimator
. Để gán một trình tạo hoạt hình danh sách trạng thái
cho một dạng xem trong mã của bạn, hãy sử dụng phương thức {@link android.animation.AnimatorInflater#loadStateListAnimator
AnimationInflater.loadStateListAnimator()} và gán trình tạo hoạt hình cho dạng xem của bạn bằng phương thức
{@link android.view.View#setStateListAnimator View.setStateListAnimator()}.
Khi chủ đề của bạn mở rộng ra chủ đề material, các nút sẽ có hoạt hình Z theo mặc định. Để tránh hành vi
này trong nút của bạn, hãy đặt thuộc tính android:stateListAnimator
thành
@null
.
Lớp {@link android.graphics.drawable.AnimatedStateListDrawable} cho phép bạn tạo các nội dung vẽ được để hiển thị hoạt hình giữa các thay đổi trạng thái của dạng xem được liên kết. Một số widget hệ thống trong Android 5.0 sử dụng những hoạt hình này theo mặc định. Ví dụ sau cho biết cách cách định nghĩa {@link android.graphics.drawable.AnimatedStateListDrawable} dưới dạng tài nguyên XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Nội dung vẽ được Véc-tơ sẽ co giãn được mà không làm mất độ sắc nét. Lớp {@link android.graphics.drawable.AnimatedVectorDrawable} cho phép bạn tạo hiệu ứng hoạt hình các thuộc tính của nội dung vẽ được véc-tơ.
Thường thì bạn định nghĩa nội dung vẽ được véc-tơ hoạt hình theo ba tệp XML:
<vector>
trong
res/drawable/
<animated-vector>
trong
res/drawable/
<objectAnimator>
trong
res/anim/
Nội dung vẽ được véc-tơ hoạt hình có thể tạo hiệu ứng hoạt hình các thuộc tính của phần tử <group>
và
<path>
. Phần tử <group>
định nghĩa một bộ
đường dẫn hoặc nhóm phụ và phần tử <path>
định nghĩa các đường dẫn sẽ được vẽ.
Khi định nghĩa một nội dung vẽ được véc-tơ mà bạn muốn tạo hiệu ứng hoạt hình, hãy sử dụng thuộc tính android:name
để gán một tên duy nhất cho các nhóm và đường dẫn, sao cho bạn có thể tham chiếu tới chúng từ các định nghĩa
trình tạo hoạt hình của mình. Ví dụ:
<!-- res/drawable/vectordrawable.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600"> <group android:name="rotationGroup" android:pivotX="300.0" android:pivotY="300.0" android:rotation="45.0" > <path android:name="v" android:fillColor="#000000" android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> </group> </vector>
Định nghĩa nội dung vẽ được véc-tơ hoạt hình sẽ tham chiếu tới các nhóm và đường dẫn trong nội dung vẽ được véc-tơ theo tên của chúng:
<!-- res/drawable/animvectordrawable.xml --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vectordrawable" > <target android:name="rotationGroup" android:animation="@anim/rotation" /> <target android:name="v" android:animation="@anim/path_morph" /> </animated-vector>
Định nghĩa hoạt hình biểu diễn các đối tượng {@link android.animation.ObjectAnimator} hoặc {@link android.animation.AnimatorSet}. Trình tạo hoạt hình đầu tiên trong ví dụ này sẽ xoay nhóm đối tượng 360 độ:
<!-- res/anim/rotation.xml --> <objectAnimator android:duration="6000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" />
Trình tạo hoạt hình thứ hai trong ví dụ này sẽ đổi dạng đường dẫn của nội dung vẽ được véc-tơ từ hình này sang hình khác. Cả hai đường dẫn đều phải tương thích với việc đổi dạng: chúng phải có cùng số lệnh và cùng số lượng tham số cho từng lệnh.
<!-- res/anim/path_morph.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="pathData" android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" android:valueType="pathType" /> </set>
Để biết thêm thông tin, hãy xem tài liệu tham khảo API cho {@link android.graphics.drawable.AnimatedVectorDrawable}.