java - दोहरी फलक वरीयता स्क्रीन के साथ मुद्दे




android android-fragments (2)

नीचे दिए गए कोड के पीछे मुख्य विचार प्रश्न में जुड़े कॉमन्सवेयर ब्लॉग एंट्री से आया है, इसलिए यह प्रासंगिक लगता है। मुझे विशेष रूप से एक अभिविन्यास परिवर्तन समस्या से निपटने के लिए अवधारणा का विस्तार करना पड़ा जो कि प्रश्न में से एक जैसा ही लगता है, इसलिए यहां उम्मीद है कि यह आपको एक शुरुआत देता है।

सेटिंग क्लास को ओरिएंटेशन इश्यू पर कोई असर नहीं होना चाहिए, लेकिन इसे स्पष्ट करने के लिए वैसे भी शामिल है।

मेरी कोड टिप्पणी के अनुसार, देखें कि checkNeedsResource में checkNeedsResource कॉल में मदद मिलेगी:

public class SettingsActivity
extends 
    PreferenceActivity
{

@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Show settings without headers for single pane or pre-Honeycomb. Make sure to check the
    // single pane or pre-Honeycomb condition again after orientation change.
    if (checkNeedsResource()) {
        MyApp app = (MyApp)getApplication();
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);
        Settings settings = new Settings();
        addPreferencesFromResource(R.xml.prefs_api);
        settings.setupPreference(findPreference(MyApp.KEY_USERNAME), prefs.getString(MyApp.KEY_USERNAME, null), true);
        settings.setupPreference(findPreference(MyApp.KEY_API_URL_ROOT), prefs.getString(MyApp.KEY_API_URL_ROOT, null), true);
        if (this.isHoneycomb) {
            // Do not delete this. We may yet have settings that only apply to Honeycomb or higher.
            //addPreferencesFromResource(R.xml.prefs_general);
        }
        addPreferencesFromResource(R.xml.prefs_about);
        settings.setupPreference(findPreference(MyApp.KEY_VERSION_NAME), app.getVersionName());
    }
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onBuildHeaders(List<Header> target) {
    super.onBuildHeaders(target);

    // This check will enable showing settings without headers for single pane or pre-Honeycomb. 
    if (!checkNeedsResource()) {
        loadHeadersFromResource(R.xml.pref_headers, target);
    }
}

private boolean checkNeedsResource() {
    // This check will enable showing settings without headers for single pane or pre-Honeycomb. 
    return (!this.isHoneycomb || onIsHidingHeaders() || !onIsMultiPane());
}

private boolean isHoneycomb = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB);

}

public class Settings {

public Settings() {
}

public void setupPreference(Preference pref, String summary, boolean setChangeListener) {
    if (pref != null) {
        if (summary != null) {
            pref.setSummary(summary);
        }

        pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

            @Override
            public boolean onPreferenceChange(Preference pref, Object newValue) {
                pref.setSummary(newValue.toString());
                return true;
            }

        });
    }
}

public void setupPreference(Preference pref, String summary) {
    setupPreference(pref, summary, false);
}

}

https://code.i-harness.com

मुसीबत
एक डिवाइस को एक-फलक पोर्ट्रेट से PreferenceScreen से दो-फलक परिदृश्य PreferenceScreen स्क्रीन पर PreferenceScreen , परिदृश्य को केवल एक-फलक के रूप में दिखाता है। हेडर स्क्रीन देखने पर नहीं होता है।

सेट अप
यह आईसीएस और केवल के लिए है। मेरे पास preference-headers जो preference-headers लोड करती है। प्रत्येक शीर्षलेख एक Fragment साथ लिंक करता है, जो बदले में एक PreferenceScreen स्क्रीन लोड करता है। मिल का सुंदर भाग

विवरण
सबकुछ ठीक से काम करता है जब तक मैंने देखा कि एंड्रॉइड केवल कुछ स्क्रीन के लिए दो-फलक के रूप में ऑटो-स्विच करेगा। कुछ शोध के बाद मैंने कॉमन्सवेयर पोस्ट से सीखा कि एंड्रॉइड केवल sw720dp के लिए ऐसा करेगा। अपशिष्ट की बिट अगर आप मुझसे पूछें क्योंकि कई डिवाइसों के डिफ में दो-पैन के लिए पर्याप्त जगह है। तो मैंने w600dp और ऊपर के लिए सही लौटने के लिए onIsMultiPane() विधि को ओवरराइड किया। एक आकर्षण की तरह काम किया .... थोड़े।

एक उपकरण दिया गया है जो चित्र में एकल-फलक दिखाएगा और परिदृश्य में दोहरी-फलक दिखाएगा; हेडर को चित्र में देखना और परिदृश्य में घूमना, ठीक काम करता है। हालांकि अगर कोई हेडर चुनता है और पोर्ट्रेट मोड में इसकी अगली स्क्रीन लोड करता है, तो लैंडस्केप पर घुमाएं, डिवाइस दोहरी-फलक पर स्विच करने के बजाए एकल-फलक रहेगा। यदि आप फिर हेडर स्क्रीन पर नेविगेट करते हैं, तो यह दोहरी-फलक लुक पर वापस आ जाएगा सिवाय इसके कि यह एक शीर्षलेख का चयन नहीं करेगा। नतीजतन विस्तृत फलक खाली रहता है।

क्या यह इरादा व्यवहार है? वैसे भी इसके आसपास काम करने के लिए? मैंने onIsHidingHeaders() पर भी ओवरराइड करने की कोशिश की लेकिन इससे सब कुछ एक खाली स्क्रीन दिखाने के लिए हुआ।

कोड
वरीयता गतिविधि:

public class SettingsActivity extends PreferenceActivity {
@Override
public void onBuildHeaders(List<Header> target) {
    super.onBuildHeaders(target);
    loadHeadersFromResource(R.xml.preference, target);
}

@Override
public boolean onIsMultiPane() {
    return getResources().getBoolean(R.bool.pref_prefer_dual_pane);
}
}


एक वरीयता हैडर फ्रैग:

public class ExpansionsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.pref_expansions);
}

public static ExpansionsFragment newInstance() {
    ExpansionsFragment frag = new ExpansionsFragment();

    return frag;
}
}

समस्या सुलझ गयी
यह सवाल कितना लोकप्रिय हो गया है, मैंने इस मुद्दे को फिर से देखने का फैसला किया और देखा कि क्या मुझे एक प्रस्ताव मिल सकता है ... और मैंने किया। चारों ओर एक अच्छा छोटा काम मिला जो दोहरी फलक के बजाए दिखाए गए एकल फलक को हल करता है और दोहरी फलक मोड में हेडर सुनिश्चित करना हमेशा पूर्व-चयनित होता है।

यदि आपको स्पष्टीकरण की परवाह नहीं है, तो आप बस कोड पर जा सकते हैं। यदि आपको आईसीएस की परवाह नहीं है, तो हेडर ट्रैकिंग कोड को हटाया जा सकता है क्योंकि जेबी ने हेडर एरे सूची के लिए गेटटर जोड़ा है।

दोहरी फलक अंक
एकल फलक मोड या दोहरी फलक मोड में वरीयता शीर्षलेख सूची को देखते समय, केवल एक प्राथमिकता उत्पन्न होती है और यह दोनों मामलों के लिए एक ही गतिविधि है। नतीजतन, स्क्रीन रोटेशन को संभालने में कोई समस्या नहीं है जो फलक मोड को स्विच करेगा।

हालांकि, जब आप हेडर पर क्लिक करते हैं तो एकल फलक मोड में, संबंधित खंड एक नई वरीयता सक्रियता से जुड़ा होता है। वरीयता onBuildHeaders() युक्त यह नया खंड कभी भी onBuildHeaders() नहीं onBuildHeaders() करता है। और यह क्यों होगा? इसे प्रदर्शित करने की आवश्यकता नहीं है। यह समस्या झूठ बोलता है।

उस खंड को दोहरी फलक मोड में घूर्णन करते समय, इसमें दिखाने के लिए कोई हेडर सूची नहीं है, इसलिए यह केवल खंड को दिखाना जारी रखता है। यहां तक ​​कि यदि यह हेडर की सूची दिखाता है, तो आपके पास कुछ बैकस्टैक समस्याएं होंगी क्योंकि अब आपके पास हेडर्स दिखाने वाली वरीयता सक्रियता की दो प्रतियां होंगी। पर्याप्त शीर्षलेखों पर क्लिक करना जारी रखें और उपयोगकर्ता को वापस नेविगेट करने के लिए गतिविधियों की काफी लंबी ढेर मिल जाएगी। नतीजतन, जवाब सरल है। बस गतिविधि finish() । इसके बाद वह मूल वरीयता सक्रियता लोड करेगा जिसमें शीर्षलेख सूची होगी और उचित रूप से दोहरी फलक मोड दिखाएगी।

ऑटो चयन हेडर
अगले मुद्दे को हल करने की आवश्यकता थी कि नए फिक्स के साथ एकल से दोहरी फलक मोड के बीच स्विचिंग ने हेडर का चयन नहीं किया था। आपको हेडर सूची के साथ छोड़ दिया गया था और कोई विवरण खंड लोड नहीं हुआ था। यह फिक्स काफी सरल नहीं है। असल में आपको केवल यह ट्रैक रखना होगा कि कौन सा शीर्षलेख पिछली बार क्लिक किया गया था और वरीयता सक्रियता निर्माण के दौरान सुनिश्चित किया गया था ... एक शीर्षलेख हमेशा चुना जाता है।

यह आईसीएस में थोड़ा परेशान होने के बाद समाप्त होता है क्योंकि एपीआई आंतरिक रूप से ट्रैक की गई शीर्षलेख सूची के लिए गेटटर का पर्दाफाश नहीं करता है। एंड्रॉइड पहले से ही उस सूची को जारी रखता है और आप तकनीकी रूप से उसी निजी रूप से संग्रहीत आंतरिक स्ट्रिंग कुंजी का उपयोग कर इसे पुनर्प्राप्त कर सकते हैं, हालांकि यह केवल एक खराब डिज़ाइन विकल्प है। इसके बजाए, मैं सुझाव देता हूं कि मैन्युअल रूप से इसे स्वयं जारी रखें।

यदि आपको आईसीएस की परवाह नहीं है, तो आप केवल जेबी में प्राप्त getHeaders() विधि का उपयोग कर सकते हैं और getHeaders() किसी भी सहेजे गए / पुनर्स्थापित राज्य सामग्री के बारे में चिंता न करें।

कोड

public class SettingsActivity extends PreferenceActivity {
private static final String STATE_CUR_HEADER_POS = "Current Position";
private static final String STATE_HEADERS_LIST   = "Headers List";

private int mCurPos = AdapterView.INVALID_POSITION;  //Manually track selected header position for dual pane mode
private ArrayList<Header> mHeaders;  //Manually track headers so we can select one. Required to support ICS.  Otherwise JB exposes a getter instead.

@Override
public void onBuildHeaders(List<Header> target) {
    loadHeadersFromResource(R.xml.preference, target);
    mHeaders = (ArrayList<Header>) target;  //Grab a ref of the headers list
}

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

    //This is the only code required for ensuring a dual pane mode shows after rotation of a single paned preference screen
    if (onIsMultiPane() && onIsHidingHeaders()) {
        finish();
    }
}

@Override
public boolean onIsMultiPane() {
    //Override this if you want dual pane to show up on smaller screens
    return getResources().getBoolean(R.bool.pref_prefer_dual_pane);
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    //Intercept a header click event to record its position.
    mCurPos = position;
}

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

    //Retrieve our saved header list and last clicked position and ensure we switch to the proper header.
    mHeaders = state.getParcelableArrayList(STATE_HEADERS_LIST);
    mCurPos = state.getInt(STATE_CUR_HEADER_POS);
    if (mHeaders != null) {
        if (mCurPos != AdapterView.INVALID_POSITION) {
            switchToHeader(mHeaders.get(mCurPos));
        } else {
            switchToHeader(onGetInitialHeader());
        }
    }
}

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

    //Persist our list and last clicked position
    if (mHeaders != null && mHeaders.size() > 0) {
        outState.putInt(STATE_CUR_HEADER_POS, mCurPos);
        outState.putParcelableArrayList(STATE_HEADERS_LIST, mHeaders);
    }
}
}




preferenceactivity