Ich habe über dieses Thema berichtet hier (Sie können auch dort meine Abhilfe Projekt überprüfen), aber für jetzt, ich habe ein bisschen Hack-y, aber einfache Weise zu überwinden diese gefunden:
Für PreferenceCategory
setze ich den Start / Links-Abstand seiner Layouts auf 0.
Für andere Arten von Einstellungen habe ich mich entschieden, diese auszublenden, icon_frame
falls sie kein Symbol haben.
Hier ist der Code. Verlängern Sie einfach diese Klasse und der Rest erfolgt automatisch:
Kotlin
abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
override fun onCreateAdapter(preferenceScreen: PreferenceScreen?): RecyclerView.Adapter<*> {
return object : PreferenceGroupAdapter(preferenceScreen) {
override fun onBindViewHolder(holder: PreferenceViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
val preference = getItem(position)
if (preference is PreferenceCategory)
setZeroPaddingToLayoutChildren(holder.itemView)
else
holder.itemView.findViewById<View?>(R.id.icon_frame)?.visibility = if (preference.icon == null) View.GONE else View.VISIBLE
}
}
}
private fun setZeroPaddingToLayoutChildren(view: View) {
if (view !is ViewGroup)
return
val childCount = view.childCount
for (i in 0 until childCount) {
setZeroPaddingToLayoutChildren(view.getChildAt(i))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
view.setPaddingRelative(0, view.paddingTop, view.paddingEnd, view.paddingBottom)
else
view.setPadding(0, view.paddingTop, view.paddingRight, view.paddingBottom)
}
}
}
Java
public abstract class BasePreferenceFragmentCompat extends PreferenceFragmentCompat {
@Override
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
return new PreferenceGroupAdapter(preferenceScreen) {
@SuppressLint("RestrictedApi")
@Override
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
Preference preference = getItem(position);
if (preference instanceof PreferenceCategory)
setZeroPaddingToLayoutChildren(holder.itemView);
else {
View iconFrame = holder.itemView.findViewById(R.id.icon_frame);
if (iconFrame != null) {
iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
}
}
}
};
}
private void setZeroPaddingToLayoutChildren(View view) {
if (!(view instanceof ViewGroup))
return;
ViewGroup viewGroup = (ViewGroup) view;
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
setZeroPaddingToLayoutChildren(viewGroup.getChildAt(i));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
viewGroup.setPaddingRelative(0, viewGroup.getPaddingTop(), viewGroup.getPaddingEnd(), viewGroup.getPaddingBottom());
else
viewGroup.setPadding(0, viewGroup.getPaddingTop(), viewGroup.getPaddingRight(), viewGroup.getPaddingBottom());
}
}
}
Und das Ergebnis (XML-Beispiel finden Sie hier in diesem Google-Beispiel , das ich hier zum Auschecken erstellt habe ):
Dieser Code ist etwas gefährlich. Stellen Sie daher sicher, dass Sie bei jedem Update der Bibliothek überprüfen, ob er ordnungsgemäß funktioniert.
Außerdem funktioniert es in einigen Sonderfällen möglicherweise nicht gut, z. B. wenn Sie android:layout
für die Präferenz eine eigene Definition festlegen. Daher müssen Sie diese für diese Angelegenheit ändern.
Ich habe eine bessere, offiziellere Lösung:
Verwenden Sie für jede Präferenz app:iconSpaceReserved="false"
. Dies sollte gut funktionieren, aber aus irgendeinem Grund gibt es einen (bekannten) Fehler, der für PreferenceCategory nicht funktioniert. Es wurde hier berichtet und sollte in naher Zukunft behoben werden.
Im Moment können Sie also eine Mix-Version der von mir geschriebenen Problemumgehung und dieses Flag verwenden.
EDIT: Noch eine andere Lösung gefunden. Dieser wird alle Einstellungen überwinden und isIconSpaceReserved
für jede festlegen . Wie ich oben geschrieben habe, ruiniert es leider, wenn Sie PreferenceCategory verwenden, aber es sollte gut funktionieren, wenn Sie es nicht verwenden:
Kotlin
abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
super.setPreferenceScreen(preferenceScreen)
if (preferenceScreen != null) {
val count = preferenceScreen.preferenceCount
for (i in 0 until count)
preferenceScreen.getPreference(i)!!.isIconSpaceReserved = false
}
}
Java
public class BasePreferenceFragment extends PreferenceFragmentCompat {
@Override
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
super.setPreferenceScreen(preferenceScreen);
if (preferenceScreen != null) {
int count = preferenceScreen.getPreferenceCount();
for (int i = 0; i < count; i++)
preferenceScreen.getPreference(i).setIconSpaceReserved(false);
}
}
}
BEARBEITEN: Nachdem Google die Bibliothek endgültig repariert hat (Link hier ), können Sie das Flag für jede Voreinstellung setzen oder diese Lösung verwenden, die dies für alle erledigt:
abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
private fun setAllPreferencesToAvoidHavingExtraSpace(preference: Preference) {
preference.isIconSpaceReserved = false
if (preference is PreferenceGroup)
for (i in 0 until preference.preferenceCount)
setAllPreferencesToAvoidHavingExtraSpace(preference.getPreference(i))
}
override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
if (preferenceScreen != null)
setAllPreferencesToAvoidHavingExtraSpace(preferenceScreen)
super.setPreferenceScreen(preferenceScreen)
}
override fun onCreateAdapter(preferenceScreen: PreferenceScreen?): RecyclerView.Adapter<*> =
object : PreferenceGroupAdapter(preferenceScreen) {
@SuppressLint("RestrictedApi")
override fun onPreferenceHierarchyChange(preference: Preference?) {
if (preference != null)
setAllPreferencesToAvoidHavingExtraSpace(preference)
super.onPreferenceHierarchyChange(preference)
}
}
}
Erweitern Sie es einfach, und Sie werden nicht die nutzlose Polsterung für Ihre Vorlieben haben. Beispielprojekt hier , bei dem ich anstelle dieser Tricks auch einen offiziellen Weg fordere, dies zu vermeiden. Bitte erwägen Sie, es zu markieren.