Android Preference Fragment with Long Click Listener

Numero Uno. 

In the great tradition of half-assedness and incompleteness, this post starts where I am. My current predicament. A problem relating to Android preferences and fragments.

Android preference classes are used to add settings to an android app.  These classes are used in place of the typical view when creating the settings user interface.

 

These settings pages allow programmers to easily implement a configuration page without worrying about storage or modification of the underlying settings.

http://developer.android.com/guide/topics/ui/settings.html

Android preference implementations come in 2 major flavors: Activities and Fragments. Activities and Fragments are fundamental to android. A description of these could be a topic in itself. For now, lets shorten it to the following over-simplification:

Activity - An entire displayable page.
Fragment - A reusable building block or sub section of a page.

So what this boils down to is whether you show the preferences over the whole screen or inside another view, such as a tabbed display.

I am currently working to shoe-horn a preference activity from older code into the sleek new form factor of a fragment! This is quite a bit more cumbersome than it first appears. As the preference activity I am modifying is very dynamic.

The most simplistic android preference page looks something like the following:


package com.your.name.android.fragments;

import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceFragment;

public class SettingsFragment extends PreferenceFragment
{
    private static final String TAG = "SettingsFragment";

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }
}

However, I'm looking to do a bit more than this, such as click listeners and long click listeners to add and delete dynamic fields. This was previously done in the settings activity, however the fragment doesn't have quite the same access. 

To enable a long click listener in the settings fragment, we must first get the ListView that is used to display the settings. As luck would have it, there is no direct access. So instead we must find the view that is being used and ensure that it is a ListVew. This can only be done by overriding the onCreateView function and "borrowing" the view. From there we can cast it as a ListView and use it:


@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 
    {
      //The view created is not a list view!
    }
  }
  return result;
}

Last, just override the onItemLongClick listener.


@Override
public boolean onItemLongClick(AdapterView<?> parent, 
                               View view, 
                               int pos, 
                               long id )
{
  ListView listView = (ListView)parent;
  ListAdapter listAdapter = listView.getAdapter();
  Object obj = listAdapter.getItem( pos );

  if ( obj instanceof Preference )
  {
    Preference p = (Preference)obj;
    if ( p.getKey().matches( Main.REPORT ) ) 
    {
      showDeletePrompt( "Delete Report",
      String.format( "Do you want to delete the report '%s'?", p.getTitle() ),
      p.getKey(),
      pos );
      return true;
    }
  }/*if*/

  return false;
}

And Bob is your father's brother.