onUserInteraction not working in DialogPreference
Here is a complete solution for a DialogFragment
, which triggers Activity's onUserInteraction()
on a touch and preserves default callback's behavior:
public abstract class BaseDialogFragment extends DialogFragment {
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Window window = getDialog().getWindow();
if (window != null) {
window.setCallback(new UserInteractionAwareCallback(window.getCallback(), getActivity()));
}
}
}
And here is the Callback itself:
public class UserInteractionAwareCallback implements Window.Callback {
private final Window.Callback originalCallback;
private final Activity activity;
public UserInteractionAwareCallback(final Window.Callback originalCallback, final Activity activity) {
this.originalCallback = originalCallback;
this.activity = activity;
}
@Override
public boolean dispatchKeyEvent(final KeyEvent event) {
return originalCallback.dispatchKeyEvent(event);
}
@Override
public boolean dispatchKeyShortcutEvent(final KeyEvent event) {
return originalCallback.dispatchKeyShortcutEvent(event);
}
@Override
public boolean dispatchTouchEvent(final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
if (activity != null) {
activity.onUserInteraction();
}
break;
default:
}
return originalCallback.dispatchTouchEvent(event);
}
@Override
public boolean dispatchTrackballEvent(final MotionEvent event) {
return originalCallback.dispatchTrackballEvent(event);
}
@Override
public boolean dispatchGenericMotionEvent(final MotionEvent event) {
return originalCallback.dispatchGenericMotionEvent(event);
}
@Override
public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
return originalCallback.dispatchPopulateAccessibilityEvent(event);
}
@Nullable
@Override
public View onCreatePanelView(final int featureId) {
return originalCallback.onCreatePanelView(featureId);
}
@Override
public boolean onCreatePanelMenu(final int featureId, final Menu menu) {
return originalCallback.onCreatePanelMenu(featureId, menu);
}
@Override
public boolean onPreparePanel(final int featureId, final View view, final Menu menu) {
return originalCallback.onPreparePanel(featureId, view, menu);
}
@Override
public boolean onMenuOpened(final int featureId, final Menu menu) {
return originalCallback.onMenuOpened(featureId, menu);
}
@Override
public boolean onMenuItemSelected(final int featureId, final MenuItem item) {
return originalCallback.onMenuItemSelected(featureId, item);
}
@Override
public void onWindowAttributesChanged(final WindowManager.LayoutParams attrs) {
originalCallback.onWindowAttributesChanged(attrs);
}
@Override
public void onContentChanged() {
originalCallback.onContentChanged();
}
@Override
public void onWindowFocusChanged(final boolean hasFocus) {
originalCallback.onWindowFocusChanged(hasFocus);
}
@Override
public void onAttachedToWindow() {
originalCallback.onAttachedToWindow();
}
@Override
public void onDetachedFromWindow() {
originalCallback.onDetachedFromWindow();
}
@Override
public void onPanelClosed(final int featureId, final Menu menu) {
originalCallback.onPanelClosed(featureId, menu);
}
@Override
public boolean onSearchRequested() {
return originalCallback.onSearchRequested();
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public boolean onSearchRequested(final SearchEvent searchEvent) {
return originalCallback.onSearchRequested(searchEvent);
}
@Nullable
@Override
public ActionMode onWindowStartingActionMode(final ActionMode.Callback callback) {
return originalCallback.onWindowStartingActionMode(callback);
}
@TargetApi(Build.VERSION_CODES.M)
@Nullable
@Override
public ActionMode onWindowStartingActionMode(final ActionMode.Callback callback, final int type) {
return originalCallback.onWindowStartingActionMode(callback, type);
}
@Override
public void onActionModeStarted(final ActionMode mode) {
originalCallback.onActionModeStarted(mode);
}
@Override
public void onActionModeFinished(final ActionMode mode) {
originalCallback.onActionModeFinished(mode);
}
}
As far as I know, the onUserInteraction()
is simply not called while the user is interacting with a dialog (even started from Activity
in which you're monitoring interactions).
Two solutions I know are:
Subclass
Dialog
/DialogPreference
class and overridedispatchTouchEvent()
.Implement
Window.Callback
interface and set it asDialog
s window callback by issuing:dialog.getWindow().setCallback(callbackImplementation);
Note: this implementation should process all received events by calling appropriate dialog methods or handle the events in your own way (e.g. by manually calling
onUserInteraction()
).
Edit
You have couple of ways to get Activity
from the custom PreferenceDialog
instance.
Call
DialogPreference.getPreferenceManager()
method which returnsPreferenceManager
. It has agetActivity()
method but it's package-private so you would have to put your customDialogPreference
inandroid.preference
package to access it.In the
PreferenceActivity.onCreate()
, after inflating the preferences, usefindPreference()
to find your customDialogPreference
by key. Then cast it to your custom class and set activity tothis
via an accessor.
I would go with the second option.