Отрегулируйте поля / отступы в "PreferenceScreen" в Android

Я хотел бы настроить значения полей / отступов по умолчанию для "PreferenceScreen" в Android, я знаю, что невозможно просто установить его в коде XML (файл макета), но Android определенно получает эти значения откуда-то и НАДЕЖНО (я надеюсь) Я могу установить некоторые атрибуты стиля и достичь их.

Значения, которые я хочу настроить:

Я нашел этот ответ онлайн: Android: Как максимизировать ширину PreferenceFragment (или избавиться от наценки)?

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

Кто-нибудь знает, как я могу добиться этого путем настройки стиля (ов) или некоторых других полей?

1 ответ

Решение

К сожалению, я не думаю, что вы найдете лучший ответ, чем вы уже обнаружили в Android: как максимизировать ширину PreferenceFragment (или избавиться от маржи)?, Я объясню почему и дам вам альтернативу, которую вы можете считать худшей, чем та, которая представлена ​​в ответе, на который вы ссылаетесь.

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

implementation 'com.android.support:preference-v7:27.1.1'
implementation 'com.android.support:preference-v14:27.1.1'

preferenceTheme Атрибут темы определяет, как будут выглядеть настройки.

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <!-- Theme for the preferences -->
    <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>

Поднимаясь по родительской цепочке (ctrl-B) от PreferenceThemeOverlay.v14.Material мы видим

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

Preference.Material определяется как:

<style name="Preference.Material">
    <item name="android:layout">@layout/preference_material</item>
</style>    

Макет для предпочтения preference_material.xml, Вот источник.

Следующий раздел этого макета нас интересует:

...
<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:paddingTop="16dp"
    android:paddingBottom="16dp">
    <TextView android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textAppearance="?attr/textAppearanceListItem"
        android:ellipsize="marquee" />
    <TextView android:id="@+id/summary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/title"
        android:layout_alignStart="@id/title"
        android:textAppearance="?attr/textAppearanceListItemSecondary"
        android:textColor="?attr/textColorSecondary"
        android:maxLines="10"
        android:ellipsize="end" />
</RelativeLayout>
...

Как видите, верхняя и нижняя обивка для RelativeLayout жестко запрограммирован. Поскольку атрибут style не используется, нет способа переопределить заполнение. Из-за этого жесткого кодирования у вас есть два варианта:

  1. Используйте "действительно плохой обходной путь", изложенный в ответе, который вы нашли, который включает в себя код Java для изменения заполнения, или,

  2. Используйте свой собственный макет, определяя android:layout="@layout/custom_preference" в XML для ваших предпочтений. Вы можете скопировать макет Android и внести свои изменения.

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


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

MainActivity.java
Для удобства эта деятельность добавляется во фрагмент предпочтения.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            Fragment preferenceFragment = new PrefsFragment();
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.add(R.id.prefContainer, preferenceFragment);
            ft.commit();
        }
    }

    public static class PrefsFragment extends PreferenceFragmentCompat {

        @Override
        public void onCreatePreferences(Bundle bundle, String s) {
            addPreferencesFromResource(R.xml.app_preferences);
        }
    }
}

app_preference.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <android.support.v7.preference.Preference
        android:key="preference"
        android:layout="@layout/custom_pref_layout"
        android:summary="Doesn't really do anything."
        android:title="Preference Title" />

    <android.support.v7.preference.EditTextPreference
        android:defaultValue="Default EditTextPreference value"
        android:dialogMessage="EditTextPreference Dialog Message"
        android:inputType="number"
        android:key="editTextPreference"
        android:layout="@layout/custom_pref_layout"
        android:summary="EditTextPreference Summary"
        android:title="EditTextPreference Title" />

    <android.support.v7.preference.SwitchPreferenceCompat
        android:defaultValue="true"
        android:key="switchPreference"
        android:layout="@layout/custom_pref_layout"
        android:summary="SwitchPreference Summary"
        android:title="SwitchPreference Title" />

    <android.support.v7.preference.CheckBoxPreference
        android:defaultValue="true"
        android:key="checkBoxPreference"
        android:layout="@layout/custom_pref_layout"
        android:summary="CheckBoxPreference Summary"
        android:title="CheckBoxPreference Title" />

    <android.support.v7.preference.ListPreference
        android:defaultValue="180"
        android:entries="@array/pref_sync_frequency_titles"
        android:entryValues="@array/pref_sync_frequency_values"
        android:key="list_preference"
        android:layout="@layout/custom_pref_layout"
        android:negativeButtonText="@null"
        android:positiveButtonText="@null"
        android:title="List Preference Title" />

</android.support.v7.preference.PreferenceScreen>

activity_main.xml
Просто определяет дом для предпочтительного фрагмента.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/prefContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.preferencecustomlayout.MainActivity" />

custom_pref_layout.xml
Некоторые изменения были сделаны, чтобы приспособить использование этого файла, в основном обновленного ?attr/somthing в ?android:attr/something,

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
          http://www.apache.org/licenses/LICENSE-2.0
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<!-- Layout for a Preference in a PreferenceActivity. The
     Preference is able to place a specific widget for its particular
     type in the "widget_frame" layout. -->

<!-- Modified from the original to accommodate usage as a local layout file. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:clipToPadding="false"
    android:gravity="center_vertical"
    android:minHeight="?attr/listPreferredItemHeightSmall"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart">

    <LinearLayout
        android:id="@+id/icon_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="-4dp"
        android:gravity="start|center_vertical"
        android:minWidth="60dp"
        android:orientation="horizontal"
        android:paddingBottom="4dp"
        android:paddingEnd="12dp"
        android:paddingTop="4dp">

        <com.android.internal.widget.PreferenceImageView
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxHeight="48dp"
            android:maxWidth="48dp" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:paddingBottom="16dp"
        android:paddingTop="16dp">

        <TextView
            android:id="@android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:singleLine="true"
            android:textAppearance="?attr/textAppearanceListItem" />

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@android:id/title"
            android:layout_below="@android:id/title"
            android:ellipsize="end"
            android:maxLines="10"
            android:textAppearance="?attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary" />
    </RelativeLayout>
    <!-- Preference should place its actual preference widget here. -->
    <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"
        android:paddingStart="16dp" />
</LinearLayout>

Gradle файл

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    buildToolsVersion '27.0.3'

    defaultConfig {
        applicationId "com.example.preferencecustomlayout"
        minSdkVersion 18
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:preference-v7:27.1.1'
    implementation 'com.android.support:preference-v14:27.1.1'
}
Другие вопросы по тегам