การวาด UI เป็นเพียงส่วนหนึ่งของการสร้างมุมมองที่กำหนดเอง คุณยังต้อง ทำให้มุมมองของคุณตอบสนองต่อข้อมูลจากผู้ใช้ในลักษณะที่คล้ายคลึงกับ จากสถานการณ์จริง ที่คุณกำลังเลียนแบบ
ทำให้วัตถุในแอปทำหน้าที่เหมือนวัตถุจริง ตัวอย่างเช่น อย่าปล่อยให้ รูปภาพในแอปจะแสดงที่ไม่มีอยู่และปรากฏขึ้นอีกครั้งที่อื่น เนื่องจากออบเจ็กต์ต่างๆ ในโลกแห่งความเป็นจริง อย่าทำแบบนั้น แต่ให้ย้ายรูปภาพจากที่หนึ่งไปที่ อีกรายการ
ผู้ใช้สัมผัสได้ถึงพฤติกรรมที่บอบบางหรือรู้สึกถึงอินเทอร์เฟซและตอบสนองอย่างดีที่สุด รายละเอียดเล็กๆ น้อยๆ ที่เลียนแบบโลกจริง ตัวอย่างเช่น เมื่อผู้ใช้สะบัดออบเจ็กต์ UI ในระยะแรก โมเดลก็จะเกิดความเฉื่อย ซึ่งจะหน่วงเวลาการเคลื่อนไหว ในช่วงท้าย ทำให้โมเดลรับรู้ถึงแรงโมเมนตัมที่พาวัตถุออกไปนอก สะบัด
หน้านี้จะแสดงวิธีใช้ฟีเจอร์ต่างๆ ของเฟรมเวิร์ก Android ในการเพิ่ม พฤติกรรมการใช้งานจริงเหล่านี้กับมุมมองที่คุณกำหนดเอง
ดูข้อมูลที่เกี่ยวข้องเพิ่มเติมได้ใน ภาพรวมของเหตุการณ์การป้อนข้อมูลและ ภาพเคลื่อนไหวของพร็อพเพอร์ตี้ ภาพรวม
จัดการท่าทางสัมผัสในการป้อนข้อมูล
Android รองรับโมเดลเหตุการณ์การป้อนข้อมูลเช่นเดียวกับเฟรมเวิร์ก UI อื่นๆ อีกจำนวนมาก ผู้ใช้
การดำเนินการจะเปลี่ยนเป็นเหตุการณ์ที่ทริกเกอร์ Callback และคุณสามารถลบล้าง
Callback เพื่อปรับแต่งวิธีที่แอปตอบสนองต่อผู้ใช้ อินพุตที่ใช้บ่อยที่สุด
ในระบบ Android คือการแตะ ซึ่งจะทริกเกอร์
onTouchEvent(android.view.MotionEvent)
ลบล้างเมธอดนี้เพื่อจัดการเหตุการณ์ ดังนี้
Kotlin
override fun onTouchEvent(event: MotionEvent): Boolean { return super.onTouchEvent(event) }
Java
@Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }
เหตุการณ์การสัมผัสเพียงอย่างเดียวนั้นไม่มีประโยชน์มากนัก UI ระบบสัมผัสที่ทันสมัย
ให้คำจำกัดความการโต้ตอบในแง่ของท่าทางสัมผัส เช่น การแตะ การดึง การผลัก
การสะบัดและการซูม การแปลงเหตุการณ์การสัมผัสเป็นข้อมูลดิบเป็นท่าทางสัมผัส Android
ให้
GestureDetector
สร้าง GestureDetector
โดยการส่งอินสแตนซ์ในคลาส
ซึ่งใช้
GestureDetector.OnGestureListener
หากคุณต้องการประมวลผลท่าทางสัมผัสเพียงไม่กี่ครั้ง คุณสามารถขยายเวลา
GestureDetector.SimpleOnGestureListener
แทนที่จะใช้เมธอด GestureDetector.OnGestureListener
ของ Google ตัวอย่างเช่น โค้ดนี้จะสร้างคลาสที่ขยาย
GestureDetector.SimpleOnGestureListener
และการลบล้าง
onDown(MotionEvent)
Kotlin
private val myListener = object : GestureDetector.SimpleOnGestureListener() { override fun onDown(e: MotionEvent): Boolean { return true } } private val detector: GestureDetector = GestureDetector(context, myListener)
Java
class MyListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDown(MotionEvent e) { return true; } } detector = new GestureDetector(getContext(), new MyListener());
ไม่ว่าคุณจะใช้ GestureDetector.SimpleOnGestureListener
หรือไม่ก็ตาม
ใช้
วันที่ onDown()
ซึ่งแสดงผล true
นี่เป็นสิ่งจำเป็นเนื่องจากท่าทางสัมผัสทั้งหมด
เริ่มต้นด้วยข้อความ onDown()
หากคุณส่งคืน false
จาก onDown()
ในฐานะ
GestureDetector.SimpleOnGestureListener
รองรับ ระบบจะถือว่าระบบ
ไม่ต้องสนใจท่าทางสัมผัสที่เหลือ รวมถึงวิธีอื่นๆ
ไม่ได้เรียก GestureDetector.OnGestureListener
เฉพาะขากลับ
false
จาก onDown()
หากคุณต้องการละเว้น
ท่าทางสัมผัส
หลังจากติดตั้งใช้งาน GestureDetector.OnGestureListener
และสร้าง
อินสแตนซ์ของ GestureDetector
คุณสามารถใช้
GestureDetector
เพื่อตีความเหตุการณ์การแตะที่คุณได้รับ
onTouchEvent()
Kotlin
override fun onTouchEvent(event: MotionEvent): Boolean { return detector.onTouchEvent(event).let { result -> if (!result) { if (event.action == MotionEvent.ACTION_UP) { stopScrolling() true } else false } else true } }
Java
@Override public boolean onTouchEvent(MotionEvent event) { boolean result = detector.onTouchEvent(event); if (!result) { if (event.getAction() == MotionEvent.ACTION_UP) { stopScrolling(); result = true; } } return result; }
เมื่อคุณผ่าน onTouchEvent()
กิจกรรมการสัมผัสที่ไม่ได้ผ่าน
จดจำได้ ซึ่งเป็นส่วนหนึ่งของท่าทางสัมผัส จะแสดง false
จากนั้นคุณจะสามารถเรียกใช้
รหัสตรวจจับท่าทางสัมผัสที่กำหนดเองของคุณ
สร้างการเคลื่อนไหวที่จับต้องได้
ท่าทางสัมผัสเป็นวิธีที่มีประสิทธิภาพในการควบคุมอุปกรณ์ที่มีหน้าจอสัมผัส แต่สามารถ ฟังดูขัดกับสัญชาตญาณและจำยาก หากไม่ผลิตเนื้อหาขึ้นมา ผลลัพธ์ที่เป็นไปได้
ตัวอย่างเช่น สมมติว่าคุณต้องการใช้ท่าทางสัมผัสการสะบัดในแนวนอน จะเป็นการกำหนดให้รายการที่วาดในมุมมองหมุนไปรอบๆ แกนแนวตั้ง ท่าทางสัมผัสนี้ เหมาะสมหาก UI ตอบสนองด้วยการเคลื่อนที่อย่างรวดเร็วในทิศทางการสะบัด จากนั้นก็ลดความเร็วลง ราวกับว่าผู้ใช้ออกแรงกดบนล้อเลื่อนและหมุนวน
เอกสารประกอบเกี่ยวกับวิธี
ทำให้การเลื่อนเคลื่อนไหว
ท่าทางสัมผัสให้คำอธิบายโดยละเอียดเกี่ยวกับวิธีนำสก็อตของคุณเองมาใช้
พฤติกรรมของคุณ แต่การจำลองความรู้สึกของมอเตอร์ไซค์ก็ไม่ใช่เรื่องง่าย ฟิสิกส์เยอะ
และจะต้องใช้คณิตศาสตร์เพื่อทำให้โมเดลฟลายวีลทำงานอย่างถูกต้อง โชคดี
Android มีคลาสตัวช่วยเพื่อจำลองสิ่งนี้และพฤติกรรมอื่นๆ
Scroller
คลาสเป็นพื้นฐานของการจัดการท่าทางสัมผัสการสะบัดแบบล้อเลื่อน
หากต้องการเริ่มการสะบัด ให้โทร
fling()
ด้วยอัตราความเร็วเริ่มต้นและค่าต่ำสุดและสูงสุด x และ y
ของการปัด สำหรับค่าความเร็ว คุณสามารถใช้ค่าที่คำนวณโดย
GestureDetector
Kotlin
fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { scroller.fling( currentX, currentY, (velocityX / SCALE).toInt(), (velocityY / SCALE).toInt(), minX, minY, maxX, maxY ) postInvalidate() return true }
Java
@Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY); postInvalidate(); return true; }
การเรียก fling()
เกี่ยวกับการสร้างโมเดลฟิสิกส์สำหรับการขว้าง
ท่าทางสัมผัส หลังจากนั้น โปรดอัปเดต Scroller
โดยโทรไปที่
วันที่ Scroller.computeScrollOffset()
อย่างสม่ำเสมอ computeScrollOffset()
อัปเดต
สถานะภายในของออบเจ็กต์ Scroller
โดยการอ่านเวลาปัจจุบันและ
ใช้โมเดลฟิสิกส์เพื่อคำนวณตำแหน่ง x และ y ที่ตำแหน่งนั้น
โทร
getCurrX()
และ
วันที่ getCurrY()
เพื่อดึงข้อมูลค่าเหล่านี้
มุมมองส่วนใหญ่จะส่ง x และ y ของออบเจ็กต์ Scroller
ตำแหน่งโดยตรงไปยัง
scrollTo()
ตัวอย่างนี้ต่างออกไปเล็กน้อยโดยใช้ตำแหน่งการเลื่อน x ในปัจจุบัน
เพื่อตั้งค่ามุมหมุนของมุมมอง
Kotlin
scroller.apply { if (!isFinished) { computeScrollOffset() setItemRotation(currX) } }
Java
if (!scroller.isFinished()) { scroller.computeScrollOffset(); setItemRotation(scroller.getCurrX()); }
คลาส Scroller
จะคำนวณตำแหน่งการเลื่อนให้คุณ
จะไม่ใช้ตำแหน่งเหล่านั้นกับมุมมองของคุณโดยอัตโนมัติ ใช้พิกัดใหม่
บ่อยพอที่จะทำให้ภาพเคลื่อนไหวแบบเลื่อนได้ดูลื่นไหล คุณทำสิ่งต่อไปนี้ได้ 2 วิธี
ทำสิ่งนี้
- บังคับการวาดใหม่โดยการเรียกใช้
postInvalidate()
หลังจากโทรหาfling()
คุณต้องใช้เทคนิคนี้ การชดเชยการเลื่อนการประมวลผลในonDraw()
และเรียกใช้postInvalidate()
ทุกครั้งที่ออฟเซ็ตการเลื่อน การเปลี่ยนแปลง - ตั้งค่า
ValueAnimator
เพื่อให้เคลื่อนไหวในช่วง สะบัดข้อมือ และเพิ่มผู้ฟังในการดำเนินขั้นตอน อัปเดตภาพเคลื่อนไหวด้วยการเรียกaddUpdateListener()
เทคนิคนี้ช่วยให้คุณทําให้พร็อพเพอร์ตี้ของView
ทำให้ทรานซิชันราบรื่น
ผู้ใช้คาดหวังให้ UI ที่ทันสมัยเปลี่ยนผ่านระหว่างสถานะต่างๆ ได้อย่างราบรื่น: องค์ประกอบ UI ค่อยๆ เลือนหายไปและค่อยๆ หายไปแทนที่จะปรากฏและหายไป และเริ่มการเคลื่อนไหว แล้วจบลงอย่างลื่นไหล แทนที่จะต้องเริ่มหรือหยุดลงอย่างกะทันหัน Android ภาพเคลื่อนไหวของพร็อพเพอร์ตี้ ทำให้การเปลี่ยนราบรื่นง่ายขึ้น
หากต้องการใช้ระบบภาพเคลื่อนไหว เมื่อใดก็ตามที่พร็อพเพอร์ตี้เปลี่ยนแปลงสิ่งที่ส่งผลต่อ
อย่าเปลี่ยนแปลงพร็อพเพอร์ตี้โดยตรง ให้ใช้
ValueAnimator
เพื่อทำการเปลี่ยนแปลง ในตัวอย่างต่อไปนี้
การแก้ไขคอมโพเนนต์ย่อยที่เลือกในมุมมอง
จะทำให้การแสดงผลทั้งหมด
เพื่อให้เคอร์เซอร์การเลือกอยู่ตรงกลาง
ValueAnimator
เปลี่ยนการหมุนเวียนในช่วงเวลาหลายร้อยครั้ง
มิลลิวินาที แทนที่จะกำหนดค่าการหมุนเวียนใหม่โดยทันที
Kotlin
autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply { setIntValues(targetAngle) duration = AUTOCENTER_ANIM_DURATION start() }
Java
autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0); autoCenterAnimator.setIntValues(targetAngle); autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION); autoCenterAnimator.start();
หากค่าที่ต้องการเปลี่ยนเป็นหนึ่งในฐาน View
คุณสมบัติพิเศษอื่นๆ ในการสร้างภาพเคลื่อนไหวก็ทำได้ง่ายขึ้น เนื่องจากการดูมี
วันที่ ViewPropertyAnimator
ซึ่งได้รับการเพิ่มประสิทธิภาพสำหรับภาพเคลื่อนไหว
แบบต่อเนื่องของพร็อพเพอร์ตี้หลายรายการ เช่น
ตัวอย่างต่อไปนี้
Kotlin
animate() .rotation(targetAngle) .duration = ANIM_DURATION .start()
Java
animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();