Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách phát hiện thay đổi hướng màn hình (Orientation) trên Android bằng Kotlin

Giới thiệu

Hướng dẫn này trình bày cách phát hiện sự thay đổi hướng màn hình (portrait ↔ landscape) trên Android bằng cách override phương thức onConfigurationChanged() trong Activity, sử dụng Kotlin.

Các bước thực hiện

Bước 1: Tạo dự án mới

Tạo project: File → New Project.

Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp"
        android:text="Tutorials Point"
        android:textAlignment="center"
        android:textColor="@android:color/holo_green_dark"
        android:textSize="32sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Hello World!"
        android:textSize="24sp"
        android:textStyle="bold" />

</RelativeLayout>

Bước 3: Xử lý logic (src/MainActivity.kt)

import android.content.res.Configuration
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "KotlinApp"
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)

        when (newConfig.orientation) {
            Configuration.ORIENTATION_LANDSCAPE -> {
                Toast.makeText(baseContext, "Landscape Mode", Toast.LENGTH_SHORT).show()
                // Xử lý layout landscape
            }
            Configuration.ORIENTATION_PORTRAIT -> {
                Toast.makeText(baseContext, "Portrait Mode", Toast.LENGTH_SHORT).show()
                // Xử lý layout portrait
            }
            Configuration.ORIENTATION_UNDEFINED -> {
                Toast.makeText(baseContext, "Undefined Orientation", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

Bước 4: Cấu hình Manifest (androidManifest.xml) - QUAN TRỌNG

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.q11">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. Xoay thiết bị ngang/dọc. Toast sẽ hiển thị "Landscape Mode" hoặc "Portrait Mode" tương ứng. Activity không bị destroy/recreate nhờ android:configChanges.

Giải thích android:configChanges

Mặc định, khi xoay màn hình, Android destroy và recreate Activity (gọi onDestroy → onCreate). Để tự xử lý thay đổi cấu hình, khai báo android:configChanges:

  • orientation: Thay đổi hướng màn hình
  • screenSize: Thay đổi kích thước màn hình (bắt buộc từ API 13+)
  • screenLayout: Thay đổi bố cục màn hình
  • keyboardHidden: Bàn phím ẩn/hiện
  • fontScale: Thay đổi cỡ font hệ thống
  • uiMode: Chế độ Night/Day, Car, Desk, VR...
  • density: Mật độ pixel (multi-window)

Khi nào nên dùng onConfigurationChanged?

  • Video player: Giữ trạng thái phát khi xoay.
  • Game: Không muốn reset state.
  • WebView: Giữ trang web đang load.
  • Camera preview: Không ngắt luồng camera.

Khi nào KHÔNG nên dùng?

  • UI đơn giản: Delegate cho hệ thống recreate an toàn hơn.
  • Cần layout khác nhau cho portrait/landscape (dùng layout-port/layout-land).
  • Sử dụng ViewBinding/DataBinding phức tạp (recreate dễ quản lý).

Cách hiện đại: ViewModel + LiveData

Thay vì override configChanges, hãy dùng ViewModel để giữ data qua recreation:

class MyViewModel : ViewModel() {
    val data = MutableLiveData()
}

// Activity
val model = ViewModelProvider(this).get(MyViewModel::class.java)
model.data.observe(this) { updateUI(it) }

// Layout khác nhau:
res/layout/activity_main.xml (portrait)
res/layout-land/activity_main.xml (landscape)

Lưu ý

  • Nếu dùng android:configChanges, bạn phải tự cập nhật UI trong onConfigurationChanged (inflate layout mới, rebind view, v.v.).
  • Trên Android 12+, có thêm screenLayout và density changes khi multi-window.