consp1racy / android-support-preference

Android Preferences according to Material design specs
Apache License 2.0
331 stars 49 forks source link

Set title and summary on multilines #42

Closed goldmont closed 8 years ago

goldmont commented 8 years ago

Hi,

Please add a parameter to set both title and summary of a CheckBoxPreference on multilines because, for example, when I use a long title it get cut and hidden. I wrote a custom CheckBoxPreference based on yours:


    @Override
    public void onBindViewHolder(final PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);

        TextView mTitle = (TextView) holder.findViewById(android.R.id.title);
        mTitle.setSingleLine(false);

        View checkboxView = holder.findViewById(android.R.id.checkbox);
        if (checkboxView == null) {
            checkboxView = holder.findViewById(R.id.checkbox);
        }
        if (checkboxView instanceof Checkable) {
            ((Checkable) checkboxView).setChecked(mChecked);
        }

        syncSummaryView(holder);
    }

This is the custom onBindViewHolder method I'm using currently. Thank you for your work.

consp1racy commented 8 years ago

Your titles should fit one line no problem. Check this for guidelines https://material.google.com/patterns/settings.html#settings-placement.

preference-v7 limits are even worse (1/4) than mine (1/10), that should hint you into being more effective while writing settings labels. Nobody likes to read them. Be short and clear.


I will not be changing these limits, however...

Put this in your res/layout folder to alter base preference layout:

asp_preference.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?selectableItemBackground"
    android:baselineAligned="false"
    android:clipToPadding="false"
    android:gravity="center_vertical"
    android:minHeight="?listPreferredItemHeightSmall"
    android:paddingLeft="?listPreferredItemPaddingLeft"
    android:paddingRight="?listPreferredItemPaddingRight"
    tools:ignore="RtlHardcoded">

    <FrameLayout
        android:id="@+id/icon_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="12dp"
        android:layout_marginLeft="-4dp"
        android:layout_marginRight="12dp"
        android:layout_marginStart="-4dp"
        android:minWidth="48dp"
        android:visibility="gone"
        tools:visibility="visible">

        <ImageView
            android:id="@android:id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxHeight="48dp"
            android:maxWidth="48dp"
            android:scaleType="fitStart"
            android:visibility="gone"
            tools:ignore="ContentDescription"
            tools:visibility="visible"/>
    </FrameLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        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"
            maxLines="2"
            android:textAppearance="?textAppearanceListItem"/>

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="10"
            android:textAppearance="?asp_textAppearanceListItemSecondary"
            android:textColor="?android:textColorSecondary"/>

    </LinearLayout>

    <!-- 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:layout_marginEnd="-16dp"
        android:layout_marginRight="-16dp"
        android:clipToPadding="false"
        android:gravity="end|center_vertical"
        android:orientation="vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"/>

</LinearLayout>

This layout will affect everything except SeekBarPreference.

goldmont commented 8 years ago

Amazing.. Solved! Thank you man.

goldmont commented 7 years ago

Hi @consp1racy , I have not managed to make the above solution working again in an another App. The library works fine but even if I put the custom layout in /res/layout, nothing changes. I'm using the latest version of this library. Waiting for a prompt response. Thank you and merry Christmas!

P.s. The widget I'm talking about is a CheckboxPreference

consp1racy commented 7 years ago

The correct way is to use the style framework:

<style name="AppTheme" parent="Theme.AppCompat">
    <item name="preferenceTheme">@style/PreferenceThemeOverlay.MyApp</item>
</style>

<style name="PreferenceThemeOverlay.MyApp" parent="PreferenceThemeOverlay.Material">
    <item name="checkBoxPreferenceStyle">@style/Preference.MyApp.CheckBoxPreference</item>
</style>

<style name="Preference.MyApp.CheckBoxPreference" parent="Preference.Material.CheckBoxPreference">
    <item name="android:layout"><!-- put item layout reference here --></item>
    <item name="android:widgetLayout"><!-- put item widget layout reference here --></item>
</style>

Here are the rules:

goldmont commented 7 years ago

The log says:

Error:(2649, 21) No resource found that matches the given name: attr 'preferenceThemeOverlay'.
goldmont commented 7 years ago

I tried to replace the attr "preferenceThemeOverlay" with "preferenceTheme" but your solution still does not work.. Can't understand what's the problem

consp1racy commented 7 years ago

What version of the app are you using in both apps? Any other differences? Can you post the layout with filename? What's the expected vs. current result?

goldmont commented 7 years ago

I'm using the latest versions of the requested libraries:

compile "com.android.support:preference-v7:25.1.0"
compile "net.xpece.android:support-preference:1.2.1"

The preference layout is the following and its name in my layout folder is "custom_preference_layout":

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?selectableItemBackground"
    android:baselineAligned="false"
    android:clipToPadding="false"
    android:gravity="center_vertical"
    android:minHeight="?listPreferredItemHeightSmall"
    android:paddingLeft="?listPreferredItemPaddingLeft"
    android:paddingRight="?listPreferredItemPaddingRight"
    tools:ignore="RtlHardcoded">

    <FrameLayout
        android:id="@+id/icon_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="12dp"
        android:layout_marginLeft="-4dp"
        android:layout_marginRight="12dp"
        android:layout_marginStart="-4dp"
        android:minWidth="48dp"
        android:visibility="gone"
        tools:visibility="visible">

        <ImageView
            android:id="@android:id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxHeight="48dp"
            android:maxWidth="48dp"
            android:scaleType="fitStart"
            android:visibility="gone"
            tools:ignore="ContentDescription"
            tools:visibility="visible"/>
    </FrameLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        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:maxLines="10"
            android:textAppearance="?textAppearanceListItem"/>

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="10"
            android:textAppearance="?asp_textAppearanceListItemSecondary"
            android:textColor="?android:textColorSecondary"/>

    </LinearLayout>

    <LinearLayout
        android:id="@android:id/widget_frame"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginEnd="-16dp"
        android:layout_marginRight="-16dp"
        android:clipToPadding="false"
        android:gravity="end|center_vertical"
        android:orientation="vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"/>

</LinearLayout>

I have just replaced

android:singleLine="true"

with

android:maxLines="10"

The checkbox layout is the following and its name in my layout folder is "custom_checkbox_preference_layout" (the layout is equal to the original):

<?xml version="1.0" encoding="utf-8"?>
<CheckBox android:id="@+id/checkbox"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginLeft="-4dp"
          android:layout_marginRight="-4dp"
          android:background="@null"
          android:clickable="false"
          android:focusable="false"/>

Then I set them in my styles.xml as you told to me. The result is that nothing changes, like my layout isn't applied

consp1racy commented 7 years ago

Can you share a sample project showing the symptoms? Thanks, I'll look into it.

goldmont commented 7 years ago

I did it! I managed to get it working! I had in mind to use XpPreferenceFragment instead of original PreferenceFragment. Then I have just replaced the preference layout with a new one having the same name in my res/layout directory and it worked. But now there is another problem. Using XpPreferenceFragment appears on the screen something like a white overlay on the Fragment space; instead, using the original PreferenceFragment, the overlay does not appear.

XpPreferenceFragment: http://imgur.com/mCaHszE Original PreferenceFragment: http://imgur.com/4FyecTL

consp1racy commented 7 years ago

Have you tried this?

You may have experienced unexpected background color which manifests as holo blue on Android 4 and grey on Android 5. This is caused by PreferenceFragment's RecyclerView grabbing focus on fragment start. We can disable this behavior while still being able to navigate between individual preferences with a D-pad.

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    final RecyclerView listView = getListView();

    // We don't want this. The children are still focusable.
    listView.setFocusable(false);
}
goldmont commented 7 years ago

Now everything seems to work fine ;) Thank you man!!