调整margin/padding在'PreferenceScreen'在Android
Adjust margin/padding in the 'PreferenceScreen' in Android
我想调整 Android 中 'PreferenceScreen' 的默认 margin/padding 值,我知道不可能简单地在 XML 代码中设置它(布局文件),但 Android 肯定是从某个地方获取这些值,并且可能(我希望)我可以设置一些 'style attribute(s)' 并实现它。
我要调整的值是:
我在网上找到了这个答案:
Android: How to maximize PreferenceFragment width (or get rid of margin)?
但据我所知,它确实使用了一个非常糟糕的解决方法,我想尝试操纵一些官方参数。
有谁知道如何通过调整样式或其他一些字段来实现它?
遗憾的是,我认为您不会找到比您在 Android: How to maximize PreferenceFragment width (or get rid of margin)? 中已经发现的更好的答案。我将解释原因并为您提供一个您可能认为比您参考的答案中提供的更糟糕的替代方案。
首选项屏幕下方是我们将识别的每个项目的布局。这些是我们将使用的首选项库依赖项:
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>
从 PreferenceThemeOverlay.v14.Material
向上父链 (ctrl-B) 我们看到
<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
。这是 source.
我们对这个布局的以下部分感兴趣:
...
<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
的顶部和底部填充是硬编码的。由于未使用样式属性,因此无法覆盖填充。由于这种硬编码,您有两个选择:
使用您找到的答案中概述的 "really bad workaround",其中涉及 Java 代码来修改填充,或者,
通过在 XML 中根据您的喜好定义 android:layout="@layout/custom_preference"
来使用您自己的布局。您可以复制 Android 布局并进行修改。
每种方法都有缺点,所以选择您认为最适合的方法。
以下是演示首选项布局替换的小应用程序的关键组件。
MainActivity.java
这个activity为方便起见放在偏好片段中。
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'
}
我想调整 Android 中 'PreferenceScreen' 的默认 margin/padding 值,我知道不可能简单地在 XML 代码中设置它(布局文件),但 Android 肯定是从某个地方获取这些值,并且可能(我希望)我可以设置一些 'style attribute(s)' 并实现它。
我要调整的值是:
我在网上找到了这个答案: Android: How to maximize PreferenceFragment width (or get rid of margin)?
但据我所知,它确实使用了一个非常糟糕的解决方法,我想尝试操纵一些官方参数。
有谁知道如何通过调整样式或其他一些字段来实现它?
遗憾的是,我认为您不会找到比您在 Android: How to maximize PreferenceFragment width (or get rid of margin)? 中已经发现的更好的答案。我将解释原因并为您提供一个您可能认为比您参考的答案中提供的更糟糕的替代方案。
首选项屏幕下方是我们将识别的每个项目的布局。这些是我们将使用的首选项库依赖项:
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>
从 PreferenceThemeOverlay.v14.Material
向上父链 (ctrl-B) 我们看到
<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
。这是 source.
我们对这个布局的以下部分感兴趣:
...
<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
的顶部和底部填充是硬编码的。由于未使用样式属性,因此无法覆盖填充。由于这种硬编码,您有两个选择:
使用您找到的答案中概述的 "really bad workaround",其中涉及 Java 代码来修改填充,或者,
通过在 XML 中根据您的喜好定义
android:layout="@layout/custom_preference"
来使用您自己的布局。您可以复制 Android 布局并进行修改。
每种方法都有缺点,所以选择您认为最适合的方法。
以下是演示首选项布局替换的小应用程序的关键组件。
MainActivity.java
这个activity为方便起见放在偏好片段中。
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'
}