wake-up-neo.com

Keine ActionBar in PreferenceActivity nach dem Upgrade auf die Support Library v21

Nach dem Upgrade auf die Support Library v21 ist meine ActionBar in meiner PreferenceActivity weg.

Habe ich einige Attribute in meinem Design vermisst, um es wieder zu aktivieren? Ich hatte ähnliche Probleme mit einer schwarzen ActionBar .

Ich habe auch versucht, es etwas hackig hinzuzufügen, indem ich ein Toolbar zum Root-Layout hinzufügte, aber das funktionierte nicht wie erwartet.

84
rekire

Hier finden Sie das GitHub-Repo: HERE


Sehr ähnlich zu Ihrem eigenen Code, aber hinzugefügtes XML, um den Satztitel zu ermöglichen:

PreferenceActivity weiterhin verwenden:

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 (Kompatibilität mit Lebkuchen):

Wie hier hervorgehoben wird, geben Gingerbread-Geräte in dieser Zeile NullPointerException zurück:

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

Irgendwelche Probleme mit dem oben genannten lassen Sie mich wissen!


UPDATE 2: TINTENABARBEITUNG

Wie in vielen Dev-Hinweisen dargelegt, unterstützt PreferenceActivity keine Tönung von Elementen. Durch die Verwendung einiger interner Klassen können Sie dies jedoch erreichen. Das ist so lange, bis diese Klassen entfernt werden. (Funktioniert mit AppCompat Support-v7 v21.0.3).

Fügen Sie die folgenden Importe hinzu:

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;

Dann überschreiben Sie die onCreateView-Methode:

@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 führte neue getönte Elemente ein, so dass die internen Klassen nicht mehr verwendet werden müssen, um denselben Effekt wie beim letzten Update zu erzielen. Folgen Sie stattdessen diesem (überschreiben Sie 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.JELLY_BEAN) {
        // 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

Viele Leute haben Probleme mit dem Einbinden der Toolbar in verschachtelten <PreferenceScreen />s. Ich habe jedoch eine Lösung gefunden !! - Nach vielem Ausprobieren!

Fügen Sie Ihrer SettingsActivity Folgendes hinzu:

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

Der Grund, dass PreferenceScreens so schmerzhaft sind, liegt darin, dass sie als Wrapper-Dialog basieren. Daher müssen wir das Dialoglayout erfassen, um die Symbolleiste hinzuzufügen.


Symbolleiste Schatten

Beim Design-Import von Toolbar ist keine Erhöhung und Schattierung in Geräten vor Version 21 möglich. Wenn Sie also eine Erhöhung auf Ihrer Toolbar haben möchten, müssen Sie sie in eine AppBarLayout einschließen:

`settings_toolbar.xml:

<Android.support.design.widget.AppBarLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

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

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

Vergessen Sie nicht, das Hinzufügen der Design Support-Bibliothek als Abhängigkeit in build.gradle-Datei hinzuzufügen:

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

Ich habe das berichtete überlappende Problem untersucht und kann das Problem nicht reproduzieren.

Der vollständige Code, der wie oben verwendet wird, erzeugt Folgendes:

enter image description here

Wenn mir etwas fehlt, lass es mich bitte über dieses Repo wissen und ich werde es untersuchen.

171
David Passmore

Verwenden Sie AppCompatActivity & PreferenceFragment, um das Problem zu lösen:

AppCompatActivity:

public class SettingsActivity extends AppCompatActivity {

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    getFragmentManager().beginTransaction().replace(Android.R.id.content, new SettingsFragment()).commit();
}}

PreferenceFragment:

public class SettingsFragment extends PreferenceFragment {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.settings_preferences);
}}
44
Abdullah

Ich beendete das Hinzufügen der Toolbar selbst mit diesem einfachen Code:

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

Hier ist meine preferences_toolbar.xml:

<Android.support.v7.widget.Toolbar
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_height="wrap_content"
    Android:layout_width="match_parent"
    Android:minHeight="?attr/actionBarSize"
    app:navigationContentDescription="@string/abc_action_bar_up_description"
    Android:background="?attr/colorPrimary"
    app:navigationIcon="?attr/homeAsUpIndicator"
    app:theme="@style/Theme.Toolbar" />
7
rekire

Eine bessere Lösung als das "Rollen Ihrer eigenen" Aktionsleiste ist die Verwendung der AppCompatDelegate Klasse, mit der Sie eine tatsächlich-tatsächliche Aktionsleiste aus der Support-Bibliothek einlesen können. Hier ist ein Beispielcode, den Sie verwenden können, der Antwort von Ľubomír Kučera auf diese Frage .

...
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;
    }
}
6
Tad

Hi ich bin nicht, wenn du dieses Problem noch hast. Aber ich denke, ich werde posten, was ich getan habe, um das Problem zu lösen, und hoffe, dass es jemandem helfen wird.

1) Zunächst einmal haben Sie vielleicht bemerkt, dass PreferenceActivity die ListActivity-Funktion erweitert, die wiederum von Activity ausgeht. 

Laut den Kommentaren im Entwickler-Blog ( http://Android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html ), verwenden Sie v21 alle Ihre Aktivitäten muss von ActionBarActivity erben. Also da ist dein Problem.

2) Die Schritte, die ich zur Lösung verwendet habe, sind:

a) Make sure that you set the Theme of your PreferenceActivity to inherits one ot the Theme.AppCompat Themes.

b) Make your class PreferenceActivity extends ActionBarActivity.

c) Use the PreferenceFragment as your container for all your preferences.

Dies sollte es lösen.

Prost!

4
AfrikAndroid

Ich hatte das gleiche Problem. Versuchen Sie einfach, das Thema der Aktivität in das zu ändern, in dem sich eine ActionBar befindet. Die folgende Zeile im Activity-Tag von SettingsActivity hinzugefügt:

Android:theme="Theme.AppCompat.DayNight.DarkActionBar" 

0
any mous

Ich habe etwas Ähnliches wie die akzeptierte Frage gemacht, aber ich verwende mein Layout auch in anderen Aktivitäten (auch MainActivity), sodass ich einen Pfeil darin nicht einfach hartcodieren kann.

Was für mich funktioniert hat:

private void setupActionBar() {
    LinearLayout root = (LinearLayout)findViewById(Android.R.id.list).getParent().getParent().getParent();
    Toolbar toolbar = (Toolbar)LayoutInflater.from(this).inflate(R.layout.app_bar, root, false);
    root.addView(toolbar, 0);
    setSupportActionBar(toolbar);
    ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
}
0
Moterrola