programing

Android: 태블릿에 세로와 가로를 허용하지만 전화기에 세로를 강제로 설정하시겠습니까?

bestprogram 2023. 7. 31. 21:34

Android: 태블릿에 세로와 가로를 허용하지만 전화기에 세로를 강제로 설정하시겠습니까?

태블릿을 세로 및 가로(sw600dp 이상)로 표시할 수 있도록 하고 싶지만, 전화기는 세로로만 제한됩니다.저는 조건부로 오리엔테이션을 선택할 방법을 찾을 수 없습니다.좋은 의견이라도 있나?

리소스 및 크기 한정자를 사용하는 좋은 방법은 다음과 같습니다.

이 bool 리소스를 res/values에 bools.xml 또는 기타 형식으로 저장합니다(여기서는 파일 이름이 중요하지 않습니다).

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="portrait_only">true</bool>
    </resources>

res/values-sw600dp 및 res/values-xlarge:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="portrait_only">false</bool>
    </resources>

Android Studio에서 이러한 디렉터리 및 파일을 추가하는 데 도움이 되는 추가 답변을 참조하십시오.

그런 다음 활동의 onCreate 메서드에서 다음 작업을 수행할 수 있습니다.

    if(getResources().getBoolean(R.bool.portrait_only)){
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

최소 폭 방향으로 600dp 이상인 장치 또는 안드로이드 3.2 이전 장치(태블릿, 기본적으로)에서 x-large인 장치는 센서 및 사용자 잠금 회전 등을 기준으로 정상적으로 작동합니다.다른 모든 것(전화기, 거의 대부분)은 초상화일 뿐입니다.

승인된 답변에 대한 보충 사항

하여 Android Studio를 할 수 .res/values-sw600dp그리고.res/values-large용중디리토렉이 bools.xmlfiles 파일

values-sw600dp

먼저 프로젝트 탭에서 탐색기에서 프로젝트(Android가 아닌) 필터를 선택합니다.

enter image description here

그런 다음 마우스 오른쪽 단추를 클릭합니다.app/src/main/res디렉토리입니다.New > Android Resource Directory를 선택합니다.

최소 화면 너비를 선택한 다음 >> 버튼을 누릅니다.

enter image description here

에 입력600화면 너비가 가장 작은 경우.디렉토리 이름이 자동으로 생성됩니다.OK 해주세요.

enter image description here

그런 다음 새로 만든 항목을 마우스 오른쪽 단추로 클릭합니다.values-sw600dp파일. New > Values 자원 파일을 선택합니다.유형bools이름으로

가치관이 큰

추가values-large디렉터리는 Android 3.2 이전 버전(API 레벨 13)을 지원하는 경우에만 필요합니다.그렇지 않으면 이 단계를 건너뛸 수 있습니다.values-large는 디토리다해니다당합음에에 합니다.values-sw600dp. (values-xlarge에해는하에 합니다.values-sw720dp.)

다음을 작성하려면values-large디렉터리는 위와 동일한 단계를 따르지만 이 경우 최소 화면 너비 대신 크기를 선택합니다.Large를 선택합니다.디렉토리 이름이 자동으로 생성됩니다.

enter image description here

오른쪽 버튼으로 하여 "" "" "" "" ""를 합니다.bools.xmljava.

지니의 대답에 따라, 저는 그것을 하는 가장 확실한 방법은 다음과 같다고 생각합니다.

여기에 설명된 대로 리소스 sw600dp에 부울을 입력합니다.접두사가 있어야 제대로 작동하지 않습니다.

in res/values-sw600dp/dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="isTablet">true</bool>
</resources>

res/values/dimens.xml에서

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="isTablet">false</bool>
</resources>

그런 다음 부울을 검색하는 방법을 만듭니다.

public class ViewUtils {
    public static boolean isTablet(Context context){
        return context.getResources().getBoolean(R.bool.isTablet);
    }
}

또한 이러한 행동을 원하는 활동에서 확장할 수 있는 기본 활동:

public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!ViewUtils.isTablet(this)) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

따라서 각 활동은 기본 활동을 확장합니다.

public class LoginActivity extends BaseActivity //....

중요: 다음에서 확장하더라도BaseActivity.android:configChanges="orientation|screenSize"ActivityAndroidManifest.xml 파일:

    <activity
        android:name=".login.LoginActivity"
        android:configChanges="orientation|screenSize">
    </activity>

http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html 에서 영감을 받은 방법은 다음과 같습니다.

AndroidManifest.xml에서 세로와 가로 사이에서 변경할 수 있는 각 활동에 대해 화면 크기를 추가해야 합니다. 이전에는 이 기능이 필요하지 않았습니다!여기서 화면 방향을 설정할 필요는 없습니다. :

android:configChanges="keyboardHidden|orientation|screenSize"

각 활동에 추가하는 방법:

public static boolean isXLargeScreen(Context context) {
    return (context.getResources().getConfiguration().screenLayout
    & Configuration.SCREENLAYOUT_SIZE_MASK)
    >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
} 

그리고: (이 메서드를 재정의하지 않으면 방향을 변경할 때 앱에서 Create()를 호출합니다.)

@Override
public void onConfigurationChanged (Configuration newConfig)
{       
    super.onConfigurationChanged(newConfig);

    if (!isXLargeScreen(getApplicationContext()) ) {            
        return; //keep in portrait mode if a phone      
    }

    //I set background images for landscape and portrait here
}

각 활동의 작성() 시:

if (!isXLargeScreen(getApplicationContext())) { //set phones to portrait; 
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);            
}
else {
  //I set background images here depending on portrait or landscape orientation 
}

제가 알 수 없는 유일한 것은 가로에서 세로로 전환하거나 그 반대로 전환할 때 앱이 레이아웃 파일을 변경하도록 하는 방법입니다.위의 링크가 수행하는 것과 유사한 작업을 수행하는 것이 정답이라고 생각합니다. 하지만 저는 그것이 제 모든 데이터를 삭제하도록 할 수 없었습니다.그러나 세로와 가로에 대해 동일한 레이아웃 파일을 가지고 있을 정도로 간단한 앱이 있다면, 이것은 작동할 것입니다.

제공된 솔루션과 관련하여 문제가 발생했습니다. 마지막으로 다음과 같은 문제가 해결되었습니다.

  1. AndroidManifest.xml활동 방향을 "잠금"으로 설정합니다.
<activity
    android:name="com.whatever.YourActivity"
    android:screenOrientation="locked"
    ... />
  1. OnCreate(...)방법은 다음을 사용합니다.
@SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
    if (isTablet(resources)) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
    } else if (resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    }
    super.onCreate(savedInstanceState)
}

을 사용할 할 수 .isTablet(resources).DeviceProperties 것과는 로 것별들는개로, 은업수과가 있는지 합니다.smallestScreenWidthDp >= 600.

최근에 이러한 요구 사항을 발견했지만 이러한 솔루션을 사용하고 싶지 않았습니다.그들 모두는 그들이 부르는 공통점을 가지고 있습니다.setRequestedOrientation의 결함이 입니다.이것의 문제는 방향을 너무 늦게 설정하고 UI에 약간의 결함이 발생한다는 것입니다.앱을 실행할 때 장치가 가로 방향이면 장치가 가로 방향으로 로드된 다음 회전합니다.이는 테마를 사용하여 배경 이미지가 잘못된 방향으로 표시되므로 스플래시 화면 효과를 생성하는 경우 특히 두드러집니다.이는 또한 최근 앱에 앱이 표시되는 방식과 다른 답변 주석에 명시된 구성 변경 문제에 영향을 미칠 수 있습니다.

결론적으로 앱을 실행하지 않고 시스템이 방향을 알 수 있도록 매니페스트에 올바른 방향을 설정해야 합니다.

이것을 하는 방법에 대한 해결책이 있습니다(이것은 상당한 노력이지만 당신은 더 잘 잘 수 있을 것입니다).

먼저 매니페스트의 방향을 자리 표시자로 설정합니다.

<activity
      android:screenOrientation="${screenOrientation}"
     ...
</activity>

그런 다음 일반/태블릿 맛을 추가하여 app/build.gradle에 값을 설정해야 합니다. (이미 맛을 사용하는 경우 새 빌드 유형으로 달성할 수 있습니다.)

android {
    ...
    productFlavors {
        normal {
            manifestPlaceholders = [screenOrientation: "portrait"]
        }
        tablet {
            manifestPlaceholders = [screenOrientation: "unspecified"]
        }
    }
}

이제 우리는 태블릿 빌드에 대형 기기만을 위한 것이라고 말해야 합니다.이 작업은 태블릿 매니페스트만 추가하여 기본 매니페스트와 병합할 수 있습니다.->에서 새 매니페스트 파일 추가

app
 src
  tablet
   AndroidManifest.xml

아래는 이 매니페스트가 기본 매니페스트와 병합되므로 필요한 모든 것입니다. ->

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="{package}">

    <supports-screens
        android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="true"
        android:xlargeScreens="true"
        android:requiresSmallestWidthDp="600"
        />

</manifest>

마지막 요령은 플레이스토어가 코드가 일치하는 두 개의 업로드를 가질 수 없기 때문에 빌드를 버전 코드별로 구분해야 한다는 것입니다.태블릿(더 제한적인 빌드)에 더 높은 코드가 있는지 확인하려고 합니다.간단한 방법은 기본 코드를 취한 다음 태블릿에 사용하는 것입니다.base * 2 일반적인 통의보.base * 2 - 1저는 빌드 번호인 기본 코드로 CI를 사용하지만 당신의 취향에 따라 하드 코딩하기에 충분히 쉽습니다.

이제 두 가지 맛을 모두 만들어 보십시오.

 app-normal.apk/aab (v1.0.0, version code 1)
 app-tablet.apk/aab (v1.0.0, version code 2)

여러 개의 apk/aab 업로드로 Playstore에 업로드한 다음 태블릿에 다운로드한 경우 Playstore는 회전하는 apk를 제공하고 전화기에 다운로드한 경우 초상화는 하나만 제공합니다.

참고: Google Playstore/Amazon Kindle을 통해 배포하는 경우에만 작동합니다.

자세한 내용은 https://developer.android.com/google/play/publishing/multiple-apks https://developer.amazon.com/docs/fire-tablets/ft-screen-layout-and-resolution.html 을 참조하십시오.

수락된 답변에 따라 누군가에게 도움이 되기를 바라며 솔루션과 함께 코틀린 파일을 추가합니다.

를 풀리를저다니장에 .res/valuesbools.xml 또는 기타 형식(여기서는 파일 이름이 중요하지 않음):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="portrait_only">true</bool>
</resources>

을 이거넣어요에 넣으세요.res/values-sw600dp그리고.res/values-sw600dp-land:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="portrait_only">false</bool>
</resources>

그런 다음 활동 또는 단편성에서 아래 행에 추가합니다.

class MyActivity : Activity() {

    @SuppressLint("SourceLockedOrientationActivity")
    override fun onCreate(savedInstanceState: Bundle?) {
        if (resources.getBoolean(R.bool.portrait_only)) {
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
        super.onCreate(savedInstanceState)
    }

    @SuppressLint("SourceLockedOrientationActivity")
    override fun onConfigurationChanged(newConfig: Configuration) {
        if (resources.getBoolean(R.bool.portrait_only)) {
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
        super.onConfigurationChanged(newConfig)
    }
}

다른 해결책은 저에게 효과가 없었습니다.저는 여전히 대화와 레크리에이션 문제로 이상한 방향 문제가 있었습니다.저의 해결책은 활동을 확장하고, 그것을 초상화처럼 보이게 하는 것이었습니다.

예:

public class MainActivityPhone extends MainActivity {}

manifest.xml:

        <activity
        android:screenOrientation="portrait"
        android:name=".MainActivityPhone"
        android:theme="@style/AppTheme.NoActionBar" />

스플래시 화면 활동:

    Intent i = null;
    boolean isTablet = getResources().getBoolean(R.bool.is_tablet);
    if (!isTablet)
        i = new Intent(this, MainActivityPhone.class);
    else
        i = new Intent(this, MainActivity.class);
    startActivity(i);

내가 아는 오래된 질문.태블릿 등에서 방향을 바꾸거나 바꿀 수 있는 경우에도 앱을 항상 세로 모드로 실행하기 위해 장치에서 세로 및 가로 기능이 어떻게 구성되는지 알 필요 없이 장치를 올바른 방향으로 설정하는 데 사용되는 이 기능을 설계했습니다.

   private void initActivityScreenOrientPortrait()
    {
        // Avoid screen rotations (use the manifests android:screenOrientation setting)
        // Set this to nosensor or potrait

        // Set window fullscreen
        this.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        DisplayMetrics metrics = new DisplayMetrics();
        this.activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

         // Test if it is VISUAL in portrait mode by simply checking it's size
        boolean bIsVisualPortrait = ( metrics.heightPixels >= metrics.widthPixels ); 

        if( !bIsVisualPortrait )
        { 
            // Swap the orientation to match the VISUAL portrait mode
            if( this.activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT )
             { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }
            else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ); }
        }
        else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); }

    }

매력적으로 작동합니다!

하기: 변경하기this.activity사용자의 활동에 따라 또는 기본 활동에 추가하고 제거합니다.this.activity;-)

반대로 하려면 코드를 가로로 변경해야 합니다(그러나 이 방법은 명확하다고 생각합니다).

유감스럽게도 메서드 setRequestedOrientation(...)을 사용하면 활동이 다시 시작되므로, onCreate 메서드에서 이 작업을 호출하더라도 활동 수명 주기를 거친 다음 요청된 방향으로 동일한 활동을 다시 만듭니다.따라서 @Brian Christensen의 대답은 활동 코드가 두 번 호출될 수 있고, 이는 시각적인 것뿐만 아니라 네트워크 요청, 분석 등에서도 나쁜 영향을 미칠 수 있다는 것을 고려해야 합니다.

또한 매니페스트에서 configChanges 속성을 설정하는 것은 엄청난 리팩터링 비용이 소요될 수 있는 큰 트레이드오프라고 생각합니다.Android Devs는 해당 속성을 변경하는 것을 권장하지 않습니다.

마지막으로 화면 방향을 어떻게든 다르게 설정하는 것은 불가능합니다(재시작 문제를 피하기 위해). 변경할 수 없는 정적 매니페스트로 인해 정적으로 불가능합니다. 프로그래밍적으로 이미 시작된 작업에서만 해당 메서드를 호출할 수 있습니다.

요약:.제 생각에는 @Brian Christensen 제안이 최고의 절충안이지만, 다시 시작하는 활동 문제를 알고 있어야 합니다.

매니페스트 파일에 다음 코드를 추가합니다.

android:screenOrientation="fullSensor"

은 "XML 파일" 아래에 합니다.layout-landfolder

는 이 코드 에 했습니다.MainActivity.java파일입니다. 제 경우에도 효과가 있었습니다.

 @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            handleOrientationConfiguration();
        }

        private void handleOrientationConfiguration() {

            if (isTablet()) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
        }

        private boolean isTablet() {
            Configuration configuration = this.getContext().getResources()
                    .getConfiguration();/*from   www .j ava  2  s. c  o  m*/
            return (configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
        }

developer.android.com 에서 매니페스트에 화면 방향을 '센서' 값으로 선언해야 합니다.

방향은 물리적 방향 센서를 참조하지 않고 결정됩니다.센서는 무시되므로 사용자가 장치를 이동하는 방식에 따라 디스플레이가 회전하지 않습니다.

그러면 회전이 '자연스러운' 장치 동작이 됩니다(전화: 세로/태블릿: 가로).

데이터베이스 레코드를 표시하는 활동이 있는 경우와 같이 활동별로 서로 다른 순환을 혼합할 수 있다는 장점이 있습니다. 그러면 다른 사용자는 "센서 없음"을 사용하는 동안 활동 방향을 "전체 사용자"로 설정할 수 있습니다."전체 사용자" 활동은 사용자 선택에 따라 회전합니다(회전 활성화: 센서 사용, 사용자 기본 설정 사용).

<activity android:name=".scanner.ScannerPropertiesActivity" 
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/title_activity_scanner_properties"
android:screenOrientation="${screenOrientation}"/>

${screenOrientation}은(는) ManifestPlaceHolder이므로 다음을 사용하여 모든 오리엔테이션 동작 간에 테스트하려는 모든 활동을 쉽게 전환할 수 있습니다.

//module's build.gradle
defaultConfig {
//...
    manifestPlaceholders = [applicationName:appName,screenOrientation:'nosensor']
//...
}

더 복잡한 것이 필요한 경우(즉,태블릿에서만 화면 회전을 허용하고 전화 방향을 세로로 고정)한 다음 잠금 장치를 사용해야 합니다.

android:screenOrientation="locked"센서가 전화기를 가로 방향으로 회전시키는 동안 방향을 세로 방향으로 강제로 지정하면 코드가 실행되면 활동이 가로 방향으로 시작되고 다른 방향과 함께 세로 방향으로 회전합니다.잠금은 이전 회전을 유지하므로 이전 활동에서 이미 세로로 잠겼을 수 있습니다.그런 다음 장치가 태블릿 또는 전화기일 때를 알아야 합니다.이렇게 하려면 다음을 사용하는 것이 좋습니다.

Detect tablet using resource overload

//normal tablet_detection file content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="isTablet" type="bool">false</item>
</resources>
//sw600dp tablet_detection file content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="isTablet" type="bool">true</item>
</resources>
//Now in your code you can detect if it's a tablet or not by calling following function in your Activity's **onCreate** and apply screen orientation by code:
protected  void updateScreenOrientation(){
boolean isTablet =context.getResources().getBoolean(R.bool.isTablet);
//And select the orientation you wish to set:
int defaultOrientation=isTablet? ActivityInfo.SCREEN_ORIENTATION_FULL_USER:ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        if(getRequestedOrientation()== ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
            //Apply this only on Activities where you set the orientation to 'locked' in the manifest
            this.setRequestedOrientation(defaultOrientation);
        }
}

치수에 대해 방향을 잠그지 않는 좋습니다. 하지만 여기에 있는 지침을 따르면 방향을 고정할 수 있습니다.

단계에서 맨 먼저 해야 할 일은 매니페스트의 방향을 해제하는 것입니다.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

그런 다음 Jetpack Window Manager를 사용하여 앱의 화면 공간을 확인할 수 있습니다.

/** Determines whether the device has a compact screen. **/
fun compactScreen(): Boolean {
    val screenMetrics = WindowMetricsCalculator
                        .getOrCreate()
                        .computeMaximumWindowMetrics(this)
    val shortSide = min(screenMetrics.bounds.width(),
                        screenMetrics.bounds.height())
    return shortSide / resources.displayMetrics.density < 600
}

그리고 마지막으로 일반적으로 전화기에서 공간이 더 작을 때 방향을 잠급니다.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    requestedOrientation = if (compactScreen())
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    ...
}

언급URL : https://stackoverflow.com/questions/9627774/android-allow-portrait-and-landscape-for-tablets-but-force-portrait-on-phone