studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones android preference checkboxpreference

programacion - Android: Cómo obtener eliminar margen/relleno en la pantalla de preferencias



manual de programacion android pdf (15)

Actualizando esto para androidx.

Después de mucha experimentación, resolví este problema agregando esto a cada preferencia que tenía una sangría excesiva:

app:iconSpaceReserved="false"

Por supuesto, también deberá agregar esto a la declaración PreferenceScreen en la parte superior de su xml:

xmlns:app="http://schemas.android.com/apk/res-auto"

Estoy enfrentando un problema muy extraño en el diseño de la pantalla de preferencias. Aunque no estoy dando ningún margen en el diseño, queda algo de espacio a la izquierda.

Como se puede ver en la imagen de abajo:

XML:

<PreferenceScreen android:title="demo" > <CheckBoxPreference android:defaultValue="false" android:key="prefSync"` android:title="Auto Sync" /> </PreferenceScreen>

¿Estoy haciendo algo mal al agregar la preferencia de la casilla de verificación en la pantalla?


Agregue android:defaultValue="false" a su etiqueta <PreferenceScreen [...] :

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:defaultValue="false">


Aparentemente, agregar android:layout="@null" a su preferencia en xml haría el truco. Pero en consecuencia, también aumentará el tamaño del título.


Cambia el tema de preferencias como este. Asegúrese de usar la última versión de la biblioteca de preferencias androidx.preference 1.1.0-alpha01

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="preferenceTheme">@style/CustomPreferenceTheme</item> </style> <style name="CustomPreferenceTheme" parent="@style/PreferenceThemeOverlay"> <item name="preferenceFragmentCompatStyle">@style/CustomPreferenceFragmentCompatStyle</item> <item name="preferenceCategoryStyle">@style/CustomPreferenceCategory</item> <item name="preferenceStyle">@style/CustomPreference</item> <item name="checkBoxPreferenceStyle">@style/CustomCheckBoxPreference</item> <item name="dialogPreferenceStyle">@style/CustomDialogPreference</item> <item name="switchPreferenceCompatStyle">@style/CustomSwitchPreferenceCompat</item> <!-- for pre lollipop(v21) --> <item name="switchPreferenceStyle">@style/CustomSwitchPreference</item> </style> <style name="CustomPreferenceFragmentCompatStyle" parent="@style/PreferenceFragment.Material"> <item name="android:layout">@layout/fragment_settings</item> </style> <style name="CustomPreferenceCategory" parent="Preference.Category.Material"> <item name="iconSpaceReserved">false</item> </style> <style name="CustomPreference" parent="Preference.Material"> <item name="iconSpaceReserved">false</item> </style> <style name="CustomCheckBoxPreference" parent="Preference.CheckBoxPreference.Material"> <item name="iconSpaceReserved">false</item> </style> <style name="CustomDialogPreference" parent="Preference.DialogPreference.Material"> <item name="iconSpaceReserved">false</item> </style> <style name="CustomSwitchPreferenceCompat" parent="Preference.SwitchPreferenceCompat.Material"> <item name="iconSpaceReserved">false</item> </style> <style name="CustomSwitchPreference" parent="Preference.SwitchPreference.Material"> <item name="iconSpaceReserved">false</item> </style>


Desafortunadamente, nada de arriba funcionó para mí.

Respuesta corta :

Resolví esto utilizando márgenes negativos en el contenedor superior del diseño de preferencias personalizado.

Pasos:

  • Cree un diseño personalizado para la preferencia (p. Ej. Preferences_category.xml)
  • especifique que su preferencia usa el diseño personalizado agregando android: layout param a una etiqueta de preferencia en XML
  • Aplicar márgenes negativos.

Respuesta detallada:

La preferencia XML:

<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/settings_title" > <android.support.v7.preference.PreferenceCategory android:layout="@layout/preference_category" android:key="settings_list" android:title="@string/pref_category_settings" /> <android.support.v7.preference.SwitchPreferenceCompat android:layout="@layout/preference_row" android:icon="@drawable/ic_nav_switch" android:key="pref_switch" android:title="@string/pref_switch_title" /> </android.support.v7.preference.PreferenceScreen>

El diseño personalizado para la fila de preferencias que elimina los márgenes izquierdo y derecho innecesarios:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="-12dp" android:layout_marginEnd="-8dp" android:minHeight="?android:attr/listPreferredItemHeight" android:gravity="center_vertical"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@android:id/icon" android:layout_width="58dp" android:layout_height="58dp" android:padding="8dp" android:layout_gravity="center" android:visibility="visible" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="15dp" android:layout_marginEnd="6dp" android:layout_marginTop="6dp" android:layout_marginBottom="6dp" android:layout_weight="1"> <TextView android:id="@android:id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceListItem" android:ellipsize="marquee" android:fadingEdge="horizontal" /> <TextView android:id="@android:id/summary" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@android:id/title" android:layout_alignStart="@android:id/title" android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textColor="?android:attr/textColorSecondary" android:maxLines="2"/> </RelativeLayout> <LinearLayout android:id="@android:id/widget_frame" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="end|center_vertical" android:orientation="vertical"> </LinearLayout> </LinearLayout>

El diseño personalizado para la categoría de preferencia que elimina los márgenes izquierdo y derecho innecesarios:

<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/colorAccent" android:textStyle="bold" android:textSize="12sp" android:gravity="center_vertical" android:textAllCaps="true" android:layout_marginStart="-4dp" android:layout_marginEnd="-8dp" android:id="@+android:id/title" />


El ''relleno'' se inicia en PreferenceFrameLayout.java :

public PreferenceFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PreferenceFrameLayout, defStyle, 0); float density = context.getResources().getDisplayMetrics().density; int defaultBorderTop = (int) (density * DEFAULT_BORDER_TOP + 0.5f); int defaultBottomPadding = (int) (density * DEFAULT_BORDER_BOTTOM + 0.5f); int defaultLeftPadding = (int) (density * DEFAULT_BORDER_LEFT + 0.5f); int defaultRightPadding = (int) (density * DEFAULT_BORDER_RIGHT + 0.5f); mBorderTop = a.getDimensionPixelSize( com.android.internal.R.styleable.PreferenceFrameLayout_borderTop, defaultBorderTop); mBorderBottom = a.getDimensionPixelSize( com.android.internal.R.styleable.PreferenceFrameLayout_borderBottom, defaultBottomPadding); mBorderLeft = a.getDimensionPixelSize( com.android.internal.R.styleable.PreferenceFrameLayout_borderLeft, defaultLeftPadding); mBorderRight = a.getDimensionPixelSize( com.android.internal.R.styleable.PreferenceFrameLayout_borderRight, defaultRightPadding); a.recycle(); }

Si sabe cómo anular los estilos definidos por Android, probablemente podría resolver esto. Sin embargo, no es muy sencillo.


El relleno es causado por el ListView principal en la ListView de PreferenceScreen contiene sus ajustes. Si está utilizando un PreferenceFragment para crear sus preferencias, solo vaya a la función onActivityCreated del PreferenceFragement y haga lo siguiente para eliminar el relleno:

public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); View lv = getView().findViewById(android.R.id.list); if (lv != null) lv.setPadding(0, 0, 0, 0); }


He informado sobre este problema here (también puede consultar mi proyecto de solución), pero por ahora, he encontrado un poco de piratería, pero una forma fácil de superar esto:

  • Para PreferenceCategory , establezco el inicio / relleno izquierdo de sus diseños en 0.

  • Para otros tipos de preferencias, elijo ocultar el icon_frame en caso de que no tengan un icono.

Aquí está el código. Solo amplíe desde esta clase y el resto es automático:

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

Y el resultado (la muestra XML se puede encontrar here de esta muestra de Google , que he creado here para verla):

Este código es un poco peligroso, así que asegúrese de que con cada actualización de la biblioteca, verifique que funcione bien.

Además, es posible que no funcione bien en algunos casos especiales, como cuando define android:layout propio para la preferencia, por lo que tendrá que modificarlo para este asunto.

Tengo una solución mejor, más oficial:

Para cada preferencia, use la app:iconSpaceReserved="false" . Esto debería funcionar bien, pero por alguna razón hay un error (conocido) que no funciona para PreferenceCategory. Se informó here , y se debe arreglar en un futuro próximo.

Así que por ahora puedes usar una versión mixta de la solución que escribí y esta bandera.

EDIT: Encontró otra solución. Éste superará todas las preferencias y establecerá isIconSpaceReserved para cada una. Lamentablemente, como he escrito anteriormente, si usas la Categoría de Preferencia, la arruina, pero debería funcionar bien si no la usas:

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

EDITAR: después de que Google finalmente arregle la biblioteca (enlace here ), puede establecer la marca para cada preferencia, o usar esta solución que lo hace para todos, para usted:

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

Simplemente extiéndalo, y no tendrás el relleno inútil para tus preferencias. Ejemplo de proyecto here , donde también solicito tener una forma oficial de evitarlo, en lugar de esos trucos. Por favor considere protagonizarlo.


Ninguna de las respuestas anteriores funcionó, tuve que copiar el diseño de preference , crear un nuevo archivo de diseño como custom_preference.xml, anular el contenido del diseño configurando la visibilidad del marco del icono en GONE . Y luego, en pref.xml, establezca el diseño de la preferencia para usar este diseño personalizado.

<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v7.preference.EditTextPreference android:title="@string/pref_label" android:hint="@string/pref_hint" android:key="@string/pref_key" android:inputType="text" android:singleLine="true" android:layout="@layout/custom_preference_layout" /> </PreferenceScreen>


No sé si es demasiado tarde para una respuesta, pero hoy tuve el mismo problema y ninguna de estas respuestas me ayudó.

Así que utilicé esta solución:

En mi DisclaimerPreference que extends Preference , dejo de lado el onBindView(View view) de esta manera:

@Override protected void onBindView(View view) { super.onBindView(view); if(view instanceof ViewGroup){ ViewGroup vg = (ViewGroup)view; View currView; for(int i=0; i<vg.getChildCount(); i++){ currView = vg.getChildAt(i); if (currView instanceof RelativeLayout) currView.setVisibility(View.GONE); } } }

La clave es configurar el RelativeLayout dentro de la Vista principal como GONE . Por favor, hágamelo saber si algo está mal :)


Pregunté hace bastante tiempo, pero lo que me ayudó a resolver esto fue márgenes negativos, sin necesidad de archivos personalizados.

Cuando crea su clase SettingsActivity (que contiene PreferenceFragment), simplemente configura su diseño para que sea un fragmento y agregue un margen negativo.

settings_activity:

<?xml version="1.0" encoding="utf-8"?> <fragment android:layout_marginLeft="-40dp" android:name="com.example.USER.APPNAME.SettingsActivity$PrefsFragment" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.USER.APPNAME.SettingsActivity"> </fragment>


Prueba esto:

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = super.onCreateView(inflater, container, savedInstanceState); if(v != null) { ListView lv = (ListView) v.findViewById(android.R.id.list); lv.setPadding(10, 10, 10, 10); } return v; }

Puedes configurar el relleno usando: setPadding();


Si está utilizando la biblioteca com.android.support:preference-v7 , asegúrese de que el tema para la actividad que aloja sus preferencias tenga un tema de preferencia en la superposición del tema de preferencia de Material v14:

<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>


Trato de usar

android:icon="@null"

con CheckBoxPreference en Android 4.4 pero no se puede rellenar desde la izquierda. Utilicé un pequeño icono transparente y lo agregué

android:icon="@drawable/transparent_icon"

Y parece que funciona para mí. Espero que pueda ayudar. Gracias.


compile ''com.android.support:preference-v7:24.2.1''

Use PreferenceFragmentCompat puede hacer esto:

1. Definir un adaptador de grupo de preferencia:

static class CustomAdapter extends PreferenceGroupAdapter { public CustomAdapter(PreferenceGroup preferenceGroup) { super(preferenceGroup); } @Override public PreferenceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { PreferenceViewHolder preferenceViewHolder = super.onCreateViewHolder(parent, viewType); parent.setPadding(0, 0, 0, 0); preferenceViewHolder.itemView.setPadding(20, 5, 20, 5); return preferenceViewHolder; } }

2. Anular el método onCreateAdapter de PreferenceFragmentCompat:

@Override protected Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { return new CustomAdapter(preferenceScreen); }

Use style.xml puede hacer esto:

1.values ​​/ estilos.xml:

<style name="customPreferenceThemeOverlay" parent="@style/PreferenceThemeOverlay"> <item name="preferenceFragmentListStyle">@style/customPreferenceFragmentList</item> </style> <style name="customPreferenceFragmentList"> <item name="android:paddingLeft">0dp</item> <item name="android:paddingRight">0dp</item> </style>

2.values-v17 / styles.xml:

<style name="customPreferenceFragmentList"> <item name="android:paddingLeft">0dp</item> <item name="android:paddingRight">0dp</item> <item name="android:paddingStart">0dp</item> <item name="android:paddingEnd">0dp</item> </style>

3.value / styles.xml:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> ... ... <item name="preferenceTheme">@style/customPreferenceThemeOverlay</item> </style>