Android: как убрать поля/отступы на экране настроек - программирование
Подтвердить что ты не робот

Android: как убрать поля/отступы на экране настроек

У меня возникает очень странная проблема при проектировании экрана предпочтений. Хотя я не даю разницы в макете, он оставляет некоторое пространство слева.

Как вы можете видеть на изображении ниже: enter image description here

XML:

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

Я делаю что-то не так, добавляя предпочтение check-box на экране?

4b9b3361

Ответ 1

Обновление для androidx.

После большого количества экспериментов я решил эту проблему, добавив это к каждому предпочтению с избыточным отступом:

app:iconSpaceReserved="false"

Конечно, вам также нужно добавить это в само объявление PreferenceScreen в верхней части вашего xml:

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

Ответ 2

Я сообщил об этой проблеме здесь (вы также можете проверить мой обходной проект там), но на данный момент я нашел немного хакерский, но простой способ преодолеть это:

  • Для PreferenceCategory я установил начальное/левое заполнение его макетов на 0.

  • Для других типов предпочтений я предпочитаю скрывать icon_frame, если у них нет значка.

Здесь код. Просто выйдите из этого класса, а все остальное происходит автоматически:

Котлин

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

И результат (образец XML можно найти здесь here из этого образца Google, который я создал здесь для проверки):

enter image description here

Этот код немного опасен, поэтому убедитесь, что при каждом обновлении библиотеки вы проверяете, что он работает нормально.

Кроме того, это может не сработать в некоторых особых случаях, например, когда вы определяете android:layout самостоятельно для предпочтения, поэтому вам придется изменить его по этому вопросу.


Получил лучшее, более официальное решение:

Для каждого предпочтения используйте app:iconSpaceReserved="false". Это должно работать нормально, но по какой-то причине есть (известная) ошибка, которая не работает для PreferenceCategory. Об этом было сообщено здесь, и оно должно быть исправлено в ближайшее время.

Так что сейчас вы можете использовать смешанную версию обходного пути, который я написал, и этот флаг.


ОБНОВЛЕНИЕ: нашел еще одно решение. Он преодолеет все предпочтения и установит isIconSpaceReserved для каждого. К сожалению, как я уже писал выше, если вы используете PreferenceCategory, он разрушает его, но он должен работать нормально, если вы его не используете:

Котлин

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

ОБНОВЛЕНИЕ: после того, как Google окончательно исправил библиотеку (ссылка здесь), вы можете установить флаг для каждого предпочтения или использовать это решение, которое делает это для всех, для вас:

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

Просто продолжайте, и у вас не будет бесполезного заполнения для ваших предпочтений. Пример проекта здесь, где я также прошу использовать официальный способ, чтобы избежать этого, вместо этих уловок. Пожалуйста, подумайте об этом.

Ответ 3

Простое рабочее решение из здесь:

Создать res/values-sw360dp-v13/values-preference.xml:

<resources xmlns:tools="http://schemas.android.com/tools">
    <bool name="config_materialPreferenceIconSpaceReserved" tools:ignore="MissingDefaultResource,PrivateResource">false</bool>
    <dimen name="preference_category_padding_start" tools:ignore="MissingDefaultResource,PrivateResource">0dp</dimen>
</resources>

<bool> фиксирует значение по умолчанию iconSpacePreserved для всех Preference; <dimen> исправляет категорию PreferenceCategory.

Ответ 4

Попробуйте следующее:

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

Вы можете установить дополнение с помощью: setPadding();

Ответ 5

Если вы используете библиотеку com.android.support:preference-v7, убедитесь, что тема для активности, в которой размещаются ваши предпочтения, имеет параметр preferenceTheme установленный в оверлей темы темы предпочтений v14:

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

Ответ 6

К сожалению, ничего от меня не работало.

Короткий ответ:

Я решил это, используя отрицательные поля в самом верхнем контейнере пользовательской схемы предпочтений.

Шаги:

  • Создайте пользовательский макет для предпочтения (например, preference_category.xml)
  • укажите, что ваше предпочтение использует настраиваемый макет, добавив параметр android: layout в тег предпочтений в XML
  • Применить отрицательные поля

Подробный ответ:

Предпочтение 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>

Пользовательский макет для строки предпочтений, который удаляет ненужные поля слева и справа:

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

Пользовательский макет для категории предпочтений, который удаляет ненужные поля слева и справа:

<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" />

Ответ 7

Отступ вызван родительским ListView в PreferenceScreen, содержащем ваши настройки. Если вы используете PreferenceFragment для создания своих настроек, просто перейдите к onActivityCreated функции PreferenceFragement и выполните следующие действия, чтобы удалить дополнение:

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

Ответ 8

Измените тему предпочтения следующим образом. Обязательно используйте последнюю версию библиотеки предпочтений 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>

Ответ 9

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

Использование PreferenceFragmentCompat может сделать это:

1. Определите группу предпочтений:

    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.Override PreferenceFragmentCompat onCreateAdapter метод:

   @Override
   protected Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {

      return new CustomAdapter(preferenceScreen);
   }

Использование style.xml может сделать это:

1.values ​​/styles.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>

Ответ 10

Ни один из вышеперечисленных ответов не работал, мне пришлось скопировать макет предпочтений, создать новый файл макета, такой как custom_preference.xml, переопределить содержимое макета, установив видимость кадра значка в GONE. А затем в файле pref.xml задайте макет для предпочтения использовать этот настраиваемый макет.

<?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>

Ответ 11

"padding" инициируется в 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();
}

Если вы знаете, как переопределить стили, определенные Android, вы, вероятно, можете решить эту проблему. Однако это не очень просто.

Ответ 12

Я пытаюсь использовать

android:icon="@null"

с CheckBoxPreference в Android 4.4, но не может дополнять слева. Я обманул использование небольшого прозрачного значка и добавил

android:icon="@drawable/transparent_icon" 

и, похоже, для меня это работает. Надеюсь, это поможет. Спасибо.

Ответ 13

Я не знаю, было ли слишком поздно для ответа, но сегодня у меня была такая же проблема, и ничто из этого ответа не помогло мне.

Итак, я использовал это решение:

В моем DisclaimerPreference, который extends Preference, я опускаю метод onBindView(View view) следующим образом:

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

Ключ должен установить RelativeLayout внутри основного Вид как GONE. Пожалуйста, дайте мне знать, если что-то не так:)

Ответ 14

По-видимому, добавление android:layout="@null" к вашим предпочтениям в xml сделает трюк. Но, следовательно, он также сделает размер заголовка более крупным.

Ответ 15

Спрошено довольно давно, но то, что помогло мне решить это, было отрицательной маржой, не нужно создавать собственные файлы.

Когда вы создаете свой класс SettingsActivity (который имеет PreferenceFragment внутри), вы просто устанавливаете его как фрагмент и добавляете отрицательный запас.

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>

Ответ 16

Это поздний ответ, но попробуйте установить android: icon = "@null" в CheckBoxPreferences:

<CheckBoxPreference
    ...
    android:icon="@null" />

Ответ 17

Добавьте android:defaultValue="false" в тэг <PreferenceScreen [...]:

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