ด้วยความที่แอนดรอยด์เป็นระบบปฏิบัติการณ์ที่สามารถนำไปใช้งานกับอุปกรณ์ได้หลากหลายรูปแบบ จึงมีโอกาสที่อุปกรณ์แอนดรอยด์จะถูกใช้งานได้หลากหลายทิศทาง และนั่นก็ทำให้แอนดรอยด์มีคำสั่งที่เกี่ยวกับ Screen Orientation หรือทิศทางของหน้าจออุปกรณ์ เพื่อให้นักพัฒนากำหนดได้ว่าจะให้แอปรองรับทิศทางของหน้าจอในรูปแบบใดบ้าง

ฟีเจอร์ที่เกี่ยวกับ Screen Orientation สำหรับผู้ใช้

Device's Natural Screen Orientation

อุปกรณ์แอนดรอยด์ทุกตัวจะมีสิ่งที่เรียกว่า Natural Screen Orientation หรือก็คือค่า Default Screen Orientation สำหรับอุปกรณ์แอนดรอยด์แต่ละตัว ซึ่งจะขึ้นอยู่กับว่าเป็น Form Factor แบบไหนและขึ้นอยู่ค่าใน Firmware ที่ผู้ผลิตอุปกรณ์ได้กำหนดไว้

ยกตัวอย่างเช่น Form Factor แบบ Phone จะมี Default เป็น Portrait (แนวตั้ง) และสามารถหมุนเป็น Landscape (แนวนอน) ได้ ในขณะที่ Tablet จะมี Default เป็น Landscape (แนวนอน) และสามารถหมุนเป็น Portrait (แนวตั้ง) เป็นต้น

โดยที่อุปกรณ์แอนดรอยด์ส่วนใหญ่จะรองรับ Screen Orientation ทุกทิศทางอยู่แล้ว แต่ถ้าอิงจากตัวเครื่องก็อาจจะได้แค่บางทิศทางเท่านั้น เช่น Phone จะไม่สามารถหมุนจอเป็น Reverse Portrait (แนวตั้งแบบกลับหัว) ได้ แต่สามารถสั่งผ่านคำสั่งในแอปได้

Orientation ทั้ง 4 ด้านของ Portrait และ Landscape

ถึงแม้ว่าเราจะเรียกรวม ๆ กันว่าเป็น Portrait หรือ Landscape แต่เราก็สามารถแยกย่อยทิศทางในแต่ละด้านแบบเจาะจงได้เช่นกัน โดยจะแบ่งเป็น

  • Portrait
  • Landscape
  • Reverse Portrait
  • Reverse Landscape
อย่าลืมว่า Default Orientation, Reverse Portrait และ Reverse Landscape จะแตกต่างไปตามแต่ละ Form Factor

Auto Screen Rotation

เพื่อความสะดวกของผู้ใช้ ระบบแอนดรอยด์จะมี Settings ที่เรียกว่า Auto-rorate (Auto Screen Rotation) เพื่อกำหนดว่าจะให้หน้าจอหมุนตามทิศทางการถือเครื่องโดยอัตโนมัติหรือไม่

ดังนั้นผู้ใช้อาจจะเปิด Auto-rotate หรือปิดอยู่ก็ได้ และการกำหนดค่าดังกล่าวก็จะมีผลกับการกำหนดค่า Screen Orientation ที่อยู่ในแอปด้วยเช่นกัน

Rotate Suggestion Button

บน Android 9 Pie เป็นต้นมา ต่อให้ไม่ได้เปิด Auto-rotate ก็ตาม ถ้าแอปไหนรองรับการหมุนหน้าจอ และอุปกรณ์แอนดรอยด์อยู่ในทิศทางที่หมุนหน้าจอได้ ระบบแอนดรอยด์จะแสดงปุ่มหมุนจอให้ที่ข้างล่างขวามือของหน้าจอ

0:00
/

การกำหนด Screen Orientation ในแอป

นักพัฒนาสามารถกำหนดค่า Screen Orientation ผ่าน Android Manifest โดยกำหนด android:screenOrientation ไว้ใน <activity> แบบนี้

<!-- AndroidManifest.xml -->
<manifest ...>
    <application ...>
        <activity 
            android:screenOrientation="userPortrait"
            ... />
    </application>
</manifest>

android:screenOrientation จะกำหนดแยกแต่ละ Activity ดังนั้นถ้ามีการกำหนด Screen Orientation ในแอป ก็อย่าลืมกำหนดทุก Activity ให้ครบ ไม่เช่นนั้นระบบแอนดรอยด์จะมองว่าไม่ได้กำหนดค่าไว้แล้วอิงจาก Screen Orientation ของเครื่องแทน

Screen Orientation บนแอนดรอยด์มีแบบไหนบ้าง

เพื่อให้อุปกรณ์แอนดรอยด์รองรับการใช้งานแอปในทิศทางตามที่นักพัฒนาต้องการ บ้างก็รองรับแค่ทิศทางเดียว บ้างก็รองรับแบบมีเงื่อนไขในรูปแบบที่แตกต่างกันออกไป จึงทำให้ระบบแอนดรอยด์ออกแบบการกำหนดค่าสำหรับ Screen Orientation ดังนี้

  • unspecified - เป็นค่า Default ในกรณีที่ไม่ได้กำหนดค่าใด ๆ ไว้ โดยระบบแอนดรอยด์จะเลือก Orientation ให้เหมาะสมกับเครื่องนั้น ๆ ซึ่งอาจจะได้ผลลัพธ์ที่แตกต่างกันออกไปในแต่ละเครื่อง
  • behind - กำหนดตาม Activity ที่เปิดเมื่อก่อนหน้า (ตัวล่าสุดใน Activity Back Stack)
  • landscape - กำหนดเป็น Landscape (ไม่รวม Reverse Landscape)
  • portrait - กำหนดเป็น Portrait (ไม่รวม Reverse Portrait)
  • reverseLandscape - กำหนดเป็น Reverse Landscape (ไม่รวม Landscape)
  • reversePortrait - กำหนดเป็น Reverse Portrait (ไม่รวม Portrait)
  • sensorLandscape - กำหนดเป็น Landscape หรือ Reverse Landscape โดยอ้างอิงจากเซ็นเซอร์ของตัวเครื่อง (ผู้ใช้สามารถหมุนตัวเครื่องเพื่อสลับไปเป็น Landscape อีกฝั่งได้)
  • sensorPortrait - กำหนดเป็น Portrait หรือ Reverse Portrait โดยอ้างอิงจากเซ็นเซอร์ของตัวเครื่อง (ผู้ใช้สามารถหมุนตัวเครื่องเพื่อสลับไปเป็น Portrait อีกฝั่งได้)
  • userLandscape - คล้ายกับ sensorLandscape แต่จะอิงจากการตั้งค่าของผู้ใช้ด้วย
  • userPortrait - คล้ายกับ sensorPortrait แต่จะอิงจากการตั้งค่าของผู้ใช้ด้วย และใน Form Factor อย่าง Phone จะไม่สามารถทำ Reverse Portrait ในขณะที่ทำบน Tablet ได้
  • sensor - กำหนดให้ Orientation อิงตามเซ็นเซอร์ของตัวเครื่อง ซึ่งอาจจะไม่ได้รองรับทั้ง 4 ด้าน เพราะขึ้นอยู่กับแต่ละอุปกรณ์
  • fullSensor - คล้ายกับ sensor แต่จะบังคับให้อุปกรณ์รองรับ Orientation ทั้ง 4 ด้าน ดังนั้นเมื่อใช้บน Phone จะทำให้รองรับ Reverse Portrait ได้ด้วย
  • nosensor - กำหนดให้ไม่หมุนตามเซ็นเซอร์ของตัวเครื่อง จะอิง Orientation ณ ตอนนั้นของตัวเครื่องแทน
  • user - อ้างอิงตาม Preferred Orientation ที่ผู้ใช้กำหนดไว้ใน Setting ของเครื่อง
  • fullUser - โดยปกติจะทำงานแบบเดียวกับ fullSensor แต่ถ้าผู้ใช้ตั้งค่าให้ล็อคการหมุนหน้าจอใน Setting ของเครื่อง ก็จะทำงานแบบเดียวกับ user
  • locked - อ้างอิงจาก Orientation ณ ตอนนั้นของตัวเครื่อง และล็อคการหมุนหน้าจอ

ถึงแม้ว่าจะมีค่าให้กำหนดสำหรับ Screen Orientation ได้หลายแบบ แต่ในปัจจุบันเราจะใช้งานกันอยู่แค่ไม่กี่ตัวเท่านั้น เพราะบางตัวก็ถูกสร้างขึ้นมาตั้งแต่สมัยแอนดรอยด์ในยุคแรก ๆ และไม่รองรับกับการใช้งานในแอนดรอยด์เวอร์ชันปัจจุบันซักเท่าไร

ดังนั้นเพื่อให้ง่ายต่อการเลือกใช้งาน ขอแนะนำให้ใช้งานตามนี้

  • รองรับเฉพาะ Portrait - กำหนดค่าเป็น userPortrait ที่จะบังคับให้เป็น Portrait บน Phone แต่จะรองรับทั้ง Portrait และ Reverse Portrait เมื่อใช้งานบน Tablet
  • รองรับเฉพาะ Landscape - กำหนดค่าเป็น sensorLandscape หรือ userLandscape ก็ได้ เพราะให้ผลลัพธ์ที่เหมือนกัน
  • รองรับทั้ง Portrait และ Landscape - ไม่ต้องกำหนดค่า หรือจะกำหนดค่าเป็น unspecified หรือ fullSensor ก็ได้

การกำหนด Screen Orientation ใน App Filter ของ Google Play

ในกรณีที่แอปรองรับแค่อย่างใดอย่างหนึ่งระหว่าง Portrait หรือ Landscape และนักพัฒนาไม่ต้องการให้ผู้ใช้สามารถติดตั้งแอปลงบนอุปกรณ์แอนดรอยด์ที่ไม่รองรับ Orientation นั้น ๆ ด้วย ก็สามารถกำหนดค่า <uses-feature> ไว้ใน Android Manifest แบบนี้ได้เลย

<!-- AndroidManifest.xml -->
<manifest ...>
    <uses-feature android:name="android.hardware.screen.landscape" />
</manifest>

การกำหนดค่าดังกล่าวจะทำให้อุปกรณ์ที่ไม่รองรับ Lanscape ค้นหาแอปบน Google Play ไม่เจอ

  • รองรับเฉพาะ Portrait - ใช้ android.hardware.screen.portrait
  • รองรับเฉพาะ Landscape - ใช้ android.hardware.screen.landscape

แต่ถ้าแอปสามารถใช้งานได้ทั้ง Portrait และ Landscape ก็ไม่ต้องกำหนดค่าดังกล่าว

การกำหนด Screen Orientation ผ่านโค้ด Kotlin

ถ้าต้องการเปลี่ยนค่า Screen Orientation ที่กำหนดไว้ใน android:screenOrientation ผ่านโค้ด Kotlin ก็สามารถกำหนดค่าให้กับ requestedOrientation ที่อยู่ใน Activity ได้เลย

// MainActivity.kt
class MainActivity : AppCompatActivity() {
    /* ... */
    private fun setReversePortraitScreenOrietation() {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
    }
    
    private fun setFullSensorScreenOrientation() {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
    }
}

ดักการหมุนหน้าจอ (Screen Rotation)

สามารถดักผ่าน onConfigurationChanged ได้เลย แต่เพื่อให้คำสั่งทำงานได้อย่างสมบูรณ์​ แนะนำให้อ่านต่อในบทความดัก Screen Orientation Event ใน Activity อย่างไรให้ถูกต้อง

ดัก Screen Orientation Event ใน Activity อย่างไรให้ถูกต้อง
สำหรับแอนดรอยด์แล้ว การทำให้ Layout สามารถแสดงผลแยกกันระหว่างหน้าจอแนวตั้งกับแนวนอนนั้นไม่ใช่เรื่องอยากซักเท่าไร เพราะแอนดรอยด์ได้สร้างสิ่งที่เรียกว่า Configuration Qualifier เพื่อช่วยจัดการเรื่องนี้แล้ว แต่ถ้าอยากจะดัก Event เมื่อผู้ใช้มีการหมุนหน้าจออุปกรณ์แอนดรอยด์ล่ะ ต้องทำยังไง?

สรุป

ถึงแม้ว่าแอปส่วนใหญ่ในปัจจุบันจะรองรับหน้าจอในแนวตั้ง (Portrait) ซะส่วนใหญ่ เพื่อรองรับผู้ใช้งานบน Smartphone เป็นหลัก แต่ก็อย่าลืมว่าทุกวันนี้ก็มีผู้ใช้งานบางส่วนที่ใช้อุปกรณ์แอนดรอยด์ในรูปแบบของ Tablet หรือ Desktop อยู่ด้วย

ดังนั้นเพื่อประสบการณ์ที่ดีสำหรับผู้ใช้งานเหล่านี้ก็อย่าลืมคำนึงถึงการทำแอปให้รองรับการใช้งานในแนวนอน (Landscape) ด้วย ถึงแม้ว่าทุกวันนี้แค่ทำให้รองรับแค่หน้าจอแนวตั้งก็ยังทำไม่ค่อยทันเลย...

แหล่งข้อมูลอ้างอิง