Pbal February 2016

Parent view doesn't get longpress event

I am trying to write a launcher-like app which can add Widgets to its screen.

I am using Leonardo Fischer's tutorial (http://leonardofischer.com/hosting-android-widgets-my-appwidgethost-tutorial/) which is great.

In order to remove a widget, the user is supposed to longpress the Widget and that's where I am running into some trouble; some Widgets (WhatsApp Messagelist, Evernote List, for instance) allow you to scroll them. For some reason, if you scroll, Android fires a LongClick event which wrongfully removes the widget...

My code: (creates the widget and set LongClickListener)

public void createWidget(Intent data) {
    Bundle extras = data.getExtras();
    int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
    AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

    final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
    hostView.setAppWidget(appWidgetId, appWidgetInfo);

    // relative layout
    //RelativeLayout.LayoutParams lp = new RelativeLayout()
    //mainlayout.addView(hostView, lp);
    mainlayout.addView(hostView);

    // [COMMENTED OUT] hostView.setOnLongClickListener(new AppWidgetLongClickListener(hostView));

}

UPDATE

Countless hours later, I think I partially understood what's happening, but I still can't get the correct behaviour.

According to http://balpha.de/2013/07/android-development-what-i-wish-i-had-known-earlier/ , you need to implement an onInterceptTouchEvent in the parent container (mainlayout in my case) to intercept and treat events before they reach the childre

Answers


Doug Stevenson February 2016

If you really are seeing an event for starting a scroll being followed by an event for a long click, you could deal with that by setting a flag in your event handling class that tracks when scroll begins and ends, and choose to ignore the long click if a scroll is in progress.


Pbal February 2016

So it's done...! I am not sure whether this is an elegant solution, but it works.

onInterceptTouchEvent allows a parent view to act on events before they are sent to the final sender. Please note the it won't fire if you touch the actual view. So if you have a Layout with some "blank space" and some elements, onInterceptTouchEvent won't fire if you touch the layout's "blank space" (you will need the layout's onTouchEvent in this case).

Because we can essentially only track ACTION_UP, ACTION_MOVE and ACTION_DOWN events, we need to time the duration of a ACTION_DOWN / ACTION_UPpair of events to decide whether this is a longclick or not, so what I did follows:

public class time_counter {
    private long begin_time;
    private long end_time;


    public time_counter(long i, long f) {
        this.begin_time = i;
        this.end_time = f;
    }

    public long getDuration() {
        return (this.end_time - this.begin_time);
    }

}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

    // Consume any touch events for ourselves after longpress is triggered

    // Watch for longpress events at this level to make sure
    // users can always pick up this widget
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            cnt = new time_counter(ev.getEventTime(), (long)0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            if (cnt != null) {
                cnt.end_time = ev.getEventTime();
            }
            break;
        }
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (cnt != null) {
                cnt.end_time = ev.getEventTime();
            }
            Log.i(TAG, "DURATION: " + cnt.getDuration());
            if (cnt.getDuration() > ViewConfigur 

Post Status

Asked in February 2016
Viewed 1,502 times
Voted 5
Answered 2 times

Search




Leave an answer