简体   繁体   中英

How to make a Preference long-clickable in PreferenceFragment?

Here is a similar question but assumes the use of PreferenceActivity .

However, how to make a preference long-clickable when there is no PreferenceActivity , for example when using a PreferenceFragment ?

PreferenceFragment does not provide a reference to ListView ( getListView() is hidden from the API), so the same approach is not possible.

class LongClickablePreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
    /**
     * @return true if the long-click was handled
     */
    var onPreferenceLongClickListener: ((Preference) -> Boolean)? = null

    override fun onBindViewHolder(holder: PreferenceViewHolder) {
        super.onBindViewHolder(holder)
        holder.itemView.setOnLongClickListener {
            performLongClick()
        }
    }

    private fun performLongClick(): Boolean {
        if (!isEnabled || !isSelectable) {
            return false
        }
        return onPreferenceLongClickListener?.invoke(this) ?: false
    }
}

A similar approach can be taken for other Preference types.

This solution is slightly risky because it makes assumptions about the super class PreferenceFragment (using a ListView and using the android.R.id.list id).

I tried another approach of setting an OnLongClickListener on the pref's View but this then made the checkbox unclickable and I could not find a way to correct that. So this is the best solution i have so far.

public class MyPreferenceFragment extends PreferenceFragment implements OnItemLongClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
        setPreferenceScreen(root);

        CheckBoxPreference pref = new LongClickableCheckBoxPreference(getActivity()) {
            @Override
            public boolean onLongClick(View v) {
                // YAY! you long-clicked me :)
                return true;
            }
        };
        // configure the pref here
        root.addPreference(pref);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View result = super.onCreateView(inflater, container, savedInstanceState);
        if (result != null) {
            View lv = result.findViewById (android.R.id.list);
            if (lv instanceof ListView) {
                ((ListView)lv).setOnItemLongClickListener(this);
            }
            else {
                // oh noes! it looks like this PreferenceFragment does not use the standard id for listviews
            }
        }
        return result;
    }

    private static abstract class LongClickableCheckBoxPreference extends CheckBoxPreference implements View.OnLongClickListener {
        public LongClickableCheckBoxPreference(Context context) {
            super(context);
        }
    }
}

All the answers I found on SO like these above are now obsolete as they deal with preference screen based on ListView whereas AppCmpat and androidx use RecyclerView. In such case one can do the following: 1. Extend preference class 2. Override onBindViewHolder 3. define some interface for outer fragment/activity and invoke interface method in Holder.View.OnLongClickListener

private static class OrgPreference extends SwitchPreference
    {
        private final OnEntryClickListener mOnEntryClickListener;

        public OrgPreference(Context context, OnEntryClickListener onEntryClickListener) {
            super(context);
            mOnEntryClickListener = onEntryClickListener;
        }

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

            holder.itemView.setOnLongClickListener(view -> {
                String companyId = OrgPreference.this.getKey();
                mOnEntryClickListener.onEntryLongClick(companyId);
                return true;
            });
        }
    }

In fragment/activity:

interface OnEntryClickListener {
        void onEntryLongClick(String companyId);
    }

...

OrgPreference switchPreference = new OrgPreference(getContext(), new OnEntryClickListener() {
            @Override
            public void onEntryLongClick(String companyId) {
                //Do stuff
            }
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM