อย่าโหลดแอปพลิเคชันซ้ำเมื่อมีการเปลี่ยนแนว


152

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


1
นอกจากนี้ยังสามารถล็อค (และอาจปลดล็อก) การวางแนวหน้าจอจากรหัส เพียงโทรScreen.lockOrientation(this)จากgithub.com/delight-im/Android-BaseLib/blob/master/Source/src/im/…สำหรับสิ่งนี้ อนุญาตให้ปลดล็อคซึ่งรายการไม่ได้
caw

@Escobar Ceaser คำตอบที่เหมาะสมสำหรับคำถามนี้คืออะไรแม้ว่าฉันมีข้อกำหนดเดียวกัน
Prabs

ฉันต้องการทำสิ่งนี้โดยใช้โปรแกรมในรหัส
Pollaris

คำตอบ:


249

โดยทั่วไปมีสามวิธีในการทำสิ่งนี้:

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

  2. คุณสามารถล็อคกิจกรรมในทิศทางเดียวโดยเพิ่มandroid:screenOrientation="portrait"(หรือ"landscape") <activity>ในรายการของคุณ

  3. คุณสามารถบอกระบบว่าคุณตั้งใจจะจัดการกับการเปลี่ยนแปลงหน้าจอด้วยตัวคุณเองโดยระบุandroid:configChanges="orientation|screenSize"ใน<activity>แท็ก วิธีนี้กิจกรรมจะไม่ถูกสร้างขึ้นใหม่ แต่จะได้รับการติดต่อกลับแทน (ซึ่งคุณสามารถเพิกเฉยได้เพราะมันไม่มีประโยชน์สำหรับคุณ)

โดยส่วนตัวแล้วฉันจะไปกับ (3) แน่นอนว่าถ้าล็อคแอปเข้ากับแนวใดแนวหนึ่งก็โอเคกับคุณคุณสามารถไปด้วย (2)


13
ดังนั้นสำหรับ # 3 คุณบอกว่าสิ่งที่ฉันต้องทำคือการเพิ่มบรรทัดนั้นในรายการของฉัน? เพราะมันไม่ทำงาน
Jimmy D

2
# 3 โปรดตรวจสอบstackoverflow.com/questions/456211/…
Yeo

16
@EscobarCeaser สำหรับ Android 3.2 ขึ้นไปคุณต้องandroid:configChanges="orientation|screenSize"
Pacerier

9
android:configChanges="orientation|screenSize"ทำงานได้สำหรับฉัน ขอบคุณ @Pacerier
Don Larynx

1
โปรดอัปเดตกรณีคำตอบของคุณ # 3 ด้วยandroid:configChanges="orientation|screenSize"ค่า API> = 13 เพราะมีคนจำนวนมากที่เห็นคำตอบของคุณเป็นหลัก!
radistao

215

คำตอบของ Xion นั้นใกล้เคียงกัน แต่ # 3 ( android:configChanes="orientation") จะไม่ทำงานเว้นแต่แอปพลิเคชันจะมีระดับ API เป็น 12 หรือต่ำกว่า

ใน API ระดับ 13 หรือสูงกว่าขนาดหน้าจอจะเปลี่ยนไปเมื่อการวางแนวเปลี่ยนไปดังนั้นสิ่งนี้ยังทำให้กิจกรรมถูกทำลายและเริ่มต้นเมื่อการวางแนวเปลี่ยนไป

เพียงเพิ่มแอตทริบิวต์ "screenSize" อย่างที่ฉันทำด้านล่าง:

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

ตอนนี้เมื่อคุณเปลี่ยนการวางแนว (และการเปลี่ยนแปลงขนาดหน้าจอ) กิจกรรมจะรักษาสถานะของมันและonConfigurationChanged()ถูกเรียก สิ่งนี้จะทำให้สิ่งที่อยู่บนหน้าจอ (เช่น: เว็บเพจใน Webview) เมื่อการวางแนวเปลี่ยนไป

เรียนรู้สิ่งนี้จากเว็บไซต์นี้: http://developer.android.com/guide/topics/manifest/activity-element.html

นอกจากนี้ยังเห็นได้ชัดว่าเป็นการปฏิบัติที่ไม่ดีดังนั้นโปรดอ่านลิงก์ด้านล่างเกี่ยวกับการจัดการการเปลี่ยนแปลงรันไทม์:

http://developer.android.com/guide/topics/resources/runtime-changes.html


2
ขอบคุณ ... มันทำงานหลังจากเพิ่ม "screenSize" กับ "ปฐมนิเทศ"
Pratik Butani

ใช้งานได้กับ Samsung Galaxy Nexus android 4.2.1! android:configChanges="orientation|screenSize"
Vincent Ducastel

น่าอัศจรรย์ ทำงานผ่านรหัสมาหลายชั่วโมงเพื่อแก้ปัญหาที่ฉันเคยทำเมื่อมีการโหลดกิจกรรมใหม่และวิดีโอเริ่มตั้งแต่ต้น และนี่คือทางออก! ++++ 1
Mathias Asberg

6
การปฏิบัติที่ไม่ดี? Pfft ผู้คนในชีวิตจริงมีกำหนดเวลาและหากได้ผลก็ใช้งานได้)
Kacy

หากนี่เป็นการฝึกฝนที่ไม่ดีทำไมมันถึงได้คะแนนมาก
Sharp Edge

26

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

android:configChanges="orientation|screenSize"

ดังนั้นคุณจะมีสิ่งนี้:

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

หวังว่ามันจะใช้งานได้!


มันไม่โหลดเค้าโครงที่ดินของฉัน :( ไม่ได้ผลสำหรับฉัน
piyush poriya

16
<activity android:name="com.example.abc" 
 android:configChanges="orientation|screenSize"></activity>

เพียงเพิ่ม android:configChanges="orientation|screenSize"ในแท็บกิจกรรมของไฟล์รายการ

ดังนั้นกิจกรรมจะไม่เริ่มต้นใหม่เมื่อมีการเปลี่ยนทิศทาง


มันทำงาน แต่เมื่อฉันใช้เลย์เอาต์ที่แยกต่างหากสำหรับแต่ละเค้าโครง layout.xml และ layout-land.xml มันใช้เค้าโครงภูมิทัศน์สำหรับการวางแนวทั้งสอง ถ้าฉันใช้ "การวางแนว" เท่านั้นมันให้สิ่งที่ฉันคาดหวัง แต่โหลดใหม่ คุณช่วยได้ไหม
Karthikeyan

1
@KarthikeyanVe นั่นเป็นปัญหาเมื่อคุณพยายามที่จะโกง คุณจะต้องเริ่มกิจกรรมใหม่เพื่อเปลี่ยนเค้าโครง ไปข้างหน้าและเพียงแค่ใช้วิธีการแก้ปัญหาที่แท้จริงซึ่งมีการใช้และonSaveInstanceState() onCreate()
Marc Plano-Lesay

@ MarcPlano-Lesay และฉันจะทำเช่นนั้นได้อย่างไร?
Ahsan

@ Weaboo เชื่อมโยงการแก้ปัญหาที่เกิดขึ้นจริงในคำถาม: developer.android.com/guide/topics/resources/…
Marc Plano-Lesay

@ MarcPlano-Lesay ฉันได้เลย์เอาต์แยกต่างหากสำหรับโหมดแนวตั้งและแนวนอนหากฉันเปิดแอปในโหมดแนวนอนหรือแนวตั้งก็ใช้งานได้ดี แต่เมื่อใดก็ตามที่ฉันพยายามเปลี่ยนการวางแนวในเวลาทำงานมันจะปิดแอปของฉัน จากนั้นไปที่ MainActivity แล้วลองเปลี่ยนการวางแนวมันจะโหลดกิจกรรมนั้นใหม่และทำงานได้ดี ตอนนี้คำถามคือทำไม มีรหัสข้อผิดพลาดทางตรรกะหรือไม่? Idk แต่ฉันได้ลองดีบั๊กแอปหลายครั้งแล้วและหาอะไรไม่เจอ ยิ่งไปกว่านั้นฉันไม่ต้องการเริ่มกิจกรรมใหม่ทำไมเราไม่สามารถปรับเค้าโครงที่เกี่ยวข้องเมื่อใดก็ตามที่การเปลี่ยนแปลงการกำหนดค่า
Ahsan

10

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

คุณควรบันทึกรูปภาพที่กำลังแสดงอยู่onSaveInstanceState()และเรียกคืนรูปภาพได้อย่างถูกต้องเมื่อแอปพลิเคชันของคุณทำงานonCreate()อีกครั้ง


# 3 เป็นทางออกที่ถูกต้องสมบูรณ์ มันเป็นเครื่องมือที่ถูกสร้างขึ้นมาเพื่อแก้ปัญหานี้ ทำไมคุณถึงบอกว่ามันคือรองเท้าในตอนเช้า?
Pacerier

1
@Pacerier เพียงอ่านเอกสาร "หมายเหตุ: android:configChangesควรหลีกเลี่ยงการใช้และใช้เป็นทางเลือกสุดท้ายโปรดอ่านการจัดการการเปลี่ยนแปลงรันไทม์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการจัดการการรีสตาร์ทอย่างถูกต้องเนื่องจากการเปลี่ยนแปลงการกำหนดค่า"
Marc Plano-Lesay

คุณช่วยโพสต์ตัวอย่างการบันทึกและกู้คืนได้ไหม
Pollaris

6

วิธีนี้เป็นวิธีการทำงานที่ดีที่สุด ในไฟล์รายการเพิ่มของคุณ

<activity
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:name="your activity name"
    android:label="@string/app_name" 
    android:screenOrientation="landscape">
  </activity

และในชั้นเรียนของคุณเพิ่มรหัสต่อไปนี้

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

    }
}

4

เพิ่มandroid:configChanges="keyboardHidden|orientation|screenSize"สำหรับแท็กกิจกรรมแอพทั้งหมดในไฟล์ Manifest


3

เพียงเพิ่มลงในของคุณ AndroidManifest.xml

<activity android:screenOrientation="landscape">

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


ฉันไม่ได้มองหาที่จะใช้ความสามารถในการหมุนหน้าจอ ฉันแค่ไม่ต้องการให้แอปโหลดซ้ำ ... ดังที่ฉันพูดไป
Jimmy D

ป.ล. ... มันไม่ทำงาน มันบังคับให้แอปแสดงในทิศทางที่กำหนด การหมุนหน้าจอยังคงโหลดกิจกรรมอีกครั้ง
Jimmy D

3

ในไฟล์ manifiest เพิ่มในแต่ละกิจกรรมนี้ สิ่งนี้จะช่วยได้

android:configChanges = "orientation|keyboard|keyboardHidden|screenLayout|screenSize"

หน้าจอเค้าโครงใช้งานได้สำหรับฉันป้องกันการรีเฟรชเมื่อปรับขนาดแอพพลิเคชั่นสำหรับ splitscreen บน Android
Terren

2

คำตอบทั้งหมดข้างต้นไม่ได้ผลสำหรับฉัน ดังนั้นฉันได้รับการแก้ไขโดยการกล่าวถึงlabelด้วยscreenOrientationเช่นด้านล่าง ตอนนี้ทุกอย่างเรียบร้อยดี

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


1

บันทึกรายละเอียดภาพในของคุณonPause()หรือonStop()และใช้ในการonCreate(Bundle savedInstanceState)เรียกคืนภาพ

แก้ไข:

ข้อมูลเพิ่มเติมเกี่ยวกับกระบวนการจริงมีรายละเอียดที่นี่http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycleซึ่งแตกต่างใน Honeycomb มากกว่า Android รุ่นก่อนหน้า


จริงที่คุณควรจะทำมันใน onSaveInstanceState () วิธีการ
ทึก Mentzel



-1

ฉันไม่รู้ว่าทางออกที่ดีที่สุด แต่ฉันอธิบายได้ที่นี่:

ก่อนอื่นคุณต้องมีใบรับรองกับคุณแอปพลิเคชันคลาสของแอปของคุณอยู่ในรายการของคุณ:

<application
    android:name=".App"
    ...

ประการที่สองในแอปในชั้นเรียนของฉันฉันทำสิ่งนี้:

public class App extends Application {
    public static boolean isOrientationChanged = false;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onConfigurationChanged(@NotNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ||
                newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            isOrientationChanged = true;
        }
    }

}

ประการที่สามคุณต้องตั้งค่าสถานะเป็น Orientation Change ในกรณีของฉันฉันจะตั้งค่าเสมอเมื่อมีการเรียกกิจกรรมก่อนหน้านี้ในการนำทางแอปดังนั้นการโทรครั้งเดียวเมื่อกิจกรรมในภายหลังถูกสร้างขึ้น

isOrientationChanged = false;

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

โดยทั่วไปฉันต้องใช้มันทุกครั้งที่ฉันทำคำขอติดตั้งแบบอะซิงโครนัสซึ่งเขาเรียกว่าทุกช่วงเวลาที่เปลี่ยนทิศทาง

if (!isOrientationChanged) {
    presenter.retrieveAddress(this, idClient, TYPE_ADDRESS);
}

ฉันไม่รู้ว่ามันเป็นทางออกที่หรูหราและสวยงามที่สุดหรือไม่ แต่อย่างน้อยนี่ก็ใช้งานได้ :)


-2

เพิ่มรหัสนี้หลังonCreateเมธอด, ในกิจกรรมของคุณที่มีWebView

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);    
}

@Override
protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);    
}

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