환경 설정 화면을 디자인하는 데 매우 이상한 문제가 있습니다. 레이아웃에 여백을주지 않지만 왼쪽에 약간의 공간이 남습니다.
아래 이미지에서 볼 수 있듯이 :
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"
사용자 지정 기본 설정에 대한 후속 조치
사용자 지정 기본 설정의 경우, 특히 오래된 장치에서이 솔루션이 항상 작동하는 것은 아니라는 것을 알았습니다. 예를 들어 다음과 같은 기본 설정은 여전히 들여 쓰기 될 수 있습니다.
com.example.preference.SomeCustomPreference
android:id="@+id/some_custom_preference"
android:name="Custom Preference"
android:key="@string/custom_pref_key"
android:summary="@string/custom_pref_summary"
android:title="@string/preference_custom_title"
app:iconSpaceReserved="false"
이 문제는 사용자 지정 기본 설정 클래스에서 세 번째 생성자 매개 변수의 사용을 추적합니다. 세 번째 매개 변수를 전달하면 목록 항목이 들여 쓰기됩니다. 생략하면 목록이 올바르게 정렬됩니다.
class SomeCustomPreference
@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = android.R.attr.someCustomPreferenceStyle
) : DialogPreference(context, attrs, defStyle) {
override fun getDialogLayoutResource(): Int {
return R.layout.my_layout
}
}
그 대신 다음을 사용하십시오.
class SomeCustomPreference
@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : DialogPreference(context, attrs) {
override fun getDialogLayoutResource(): Int {
return R.layout.my_layout
}
}
이것에 대한 크레딧은이 아주 오래된 포스트의 @CommonsWare로 이동합니다 .
답변
여기 에서이 문제에 대해보고 했지만 (거기에서 내 해결 방법 프로젝트를 확인할 수도 있습니다), 지금은 약간 해킹이되었지만이를 극복 할 수있는 쉬운 방법을 찾았습니다.
-
의 경우
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)
}
}
}
자바
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());
}
}
}
그리고 결과 ( 이 Google 샘플 의 XML 샘플은 여기 에서 찾을 수 있습니다. 여기 에서 확인하기 위해 생성 했습니다.)
이 코드는 약간 위험하므로 라이브러리를 업데이트 할 때마다 제대로 작동하는지 확인하십시오.
또한 android:layout
기본 설정을 직접 정의 할 때와 같은 일부 특수한 경우에는 제대로 작동하지 않을 수 있으므로이 문제에 대해 수정해야합니다.
더 나은 공식 솔루션이 있습니다.
각 환경 설정에 대해 app:iconSpaceReserved="false"
. 이것은 잘 작동하지만 어떤 이유로 PreferenceCategory에서 작동하지 않는 (알려진) 버그가 있습니다. 그것은보고 여기에 , 그리고 가까운 장래에 고정되어야한다.
따라서 지금은 내가 작성한 해결 방법과이 플래그의 혼합 버전을 사용할 수 있습니다.
편집 : 또 다른 해결책을 찾았습니다. 이것은 모든 기본 설정 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
}
}
자바
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)
}
}
}
그것에서 확장하면 선호도에 쓸모없는 패딩이 없습니다. 여기에 샘플 프로젝트가 있습니다 . 여기서는 그러한 트릭 대신 공식적인 방법을 요청합니다. 주연을 고려하십시오.
답변
여기 에서 간단한 작업 솔루션 .
모든 기본 설정에 쓸 필요없이 모든 기본 설정에서 작동합니다.app:iconSpaceReserved="false"
만들기 res/values-sw360dp/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를 해결.
편집 : 사용하는 경우 androidx.preference:preference:1.1.1
치수가 필요하지 않습니다 preference_category_padding_start
. Android 6-10에서 테스트되었습니다.
답변
이 시도:
@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 Material 환경 설정 테마 오버레이 로 설정되어 있는지 확인하십시오 .
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
답변
불행히도 위의 아무것도 나를 위해 일하지 않았습니다.
짧은 대답 :
사용자 지정 기본 설정 레이아웃의 맨 위 컨테이너에 음수 여백 을 사용하여이 문제를 해결했습니다 .
단계 :
- 기본 설정에 대한 사용자 지정 레이아웃 만들기 (예 : preferences_category.xml)
- XML의 환경 설정 태그에 android : layout param을 추가하여 환경 설정이 사용자 정의 레이아웃을 사용하도록 지정
- 마이너스 여백 적용
자세한 답변 :
기본 설정 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);
}