1

Does anyone know a way I can capture a long tap as well as a click on a preference in a preference fragment?

Specifically, I have a class extending DialogPreference and I would like it to open a different dialog based on whether it was Clicked or Long Tapped.

I've been trying to implement this for some time now and can't seem to make it work with preference fragments. How to add a "long click listener" to a Preference?

Thanks!

Community
  • 1
  • 1

2 Answers2

2

I had difficulty making this work in the case of nested preference screens. The ListView seen by the fragment itself is only the top level list. When you open a subscreen, under the hood you're actually popping up a dialog. This is problematic because (1) PreferenceScreen is final, and (2) The dialog does not exist until the item is clicked, and it's hard or impossible to get the dialog from the fragment because of (1).

The way I solved it is a bit of a hack, but I figured, "If I can't get the listView from above in the hierarchy, I can get it from below." My PreferenceScreen happened to be full of instances of custom Preferences. Since Preference is obviously not final, we can take advantage of the fact that when the Preference's view is created, the PreferenceScreen is on is definitely there. You can access it pretty easily and apply Kostya's method.

public class MyEditTextPreference extends EditTextPreference {

    @Override
    protected View onCreateView(ViewGroup parent) {
        ListView listView = (ListView)parent;
        listView.setOnItemLongClickListener(new ListView.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;
            }
        });
        return super.onCreateView(parent);
    }
}

Of course if you have multiple preferences doing this you'll keep setting the Listener over and over. You can add some checks to prevent this if you want.

atw13
  • 719
  • 3
  • 7
0

Add onCreateView() to your PreferenceFragment class:

public class MyPreferenceFragment extends PreferenceFragment implements  OnItemLongClickListener {

...

    @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        Log.d("TAG", "onCreateView");

        View view = inflater.inflate(R.layout.settings, container, false);
        ListView listView = (ListView) view.findViewById(android.R.id.list);
        listView.setOnItemLongClickListener(this);
        return view;
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {

        Log.d("TAG", "onItemLongClick");

        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;
            ...
        }

        return true;
    }

...

}

settings.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>
almisoft
  • 2,153
  • 2
  • 25
  • 33