Android : 활동에서 방향 변경을 일시적으로 비활성화


116

내 주요 활동에는 중단해서는 안되는 일부 데이터베이스를 변경하는 코드가 있습니다. 다른 스레드에서 무거운 작업을 수행하고 취소 불가능으로 설정 한 진행 대화 상자를 사용하고 있습니다. 그러나 전화기를 회전하면 실행중인 프로세스에 대해 정말 나쁜 활동이 다시 시작되고 강제 종료가 발생한다는 것을 알았습니다.

내가 원하는 것은 방향 변경이 활성화되는 프로세스가 완료 될 때까지 화면 방향 변경을 프로그래밍 방식으로 비활성화하는 것입니다.


아무도이 부분을 언급하지 않는 것 같으므로 ActivityInfo 식별자를 사용하기 위해 android.content.pm.ActivityInfo를 가져오고 싶을 것입니다.
zsalwasser


1
참조 : stackoverflow.com/a/32885911/2673792- 최상의 솔루션
Sudhir Sinha

답변:


165

로 자신의 크리스에 의해 설명 자동 응답 전화,

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

그리고

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

정말 매력처럼 작동합니다 ... 실제 장치에서!

에뮬레이터에서 테스트 할 때 손상되었다고 생각하지 마세요. ctrl + F11 단축키는 센서 이동을 에뮬레이션하지 않고 항상 화면 방향을 변경합니다.

편집 : 이것은 최선의 대답이 아니 었습니다. 의견에서 설명했듯이이 방법에는 문제가 있습니다. 진짜 답은 여기에 있습니다 .


그 상수를 찾을 수 없습니다. 감사합니다.
Christopher Perry

41
이러한 메서드에 문제가 있습니다 ... setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); 장치가 기본 방향 사용이 아닌 경우 활동 방향이 즉시 장치 기본 방향으로 변경 (파괴 및 재생성)됩니다. 예를 들어 휴대 전화에서 가로 방향으로 잡고 있으면 센서를 다시 활성화 할 때 활동이 세로로 전환되고 다시 가로로 전환됩니다. Archos A5 IT의 동일한 반대 문제 : 세로로 사용하면 활동이 가로로 전환되고 다시 세로로 전환됩니다.
Kevin Gaudin

1
원래 질문에 대한 실제 대답은 다음과 같습니다. stackoverflow.com/questions/3821423/…
Kevin Gaudin

2
이것은 나를 위해 작동하지 않았습니다. 이것은 작동했습니다. stackoverflow.com/a/10488012/1369016 setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); 또는 setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); getResources (). getConfiguration (). orientation에서 검색된 현재 방향을 기반으로합니다.
Tiago

ActivityInfo.SCREEN_ORIENTATION_SENSORAndroid의 기본 방향 잠금을 존중하지 않습니다. 방향을로 재설정합니다 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED.
tvkanters

43

다른 답변 중 어느 것도 나를 위해 완벽하게 트릭을 만들지 못했지만 여기에 내가 찾은 것이 있습니다.

현재 방향 잠금 ...

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

방향 변경을 다시 허용해야하는 경우 기본값으로 다시 설정하십시오.

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

9
이것의 문제 Configuration.ORIENTATION_PORTRAIT는 두 가로 모드 (즉, '보통'과 반전)에서 반환 된다는 것입니다. 따라서 전화기가 가로 방향이 반전되어 있고 설정하면 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE거꾸로 뒤집 힙니다. API 9에서 ActivityInfo는 SCREEN_ORIENTATION_REVERSE_LANDSCAPE상수를 도입 했지만 Configuration클래스를 통해 이러한 방향을 감지하는 방법을 찾지 못했습니다 .
Błażej Czapp 2012

1
이것은 효과가 있었다. 위의 우려에 대한 답변은이 답변에 있습니다. stackoverflow.com/a/10453034/1223436
Zack

너무 내 요구에 대한 매력처럼 화려한 감사 일했다
user2029541

39

다음은 API 8 이상에서 작동하고 역 세로 및 가로에서 작동하며 "자연"방향이 가로 인 Galaxy 탭에서 작동하는보다 완전하고 최신 솔루션입니다 ( activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)방향을 잠금 해제하려면 호출 ).

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public static void lockActivityOrientation(Activity activity) {
    Display display = activity.getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int height;
    int width;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
        height = display.getHeight();
        width = display.getWidth();
    } else {
        Point size = new Point();
        display.getSize(size);
        height = size.y;
        width = size.x;
    }
    switch (rotation) {
    case Surface.ROTATION_90:
        if (width > height)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_180:
        if (height > width)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        break;          
    case Surface.ROTATION_270:
        if (width > height)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    default :
        if (height > width)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

태블릿과 휴대폰으로 잘 작동했습니다.
ScruffyFox 2014 년

나를 위해 모든 종류의 장치에서 작동하는 유일한 정답입니다.
amdev

확실히 최고의 답변입니다! 이 메서드 static를 만들고 Activity activity매개 변수로 추가 할 수 있습니다 .
까악 까악

18

역방향 모드도 관리하기 위해 해당 코드를 사용하여 활동 방향을 수정했습니다.

int rotation = getWindowManager().getDefaultDisplay().getRotation();

    switch(rotation) {
    case Surface.ROTATION_180:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_270:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);         
        break;
    case  Surface.ROTATION_0:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    case Surface.ROTATION_90:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        break;
    }

그리고 다시 방향을 허용하려면 :

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

17

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);현재 방향을 가로 또는 세로로 고정하는 데 사용 합니다.

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);잠금 해제 방향에 사용 합니다.


짧은 임시 잠금을위한 최상의 솔루션입니다. 센서의 현재 방향을 방해하지 않습니다.
놀라운 1

2
Build.VERSION.SDK_INT> = 18에서 작동합니다.이 페이지에서 tdjprog에 의해 더 완전한 답변이 제공됩니다. stackoverflow.com/a/41812971/5235263
bastami82


11

모두 감사합니다. 이전 상태로 복원되었는지 확인하기 위해 Pilot_51의 솔루션을 수정했습니다. 또한 비가로 및 비세로 화면을 지원하기 위해 변경 사항을 적용했습니다 (그러나 이러한 화면에서 테스트하지는 않았습니다).

prevOrientation = getRequestedOrientation();
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}

그런 다음 복원하려면

setRequestedOrientation(prevOrientation);

좋은 물건-왜 사용하지 않았는지 확실하지 않습니다 switch.

세 번째 옵션을 추가 한 후 정리하고 스위치로 변경하는 것을 잊었습니다.
ProjectJourneyman

활동 개체에 대한 액세스 권한이 없지만 컨텍스트 ActivityInfo.SCREEN_ORIENTATION_NOSENSOR | ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
max4ever

8
protected void setLockScreenOrientation(boolean lock) {
    if (Build.VERSION.SDK_INT >= 18) {
        setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        return;
    }

    if (lock) {
        switch (getWindowManager().getDefaultDisplay().getRotation()) {
            case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1
            case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9
            case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0
            case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8
        }
    } else
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10
}

답변에 대한 설명을 추가해 주시겠습니까?
slfan

백그라운드에 작업이있을 때 setLockScreenOrientation (true)을 호출하여 방향을 잠그고 현재 활동을 다시 생성하기 위해 파괴를 방지합니다. 이러한 작업이 완료되었는지 확인하면 setLockScreenOrientation (false)을 호출합니다.
tdjprog

2
이것이 최선의 대답입니다!
Fakher

7

다음은 매번 작동하고 현재 방향을 유지하는 솔루션입니다 ( Activity.Info.SCREEN_ORIENTATION_PORTRAIT예를 들어 0 °로 설정을 사용 하지만 사용자는 현재 방향으로 180 ° 방향을 가질 수 있음).

// Scope: Activity

private void _lockOrientation() {
    if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
    } else {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
    }
}

private void _unlockOrientation() {
    super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

2
언급 할 가치가있는 사항 : API 18+ 전용
Dmitry Zaytsev

1

사용 ActivityInfo.SCREEN_ORIENTATION_USER당신은이 장치에서 활성화 한 경우에만 화면 회전하십시오.


1

이것은 나를 위해 완벽하게 작동합니다. 태블릿 / 휴대 전화의 "자연스러운 방향"이 다른 문제를 해결합니다.)

int rotation = getWindowManager().getDefaultDisplay().getRotation();

        Configuration config = getResources().getConfiguration();
        int naturalOrientation;

        if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
                config.orientation == Configuration.ORIENTATION_LANDSCAPE)
                || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
                config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
            naturalOrientation = Configuration.ORIENTATION_LANDSCAPE;
        } else {
            naturalOrientation = Configuration.ORIENTATION_PORTRAIT;
        }

        // because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet)
        // we need to update rotation variable if natural orienation isn't 0 (mainly tablets)
        if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE)
            rotation = ++rotation % 4;

        switch (rotation) {
            case Surface.ROTATION_0: //0
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                break;
            case Surface.ROTATION_90: //1
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                break;
            case Surface.ROTATION_180: //2
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                break;
            case Surface.ROTATION_270: //3
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                break;
        }
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }

0

디스플레이 회전에 따라 장치의 방향을 결정하는 솔루션을 찾았습니다. 방향을 알면 방향을 잠그고 필요할 때 나중에 해제 할 수 있습니다. 이 솔루션은 장치가 역 가로 모드 인지 여부도 확인할 수 있습니다 .

private void lockOrientation(){
    switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) {


        // Portrait
        case Surface.ROTATION_0:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;


        //Landscape     
        case Surface.ROTATION_90: 
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            break;


        // Reversed landscape
        case Surface.ROTATION_270:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);             
            break;
    }
}

나중에 방향을 해제해야하는 경우이 메서드를 호출 할 수 있습니다.

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

0

이 코드는 읽기가 더 쉽다고 생각합니다.

private void keepOrientation() {

    int orientation = getResources().getConfiguration().orientation;
    int rotation = getWindowManager().getDefaultDisplay().getRotation();

    switch (rotation) {
        case Surface.ROTATION_0:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            break;
        case Surface.ROTATION_90:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            break;
        case Surface.ROTATION_180:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
            break;
        default:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
    }
}

0

네 가지 가능성을 다루기 위해 기존의 회전 / 방향 값 조합이 필요하다는 사실을 발견했습니다. 세로 / 가로 값과 장치의 자연스러운 방향이 있습니다. 화면이 "자연"세로 또는 가로 방향 일 때 장치의 자연 방향이 0 도의 회전 값을 갖는다 고 가정 해 보겠습니다. 마찬가지로 가로 또는 세로 일 때 90 도의 회전 값이 있습니다 (방향 @ 0 도의 반대 임). 따라서 0도 또는 90 도가 아닌 회전 값은 "역방향"방향을 의미합니다. 좋아, 다음은 몇 가지 코드입니다.

public enum eScreenOrientation 
{
PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),
LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT),
LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE),
UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

    public final int activityInfoValue;

    eScreenOrientation ( int orientation )
    {
        activityInfoValue = orientation;
    }
}



public eScreenOrientation currentScreenOrientation ( )
{
    final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

    final int orientation = getResources().getConfiguration().orientation;
    switch ( orientation ) 
    {
    case Configuration.ORIENTATION_PORTRAIT:
        if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
            return eScreenOrientation.PORTRAIT;
        else
            return eScreenOrientation.PORTRAIT_REVERSE;
    case Configuration.ORIENTATION_LANDSCAPE:
        if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
            return eScreenOrientation.LANDSCAPE;
        else
            return eScreenOrientation.LANDSCAPE_REVERSE;
    default:
        return eScreenOrientation.UNSPECIFIED_ORIENTATION;
    }
}

public void lockScreenOrientation ( )
    throws UnsupportedDisplayException
{
    eScreenOrientation currentOrientation = currentScreenOrientation( );
    if ( currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION )
        throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation");
    else
        setRequestedOrientation( currentOrientation.activityInfoValue );
}

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

0

잠금 해제에서 이전 상태와 반대로 UNSPECIFIED로 설정했기 때문에 여기에있는 대부분의 답변이 마음에 들지 않았습니다. ProjectJourneyman은이를 고려하여 훌륭했지만 저는 Roy의 잠금 코드를 선호했습니다. 따라서 내 권장 사항은 두 가지를 혼합하는 것입니다.

private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;

private void unlockOrientation() {
    setRequestedOrientation(prevOrientation);
}

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void lockOrientation() {
    prevOrientation = getRequestedOrientation();
    Display display = getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int height;
    int width;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
        height = display.getHeight();
        width = display.getWidth();
    } else {
        Point size = new Point();
        display.getSize(size);
        height = size.y;
        width = size.x;
    }
    switch (rotation) {
        case Surface.ROTATION_90:
            if (width > height)
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            else
                setRequestedOrientation(9/* reversePortait */);
            break;
        case Surface.ROTATION_180:
            if (height > width)
                setRequestedOrientation(9/* reversePortait */);
            else
                setRequestedOrientation(8/* reverseLandscape */);
            break;
        case Surface.ROTATION_270:
            if (width > height)
                setRequestedOrientation(8/* reverseLandscape */);
            else
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;
        default :
            if (height > width)
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            else
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

0

당신이 사용할 수있는

public void swapOrientaionLockState(){
    try{
        if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) {
            Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation());
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0);
        } else {
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1);
        }

        Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0);

    } catch (Settings.SettingNotFoundException e){
        e.printStackTrace();
    }
}

public boolean orientationIsLocked(){
    if(canModifiSetting(mContext)){
        try {
            return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0;
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
    }
    return false;
}

public static boolean canModifiSetting(Context context){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return Settings.System.canWrite(context);
    } else {
        return true;
    }
}

-1

그 코드 줄을 사용

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  

ur 활동에서 생성 방법

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.