วิธีล็อคการวางแนวระหว่างรันไทม์


107

มีวิธีล็อคการวางแนวระหว่างรันไทม์หรือไม่? ตัวอย่างเช่นฉันต้องการอนุญาตให้ผู้ใช้ล็อกหน้าจอให้เป็นแนวนอนหากผู้ใช้อยู่ในแนวนอนและสลับตัวเลือกเมนู

คำตอบ:


133
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

เรียกว่ากิจกรรมจะล็อคให้อยู่ในแนวนอน มองหาแฟล็กอื่น ๆ ในคลาส ActivityInfo คุณสามารถล็อคกลับเป็นแนวตั้งหรือทำให้เซ็นเซอร์ / ตัวเลื่อนขับเคลื่อน

ข้อมูลเพิ่มเติมที่นี่: http://www.devx.com/wireless/Article/40792


13
โอเคขอบคุณ. ใช้งานได้ดี ที่จะได้รับการวางแนวปัจจุบัน getResources (). getConfiguration (). การวางแนว
Jared

7
ระวัง! คุณต้องแยกความแตกต่างระหว่างสิ่งที่ getConfiguration () ส่งคืนและสิ่งที่ setRequestedOrientation ต้องการ - ดูคำตอบของฉันด้านล่างสำหรับรายละเอียด
Andy Weinstein

มีปัญหากับแนวทางนี้ ตรวจสอบให้แน่ใจว่าคุณได้อ่านความคิดเห็นของคำตอบนี้แล้ว
Bugs Happen

แต่มันกำหนดทิศทางเดียวกันสำหรับกิจกรรมทั้งหมดมีวิธีอื่นอีกไหมที่เราสามารถเปลี่ยนการวางแนวได้
silverFoxA

106

โปรดระวังความแตกต่างระหว่างสิ่งที่ getConfiguration ส่งกลับและสิ่งที่ setRequestedOrientation ต้องการ - ทั้งคู่เป็น int แต่มาจากนิยามคงที่ต่างกัน

ต่อไปนี้เป็นวิธีล็อคการวางแนวปัจจุบันในขณะที่สามารถพลิกได้ 180 องศา

int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
else {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}

13
คุณอาจต้องการใช้ SCREEN_ORIENTATION_USER_LANDSCAPE เนื่องจากไม่อนุญาตให้พลิก 180 องศาหากผู้ใช้ปิดใช้งานการหมุนหน้าจอในการตั้งค่า ในทำนองเดียวกันเมื่อเปลี่ยนกลับเป็นการหมุนฟรี SCREEN_ORIENTATION_USER จะดีกว่า SCREEN_ORIENTATION_SENSOR เนื่องจากรุ่นหลังอนุญาตให้หมุนฟรีแม้ว่าการตั้งค่าจะบอกว่าไม่ทำก็ตาม
Steve Waring

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

47

สิ่งนี้ใช้ได้กับอุปกรณ์ที่มีแนวตั้งย้อนกลับและแนวนอนย้อนกลับ

การวางแนวล็อค:

    int orientation = getActivity().getRequestedOrientation();
    int rotation = ((WindowManager) getActivity().getSystemService(
            Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
    switch (rotation) {
    case Surface.ROTATION_0:
        orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        break;
    case Surface.ROTATION_90:
        orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        break;
    case Surface.ROTATION_180:
        orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
        break;
    default:
        orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        break;
    }

    getActivity().setRequestedOrientation(orientation);

การวางแนวปลดล็อก:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

5
ได้รับการหมุนแหล่งที่มา"Returns the rotation of the screen from its "natural" orientation." ดังนั้นในโทรศัพท์ที่บอกว่า ROTATION_0 เป็นแนวตั้งน่าจะถูกต้อง แต่ในแท็บเล็ตการวางแนว "ธรรมชาติ" น่าจะเป็นแนวนอนและ ROTATION_0 ควรกลับเป็นแนวนอนแทนที่จะเป็นแนวตั้ง
jp36

@ jp36 ฉันทดสอบกับ Nexus 7 ซึ่งมีการวางแนวที่เป็นธรรมชาติเหมือนกับโทรศัพท์ ขอบคุณสำหรับการทดสอบกับแท็บเล็ตที่ใหญ่กว่า (ซึ่งฉันไม่มี)
pstoppani

1
ดังที่ jp36 กล่าวไว้มันใช้ไม่ได้กับแท็บเล็ตที่มีแนวนอนตามธรรมชาติ!
DominicM

เราจะทดสอบภาพย้อนกลับในอุปกรณ์ได้อย่างไร?
AndyBoy

27

ฉันดูเหมือนจะมีกรณีที่คล้ายกัน ฉันต้องการสนับสนุนการวางแนวใด ๆ แต่ฉันต้องอยู่ในทิศทางปัจจุบันหลังจากถึงจุดหนึ่งในเวิร์กโฟลว์ วิธีแก้ปัญหาของฉันคือ:

เมื่อเข้าสู่เวิร์กโฟลว์ที่มีการป้องกัน:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

เมื่อออกจากเวิร์กโฟลว์ที่มีการป้องกัน:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

2
สิ่งนี้ไม่ได้กล่าวถึง OQ อย่างน้อยบน Android> = 16 setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) อาจตั้งค่าอุปกรณ์เป็นแนวนอนแม้ว่าจะอยู่ในแนวตั้งก็ตามในขณะที่คำถามหมายถึงการล็อกการวางแนวที่กำหนด
greg7gkb

3
สำหรับฉันการตั้งค่าเป็น nosensor จะพาฉันกลับไปที่โหมดแนวตั้งหากฉันอยู่ในแนวนอนฉันใช้ SCREEN_ORIENTATION_LOCKED แทนและมันก็ใช้ได้ผลสำหรับฉัน
Jimmar

1
@JiMMaR SCREEN_ORIENTATION_LOCKED เป็นวิธีที่ดีที่สุดสำหรับ Android> = 18 แต่ในกรณีที่คุณกำหนดเป้าหมายสิ่งที่ต่ำกว่านั้นจะไม่ได้ผล ฉันขอแนะนำให้ใช้คำตอบของ jp36 ด้านล่าง
Patrick Boos

23

ทางเลือกสำหรับคำตอบ @pstoppani พร้อมการรองรับแท็บเล็ต (เช่นเดียวกับคำตอบ @pstoppani สิ่งนี้จะใช้ได้เฉพาะกับอุปกรณ์> 2.2)
- ทดสอบSamsung Galaxy SIIIและSamsung Galaxy Tab 10.1

public static void lockOrientation(Activity activity) {
    Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int rotation = display.getRotation();
    int tempOrientation = activity.getResources().getConfiguration().orientation;
    int orientation = 0;
    switch(tempOrientation)
    {
    case Configuration.ORIENTATION_LANDSCAPE:
        if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
            orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        else
            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        break;
    case Configuration.ORIENTATION_PORTRAIT:
        if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
            orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        else
            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    }
    activity.setRequestedOrientation(orientation);
}

ขอบคุณมันทำงานได้ดี แต่ผมไม่เข้าใจว่าทำไมมันตรวจสอบกับ||ในและrotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270ดังนั้นฉันจึงมีข้อสงสัย 2 ประการ :::: ประการแรกทำไมROTATION_0แทนที่จะเป็นROTATION_180ในกรณีที่สองและอีกประการหนึ่งทำไมต้องตรวจสอบ 0 องศาด้วย 90 ไม่ใช่ 180 ??
AndyBoy

@AndyBoy มันเกี่ยวข้องกับการวางแนวเริ่มต้นของอุปกรณ์ โดยทั่วไปโทรศัพท์จะมีการวางแนวเริ่มต้นในแนวตั้งซึ่งหมายความว่าการหมุนจะคืนค่าเป็นศูนย์สำหรับแนวตั้ง แต่แท็บเล็ตบางรุ่นมีค่าเริ่มต้นของแนวนอนซึ่งหมายความว่าการหมุนจะส่งกลับศูนย์สำหรับแนวนอน ดังนั้นการ||ตรวจสอบที่แตกต่างกันจึงจัดการการวางแนวเริ่มต้นที่เป็นไปได้สองแบบโดยอิงตามอุปกรณ์ที่รายงานแนวนอนเทียบกับแนวตั้ง
jp36

5

นี่คือรหัสของฉันคุณสามารถล็อคด้วยวิธีใดวิธีหนึ่งต่อไปนี้หน้าจอของคุณและเมื่อเสร็จงานแล้วจะปลดล็อกด้วยการปลดล็อก

/** Static methods related to device orientation. */
public class OrientationUtils {
    private OrientationUtils() {}

    /** Locks the device window in landscape mode. */
    public static void lockOrientationLandscape(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    /** Locks the device window in portrait mode. */
    public static void lockOrientationPortrait(Activity activity) {
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    /** Locks the device window in actual screen mode. */
    public static void lockOrientation(Activity activity) {
        final int orientation = activity.getResources().getConfiguration().orientation;
        final int rotation = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

        // Copied from Android docs, since we don't have these values in Froyo 2.2
        int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
        int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;

        // Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO
        if (!BuildVersionUtils.hasGingerbread()) {
            SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
            SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        }

        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90){
            if (orientation == Configuration.ORIENTATION_PORTRAIT){
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
            else if (orientation == Configuration.ORIENTATION_LANDSCAPE){
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
        }
        else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) 
        {
            if (orientation == Configuration.ORIENTATION_PORTRAIT){
                activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            }
            else if (orientation == Configuration.ORIENTATION_LANDSCAPE){
                activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
        }
    }

    /** Unlocks the device window in user defined screen mode. */
    public static void unlockOrientation(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
    }

}

0

นี่คือการแปลง Xamarin เป็นคำตอบของ @pstoppani ด้านบน

หมายเหตุ: สำหรับ Fragment แทนที่Activity ด้วยสิ่งนี้ หากใช้ภายในกิจกรรม

public void LockRotation()
{
    ScreenOrientation orientation;

    var surfaceOrientation = Activity.WindowManager.DefaultDisplay.Rotation;

    switch (surfaceOrientation) {
        case SurfaceOrientation.Rotation0:
            orientation = ScreenOrientation.Portrait;
            break;
        case SurfaceOrientation.Rotation90:
            orientation = ScreenOrientation.Landscape;
            break;
        case SurfaceOrientation.Rotation180:
            orientation = ScreenOrientation.ReversePortrait;
            break;
        default:
            orientation = ScreenOrientation.ReverseLandscape;
            break;
    }

    Activity.RequestedOrientation = orientation;
}

public void UnlockRotation()
{
    Activity.RequestedOrientation = ScreenOrientation.Unspecified;
}

สิ่งนี้ยังไม่ผ่านการทดสอบเนื่องจากใช้วิธีการอื่นก่อนที่จะใช้ แต่อาจมีประโยชน์


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