จะตรวจจับการเปลี่ยนแปลงการวางแนวของเค้าโครงใน Android ได้อย่างไร


110

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

OrientationEventListenerไม่ได้ทำงาน ฉันจะรับการแจ้งเตือนเกี่ยวกับเหตุการณ์การเปลี่ยนแปลงการวางแนวเค้าโครงได้อย่างไร


ในกรณีของฉัน onCreate () ถูกเรียกเมื่อการวางแนวเปลี่ยนไป
Josiel Novaes

คำตอบ:


293

ใช้เมธอดonConfigurationChangedของกิจกรรม ดูรหัสต่อไปนี้:

@Override
public void onConfigurationChanged(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 หรือสูงกว่าคุณต้องประกาศandroid: configChanges = "orientation | screenSize" สำหรับ API ระดับ 13 ขึ้นไป

หวังว่านี่จะช่วยคุณได้ ... :)


3
นี่เป็นสิ่งที่ดี แต่จะโหลด layout xml ในโฟลเดอร์ layout-land โดยใช้ไฟล์เค้าโครง xml แนวตั้ง
Programmer

23
Aztec Coder เมื่อคุณใส่ "android: configChanges =" orientation "แสดงว่าคุณจะจัดการกับการเปลี่ยนแปลงการวางแนวซึ่งหมายความว่ากิจกรรมของคุณจะไม่ถูกสร้างขึ้นใหม่เมื่อคุณเปลี่ยนเป็นแนวนอนจะเรียก onConfigurationChanged แทนหากไม่เป็นที่ต้องการ คุณสามารถใช้ตัวแปรเพื่อจำทิศทางของกิจกรรมของคุณและทุกครั้งที่ไปโดยใช้ onPause (เช่น) เพื่อตรวจสอบว่าการวางแนวยังคงเหมือนเดิมหรือไม่
Elena

14
หากคุณกำลังพัฒนาสำหรับ API ระดับ 13 (3.2) หรือสูงกว่าคุณควรระบุ android: configChanges = "orientation | screenSize" มิฉะนั้น onConfigurationChanged จะไม่ถูกเรียก: developer.android.com/guide/topics/resources/…
Arne

1
สวัสดีฉันกำลังสร้างแอปด้วย API 10 (Android 2.3.3) และจดจำการวางแนวได้อย่างสมบูรณ์แบบเมื่อฉันใช้ android: configChanges = "orientation | keyboardHidden" แต่ Nexus S ของฉันที่ใช้ Android 4.1.2 ตรวจไม่พบการเปลี่ยนทิศทางฉันควรทำอย่างไร?
Karthik Andhamil

2
ใช้android: configChanges = "orientation | screenSize"แทน android: configChanges = "orientation | keyboardHidden" ในไฟล์ manifest ของคุณและตรวจสอบ ... !!!
Dinesh Sharma

15

สำหรับการโหลดรูปแบบในรูปแบบที่ดินโฟลเดอร์หมายความว่าคุณมีสองรูปแบบที่แยกต่างหากจากนั้นคุณจะต้องทำsetContentViewในonConfigurationChangedวิธีการ

@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);
}

19
แทนที่จะลบล้างเพียงใช้ layout / main.xml และ layout-land / main.xml
Jared Burrows


ฉันต้องการตรวจพบว่ากิจกรรมของฉันถูกยุติเนื่องจากการหมุนหน้าจอ ฉันใช้onConfigurationChanged(Configuration newConfig)วิธีนี้ (ตามคำตอบนี้) แต่แทนที่จะจัดการด้วยตัวเองฉันตั้งค่าสถานะบูลีนแล้วเรียกrecreate()วิธีการนั้นเพื่อให้ Android สร้างกิจกรรมใหม่ตามแบบปกติ
มึนงง

ปัญหาอย่างหนึ่งของrecreate()วิธีการนี้คือทำให้หน้าจอกะพริบเป็นสีดำสั้น ๆ ด้วยเหตุนี้ฉันจึงใช้วิธีการอื่น: (1) บันทึกความกว้างของหน้าจอในonCreate(...), (2) เปรียบเทียบความกว้างของหน้าจอที่บันทึกไว้กับความกว้างของหน้าจอปัจจุบันในวิธีการใด ๆ ของวงจรชีวิตเมื่อกิจกรรมกำลังยุติ (เช่นonSaveInstanceState(...))
มึนงง

13

แค่อยากจะแสดงวิธีบันทึก Bundle ทั้งหมดของคุณหลังจาก onConfigurationChanged:

สร้าง Bundle ใหม่หลังชั้นเรียนของคุณ:

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

ถัดไปหลังจาก "โมฆะป้องกัน 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");
}

หากคุณเพิ่มคลาส crated ทั้งหมดของคุณลงใน MainActivity จะถูกบันทึก

แต่วิธีที่ดีที่สุดคือเพิ่มสิ่งนี้ใน AndroidManifest ของคุณ:

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

7
นี่เป็นความเข้าใจผิด การติดตั้งonConfigurationChanged()ทำให้อินสแตนซ์ของคุณไม่ถูกทำลายเมื่อการวางแนวเปลี่ยนไปคุณจึงไม่ต้องบันทึก คุณอาจต้องการบันทึกไว้สำหรับเหตุการณ์อื่น ๆ ในวงจรชีวิตของกิจกรรม แต่ฉันไม่รู้
izzy

5

ใช้วิธีนี้

@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>

2

แทนที่เมธอดของกิจกรรมonConfigurationChanged


ฉันอยากจะชี้ให้เห็นว่าหากไม่มีบรรทัดต่อไปนี้ภายในแท็ก <activity> ในรายการการเรียกกลับ onConfigurationChanged () จะไม่ถูกทริกเกอร์ด้วยซ้ำ android: configChanges = "orientation"
Sreekanth Karumanaghat

1

ฉันแค่ต้องการเสนอทางเลือกอื่นที่จะเกี่ยวข้องกับคุณบางคนตามที่อธิบายไว้ข้างต้น:

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();
    }

ที่นี่เราจะแสดงหรือไม่แสดงแถบการทำงานขึ้นอยู่กับการวางแนวของโทรศัพท์


0

สร้างอินสแตนซ์ของOrientationEventListenerคลาสและเปิดใช้งาน

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

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

2
กรุณาอย่าทำลายคำตอบของคุณ หากต้องการลบออกคุณจะพบปุ่มลบที่ด้านล่างซ้ายของคำตอบ
CalvT

0

หากคำตอบที่ยอมรับไม่ได้ผลสำหรับคุณตรวจสอบให้แน่ใจว่าคุณไม่ได้กำหนดในไฟล์รายการ:

android:screenOrientation="portrait"

ซึ่งเป็นกรณีของฉัน


0

ในกรณีที่ใช้กับ dev รุ่นใหม่ ๆ เนื่องจากไม่ได้ระบุไว้ข้างต้น เพื่อให้ชัดเจนมาก:

คุณต้องมีสองสิ่งหากใช้onConfigurationChanged :

  1. onConfigurationChangedวิธีการในกิจกรรมการเรียนของคุณ

  2. ระบุในรายการของคุณว่าวิธีการของคุณจะจัดการการเปลี่ยนแปลงการกำหนดค่าใดonConfigurationChanged

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

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

ในรายการไฟล์ Manifest ด้านบนมีการดำเนินการต่างๆของ Android สำหรับ android:configChanges=""ที่สามารถทริกเกอร์ onCreate ในวงจรชีวิตกิจกรรมของคุณ

สิ่งนี้สำคัญมาก - สิ่งที่ไม่ได้ระบุไว้ในรายการคือสิ่งที่เรียกใช้ onCreate ของคุณและสิ่งที่ระบุในรายการคือสิ่งที่เรียกonConfigurationChangedใช้เมธอดของคุณของคุณในคลาสกิจกรรมของคุณ

ดังนั้นคุณต้องระบุว่าการเปลี่ยนแปลง config ใดที่คุณต้องจัดการด้วยตัวเอง สำหรับ 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ไม่ทำงาน คุณต้องใส่สิ่งที่เกี่ยวข้องทั้งหมดลงในไฟล์ Manifest ของคุณ

ฉันลงเอยด้วย 3 ที่เริ่มต้น onCreate จากนั้นฉันทดสอบบน S10 + และฉันยังคงได้รับ onCreate ดังนั้นฉันต้องทำแบบฝึกหัดการกำจัดของฉันอีกครั้งและฉันก็ต้องการไฟล์|screenSize. ดังนั้นทดสอบบนแพลตฟอร์มที่เลือก

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

ดังนั้นคำแนะนำของฉันแม้ว่าฉันจะแน่ใจว่ามีคนเจาะรูในสิ่งนี้:

  1. เพิ่มonConfigurationChangedวิธีการของคุณในชั้นเรียนกิจกรรมของคุณด้วย TOAST หรือ LOG เพื่อให้คุณสามารถดูได้ว่ามันทำงานเมื่อใด

  2. เพิ่มตัวเลือกการกำหนดค่าที่เป็นไปได้ทั้งหมดในรายการของคุณ

  3. ยืนยันว่าonConfigurationChangedวิธีการของคุณใช้ได้ผลโดยทดสอบแอปของคุณ

  4. ลบตัวเลือกการกำหนดค่าแต่ละรายการออกจากไฟล์รายการทีละรายการทดสอบแอปของคุณหลังจากแต่ละรายการ

  5. ทดสอบอุปกรณ์ต่างๆให้มากที่สุดเท่าที่จะทำได้

  6. อย่าคัดลอก / วางข้อมูลโค้ดของฉันด้านบนลงในไฟล์รายการของคุณ การอัปเดต Android จะเปลี่ยนรายการดังนั้นให้ใช้คำแนะนำ Android Studio ที่แสดงขึ้นเพื่อให้แน่ใจว่าคุณได้รับทั้งหมด

ฉันหวังว่านี่จะช่วยใครบางคนได้บ้าง

onConfigurationChangedวิธีการของฉันสำหรับข้อมูลด้านล่าง onConfigurationChangedถูกเรียกในวงจรชีวิตหลังจากการวางแนวใหม่พร้อมใช้งาน แต่ก่อนที่ UI จะถูกสร้างขึ้นใหม่ ดังนั้นครั้งแรกของฉันifในการตรวจสอบการวางแนวทำงานได้อย่างถูกต้องจากนั้นชั้นที่ 2 ซ้อนกัน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);
            }

        }
    }

0

สำหรับการใช้งาน 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")


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