設定画面の設計で非常に奇妙な問題に直面しています。レイアウトに余裕はありませんが、左にスペースを残しています。
下の画像でわかるように:
XML:
<PreferenceScreen Android:title="demo" >
<CheckBoxPreference
Android:defaultValue="false"
Android:key="prefSync"`
Android:title="Auto Sync" />
</PreferenceScreen>
画面にチェックボックス設定を追加する際に何か間違ったことをしていますか?
Androidx用にこれを更新します。
多くの実験の後、私はこれを追加することでこの問題を解決しました各設定に過剰なインデントがありました:
app:iconSpaceReserved="false"
もちろん、xmlの先頭にあるPreferenceScreen宣言自体にもこれを追加する必要があります。
xmlns:app="http://schemas.Android.com/apk/res-auto"
私はこの問題について報告しました here (そこに私の回避策のプロジェクトを確認することもできます)、しかし今のところ、私はveはこれを克服するための少しハックな、しかし簡単な方法を見つけました:
PreferenceCategory
の場合、レイアウトの開始/左パディングを0に設定します。
他の種類の設定については、アイコンがない場合に備えてicon_frame
を非表示にすることを選択します。
コードは次のとおりです。このクラスから拡張するだけで、残りは自動です:
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());
}
}
}
そして、結果(XMLサンプルが見つかります here of this Googleサンプル 、私が作成したもの here チェックアウトするには) :
このコードは少し危険なので、ライブラリを更新するたびに、正常に動作することを確認してください。
また、環境設定に独自のAndroid:layout
を定義する場合など、いくつかの特殊なケースではうまく機能しない可能性があるため、この問題のために変更する必要があります。
より良い、より公式なソリューションを手に入れました:
設定ごとに、app:iconSpaceReserved="false"
を使用します。これは正常に機能するはずですが、何らかの理由で、PreferenceCategoryでは機能しない(既知の)バグがあります。 here と報告されており、近い将来修正される予定です。
したがって、今のところ、私が書いた回避策とこのフラグの混合バージョンを使用できます。
編集:さらに別のソリューションが見つかりました。これはすべての設定を取得し、それぞれにisIconSpaceReserved
を設定します。悲しいことに、私が上で書いたように、PreferenceCategoryを使用すると、それは台無しになりますが、使用しなくても問題なく動作するはずです。
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);
}
}
}
編集:Googleが最終的にライブラリを修正した後(リンク here )、各設定にフラグを設定するか、これを使用できますあなたのためにすべてのためにそれを行うソリューション:
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)
}
}
}
そこから拡張するだけで、好みに合わせて無駄なパディングをする必要がなくなります。サンプルプロジェクト here 。ここでは、それらのトリックの代わりに、それを回避する公式な方法も要求しています。主演を検討してください。
here からのシンプルな作業ソリューション
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を修正します。
これを試して:
_@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();
com.Android.support:preference-v7
ライブラリを使用している場合、設定をホストしているアクティビティのテーマにpreferenceTheme
がv14マテリアル設定テーマオーバーレイに設定されていることを確認してください。
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
残念ながら、上からのことは何も役に立たなかった。
短い答え:
これを解決するには、カスタム設定レイアウトの一番上のコンテナで負のマージンを使用しました。
手順:
詳細な回答:
設定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" />
パディングは、設定を含む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);
}
このような設定テーマを変更します。設定ライブラリの最新バージョンを使用してください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>
'com.Android.support:preference-v7:24.2.1'をコンパイルします
PreferenceFragmentCompatを使用すると、次のことができます。
1. PreferenceGroupAdapterを定義します。
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. 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>
上記の回答はどれもうまくいきませんでした preference レイアウトをコピーし、custom_preference.xmlなどの新しいレイアウトファイルを作成し、visibilityを設定してレイアウトコンテンツをオーバーライドする必要がありました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>
使ってみます
Android:icon="@null"
with CheckBoxPreference
in Android 4.4しかし、左からパディングできません。小さな透明アイコンを使用して、追加しました
Android:icon="@drawable/transparent_icon"
それは私にとってはうまくいくようです。私はそれが役立つことを願っています。ありがとう。
「パディング」は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で定義されたスタイルをオーバーライドする方法を知っていれば、おそらくこれを解決できます。ただし、それほど単純ではありません。
かなり前に尋ねましたが、これを解決するのに役立ったのはマイナスのマージンで、カスタムファイルは必要ありませんでした。
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>
答えるには遅すぎるかどうかはわかりませんが、今日は同じ問題があり、この答えのどれも私を助けません。
だから私はこのソリューションを使用しました:
私のDisclaimerPreference
that _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
として設定することです。何か問題がある場合はお知らせください:)
どうやら、Android:layout="@null"
to xmlの設定でこのトリックを行います。しかし、その結果、タイトルサイズも大きくなります。