ฉันจะปิดการใช้งานการวางแนวบน Android ได้อย่างไร?


287

ฉันมีแอปพลิเคชันที่ฉันต้องการใช้ในโหมดแนวตั้งดังนั้นฉันจึงกำหนด android: screenOrientation = "portrait" ในรายการ XML ใช้งานได้กับโทรศัพท์ HTC Magic (และป้องกันการเปลี่ยนทิศทางในโทรศัพท์อื่น ๆ ด้วย)

แต่ฉันมีปัญหากับโทรศัพท์ HTC G1เมื่อฉันเปิดคีย์บอร์ด QWERTY (ไม่ใช่คีย์บอร์ดเสมือน) กิจกรรมของฉันอยู่ในโหมดแนวตั้ง แต่ดูเหมือนจะเริ่มต้นใหม่และสูญเสียสถานะทั้งหมด นี้ไม่ได้เกิดขึ้นกับHTC Heroรุ่น

แอปพลิเคชันของฉันค่อนข้างใหญ่ดังนั้นฉันไม่ต้องการให้รีสตาร์ทและสูญเสียสถานะทั้งหมดเมื่อเปิดแป้นพิมพ์ ฉันจะป้องกันได้อย่างไร


2
ลองดูที่นี่ด้วย: stackoverflow.com/questions/2366706/…
Andy Weinstein

คำตอบ:


317

อัปเดตเมษายน 2556: อย่าทำเช่นนี้ ไม่ใช่ความคิดที่ดีในปี 2009 เมื่อฉันตอบคำถามครั้งแรกและตอนนี้มันไม่ใช่ความคิดที่ดีจริงๆ ดูคำตอบโดย hackbod นี้ด้วยเหตุผล:

หลีกเลี่ยงการโหลดกิจกรรมใหม่ด้วย asynctask เกี่ยวกับการเปลี่ยนทิศทางใน Android

เพิ่มandroid:configChanges="keyboardHidden|orientation"ใน AndroidManifest.xml ของคุณ สิ่งนี้บอกระบบว่าการเปลี่ยนแปลงการกำหนดค่าที่คุณกำลังจะจัดการกับตัวเองคืออะไรในกรณีนี้โดยไม่ทำอะไรเลย

<activity android:name="MainActivity"
     android:screenOrientation="portrait"
     android:configChanges="keyboardHidden|orientation">

ดูที่การอ้างอิงผู้พัฒนาconfigChanges สำหรับรายละเอียดเพิ่มเติม

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

อัปเดต:ตั้งแต่ Android 3.2 คุณต้องเพิ่ม "screenSize":

<activity
    android:name="MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="keyboardHidden|orientation|screenSize">

จากคู่มือนักพัฒนาซอฟต์แวร์การจัดการการกำหนดค่าเปลี่ยนตัวเอง

ข้อควรระวัง: เริ่มต้นด้วย Android 3.2 (ระดับ API 13) "ขนาดหน้าจอ" จะเปลี่ยนไปเมื่ออุปกรณ์สลับระหว่างแนวตั้งและแนวนอน ดังนั้นหากคุณต้องการป้องกันไม่ให้รันไทม์รีสตาร์ทเนื่องจากการเปลี่ยนแปลงการวางแนวเมื่อพัฒนาสำหรับ API ระดับ 13 หรือสูงกว่า (ตามที่ประกาศโดยแอ็ตทริบิวต์ minSdkVersion และ targetSdkVersion) คุณต้องรวมค่า "screenSize" เพิ่มเติมจากค่า "การวางแนว" android:configChanges="orientation|screenSize"นั่นคือคุณจะต้องประกาศ อย่างไรก็ตามหากแอปพลิเคชันของคุณกำหนดเป้าหมาย API ระดับ 12 หรือต่ำกว่ากิจกรรมของคุณจะจัดการกับการเปลี่ยนแปลงการกำหนดค่านี้เสมอ (การเปลี่ยนแปลงการกำหนดค่านี้จะไม่เริ่มกิจกรรมของคุณใหม่แม้ว่าจะทำงานบนอุปกรณ์ Android 3.2 หรือสูงกว่า)


36
เพียงเพื่อเพิ่มสิ่งนี้และชัดเจนจริงๆ Android สามารถฆ่าแอปพลิเคชันของคุณได้ทุกเวลาโดยไม่คำนึงถึงการเปลี่ยนแปลงการวางแนวดังนั้นคุณควรใช้ onPause () และ onSaveInstanceState () เพื่อบันทึกสถานะไม่ว่าจะเกิดอะไรขึ้น
Eric Mill

การอัปเดต 3.2 นั้นมีประโยชน์มากและเป็นสิ่งที่ขวางกั้นฉัน ฉันไม่รู้ว่าทำไมตัวจัดการการเปลี่ยนแปลงแบบกำหนดค่าของฉันจึงไม่เริ่มทำงานและนี่คือเหตุผล ขอบคุณ!
sweetlilmre

พารามิเตอร์ที่สาม - screenSize ไม่พบใน 2.3.x ฉันควรเปลี่ยนเป็น screenLayout หรือไม่
เดดฟิช

2
@Lumma ไม่จำเป็นต้องใช้ "screenSize" สำหรับ Android 3.2 และใหม่กว่าเท่านั้น API ระดับใดที่คุณกำหนดเป้าหมาย ฉันคิดว่าคุณจะต้องเพิ่มมันหากคุณกำหนดเป้าหมายระดับ 13 ขึ้นไป ฉันจะอัปเดตคำตอบเพื่อชี้แจง
ซับซ้อน

1
ในกรณีที่มันเป็นประโยชน์กับคนอื่นฉันได้พบคุณทั้งสอง <... android: configChanges = "Orient" ... > เพื่อแทนที่การเปลี่ยนแปลงและ <... android: screenOrientation = "portrait" ... > เพื่อ กำหนดค่าเริ่มต้น
Sogger

97

คุณต้องแก้ไข AndroidManifest.xml ตามที่กล่าวถึงความซับซ้อน (แอชตันก่อนหน้านี้) และตรวจสอบให้แน่ใจว่ากิจกรรมจัดการกับเหตุการณ์ onConfigurationChanged ตามที่คุณต้องการจัดการ นี่คือลักษณะที่ควร:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

ตามที่ระบุไว้โดย Dmitry Zaitsev มันจะดีกว่าที่จะนำในsetRequestedOrientation() onCreate()
Timmmm

3
ไม่onConfigurationChanged()ได้รับการเรียกก่อนonCreate()ถ้าเป็นเช่นนั้นการตั้งค่าการปฐมนิเทศก่อนที่จะตั้ง contentViews ใน OnCreate เป็นดีกว่าวิธีการตั้งค่าการกำหนดค่าที่มันอยู่นอกจากนี้ยังทำความสะอาดเพื่อให้คำตอบนี้ยังคงยืนอยู่ที่ดี
ซามูเอล

39

ฉันพบว่าคุณต้องการทั้งคู่เสมอ

android:screenOrientation="nosensor" android:configChanges="keyboardHidden|orientation"

22

ตามที่ได้กล่าวไว้ให้ตั้งค่าandroid:configChangesกิจกรรมของคุณ (ในไฟล์รายการ) เป็นkeyboardHidden|orientationแล้ว:

1) แทนที่ onConfigurationChanged()

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //here you can handle orientation change
}

2) เพิ่มบรรทัดนี้ในกิจกรรมของคุณ onCreate()

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

มันดีกว่าเพิ่มบรรทัดเดียวกันonConfigurationChangedเพราะแอปของคุณจะเปลี่ยนเป็นโหมดแนวตั้งแล้วกลับสู่แนวนอน (มันจะเกิดขึ้นเพียงครั้งเดียว แต่มันน่ารำคาญ)

นอกจากนี้คุณสามารถตั้งค่าandroid:screenOrientation="nosensor"สำหรับกิจกรรมของคุณ (ในรายการ) แต่การใช้วิธีนี้ทำให้คุณไม่สามารถรับมือกับการเปลี่ยนแปลงการวางแนวได้เลย


ฉันควรทำอย่างไรถ้าฉันต้องการหลีกเลี่ยงการสร้างกิจกรรมซ้ำเมื่อหมุนฉันต้องการอนุญาตให้ผู้ใช้ล็อคการวางแนวผ่านการตั้งค่าระบบปฏิบัติการ
นักพัฒนา Android

@androiddeveloper เป็นคำถามแยกต่างหากซึ่งมีคำตอบแล้ว: stackoverflow.com/a/14771495/926907
Dmitry Zaytsev

ลิงค์ของคุณเกี่ยวกับการเปลี่ยนแปลงเนื้อหาด้วยตัวเองเมื่อการเปลี่ยนแปลงการกำหนดค่า แต่ฉันต้องการที่จะหลีกเลี่ยงการหมุนของกิจกรรม (เพื่อให้มันจะอยู่ในลักษณะที่ดูเหมือน) ในกรณีที่ผู้ใช้เลือกที่จะล็อคการวางแนวผ่านระบบปฏิบัติการ การตั้งค่า (มีให้ในอุปกรณ์บางรุ่นผ่านการตั้งค่าด่วนในลิ้นชักการแจ้งเตือน)
นักพัฒนา Android

@ androiddeveloper อาฉันคิดว่าฉันเข้าใจ จากนั้นดูที่ลิงค์นี้: developer.android.com/reference/android/…ตามเอกสารการปฐมนิเทศเริ่มต้นควรคำนึงถึงความพึงพอใจของผู้ใช้แล้ว หากไม่เป็นเช่นนั้นฉันก็สงสัยว่ามันเป็นพฤติกรรมเฉพาะของระบบปฏิบัติการ ฉันยินดีที่จะได้ยินเกี่ยวกับผลลัพธ์ของคุณ - ตอนนี้ฉันก็สนใจเช่นกัน :)
Dmitry Zaytsev

ฉันรู้ว่าค่าเริ่มต้นจะจัดการการตั้งค่าของผู้ใช้ แต่มันก็สร้างกิจกรรมขึ้นมาใหม่เมื่อคุณหมุนหน้าจอซึ่งเป็นสิ่งที่ฉันไม่ต้องการ
นักพัฒนา Android


13

ในวิธี OnCreate ของกิจกรรมของคุณใช้รหัสนี้:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

ตอนนี้การปฐมนิเทศของคุณจะถูกตั้งค่าเป็นแนวตั้งและจะไม่เปลี่ยนแปลง


4
เมื่อคุณไม่ป้องกันการเริ่มกิจกรรมใหม่ทุกครั้งที่มีการเปลี่ยนแปลงการกำหนดค่าการวางแนว
AxeEffect

นอกจากนี้ยังใช้ไม่ได้หากคุณเข้าสู่กิจกรรมจากกิจกรรมก่อนหน้าในแนวนอน
w3bshark

10

ในไฟล์ AndroidManifest.xml สำหรับแต่ละกิจกรรมที่คุณต้องการล็อคให้เพิ่มscreenOrientationบรรทัดสุดท้าย:

android:label="@string/app_name"
android:name=".Login"
android:screenOrientation="portrait" >

หรือหุ่นยนต์: screenOrientation = "ภูมิทัศน์"


8

ในไฟล์androidmanifest.xmlของคุณ:

   <activity android:name="MainActivity" android:configChanges="keyboardHidden|orientation">

หรือ

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

6

ในการล็อคหน้าจอด้วยรหัสคุณต้องใช้การหมุนหน้าจอจริง (0, 90, 180, 270) และคุณต้องรู้ตำแหน่งตามธรรมชาติของมันในสมาร์ทโฟนตำแหน่งธรรมชาติจะเป็นแนวตั้งและในแท็บเล็ต มันจะเป็นแนวนอน

นี่คือรหัส (วิธีล็อคและปลดล็อค) ซึ่งได้รับการทดสอบในอุปกรณ์บางอย่าง (สมาร์ทโฟนและแท็บเล็ต) และใช้งานได้ดี

public static void lockScreenOrientation(Activity activity)
{   
    WindowManager windowManager =  (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);   
    Configuration configuration = activity.getResources().getConfiguration();   
    int rotation = windowManager.getDefaultDisplay().getRotation(); 

    // Search for the natural position of the device    
    if(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&  
       (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) ||  
       configuration.orientation == Configuration.ORIENTATION_PORTRAIT &&   
       (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270))   
    {   
        // Natural position is Landscape    
        switch (rotation)   
        {   
            case Surface.ROTATION_0:    
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);    
                break;      
            case Surface.ROTATION_90:   
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
            break;      
            case Surface.ROTATION_180: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
                break;          
            case Surface.ROTATION_270: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
                break;
        }
    }
    else
    {
        // Natural position is Portrait
        switch (rotation) 
        {
            case Surface.ROTATION_0: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
            break;   
            case Surface.ROTATION_90: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
            break;   
            case Surface.ROTATION_180: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
                break;          
            case Surface.ROTATION_270: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
                break;
        }
    }
}

public static void unlockScreenOrientation(Activity activity)
{
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

พารามิเตอร์ใดที่ควรผ่านเป็นกิจกรรม
WISHY

กิจกรรมที่เรียกใช้วิธีการเพื่อล็อค / ปลดล็อคการวางแนว นั่นเป็นวิธียูทิลิตี้สาธารณะคงที่จะเรียกจากกิจกรรม differents
PoOk

1
ใช้งานได้ดี แต่อย่างจริงจัง Android ทำไมเราต้องทำทุกอย่างเพื่อการวางแนวหน้าจอล็อค !!!
Cocorico

ใช่. อันนี้ล็อคทิศทางที่เราทำในรายการ สิ่งนี้จะป้องกันไม่ให้ onConfigurationChanged ถูกเรียกใช้อีกต่อไป มีวิธีการที่ล็อค UI เป็นแนวนอนหรือไม่และยังเรียกใช้ onConfigurationChanged เช่นเดียวกับแอปกล้องในแอนดรอยด์
Ajith Memana

มีการตั้งค่าสถานะ SCREEN_ORIENTATION_LOCKED ใน SDK 18+ ซึ่งดูเหมือนว่าจะใช้งานได้ แต่คุณยังต้องการใช้รหัสด้านบนเพื่อรองรับอุปกรณ์ทุกเครื่อง
DominicM

2

ใน Visual Studio Xamarin:

  1. เพิ่ม:

using Android.Content.PM; ในรายการเนมสเปซกิจกรรม

  1. เพิ่ม:

[Activity(ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]

เป็นแอตทริบิวต์ให้คุณในชั้นเรียนเช่นนั้น:

[Activity(ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : Activity
{...}

คำถามนี้ถามเกี่ยวกับ Android ไม่ใช่ Xamarin.Android
Trevor Hart


0

โปรดทราบว่าไม่มีวิธีการใดที่ใช้งานได้ในขณะนี้!

ในAndroid Studio 1 วิธีง่ายๆในการเพิ่ม android:screenOrientation="nosensor"คือ

สิ่งนี้ล็อคการวางแนวหน้าจอได้อย่างมีประสิทธิภาพ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.