ระหว่างการใช้งานแอป ข้อมูลใหม่จะปรากฏขึ้นบนหน้าจอและข้อมูลเก่า แล้ว การเปลี่ยนสิ่งที่แสดงบนหน้าจอสามารถทำได้ทันที ที่น่าตกใจ และผู้ใช้อาจพลาดเนื้อหาใหม่ที่ปรากฏขึ้นแบบกะทันหัน ภาพเคลื่อนไหวช้า การเปลี่ยนแปลงและดึงดูดความสนใจของผู้ใช้ด้วยการเคลื่อนไหวเพื่อให้การอัปเดต ชัดเจนยิ่งขึ้น
มีภาพเคลื่อนไหวทั่วไป 3 แบบที่คุณสามารถใช้เพื่อแสดงหรือซ่อนมุมมอง ได้แก่ ภาพเคลื่อนไหวแบบครอสเฟด และภาพเคลื่อนไหวแบบ Card Flip
สร้างภาพเคลื่อนไหวครอสเฟด
ภาพเคลื่อนไหวแบบครอสเฟดหรือที่เรียกว่าการจางหายจะค่อยๆ ค่อยๆ หายไป
หนึ่ง 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
พร้อมให้บริการด้วย
ต่อไปนี้เป็นตัวอย่างที่ใช้การจัดวางจากข้อมูลโค้ดก่อนหน้าเป็น ดูเนื้อหากิจกรรม
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)
}
...
}
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
จะป้องกันมุมมอง ไม่ให้ใช้พื้นที่ของเค้าโครงและละเว้นการคำนวณการจัดวาง การประมวลผลควบคู่กันไป
วิธีการต่อไปนี้จะแสดงตัวอย่างของการดำเนินการนี้
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
}
})
}
}
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
การพลิกไพ่จะมีหน้าตาดังนี้
สร้างออบเจ็กต์แอนิเมเตอร์
หากต้องการสร้างภาพเคลื่อนไหวแบบพลิกการ์ด คุณต้องมีภาพเคลื่อนไหว 4 ตัว ผู้สร้างแอนิเมชัน 2 คนคือ สำหรับเวลาที่ด้านหน้าของการ์ดเคลื่อนไหวออกไป ด้านซ้าย และเมื่อการ์ดเคลื่อนไหว เข้าและจากทางซ้าย ผู้สร้างภาพเคลื่อนไหวอีก 2 ตัวมีไว้สำหรับเมื่อด้านหลังของการ์ด จะเคลื่อนไหวเข้าและไปทางขวา และเมื่อเคลื่อนไหวออกและไปทางขวา
การ์ด_ฟลิป_ซ้าย_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 มุมมอง เพื่อพลิกกลับ ระหว่าง ใช้เลย์เอาต์ทั้ง 2 รายการในส่วนที่คุณทำให้เคลื่อนไหวในภายหลังได้ เลย์เอาต์ต่อไปนี้จะสร้างการ์ดด้านใดด้านหนึ่งซึ่งแสดงข้อความ
<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" />
สร้างส่วนย่อย
สร้างคลาสส่วนย่อยสำหรับด้านหน้าและด้านหลังของการ์ด ในส่วนย่อยของคุณ
ให้แสดงเค้าโครงที่คุณสร้างจาก
onCreateView()
จากนั้นคุณจะสร้างอินสแตนซ์ของส่วนย่อยนี้ได้ในกิจกรรมระดับบนสุด
ที่คุณต้องการให้แสดงการ์ด
ตัวอย่างต่อไปนี้แสดงคลาสของส่วนย่อยที่ฝังอยู่ภายในกิจกรรมระดับบนสุด ที่ใช้ผลิตภัณฑ์และบริการต่อไปนี้
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)
}
}
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);
}
}
}
ทำให้การพลิกบัตรเคลื่อนไหว
แสดงส่วนย่อยภายในกิจกรรมระดับบนสุด โดยสร้างเลย์เอาต์
สำหรับกิจกรรมของคุณ ตัวอย่างต่อไปนี้จะสร้าง
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" />
ในรหัสกิจกรรม ให้ตั้งค่ามุมมองเนื้อหาเป็นเลย์เอาต์ที่คุณสร้าง แนวทางปฏิบัติที่ดีในการแสดงส่วนย่อยเริ่มต้นเมื่อมีการสร้างกิจกรรมนั้น กิจกรรมตัวอย่างต่อไปนี้จะแสดงวิธีการแสดงด้านหน้าของบัตรโดย ค่าเริ่มต้น:
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()
}
}
...
}
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();
}
}
...
}
เมื่อด้านหน้าของบัตรปรากฏอยู่ คุณจะสามารถแสดงด้านหลังของบัตรที่มี พลิกภาพเคลื่อนไหวในเวลาที่เหมาะสม สร้างวิธีการเพื่อแสดงอีกด้านของ การ์ดที่ทำงานดังต่อไปนี้
- ตั้งค่าภาพเคลื่อนไหวที่กำหนดเองที่คุณสร้างขึ้นสำหรับการเปลี่ยนส่วนย่อย
- แทนที่ส่วนย่อยที่แสดงด้วยส่วนย่อยใหม่ และทำให้เหตุการณ์นี้เคลื่อนไหว ด้วยภาพเคลื่อนไหว ที่คุณสร้างขึ้นเอง
- เพิ่มส่วนย่อยที่แสดงก่อนหน้านี้ลงในแฟรกเมนต์แบ็กสแต็ก ดังนั้นเมื่อ ผู้ใช้แตะปุ่มย้อนกลับ การ์ดกลับพลิกกลับด้าน
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()
}
}
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) ขึ้นไป
ตัวอย่างการแสดงมุมมองที่มองไม่เห็นก่อนหน้านี้มีดังนี้
// 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
}
// 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 เพื่อให้มุมมอง ที่ถูกซ่อนโดยวงกลม พารามิเตอร์สุดท้ายคือรัศมีสุดท้าย ของวงกลม เมื่อแสดงมุมมอง โปรดทำให้รัศมีสุดท้ายใหญ่กว่า เพื่อให้สามารถแสดงมุมมองได้อย่างสมบูรณ์ก่อนที่ภาพเคลื่อนไหวจะเสร็จสิ้น
หากต้องการซ่อนมุมมองที่มองเห็นก่อนหน้านี้ ให้ทำดังนี้
// 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
}
// 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