8

I have an PreferenceActivity where I would like to add Preferences dynamically.

On a long click, these shall do something, however OnPreferenceClickListener only supports normal clicks, no long clicks.

Is there a way to implement this feature, did I miss something?

Thanks

Force
  • 6,312
  • 7
  • 54
  • 85

2 Answers2

13

In the event that the link dies, here is the main body of the post at that link. Note: I did not author anything below.

The built-in Preference class has a method to receive clicks, onClick, but no method to receive long clicks. In my current project, I actually have a need for this, and found a way to implement it.

PreferenceActivity is actually a ListActivity, with a special adapter behind the scenes. The usual (not long) clicks are processed by using the usual ListView mechanism, setOnItemClickListener. The code to set this up is in PreferenceScreen:

public final class PreferenceScreen extends PreferenceGroup implements AdapterView.OnItemClickListener.... {
    public void bind(ListView listView) {
        listView.setOnItemClickListener(this);
        listView.setAdapter(getRootAdapter());

        onAttachedToActivity();
    }

    public void onItemClick(AdapterView parent, View view, int position, long id) {
        Object item = getRootAdapter().getItem(position);
        if (!(item instanceof Preference)) return;
                     
        final Preference preference = (Preference) item;
        preference.performClick(this);
    }
}

It would be really easy to subclass PreferenceScreen and override bind to add a long-item-click listener to the list view, except this class is final. Because of this, I ended up adding the following code into my PreferenceActivity subclass:

public class BlahBlahActivity extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
 
        addPreferencesFromResource(R.xml.account_options_prefs);
 
        ListView listView = getListView();
        listView.setOnItemLongClickListener(new OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                ListView listView = (ListView) parent;
                ListAdapter listAdapter = listView.getAdapter();
                Object obj = listAdapter.getItem(position);
                if (obj != null && obj instanceof View.OnLongClickListener) {
                    View.OnLongClickListener longListener = (View.OnLongClickListener) obj;
                    return longListener.onLongClick(view);
                }
                return false;
            }
        });
    }
}

Now I can have a Preference subclass that implements View.OnLongClickListener, which is automatically invoked for long clicks:

public class BlahBlahPreference extends CheckBoxPreference implements View.OnLongClickListener {
    @Override
    public boolean onLongClick(View v) {
        // Do something for long click
        return true;
    }
}
Fabi755
  • 1,495
  • 1
  • 12
  • 29
Mxyk
  • 10,678
  • 16
  • 57
  • 76
  • How would I know which of the preferences exactly was long clicked ? – android developer Apr 06 '13 at 12:55
  • @androiddeveloper item which you get from list adapter(watch onItemLongClick method) is of Preference type, just invoke getKey() method to get the key)))) – grine4ka Sep 18 '13 at 14:31
  • @grine4ka this is quite an old post, but now that i read it, i can't see that the function you are talking about has any preference class. Preference doesn't extend View ... all it gets is "AdapterView> parent, View view, int position, long id" – android developer Sep 18 '13 at 22:48
  • @androiddeveloper `ListView listView = (ListView) parent; ListAdapter listAdapter = listView.getAdapter(); Object obj = listAdapter.getItem(position);` The type of obj is Preference or one of its subclasses. – grine4ka Sep 19 '13 at 06:30
  • Seems that this function isn't available for PreferenceFragment. However, it is possible to find the ListView using `findViewById(android.R.id.list)` inside `onCreateView`. Is there a better way? – android developer Feb 18 '18 at 23:46
1

Unable to test for you at the moment, but I'm wondering if you could achieve this by using the getView() method on a Preference. Then, once you have that View, use setOnLongClickListener().

Trevor
  • 10,903
  • 5
  • 61
  • 84
  • I tried this with a CheckboxPreference and it half worked. The preference was long clickable, but the checkbox became non-clickable, and I couldn't figure out how to fix that. – Mark Mar 18 '15 at 09:11
  • @Mark ... try to return false from onLongClick() callback – Zain Feb 26 '19 at 04:46