ขณะที่ผู้ใช้ใช้แอป ข้อมูลใหม่จะปรากฏบนหน้าจอและข้อมูลเก่าจะถูกนำออก การเปลี่ยนสิ่งที่แสดงบนหน้าจอทันทีอาจทำให้ผู้ใช้รู้สึกขัดตา และพลาดเนื้อหาใหม่ที่ปรากฏขึ้นอย่างกะทันหัน ภาพเคลื่อนไหวจะชะลอการเปลี่ยนแปลงและดึงดูดสายตาผู้ใช้ด้วยการเคลื่อนไหวเพื่อให้การอัปเดตชัดเจนยิ่งขึ้น
ภาพเคลื่อนไหวทั่วไป 3 แบบที่คุณใช้เพื่อแสดงหรือซ่อนมุมมองได้ ได้แก่ ภาพเคลื่อนไหวแบบเปิดเผย ภาพเคลื่อนไหวแบบจางซ้อน และภาพเคลื่อนไหวแบบพลิกการ์ด
สร้างภาพเคลื่อนไหวแบบจางซ้อน
ภาพเคลื่อนไหวแบบจางซ้อน หรือที่เรียกว่า การละลาย จะค่อยๆ จาง
View หรือ
ViewGroup หนึ่งรายการออกไปพร้อมกับค่อยๆ จางอีกรายการเข้ามา ภาพเคลื่อนไหวนี้มีประโยชน์ในสถานการณ์ที่คุณต้องการ
เปลี่ยนเนื้อหาหรือมุมมองในแอป ภาพเคลื่อนไหวแบบจางซ้อนที่แสดงที่นี่ใช้
ViewPropertyAnimator,
ซึ่งพร้อมใช้งานสำหรับ Android 3.1 (API ระดับ 12) ขึ้นไป
ตัวอย่างภาพเคลื่อนไหวแบบจางซ้อนจากตัวบ่งชี้ความคืบหน้าไปยังเนื้อหาข้อความ
สร้างมุมมอง
สร้างมุมมอง 2 รายการที่ต้องการจางซ้อน ตัวอย่างต่อไปนี้สร้างตัวบ่งชี้ความคืบหน้าและมุมมองข้อความที่เลื่อนได้
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum"
android:padding="16dp" />
</ScrollView>
<ProgressBar android:id="@+id/loading_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
ตั้งค่าภาพเคลื่อนไหวแบบจางซ้อน
หากต้องการตั้งค่าภาพเคลื่อนไหวแบบจางซ้อน ให้ทำดังนี้
- สร้างตัวแปรสมาชิกสำหรับมุมมองที่ต้องการจางซ้อน คุณจะต้องใช้ข้อมูลอ้างอิงเหล่านี้ในภายหลังเมื่อแก้ไขมุมมองระหว่างภาพเคลื่อนไหว
- ตั้งค่าระดับการมองเห็นของมุมมองที่กำลังจางเข้ามาเป็น
GONEซึ่งจะป้องกันไม่ให้มุมมองใช้พื้นที่เลย์เอาต์และไม่รวมมุมมองจากการคำนวณเลย์เอาต์ ซึ่งจะช่วยเพิ่มความเร็วในการประมวลผล - แคชพร็อพเพอร์ตี้ระบบ
config_shortAnimTimeในตัวแปรสมาชิก พร็อพเพอร์ตี้นี้กำหนดระยะเวลา "สั้น" มาตรฐานสำหรับภาพเคลื่อนไหว ระยะเวลานี้เหมาะสำหรับภาพเคลื่อนไหวที่ละเอียดอ่อนหรือภาพเคลื่อนไหวที่เกิดขึ้นบ่อยๆconfig_longAnimTimeและconfig_mediumAnimTimeให้ใช้งานด้วย
ตัวอย่างการใช้เลย์เอาต์จากข้อมูลโค้ดก่อนหน้าเป็นมุมมองเนื้อหาของกิจกรรม
Kotlin
class CrossfadeActivity : Activity() { private lateinit var contentView: View private lateinit var loadingView: View private var shortAnimationDuration: Int = 0 ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_crossfade) contentView = findViewById(R.id.content) loadingView = findViewById(R.id.loading_spinner) // Initially hide the content view. contentView.visibility = View.GONE // Retrieve and cache the system's default "short" animation time. shortAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime) } ... }
Java
public class CrossfadeActivity extends Activity { private View contentView; private View loadingView; private int shortAnimationDuration; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crossfade); contentView = findViewById(R.id.content); loadingView = findViewById(R.id.loading_spinner); // Initially hide the content view. contentView.setVisibility(View.GONE); // Retrieve and cache the system's default "short" animation time. shortAnimationDuration = getResources().getInteger( android.R.integer.config_shortAnimTime); } ... }
จางซ้อนมุมมอง
เมื่อตั้งค่ามุมมองอย่างถูกต้องแล้ว ให้จางซ้อนมุมมองโดยทำดังนี้
- สำหรับมุมมองที่กำลังจางเข้ามา ให้ตั้งค่าอัลฟาเป็น 0 และระดับการมองเห็น
เป็น
VISIBLEจากการตั้งค่าเริ่มต้น เป็นGONEซึ่งจะทำให้มุมมองมองเห็นได้แต่โปร่งใส - สำหรับมุมมองที่กำลังจางเข้ามา ให้ทำให้ค่าอัลฟาเคลื่อนไหวจาก 0 เป็น 1 สำหรับมุมมองที่กำลังจางออก ให้ทำให้ค่าอัลฟาเคลื่อนไหวจาก 1 เป็น 0
- ใช้
onAnimationEnd()ในAnimator.AnimatorListenerเพื่อตั้งค่าระดับการมองเห็นของมุมมองที่กำลังจางออกเป็นGONEแม้ว่าค่าอัลฟาจะเป็น 0 แต่การตั้งค่าระดับการมองเห็นของมุมมองเป็นGONEจะป้องกันไม่ให้มุมมองใช้พื้นที่เลย์เอาต์และไม่รวมมุมมองจากการคำนวณเลย์เอาต์ ซึ่งจะช่วยเพิ่มความเร็วในการประมวลผล
เมธอดต่อไปนี้แสดงตัวอย่างวิธีดำเนินการ
Kotlin
class CrossfadeActivity : Activity() { private lateinit var contentView: View private lateinit var loadingView: View private var shortAnimationDuration: Int = 0 ... private fun crossfade() { contentView.apply { // Set the content view to 0% opacity but visible, so that it is // visible but fully transparent during the animation. alpha = 0f visibility = View.VISIBLE // Animate the content view to 100% opacity and clear any animation // listener set on the view. animate() .alpha(1f) .setDuration(shortAnimationDuration.toLong()) .setListener(null) } // Animate the loading view to 0% opacity. After the animation ends, // set its visibility to GONE as an optimization step so it doesn't // participate in layout passes. loadingView.animate() .alpha(0f) .setDuration(shortAnimationDuration.toLong()) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { loadingView.visibility = View.GONE } }) } }
Java
public class CrossfadeActivity extends Activity { private View contentView; private View loadingView; private int shortAnimationDuration; ... private void crossfade() { // Set the content view to 0% opacity but visible, so that it is // visible but fully transparent during the animation. contentView.setAlpha(0f); contentView.setVisibility(View.VISIBLE); // Animate the content view to 100% opacity and clear any animation // listener set on the view. contentView.animate() .alpha(1f) .setDuration(shortAnimationDuration) .setListener(null); // Animate the loading view to 0% opacity. After the animation ends, // set its visibility to GONE as an optimization step so it doesn't // participate in layout passes. loadingView.animate() .alpha(0f) .setDuration(shortAnimationDuration) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { loadingView.setVisibility(View.GONE); } }); } }
สร้างภาพเคลื่อนไหวแบบพลิกการ์ด
การพลิกการ์ดจะสลับระหว่างมุมมองเนื้อหาโดยแสดงภาพเคลื่อนไหวที่จำลองการพลิกการ์ด ภาพเคลื่อนไหวแบบพลิกการ์ดที่แสดงที่นี่ใช้
FragmentTransaction
ภาพเคลื่อนไหวแบบพลิกการ์ดมีลักษณะดังนี้
สร้างออบเจ็กต์ Animator
หากต้องการสร้างภาพเคลื่อนไหวแบบพลิกการ์ด คุณต้องมี Animator 4 รายการ Animator 2 รายการใช้สำหรับเมื่อด้านหน้าของการ์ดเคลื่อนไหวออกไปทางซ้ายและเมื่อเคลื่อนไหวเข้ามาจากทางซ้าย Animator อีก 2 รายการใช้สำหรับเมื่อด้านหลังของการ์ดเคลื่อนไหวเข้ามาจากทางขวาและเมื่อเคลื่อนไหวออกไปทางขวา
card_flip_left_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="-180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 1. See startOffset. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
card_flip_left_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 0. See startOffset. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
card_flip_right_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 1. See startOffset. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
card_flip_right_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="-180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 0. See startOffset. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
สร้างมุมมอง
การ์ดแต่ละด้านเป็นเลย์เอาต์แยกกันซึ่งมีเนื้อหาใดก็ได้ที่คุณต้องการ เช่น มุมมองข้อความ 2 รายการ รูปภาพ 2 รายการ หรือการผสมผสานมุมมองต่างๆ เพื่อสลับไปมา ใช้เลย์เอาต์ 2 รายการใน Fragment ที่คุณทำให้เคลื่อนไหวในภายหลัง เลย์เอาต์ต่อไปนี้สร้างการ์ดด้านหนึ่งซึ่งแสดงข้อความ
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#a6c"
android:padding="16dp"
android:gravity="bottom">
<TextView android:id="@android:id/text1"
style="?android:textAppearanceLarge"
android:textStyle="bold"
android:textColor="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_title" />
<TextView style="?android:textAppearanceSmall"
android:textAllCaps="true"
android:textColor="#80ffffff"
android:textStyle="bold"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_description" />
</LinearLayout>
และเลย์เอาต์ถัดไปจะสร้างการ์ดอีกด้านหนึ่งซึ่งแสดง
ImageView
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image1"
android:scaleType="centerCrop"
android:contentDescription="@string/description_image_1" />
สร้าง Fragment
สร้างคลาส Fragment สำหรับด้านหน้าและด้านหลังของการ์ด ในคลาส Fragment
ให้ส่งคืนเลย์เอาต์ที่คุณสร้างจาก
onCreateView()
เมธอด จากนั้นคุณจะสร้างอินสแตนซ์ของ Fragment นี้ในกิจกรรมหลักที่คุณต้องการแสดงการ์ดได้
ตัวอย่างต่อไปนี้แสดงคลาส Fragment ที่ซ้อนกันภายในกิจกรรมหลักที่ใช้คลาสเหล่านั้น
Kotlin
class CardFlipActivity : FragmentActivity() { ... /** * A fragment representing the front of the card. */ class CardFrontFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_card_front, container, false) } /** * A fragment representing the back of the card. */ class CardBackFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_card_back, container, false) } }
Java
public class CardFlipActivity extends FragmentActivity { ... /** * A fragment representing the front of the card. */ public class CardFrontFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_card_front, container, false); } } /** * A fragment representing the back of the card. */ public class CardBackFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_card_back, container, false); } } }
ทำให้การ์ดพลิกเคลื่อนไหว
แสดง Fragment ภายในกิจกรรมหลัก หากต้องการทำเช่นนี้ ให้สร้างเลย์เอาต์สำหรับกิจกรรม ตัวอย่างต่อไปนี้สร้าง
FrameLayoutที่คุณเพิ่ม
Fragment ได้ในรันไทม์:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
ในโค้ดกิจกรรม ให้ตั้งค่ามุมมองเนื้อหาเป็นเลย์เอาต์ที่คุณสร้าง แนวทางปฏิบัติแนะนำคือการแสดง Fragment เริ่มต้นเมื่อสร้างกิจกรรม กิจกรรมตัวอย่างต่อไปนี้แสดงวิธีแสดงด้านหน้าของการ์ดโดยค่าเริ่มต้น
Kotlin
class CardFlipActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_activity_card_flip) if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .add(R.id.container, CardFrontFragment()) .commit() } } ... }
Java
public class CardFlipActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_activity_card_flip); if (savedInstanceState == null) { getSupportFragmentManager() .beginTransaction() .add(R.id.container, new CardFrontFragment()) .commit(); } } ... }
เมื่อแสดงด้านหน้าของการ์ดแล้ว คุณจะแสดงด้านหลังของการ์ดด้วยภาพเคลื่อนไหวแบบพลิกในเวลาที่เหมาะสมได้ สร้างเมธอดเพื่อแสดงการ์ดอีกด้านหนึ่งซึ่งทำสิ่งต่อไปนี้
- ตั้งค่าภาพเคลื่อนไหวที่กำหนดเองที่คุณสร้างขึ้นสำหรับการเปลี่ยน Fragment
- แทนที่ Fragment ที่แสดงด้วย Fragment ใหม่และทำให้เหตุการณ์นี้เคลื่อนไหวด้วยภาพเคลื่อนไหวที่กำหนดเองที่คุณสร้างขึ้น
- เพิ่ม Fragment ที่แสดงก่อนหน้านี้ลงใน Back Stack ของ Fragment เพื่อให้การ์ดพลิกกลับเมื่อผู้ใช้แตะปุ่มย้อนกลับ
Kotlin
class CardFlipActivity : FragmentActivity() { ... private fun flipCard() { if (showingBack) { supportFragmentManager.popBackStack() return } // Flip to the back. showingBack = true // Create and commit a new fragment transaction that adds the fragment // for the back of the card, uses custom animations, and is part of the // fragment manager's back stack. supportFragmentManager.beginTransaction() // Replace the default fragment animations with animator // resources representing rotations when switching to the back // of the card, as well as animator resources representing // rotations when flipping back to the front, such as when the // system Back button is tapped. .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out ) // Replace any fragments in the container view with a fragment // representing the next page, indicated by the just-incremented // currentPage variable. .replace(R.id.container, CardBackFragment()) // Add this transaction to the back stack, letting users press // the Back button to get to the front of the card. .addToBackStack(null) // Commit the transaction. .commit() } }
Java
public class CardFlipActivity extends FragmentActivity { ... private void flipCard() { if (showingBack) { getSupportFragmentManager().popBackStack(); return; } // Flip to the back. showingBack = true; // Create and commit a new fragment transaction that adds the fragment // for the back of the card, uses custom animations, and is part of the // fragment manager's back stack. getSupportFragmentManager() .beginTransaction() // Replace the default fragment animations with animator // resources representing rotations when switching to the back // of the card, as well as animator resources representing // rotations when flipping back to the front, such as when the // system Back button is pressed. .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out) // Replace any fragments in the container view with a fragment // representing the next page, indicated by the just-incremented // currentPage variable. .replace(R.id.container, new CardBackFragment()) // Add this transaction to the back stack, letting users press // Back to get to the front of the card. .addToBackStack(null) // Commit the transaction. .commit(); } }
สร้างภาพเคลื่อนไหวแบบเปิดเผยวงกลม
ภาพเคลื่อนไหวแบบเปิดเผยช่วยให้ผู้ใช้เห็นความต่อเนื่องของภาพเมื่อคุณแสดงหรือซ่อนกลุ่มองค์ประกอบ UI เมธอด
ViewAnimationUtils.createCircularReveal()
ช่วยให้คุณทำให้วงกลมการตัดเคลื่อนไหวเพื่อเปิดเผยหรือซ่อนมุมมอง ภาพเคลื่อนไหวนี้มีให้ใช้งานในคลาส
ViewAnimationUtils ซึ่งพร้อมใช้งานสำหรับ Android 5.0 (API ระดับ 21) ขึ้นไป
ตัวอย่างต่อไปนี้แสดงวิธีเปิดเผยมุมมองที่มองไม่เห็นก่อนหน้านี้
Kotlin
// A previously invisible view. val myView: View = findViewById(R.id.my_view) // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. val cx = myView.width / 2 val cy = myView.height / 2 // Get the final radius for the clipping circle. val finalRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() // Create the animator for this view. The start radius is 0. val anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0f, finalRadius) // Make the view visible and start the animation. myView.visibility = View.VISIBLE anim.start() } else { // Set the view to invisible without a circular reveal animation below // Android 5.0. myView.visibility = View.INVISIBLE }
Java
// A previously invisible view. View myView = findViewById(R.id.my_view); // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // Get the final radius for the clipping circle. float finalRadius = (float) Math.hypot(cx, cy); // Create the animator for this view. The start radius is 0. Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0f, finalRadius); // Make the view visible and start the animation. myView.setVisibility(View.VISIBLE); anim.start(); } else { // Set the view to invisible without a circular reveal animation below // Android 5.0. myView.setVisibility(View.INVISIBLE); }
ภาพเคลื่อนไหว ViewAnimationUtils.createCircularReveal() ใช้พารามิเตอร์ 5 รายการ
พารามิเตอร์แรกคือมุมมองที่ต้องการซ่อนหรือแสดงบนหน้าจอ พารามิเตอร์ 2 รายการถัดไปคือพิกัด X และ Y สำหรับจุดกึ่งกลางของวงกลมการตัด โดยปกติแล้วจะเป็นจุดกึ่งกลางของมุมมอง แต่คุณยังใช้จุดที่ผู้ใช้แตะเพื่อให้ภาพเคลื่อนไหวเริ่มต้นในตำแหน่งที่ผู้ใช้เลือกได้ด้วย พารามิเตอร์ที่ 4 คือรัศมีเริ่มต้นของวงกลมการตัด
ในตัวอย่างก่อนหน้า รัศมีเริ่มต้นถูกตั้งค่าเป็น 0 เพื่อให้วงกลมซ่อนมุมมองที่แสดงอยู่ พารามิเตอร์สุดท้ายคือรัศมีสุดท้ายของวงกลม เมื่อแสดงมุมมอง ให้กำหนดรัศมีสุดท้ายให้ใหญ่กว่ามุมมองเพื่อให้มุมมองแสดงได้อย่างสมบูรณ์ก่อนที่ภาพเคลื่อนไหวจะสิ้นสุด
หากต้องการซ่อนมุมมองที่มองเห็นได้ก่อนหน้านี้ ให้ทำดังนี้
Kotlin
// A previously visible view. val myView: View = findViewById(R.id.my_view) // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. val cx = myView.width / 2 val cy = myView.height / 2 // Get the initial radius for the clipping circle. val initialRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() // Create the animation. The final radius is 0. val anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0f) // Make the view invisible when the animation is done. anim.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) myView.visibility = View.INVISIBLE } }) // Start the animation. anim.start() } else { // Set the view to visible without a circular reveal animation below // Android 5.0. myView.visibility = View.VISIBLE }
Java
// A previously visible view. final View myView = findViewById(R.id.my_view); // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // Get the initial radius for the clipping circle. float initialRadius = (float) Math.hypot(cx, cy); // Create the animation. The final radius is 0. Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0f); // 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(); } else { // Set the view to visible without a circular reveal animation below Android // 5.0. myView.setVisibility(View.VISIBLE); }
ในกรณีนี้ รัศมีเริ่มต้นของวงกลมการตัดจะถูกตั้งค่าให้มีขนาดใหญ่เท่ากับมุมมองเพื่อให้มุมมองมองเห็นได้ก่อนที่ภาพเคลื่อนไหวจะเริ่มต้น รัศมีสุดท้ายถูกตั้งค่าเป็น 0 เพื่อให้มุมมองถูกซ่อนเมื่อภาพเคลื่อนไหวสิ้นสุด
เพิ่ม Listener ลงในภาพเคลื่อนไหวเพื่อให้ตั้งค่าระดับการมองเห็นของมุมมองเป็น
INVISIBLE ได้เมื่อภาพเคลื่อนไหว
เสร็จสมบูรณ์
แหล่งข้อมูลเพิ่มเติม
- ภาพเคลื่อนไหวด้วย Jetpack Compose
- ท่าทางสัมผัสด้วย Jetpack Compose