it-swarm.asia

كيفية إضافة شريط الإجراءات من مكتبة الدعم إلى PreferenceActivity؟

تمت إضافة توافق شريط الإجراءات في مكتبة الدعم ، المراجعة 18. أصبح الآن ActionBarActivity فئة لإنشاء أنشطة باستخدام شريط الإجراءات على الإصدارات الأقدم من Android.

هل هناك أي طريقة لإضافة "شريط الإجراءات" من مكتبة الدعم إلى PreferenceActivity؟

سبق أن استخدمت ActionBarSherlock ولها SherlockPreferenceActivity.

128
Roman

تحرير: في 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 .

128
Ľubomír Kučera

لا توجد حاليًا طريقة لتحقيق ذلك مع AppCompat. لقد فتحت علة داخليا.

78
Chris Banes

لقد تمكنت من إنشاء حل مشابه لما يستخدمه متجر Google Play. رابط إلى الإجابة الأصلية

يرجى الاطلاع على GitHub Repo:هنا


تشبه إلى حد كبير الشفرة الخاصة بك ولكنها أضافت 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 :

example


UPDATE (توافق Gingerbread):

كما أشار هنا ، تقوم أجهزة Gingerbread بإرجاع NullPointerException على هذا السطر:

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

FIX:

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

أي مشاكل مع ما سبق اسمحوا لي أن أعرف!


UPDATE 2: صبغة الحل البديل

كما هو موضح في العديد من ملاحظات dev 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:

example 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;
}

شاشات تفضيل متداخلة

يواجه الكثير من الأشخاص مشكلات في تضمين شريط الأدوات في <PreferenceScreen />s المتداخلة ، ومع ذلك ، فقد وجدت حلاً !! - بعد الكثير من التجربة والخطأ!

أضف التالي إلى 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's هذا الألم هو أنها تستند إلى مربع حوار مجمّع ، لذلك نحن بحاجة لالتقاط تخطيط الحوار لإضافة شريط الأدوات إليه.


ظل شريط الأدوات

حسب التصميم ، لا يسمح استيراد Toolbar بالرفع والتظليل في أجهزة ما قبل v21 ، لذلك إذا كنت ترغب في الحصول على الارتفاع على 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>

لا تنس أن تضيف إضافة مكتبة Design Support باعتبارها تبعية في ملف 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'

أندرويد 6.0

لقد حققت في مشكلة التداخل المبلغ عنها ولا يمكنني إعادة إنتاج المشكلة.

الشفرة الكاملة المستخدمة على النحو الوارد أعلاه تنتج ما يلي:

 enter image description here 

إذا كنت أفتقد شيئًا ، فالرجاء إخباري عن طريق هذا الريبو وسأحقق.

24
David Passmore

العثور على تطبيق PreferenceFragment استنادًا إلى جزء دعم v4:

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

تحرير: لقد اختبرت ذلك وعمله عظيم!

12
Ostkontentitan

دمج PreferenceActivity مع ABC غير ممكن ، على الأقل بالنسبة لي. جربت الاحتمالين اللذين أجدهما ولكن لم ينجح أحد:

الخيار 1:

ActionBarPreferenceActivity يمتد PreferenceActivity. عند القيام بذلك ، يتم تقييدك بواسطة ActionBarActivityDelegate.createDelegate(ActionBarActivity activity). تحتاج أيضًا إلى تطبيق ActionBar.Callbacks الذي لا يمكن الوصول إليه

الخيار 2:

ActionBarPreferenceActivity يمتد ActionBarActivity. يتطلب هذا النهج إعادة كتابة PreferenceActivity ، PreferenceManager جديدة بالكامل ، وقد تكون PreferenceFragment ، مما يعني أنك بحاجة إلى الوصول إلى فئات مخفية مثل com.Android.internal.util.XmlUtils. يمكن أن يأتي الحل لهذا فقط من Google devs التي تنفذ ActionBarWrapper التي يمكن إضافتها إلى أي نشاط.

إذا كنت تحتاج حقًا إلى نشاط تفضيل ، فإن نصيحتي الآن هي ActionBarSherlock.

ومع ذلك ، تمكنت من تنفيذه هنا .

3
Maxwell Weru

خلفية المشكلة:

يريد OP أن يعرف كيف يمكننا وضع MenuItems في ActionBar من PreferenceActivity for pre-Honeycomb لأن مكتبة دعم Android بها خلل لا يسمح بحدوث ذلك.

بلدي الحل:

لقد وجدت طريقة أنظف كثيرًا ، من المقترح بالفعل ، لتحقيق الهدف (ووجدته في Android Docs ):

Android:parentActivityName

اسم فئة الوالد المنطقي للنشاط. يجب أن يتطابق الاسم هنا مع اسم الفئة المعطى لسمة Android: العنصر المقابل.

يقرأ النظام هذه السمة لتحديد النشاط الذي يجب بدءه عندما يضغط الاستخدام على الزر "أعلى" في شريط الإجراءات. يمكن للنظام أيضًا استخدام هذه المعلومات لتجميع مكدس خلفي للأنشطة باستخدام TaskStackBuilder.

لدعم مستويات واجهة برمجة التطبيقات (API) من 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(). نظرًا لكونه جزءًا من محرّر مستندات Android ، فليس له آثار جانبية.

ترميز سعيد. :)

تحديث:

هذا الحل لم يعد يعمل إذا كنت تستهدف Lollipop. إذا كنت تستخدم AppCompat ، هذا الجواب هو ما يجب أن تبحث عنه.

3
Sufian

تمكنت من الحصول على Android.app.Actionbar باستخدام getActionBar(). لقد قامت بإرجاع قيمة فارغة في البداية ... ثم ذهبت إلى البيان وغيرت السمة إلى:

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

ثم تمكنت من الحصول على شريط الحركة مرة أخرى. أفترض أن هذا سيعمل فقط مع مستويات بناء معينة. لذلك قد ترغب في القيام بالتحقق من رقم البنية أو التحقق مما إذا كانت القيمة التي تم إرجاعها فارغة.

سيكون الأمر جيدًا بالنسبة لي لأن التطبيق الذي أعمل عليه هو ICS/4.0 +.

1
RCB

الآن تم إصدار الإجابة الرسمية لهذه المشكلة. هذا هو v7/v14 دعم التفضيل المكتبة.

راجع كيفية استخدام مكتبة دعم تفضيلات الإصدار v7/v14؟ لمناقشة كيفية استخدامها.

0
Randy Sugianto 'Yuku'