सहायता लाइब्रेरी से ऐक्शन लाइब्रेरी को प्राथमिकता में कैसे जोड़ें?


128

एक्शन बार संगतता को समर्थन लाइब्रेरी में जोड़ा गया है, संशोधन 18. अब इसमें ActionBarActivityएंड्रॉइड के पुराने संस्करणों पर एक्शन बार के साथ गतिविधियां बनाने के लिए क्लास है।

क्या समर्थन पुस्तकालय से एक्शन बार को जोड़ने का कोई तरीका है PreferenceActivity?

पहले मैं इस्तेमाल करता था ActionBarSherlock का और यह है SherlockPreferenceActivity



1
मैंने अभी-अभी अपना उत्तर संपादित किया, एक्शनबेरक्टिविटी के साथ काम करने वाले सपोर्ट-वी 4 के आधार पर एक वर्किंग प्रायरफ्रैगमेंट कार्यान्वयन पाया। मैं खुद से इसका इस्तेमाल कर रहा हूं।
ओस्टकंटेंटिटन

यदि आप चाहें, तो आप मेरे समाधान का उपयोग कर सकते हैं: github.com/AndroidDeveloperLB/MaterialStuffLibrary
Android डेवलपर

जवाबों:


128

EDIT: Appcompat-v7 22.1.0 में Google ने AppCompatDelegate अमूर्त वर्ग को एक प्रतिनिधि के रूप में जोड़ा, जिसका उपयोग आप किसी भी गतिविधि के लिए AppCompat के समर्थन को बढ़ाने के लिए कर सकते हैं।

इसे इस तरह उपयोग करें:

...
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
...

public class SettingsActivity extends PreferenceActivity {

    private AppCompatDelegate mDelegate;

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

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        getDelegate().onPostCreate(savedInstanceState);
    }

    public ActionBar getSupportActionBar() {
        return getDelegate().getSupportActionBar();
    }

    public void setSupportActionBar(@Nullable Toolbar toolbar) {
        getDelegate().setSupportActionBar(toolbar);
    }

    @Override
    public MenuInflater getMenuInflater() {
        return getDelegate().getMenuInflater();
    }

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        getDelegate().setContentView(layoutResID);
    }

    @Override
    public void setContentView(View view) {
        getDelegate().setContentView(view);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        getDelegate().setContentView(view, params);
    }

    @Override
    public void addContentView(View view, ViewGroup.LayoutParams params) {
        getDelegate().addContentView(view, params);
    }

    @Override
    protected void onPostResume() {
        super.onPostResume();
        getDelegate().onPostResume();
    }

    @Override
    protected void onTitleChanged(CharSequence title, int color) {
        super.onTitleChanged(title, color);
        getDelegate().setTitle(title);
    }

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

    @Override
    protected void onStop() {
        super.onStop();
        getDelegate().onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getDelegate().onDestroy();
    }

    public void invalidateOptionsMenu() {
        getDelegate().invalidateOptionsMenu();
    }

    private AppCompatDelegate getDelegate() {
        if (mDelegate == null) {
            mDelegate = AppCompatDelegate.create(this, null);
        }
        return mDelegate;
    }
}

कोई और हैकिंग नहीं। AppCompatPreferenceActivity.java से लिया गया कोड ।


कृपया अपने उत्तर में अपने आवश्यक कोड स्निपेट डालें। संभावित टूटी लिंक समस्या से बचने के लिए।
योहन खोसियावान o

धन्यवाद, यह मेरे लिए काम करता है - मैं पहली (ViewGroup) getWindow().getDecorView().getRootView()
फुर्तीली

2
@petrsyn यह वास्तव में काम करता है। देखो यहाँ और यहाँ पता लगाने के लिए आप इसे कैसे करना चाहिए।
लुबोमिर Kučera

1
@swooby आप इस बग से पीड़ित हो सकते हैं ।
लुबोमिर Kučera

1
ठीक है, तो मैं xml में टूलबार कहां रखूं? मैं एक NullPointerException
मार्टिन Erlic

78

वर्तमान में AppCompat के साथ हासिल करने का कोई तरीका नहीं है। मैंने आंतरिक रूप से एक बग खोला है।


6
धन्यवाद @ क्रिस। इस सुविधा के लिए अच्छा होगा।
पाब्लो

12
@ क्रिस, क्या आपके पास कोई विचार है जब हम PreferenceActivityइसमें जोड़े जाने की उम्मीद कर सकते हैं ActionBarCompat?
imbryk

3
मुझे लगता है कि यह संभावना नहीं है कि यह सुविधा लागू होने जा रही है। एंड्रॉइड के पुराने संस्करणों को चलाने वाले उपकरणों की संख्या (<4.0) इस बिंदु पर 30% से कम है, और यह संख्या हर महीने कम हो रही है।
रोमन

1
यह लगभग एक साल पहले दर्ज किया गया था और कोई संकल्प नहीं ??
किसी ने

1
wtf अभी भी इंतज़ार कर रहा है ??
ब्रुक

24

मैंने Google Play Store के उपयोग के समान वर्कअराउंड बनाने में कामयाबी हासिल की है। मूल उत्तर के लिए लिंक

कृपया GitHub रेपो: यहां देखें


अपने स्वयं के कोड के समान लेकिन सेट शीर्षक के लिए अनुमति देने के लिए xml जोड़ा गया:

उपयोग करने के लिए जारी PreferenceActivity:

settings_toolbar.xml :

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    app:navigationContentDescription="@string/abc_action_bar_up_description"
    android:background="?attr/colorPrimary"
    app:navigationIcon="?attr/homeAsUpIndicator"
    app:title="@string/action_settings"
    />

SettingsActivity.java :

public class SettingsActivity extends PreferenceActivity {

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

        LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
        Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
        root.addView(bar, 0); // insert at top
        bar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }

}

Result :

उदाहरण


अद्यतन (जिंजरब्रेड संगतता):

जैसा कि यहां बताया गया है , जिंजरब्रेड डिवाइसेस इस लाइन पर NullPointerException लौटा रही हैं:

LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();

ठीक कर:

SettingsActivity.java :

public class SettingsActivity extends PreferenceActivity {

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        Toolbar bar;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent();
            bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
            root.addView(bar, 0); // insert at top
        } else {
            ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
            ListView content = (ListView) root.getChildAt(0);

            root.removeAllViews();

            bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
            

            int height;
            TypedValue tv = new TypedValue();
            if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
                height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
            }else{
                height = bar.getHeight();
            }

            content.setPadding(0, height, 0, 0);

            root.addView(content);
            root.addView(bar);
        }

        bar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
}

उपरोक्त मुद्दों के साथ कोई भी समस्या मुझे बताएं!


अद्यतन 2: टंकण कार्य

जैसा कि कई देव नोटों में बताया गया है PreferenceActivity तत्वों की टिनिंग का समर्थन नहीं करता है, हालांकि कुछ आंतरिक वर्गों का उपयोग करके आप इसे प्राप्त कर सकते हैं। यह तब तक है जब तक इन वर्गों को हटा नहीं दिया जाता है। (AppCompat support-v7 v21.0.3 का उपयोग कर काम करता है)।

निम्नलिखित आयात जोड़ें:

import android.support.v7.internal.widget.TintCheckBox;
import android.support.v7.internal.widget.TintCheckedTextView;
import android.support.v7.internal.widget.TintEditText;
import android.support.v7.internal.widget.TintRadioButton;
import android.support.v7.internal.widget.TintSpinner;

फिर onCreateViewविधि को ओवरराइड करें :

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    // Allow super to try and create a view first
    final View result = super.onCreateView(name, context, attrs);
    if (result != null) {
        return result;
    }

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        // If we're running pre-L, we need to 'inject' our tint aware Views in place of the
        // standard framework versions
        switch (name) {
            case "EditText":
                return new TintEditText(this, attrs);
            case "Spinner":
                return new TintSpinner(this, attrs);
            case "CheckBox":
                return new TintCheckBox(this, attrs);
            case "RadioButton":
                return new TintRadioButton(this, attrs);
            case "CheckedTextView":
                return new TintCheckedTextView(this, attrs);
        }
    }

    return null;
}

Result:

उदाहरण 2


AppCompat 22.1

AppCompat 22.1 ने नए रंग वाले तत्व पेश किए, जिसका अर्थ है कि अंतिम अद्यतन के समान प्रभाव प्राप्त करने के लिए आंतरिक कक्षाओं का उपयोग करने की आवश्यकता नहीं है। इसके बजाय इसका अनुसरण करें (अभी भी ओवरराइड कर रहे हैं onCreateView):

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    // Allow super to try and create a view first
    final View result = super.onCreateView(name, context, attrs);
    if (result != null) {
        return result;
    }

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        // If we're running pre-L, we need to 'inject' our tint aware Views in place of the
        // standard framework versions
        switch (name) {
            case "EditText":
                return new AppCompatEditText(this, attrs);
            case "Spinner":
                return new AppCompatSpinner(this, attrs);
            case "CheckBox":
                return new AppCompatCheckBox(this, attrs);
            case "RadioButton":
                return new AppCompatRadioButton(this, attrs);
            case "CheckedTextView":
                return new AppCompatCheckedTextView(this, attrs);
        }
    }

    return null;
}

NESTED PREFERENCE SCREENS

बहुत से लोग नेस्टेड <PreferenceScreen />एस में टूलबार सहित मुद्दों का सामना कर रहे हैं , हालांकि, मुझे एक समाधान मिल गया है !! - बहुत परीक्षण और त्रुटि के बाद!

निम्नलिखित को अपने में जोड़ें SettingsActivity:

@SuppressWarnings("deprecation")
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
    super.onPreferenceTreeClick(preferenceScreen, preference);

    // If the user has clicked on a preference screen, set up the screen
    if (preference instanceof PreferenceScreen) {
        setUpNestedScreen((PreferenceScreen) preference);
    }

    return false;
}

public void setUpNestedScreen(PreferenceScreen preferenceScreen) {
    final Dialog dialog = preferenceScreen.getDialog();

    Toolbar bar;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        LinearLayout root = (LinearLayout) dialog.findViewById(android.R.id.list).getParent();
        bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
        root.addView(bar, 0); // insert at top
    } else {
        ViewGroup root = (ViewGroup) dialog.findViewById(android.R.id.content);
        ListView content = (ListView) root.getChildAt(0);

        root.removeAllViews();

        bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);

        int height;
        TypedValue tv = new TypedValue();
        if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
            height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
        }else{
            height = bar.getHeight();
        }

        content.setPadding(0, height, 0, 0);

        root.addView(content);
        root.addView(bar);
    }

    bar.setTitle(preferenceScreen.getTitle());

    bar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dialog.dismiss();
        }
    });
}

कारण यह है कि PreferenceScreenइस तरह के एक दर्द है क्योंकि वे एक आवरण संवाद के रूप में आधारित हैं, इसलिए हमें टूलबार को इसमें जोड़ने के लिए संवाद लेआउट पर कब्जा करने की आवश्यकता है।


टूलबार छाया

डिजाइन के द्वारा आयात Toolbarपूर्व -21 उपकरणों में ऊंचाई और छाया देने की अनुमति नहीं देता है, इसलिए यदि आप अपने ऊपर ऊंचाई रखना चाहते हैं तो Toolbarआपको इसे इसमें लपेटने की आवश्यकता है AppBarLayout:

`settings_toolbar.xml:

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

   <android.support.v7.widget.Toolbar
       .../>

</android.support.design.widget.AppBarLayout>

build.gradleफ़ाइल में निर्भरता के रूप में डिज़ाइन समर्थन लाइब्रेरी को जोड़ना न भूलें :

compile 'com.android.support:support-v4:22.2.0'
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:design:22.2.0'

Android 6.0

मैंने रिपोर्ट की गई ओवरलैपिंग समस्या की जांच की है और मैं इस मुद्दे को पुन: पेश नहीं कर सकता।

उपरोक्त के रूप में उपयोग में पूर्ण कोड निम्नलिखित उत्पन्न करता है:

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

अगर मुझे कुछ याद आ रहा है तो कृपया मुझे इस रेपो के माध्यम से बताएं और मैं जांच करूंगा।


1
महान! एक आकर्षण की तरह काम करता है :)
तोबी

यह नेस्टेड स्क्रीनस्क्रीन के लिए काम क्यों नहीं करता है, लेकिन केवल मुख्य स्क्रीनस्क्रीन के लिए?
तोबी

@ तोबी ने नेस्टेड मुद्दे को हल करने के लिए अपना जवाब अपडेट किया है, और बताया है कि क्यों। :)
डेविड पासमोर

धन्यवाद! आपकी सलाह "AppCompat 22.1" ने मेरे लिए चाल चली :) बहुत उपयोगी!
मार्टिन फ़ेफ़र

1
PreferenceActivity गांड में इतना दर्द क्यों होता है उपयोग करने के लिए ??? यह समय बचाने के लिए माना जाता है। मैं एक नियमित गतिविधि कर सकता हूं और स्वयं एक रैखिक लेआउट में सभी सेटिंग्स को मैन्युअल रूप से ले सकता हूं। फुकुअक!
किसी ने

12

समर्थन-वी 4 फ़्रैगमेंट के आधार पर एक वरीयता-प्राप्त कार्यान्वयन मिला:

https://github.com/kolavar/android-support-v4-preferencefragment

संपादित करें: मैंने अभी-अभी इसका परीक्षण किया है और यह बहुत अच्छा है


@Konstantin, क्या आप कुछ कोड उदाहरण जोड़ सकते हैं? मैंने इसे डाउनलोड किया, android.preference.PreferenceFragment से android.support.v4.preference.PreferenceFragment में आयात को बदल दिया, और मुझे लगता है कि यह स्क्रीन के बीच में कुछ हेडर जोड़े, लेकिन शीर्ष पर एक्शनबार नहीं
Gavriel

यह एक्शनबार को गतिविधि के कार्य को जोड़ता नहीं है। दुर्भाग्य से मेरे पास हाथ में कोई नमूना नहीं है, लेकिन यह इसी तरह काम करना चाहिए: developer.android.com/reference/android/preference/…
Ostkontentitan

3

घालमेल PreferenceActivityएबीसी के साथ संभव नहीं है, कम से कम मेरे लिए। मैंने उन दो संभावनाओं की कोशिश की जिन्हें मैं पा सकता था लेकिन कोई भी काम नहीं किया:

विकल्प 1:

ActionBarPreferenceActivityफैली हुई है PreferenceActivity। जब आप ऐसा करते हैं तो आप प्रतिबंधित हो जाते हैं ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)। साथ ही आपको लागू करने की आवश्यकता हैActionBar.Callbacks जो सुलभ नहीं है

विकल्प 2:

ActionBarPreferenceActivityफैली हुई है ActionBarActivity। इस दृष्टिकोण को पूरी तरह से नए सिरे से लिखने की आवश्यकता होती है PreferenceActivity, PreferenceManagerऔर PreferenceFragmentइसका मतलब हो सकता है कि आपको छिपी हुई कक्षाओं तक पहुंच की आवश्यकता है जैसे कि com.android.internal.util.XmlUtils इसका समाधान केवल Google देवों से आ ActionBarWrapperसकता है जिसे लागू करना किसी भी गतिविधि में जोड़ा जा सकता है।

यदि आपको वास्तव में वरीयता गतिविधि की आवश्यकता है, तो अभी के लिए मेरी सलाह है ActionBarSherlock

हालांकि, मैं इसे यहां लागू करने में कामयाब रहा ।


1
Per4.0 दुर्घटना लाता है। मैंने इसे कांटा और सुधार किया। gist.github.com/0e9fe2119b901921b160
TeeTracker

मेरे समाधान की जाँच करें। यह किसी भी तरीके का उपयोग नहीं करता है stackoverflow.com/a/25603448/1276636
Sufian

इससे कुछ हल नहीं होता! आशा है कि आप इस मुद्दे को हाथ से समझेंगे
मैक्सवेल वीरू

3

समस्या पृष्ठभूमि:

ओपी पता है कि कैसे हम डाल सकते हैं चाहता है MenuItemमें ActionBarसेPreferenceActivity पूर्व हनीकोम्ब के लिए है क्योंकि Android के समर्थन पुस्तकालय एक बग जो ऐसा करने की अनुमति नहीं है।

मेरा समाधान:

मैंने लक्ष्य प्राप्त करने के लिए (पहले से प्रस्तावित एंड्रॉइड डॉक्स में पाया गया ) की तुलना में बहुत अधिक स्वच्छ तरीका पाया है।

android:parentActivityName

गतिविधि के तार्किक जनक का वर्ग नाम। यहां नाम संबंधित तत्व के Android को दिए गए वर्ग के नाम से मेल खाना चाहिए: नाम विशेषता।

सिस्टम इस विशेषता को यह निर्धारित करने के लिए पढ़ता है कि जब एक्शन बार में अप बटन दबाया जाए तो कौन सी गतिविधि शुरू होनी चाहिए। सिस्टम इस जानकारी का उपयोग टास्कस्टैकबर्स्टल के साथ गतिविधियों के बैक स्टैक को संश्लेषित करने के लिए भी कर सकता है।

एपीआई स्तर 4 - 16 का समर्थन करने के लिए, आप उस तत्व के साथ मूल गतिविधि भी घोषित कर सकते हैं जो "android.support.PARENT_ACTIVITY" के लिए एक मान निर्दिष्ट करता है। उदाहरण के लिए:

<activity
    android:name="com.example.app.ChildActivity"
    android:label="@string/title_child_activity"
    android:parentActivityName="com.example.myfirstapp.MainActivity" >
    <!-- Parent activity meta-data to support API level 4+ -->
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.app.MainActivity" />
</activity>

अब वह करो जो तुम सामान्य रूप से अपने में करोगे onOptionsItemSelected()। चूंकि यह एंड्रॉइड डॉक्स का एक हिस्सा है, इसलिए इसका कोई साइड-इफेक्ट नहीं है।

खुश कोडिंग। :)

अपडेट करें:

यदि आप लॉलीपॉप को लक्षित कर रहे हैं तो यह समाधान काम नहीं करता है। यदि आप AppCompat का उपयोग कर रहे हैं, तो यह उत्तर वह है जिसकी आपको तलाश होनी चाहिए।


यह वरीयता गतिविधि में एक्शन बार पाने में कैसे मदद करता है?
फ्रोजन क्रेयॉन

@ArjunU। आसान समाधान - इसे आज़माएं और इसका पता लगाएं।
सूफियान

@ArjunU। समस्या यह थी कि PreferencesActivityआइटम को ActionBarविशेष रूप से बैक बटन पर रखने का कोई तरीका नहीं होगा । मेरा जवाब उसके लिए एक अच्छा फिक्स है।
Sufian

चढ़ाव के लिए धन्यवाद। कोई भी स्पष्टीकरण कि मैं अपने उत्तर को कैसे सुधार सकता हूं या क्या गलत था?
सूफियान

1
@ सूफियान मेरे जवाब से जुड़ने के लिए धन्यवाद, खुशी है कि यह सभी की मदद कर रहा है:)
डेविड पासमोर

1

मैं का android.app.Actionbarउपयोग करके प्राप्त करने में सक्षम था getActionBar()। इसने पहली बार एक अशक्त मान लौटाया ... फिर मैंने मेनिफेस्ट में जाकर विषय को बदल दिया:

android:theme="@style/Theme.AppCompat"

तब मैं फिर से एक्शनबार के लिए सक्षम था। मुझे लगता है कि यह केवल कुछ निर्माण स्तरों के लिए काम करेगा। तो आप बिल्ड नंबर के लिए एक चेक करना चाहते हैं या चेक कर सकते हैं कि वैल्यू वापस आ गई है या नहीं।

यह मेरे लिए ठीक रहेगा क्योंकि मैं जिस ऐप पर काम कर रहा हूं वह ICS/4.0+ के लिए है।


यहाँ एक सरल उपाय दिया गया है, जो किसी भी वर्कअराउंड का उपयोग नहीं करता है stackoverflow.com/a/25603448/1276636
सूफ़ियन

0

अब इस समस्या का आधिकारिक उत्तर जारी कर दिया गया है। यह v7 / v14 प्राथमिकता समर्थन पुस्तकालय है।

देखें कि v7 / v14 प्राथमिकता सहायता पुस्तकालय का उपयोग कैसे करें? चर्चा के लिए कि इसका उपयोग कैसे किया जाए।

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