Home > android, ui > Implementing long-clickable preferences

Implementing long-clickable preferences

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;
	}
}
About these ads
Categories: android, ui
  1. January 24, 2012 at 12:44 am

    The second code block is what you put into your PreferenceActivity subclass. It’s the “infrastructure”. It checks for whether a particular preference is long-clickable by using instanceof operator.

    Therefore, a preference that wishes to receive long clicks is expected to have “implements View.OnLongClickListener” in its class declaration.

    So:

    Make your own preference class that “extends CheckBoxPreference implements View.OnLongClickListener” – that’s the third code block above.

    Eclipse will require that you implement:

    	@Override
    	public boolean onLongClick(View v) {
    		// Do something for long click
    		return true;
    	}
    

    in your preference class. This is where you can respond to long clicks.

    Then use this preference instead of a “regular” CheckBoxPreference in your preference xml file, by specifying its fully qualified class:

    <PreferenceScreen ...>
      <my.app.package.name.MyLongClickableCheckBoxPreference
             android:key="..."
             android:title="Long click me"
       ...........
      />
    </PreferenceScreen>
    
    • Rob
      January 24, 2012 at 1:17 am

      AWESOME!!! Thanks for your help!

  2. Rob
    January 23, 2012 at 11:22 pm

    Do you have a working example of the code that I could see? I don’t quite understand how to implement it.

    • January 23, 2012 at 11:37 pm

      The see the second and third code blocks above, in the body of the post.

      • Rob
        January 24, 2012 at 12:31 am

        I don’t see how the third code block is related to the second code block.

        I would like to use a checkboxPreference so I would do the following?

        BlahBlahPreference myPreference;
        // get initial settings
        addPreferencesFromResource(R.layout.blahPrefs);
        myPreference = (CheckBoxPreference) findPreference(“blah”);

        Right now I’m using
        myPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference arg0, Object arg1)
        { Log.d(TAG,”PreferenceChange”); });
        }

        How do I use your Long click code?
        myPreference.setOnItemLongClickListener(new OnItemLongClickListener() {
        //@Override
        public boolean onItemLongClick(AdapterView parent, View view, int pos, final long listId) {
        ….

        }

        I can not cast myPreference to ListView…..

  3. December 24, 2011 at 3:47 am

    Thank you very much for your article. But how to retrieve the Preference-object within onItemLongClick?
    Or: How to retrieve this object from id or position?

    public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
    Preference pref = ?
    }

    • December 24, 2011 at 12:01 pm

      Alexander,

      It’s shown above:

      Get the preference object with “Object obj = listAdapter.getItem(position);”, then check “instanceof View.OnLongClickListener”.

      • December 25, 2011 at 2:20 am

        Yes, you are right. It works:

        @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);
        } else {
        Preference pref = (Preference) obj;
        // do something with pref …
        }
        return true;
        }

  4. awesome
    September 12, 2011 at 1:31 am

    Worked like a charm, thanks.

  1. January 19, 2013 at 2:30 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 100 other followers