web-dev-qa-db-ja.com

Android:設定画面でマージン/パディングを削除する方法

設定画面の設計で非常に奇妙な問題に直面しています。レイアウトに余裕はありませんが、左にスペースを残しています。

下の画像でわかるように: enter image description here

XML:

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

画面にチェックボックス設定を追加する際に何か間違ったことをしていますか?

50
Dory

Androidx用にこれを更新します。

多くの実験の後、私はこれを追加することでこの問題を解決しました各設定に過剰なインデントがありました:

app:iconSpaceReserved="false"

もちろん、xmlの先頭にあるPreferenceScreen宣言自体にもこれを追加する必要があります。

xmlns:app="http://schemas.Android.com/apk/res-auto"
67
Alex

私はこの問題について報告しました 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 チェックアウトするには) :

enter image description 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 。ここでは、それらのトリックの代わりに、それを回避する公式な方法も要求しています。主演を検討してください。

43

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>は、すべてのiconSpacePreservedPreferenceのデフォルト値を修正します。 <dimen>はPreferenceCategoryを修正します。

14
t0m

これを試して:

_@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();

7
Sanket Shah

com.Android.support:preference-v7ライブラリを使用している場合、設定をホストしているアクティビティのテーマにpreferenceThemeがv14マテリアル設定テーマオーバーレイに設定されていることを確認してください。

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

5
mtrewartha

残念ながら、上からのことは何も役に立たなかった。

短い答え

これを解決するには、カスタム設定レイアウトの一番上のコンテナで負のマージンを使用しました。

手順:

  • 設定のカスタムレイアウトを作成します(preference_category.xmlなど)
  • android:layout paramを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" />
4
Gord

パディングは、設定を含むListViewの親PreferenceScreenが原因です。 PreferenceFragmentを使用して設定を作成している場合は、onActivityCreatedPreferenceFragement関数に移動し、次の手順でパディングを削除します。

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

'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>
1
zonda

上記の回答はどれもうまくいきませんでした 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>
1
s-hunter

使ってみます

Android:icon="@null"

with CheckBoxPreference in Android 4.4しかし、左からパディングできません。小さな透明アイコンを使用して、追加しました

Android:icon="@drawable/transparent_icon" 

それは私にとってはうまくいくようです。私はそれが役立つことを願っています。ありがとう。

0
Bao Doan

「パディング」は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で定義されたスタイルをオーバーライドする方法を知っていれば、おそらくこれを解決できます。ただし、それほど単純ではありません。

0
jayeffkay

かなり前に尋ねましたが、これを解決するのに役立ったのはマイナスのマージンで、カスタムファイルは必要ありませんでした。

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

答えるには遅すぎるかどうかはわかりませんが、今日は同じ問題があり、この答えのどれも私を助けません。

だから私はこのソリューションを使用しました:

私の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);
            }
         }
    }
_

重要なのは、メインビュー内でRelativeLayoutGONEとして設定することです。何か問題がある場合はお知らせください:)

0

どうやら、Android:layout="@null"to xmlの設定でこのトリックを行います。しかし、その結果、タイトルサイズも大きくなります。

0
John