簡體   English   中英

如何檢測Android布局中的方向變化?

[英]How to detect orientation change in layout in Android?

我剛剛實現了一個方向更改功能 - 例如,當布局從縱向變為橫向(反之亦然)時。 如何檢測方向更改事件何時完成。

OrientationEventListener不起作用。 如何獲得有關布局方向更改事件的通知?

使用 Activity 的onConfigurationChanged方法。 請參閱以下代碼:

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

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

您還必須編輯適當的清單文件中的元素以包含android:configChanges只需查看以下代碼:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

注意:對於 Android 3.2(API 級別 13)或更高版本,當設備在縱向和橫向之間切換時,“屏幕尺寸”也會發生變化。 因此,如果您想在為 API 級別 13 或更高級別開發時防止由於方向更改而導致運行時重新啟動,則必須為 API 級別 13 或更高級別聲明android:configChanges="orientation|screenSize"

希望能幫到你... :)

要在layout-land文件夾中加載布局意味着您有兩個單獨的布局,那么您必須在onConfigurationChanged方法中創建setContentView

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

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

如果您只有一種布局,則無需在此方法中設置 setContentView。 簡單地

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

只是想向您展示一種在 onConfigurationChanged 后保存所有 Bundle 的方法:

課程結束后創建新的 Bundle:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

接下來,在“protected void onCreate”之后添加:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

如果您將其添加到 MainActivity 中,您所有的 crated 類都將被保存。

但最好的方法是在你的 AndroidManifest 中添加這個:

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

使用這個方法

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

並且不要忘記在您的 Androidmainfest.xml 中添加它

android:configChanges="orientation|screenSize"

像這樣

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>

如果這對一些較新的開發人員有用,因為上面沒有指定。 只是要非常明確:

如果使用onConfigurationChanged ,您需要做兩件事:

  1. Activity 類中的onConfigurationChanged方法

  2. 在清單中指定onConfigurationChanged方法將處理哪些配置更改

清單片段在上面的答案,而無疑是正確的特定應用程序,明顯屬於,正是你需要在你的清單中添加,以觸發您的活動課的onConfigurationChanged方法是什么。 即以下清單條目可能不適合您的應用程序。

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

在上面的清單條目中, android:configChanges=""有各種 Android 操作,它們可以在您的 Activity 生命周期中觸發 onCreate。

這非常重要 -清單中未指定的是觸發您的 onCreate的那些,清單中指定的是觸發您的活動類中的onConfigurationChanged方法的那些

因此,您需要確定需要自己處理哪些配置更改。 對於像我這樣的 Android Encyclopedically Challenged,我使用了 Android Studio 中的快速提示彈出窗口,並添加了幾乎所有可能的配置選項。 列出所有這些基本上是說我會處理所有事情,並且由於配置,永遠不會調用 onCreate。

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

現在顯然我不想處理所有事情,所以我開始一次消除上述選項。 每次刪除后重新構建和測試我的應用程序。

另一個重點:如果只有一個配置選項被自動處理觸發您的 onCreate(您沒有在上面的清單中列出它),那么它看起來就像onConfigurationChanged不起作用。 您必須將所有相關的放入您的清單中。

我最終得到了 3 個最初觸發 onCreate 的結果,然后我在 S10+ 上進行了測試,我仍然得到了 onCreate,所以我不得不再次進行消除練習,而且我還需要|screenSize 因此,在選擇的平台上進行測試。

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

所以我的建議,雖然我確信有人可以在這方面戳破洞:

  1. 使用 TOAST 或 LOG 在您的活動類中添加您的onConfigurationChanged方法,以便您可以看到它何時工作。

  2. 將所有可能的配置選項添加到您的清單中。

  3. 通過測試您的應用程序來確認您的onConfigurationChanged方法正在運行。

  4. 一次從清單文件中刪除每個配置選項,並在每個選項之后測試您的應用程序。

  5. 在盡可能多的設備上進行測試。

  6. 不要將我上面的代碼片段復制/粘貼到您的清單文件中。 Android 更新會更改列表,因此請使用彈出的 Android Studio 提示確保您獲得所有提示。

我希望這可以節省一些時間。

我的onConfigurationChanged方法僅用於以下信息。 onConfigurationChanged被稱為生命周期后,新的方向是可用的,但之前的UI已創建。 因此,我的第一個if檢查方向是否正常工作,然后第二個嵌套if查看我的 UI ImageView 的可見性也正常工作。

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

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }

覆蓋活動的方法onConfigurationChanged

我只是想提出另一種替代方案,確實會引起你們中的一些人的關注,正如上面所解釋的:

android:configChanges="orientation|keyboardHidden" 

意味着我們明確聲明要注入的布局。

如果我們想通過 layout-land 和 layout 文件夾保持自動注入。 您所要做的就是將其添加到 onCreate 中:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

在這里,我們根據手機的方向顯示或不顯示操作欄

創建OrientationEventListener類的實例並啟用它。

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();

如果接受的答案對您不起作用,請確保您沒有在清單文件中定義:

android:screenOrientation="portrait"

這是我的情況。

以最簡單的形式實現 Kotilin - 僅在屏幕從縱向 <--> 橫向變化時觸發,如果需要設備翻轉檢測(180 度),您需要標記重力傳感器值

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}

如果其他人像我一樣在這方面花費太長時間 - 它在模擬器上不起作用。 必須是真機。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM