एंड्रॉइड: टैबलेट के लिए पोर्ट्रेट और परिदृश्य की अनुमति दें, लेकिन फोन पर पोर्ट्रेट को मजबूर करें?


191

मैं चित्र और परिदृश्य (sw600dp या अधिक) में प्रदर्शित करने में सक्षम होने के लिए गोलियाँ चाहूंगा, लेकिन फ़ोन केवल चित्र तक ही सीमित रहेंगे। मुझे सशर्त रूप से अभिविन्यास चुनने का कोई तरीका नहीं मिल रहा है। कोई सुझाव?


एक तरह से फोन के लिए परिदृश्य लेआउट डिजाइन करने के लिए नहीं होगा, जैसा कि layout-landअंदर resफ़ोल्डर का उपयोग करके ।
भूत

12
यह केवल परिदृश्य में दिखाने के लिए चित्र लेआउट का कारण होगा। यह वास्तव में एक फोन को परिदृश्य से घूमने से नहीं रोक सकेगा।
राडली

जवाबों:


446

यहां संसाधनों और आकार क्वालिफायर का उपयोग करने का एक अच्छा तरीका है ।

इस बूल संसाधन को bools.xml या जो भी (फ़ाइल नाम यहाँ कोई फर्क नहीं पड़ता) के रूप में रेस / मान में रखें:

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

इस एक को Res / मान-sw600dp और res / मान-xlarge में रखें:

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

एंड्रॉइड स्टूडियो में इन निर्देशिकाओं और फ़ाइलों को जोड़ने में मदद के लिए यह पूरक उत्तर देखें ।

फिर, अपनी गतिविधियों के चालू तरीके से आप यह कर सकते हैं:

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

डिवाइस जो कि छोटी चौड़ाई की दिशा में 600 डीपी से अधिक हैं, या प्री-एंड्रॉइड 3.2 डिवाइस (टैबलेट, मूल रूप से) पर एक्स-लार्ज, सेंसर और उपयोगकर्ता-लॉक किए गए रोटेशन के आधार पर , सामान्य की तरह व्यवहार करेंगे । बाकी सब कुछ (फोन, बहुत ज्यादा) केवल चित्र होगा।


1
क्या मुझे xlargeभी उपयोग करने की आवश्यकता है या क्या मैं अभी उपयोग कर सकता हूं sw600dp? शायद इन दिनों <3.2 पर चलने वाली कोई भी टैबलेट नहीं है।
दिबांग

7
परिदृश्य में शुरू होने पर, यह संभावित रूप से गतिविधि को फिर से शुरू करता है, डेवलपर
।android.com

1
@ बोंडैक्स यह टिप्पणी केवल "यदि गतिविधि वर्तमान में अग्रभूमि में है या अन्यथा स्क्रीन अभिविन्यास को प्रभावित करती है" लागू होती है जो कि इस बिंदु पर चालू होने के बाद से नहीं हो सकती है।
ब्रायन क्रिस्टेंसन

1
@BrianChristensen मैंने अनुरोध किया कि जब किसी गतिविधि को फिर से शुरू किया जाए, जिसमें अनुरोध किया गया हो onCreate()। जब मैंने कॉल को setRequestedOrientation()समय और संदर्भ में एक अलग स्थिति में ले जाया , तो पुनरारंभ किसी भी अधिक नहीं हुआ।
बॉन्डैक्स

8
यदि मैं लैंडस्केप मोड में ऐप शुरू करता हूं, तो यह अभी भी कुछ पल के लिए लैंडस्केप मोड दिखाता है।
最 最

29

आप इस तरह से कोशिश कर सकते हैं कि पहले डिवाइस का स्क्रीन साइज प्राप्त कर लें

if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {     
    Toast.makeText(this, "Large screen",Toast.LENGTH_LONG).show();

}
else if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {     
    Toast.makeText(this, "Normal sized screen" , Toast.LENGTH_LONG).show();

} 
else if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {     
    Toast.makeText(this, "Small sized screen" , Toast.LENGTH_LONG).show();
}
else {
    Toast.makeText(this, "Screen size is neither large, normal or small" , Toast.LENGTH_LONG).show();
}

और फिर उसी के अनुसार अभिविन्यास निर्धारित करें

setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

4
मुझे किस विधि को सेटिस्क्राइस्ड ऑर्डिनेशन () विधि डालनी चाहिए? एक बार ऑनक्रिएट शुरू हो जाने के बाद, यह पहले ही चुन चुका है कि इसे कौन सा ओरिएंटेशन चाहिए।
केनी वायलैंड

केनी यह जाँच करें मुझे लगता है कि यह आपकी मदद कर सकता है stackoverflow.com/questions/2833474/…
Avi Kumar Manku

मैं देख रहा हूं कि यह उत्तर अप-डाउन किया गया था, लेकिन मुझे यकीन नहीं है कि यह इस मुद्दे को हल करता है। जानकारी Configurationप्रदान करता screenLayoutहै - डीपीआई। जबकि सवाल भौतिक डिवाइस स्क्रीन आकार - फोन वीएस टैबलेट से संबंधित है। मतलब, आपके पास एक हो सकता है Configuration.SCREENLAYOUT_SIZE_NORMALऔर यह एक एमडीपीआई टैबलेट होगा।
रात्रि का उपरांत


10

स्वीकृत उत्तर के लिए अनुपूरक

आप अपनी फ़ाइलों के साथ res/values-sw600dpऔर res/values-largeनिर्देशिकाओं को जोड़ने के लिए एंड्रॉइड स्टूडियो में निम्न चरण कर सकते हैं bools.xml

मान-sw600dp

सबसे पहले, प्रोजेक्ट टैब से नेविगेटर में प्रोजेक्ट (एंड्रॉइड के बजाय) फ़िल्टर का चयन करें।

यहां छवि विवरण दर्ज करें

फिर app/src/main/resडायरेक्टरी पर राइट क्लिक करें । नया > Android संसाधन निर्देशिका चुनें ।

छोटी स्क्रीन चौड़ाई का चयन करें , और फिर >> बटन दबाएँ।

यहां छवि विवरण दर्ज करें

600छोटी स्क्रीन चौड़ाई के लिए टाइप करें । निर्देशिका नाम अपने आप उत्पन्न हो जाएगा। ठीक है बोलो।

यहां छवि विवरण दर्ज करें

फिर नई बनी values-sw600dpफाइल पर राइट क्लिक करें । नया > मान संसाधन फ़ाइल चुनें । boolsनाम के लिए टाइप करें।

मान-बड़े

values-largeनिर्देशिका जोड़ना केवल तभी आवश्यक है जब आप पूर्व Android 3.2 (API स्तर 13) का समर्थन कर रहे हों। अन्यथा आप इस चरण को छोड़ सकते हैं। values-largeनिर्देशिका से मेल खाती है values-sw600dp। (से values-xlargeमेल खाती है values-sw720dp।)

values-largeनिर्देशिका बनाने के लिए , ऊपर दिए गए समान चरणों का पालन करें, लेकिन इस मामले में लघु स्क्रीन चौड़ाई के बजाय आकार चुनें । बड़े का चयन करें । निर्देशिका नाम अपने आप उत्पन्न हो जाएगा।

यहां छवि विवरण दर्ज करें

bools.xmlफ़ाइल बनाने से पहले डायरेक्टरी पर राइट क्लिक करें ।


2
मुझे पता है अगर यह काम नहीं करता है और मैं इसे ठीक कर दूँगा। इसने मेरे लिए काम किया। मुझे एक डाउनवोट मिला, लेकिन कोई टिप्पणी नहीं, इसलिए मुझे नहीं पता कि क्या ठीक करना है।
सुरगाछ Sur

9

यहाँ मैंने यह कैसे किया ( 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;
} 

और: (यदि आप इस विधि को ओवरराइड नहीं करते हैं, तो ऐप ऑनक्रीट को कॉल करेगा) (जब ओरिएंटेशन बदलते हैं)

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

केवल एक चीज जो मैं समझ नहीं पा रहा हूं वह यह है कि लैंडस्केप से पोर्ट्रेट या स्विच करने के दौरान लेआउट फाइलों को बदलने के लिए ऐप कैसे प्राप्त करें। मुझे लगता है कि उत्तर कुछ ऐसा ही कर रहा है जो उपरोक्त लिंक करता है, लेकिन मुझे वह काम नहीं मिला जो मेरे लिए काम करता है - इसने मेरे सभी डेटा को हटा दिया। लेकिन अगर आपके पास एक सरल पर्याप्त ऐप है जो आपके पास चित्र और परिदृश्य के लिए एक ही लेआउट फ़ाइल है, तो यह काम करना चाहिए।


2
लैंडस्केप लेआउट को अपने लेआउट-लैंड फ़ोल्डर में रखें
राडली

यदि आप सुपर onConfigurationChanged नहीं बुलाते हैं तो आपको एक अपवाद मिलेगा
RominaV

8

गिन्नी के जवाब के बाद , मुझे लगता है कि ऐसा करने का सबसे विश्वसनीय तरीका इस प्रकार है:

जैसा कि यहां बताया गया है , संसाधनों में एक बूलियन sw600dp डालें। इसमें उपसर्ग sw होना चाहिए अन्यथा यह ठीक से काम नहीं करेगा:

Res / मानों में- sw600dp / dimens.xml

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

Res / मान / 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, तो आपको अपने AndroidManifest.xml में android:configChanges="orientation|screenSize"प्रत्येक पंक्ति को जोड़ना होगा Activity:

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

5

खैर, यह थोड़ा देर से है लेकिन, यहां एक एक्सएमएल-ओनली है लेकिन एक हैक समाधान जो एक गतिविधि को फिर से नहीं setRequestedOrientationकरता है जैसे कि अभिविन्यास बदलना है:

https://stackoverflow.com/a/27015879/1281930


1
काम नहीं करता है, गोलियाँ हमेशा फोन का उन्मुखीकरण लेती हैं। जाहिर तौर पर Android: स्क्रीनऑरिएशन किसी भी संसाधन संशोधक को लागू करने से पहले, प्रकट में सभी गतिविधियों के लिए एक बार सेट किया गया है।
0101100101

2

स्वीकृत उत्तर के बाद , मैं कोटलिन फ़ाइल को इस उम्मीद के साथ जोड़ रहा हूं कि यह किसी की मदद करे

इस बूल संसाधन res/valuesको बूलसेक्लेम या जो भी (फ़ाइल नाम यहां कोई फर्क नहीं पड़ता) के रूप में डालें :

<?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)
    }
}

1

अन्य समाधान मेरे काम नहीं आए। मुझे अभी भी संवाद और मनोरंजन के मुद्दों के साथ कुछ अजीब अभिविन्यास समस्या थी। मेरा समाधान गतिविधि का विस्तार करना था, इसे प्रकट रूप में चित्र के रूप में मजबूर करना।

उदाहरण:

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

0

पुराना सवाल जो मैं जानता हूं। अपने एप्लिकेशन को हमेशा पोर्ट्रेट मोड में चलाने के लिए, यहां तक ​​कि जब अभिविन्यास हो सकता है या स्वैप किया जा सकता है आदि (उदाहरण के लिए टैबलेट पर) मैंने इस फ़ंक्शन को डिज़ाइन किया है जो कि पोर्ट्रेट और परिदृश्य को जानने की आवश्यकता के बिना डिवाइस को सही अभिविन्यास में सेट करने के लिए उपयोग किया जाता है। डिवाइस पर सुविधाओं का आयोजन किया जाता है।

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

यदि आप इसके विपरीत करना चाहते हैं, तो आपको कोड को परिदृश्य में बदलना होगा (लेकिन मुझे लगता है कि यह स्पष्ट है कि यह कैसे करना है)।


0

दुर्भाग्य से, विधि setRequestedOrientation (...) का उपयोग करने से गतिविधि फिर से शुरू हो जाएगी, इसलिए भले ही आप ऑनक्रिट विधि में इसे कॉल करते हैं, यह गतिविधि जीवनचक्र के माध्यम से जाएगा और फिर यह अनुरोधित अभिविन्यास में उसी गतिविधि को फिर से करेगा। तो @ ब्रायन क्रिस्टेंसन के जवाब पर आपको विचार करना चाहिए कि गतिविधि कोड को दो बार कहा जा सकता है, इसके बुरे प्रभाव हो सकते हैं (न केवल दृश्य, बल्कि नेटवर्क अनुरोध, विश्लेषिकी आदि पर भी)।

इसके अलावा, मैन्‍युफैक्‍चर की विशेषता को प्रकट करने के लिए सेट करना मेरी राय में एक बड़ा ट्रेड-ऑफ है, जो बड़े पैमाने पर रिफैक्‍टरिंग लागत ले सकता है। Android देवता उस विशेषता को बदलने की अनुशंसा नहीं कर रहे हैं

अंत में, स्क्रीनऑरिएशन को किसी भी तरह से अलग करने की कोशिश करना (पुनः आरंभ करने की समस्या से बचने के लिए) असंभव है, स्टेटिक मैनिफ़ेस्ट के कारण स्टेटिक रूप से असंभव है जिसे परिवर्तित नहीं किया जा सकता है, प्रोग्रामेटिक रूप से पहले से शुरू की गई गतिविधि में उस पद्धति को कॉल करना संभव है।

सारांश: मेरी राय में, @ ब्रायन क्रिस्टेंसन सुझाव सबसे अच्छा व्यापार-बंद है, लेकिन गतिविधि के फिर से शुरू होने के बारे में पता होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.