我正在嘗試編寫一個類似於啓動程序的應用程序,它可以將Widgets添加到其屏幕。父視圖無法獲得longpress事件
我正在使用Leonardo Fischer的教程(http://leonardofischer.com/hosting-android-widgets-my-appwidgethost-tutorial/),這很棒。
爲了移除一個小部件,用戶應該長按這個小部件,這就是我遇到麻煩的地方;一些小部件(例如WhatsApp Messagelist,Evernote列表)允許您滾動它們。出於某種原因,如果您滾動,Android的觸發一個LongClick事件,不當取出小部件...
我的代碼: (創建窗口小部件並設置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
無數小時後,我想我部分瞭解發生了什麼,但我仍然無法得到正確的行爲。
據http://balpha.de/2013/07/android-development-what-i-wish-i-had-known-earlier/,你需要實現在父容器的onInterceptTouchEvent
(mainlayout
在我的情況),攔截和處理事件,他們到達兒童(部件在我的情況)前。
所以我用Google搜索了下面的代碼,並試圖適應我的需求:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Consume any touch events for ourselves after longpress is triggered
//Log.i(TAG,"OnIntercept: "+ev.toString());
if (mHasPerformedLongPress) {
Log.i(TAG,"Longpress OK!: "+ev.toString());
mHasPerformedLongPress = false;
return true;
}
// Watch for longpress events at this level to make sure
// users can always pick up this widget
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
postCheckForLongClick();
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress != null) {
removeCallbacks(mPendingCheckForLongPress);
}
break;
}
// Otherwise continue letting touch events fall through to children
return false;
}
class CheckForLongPress implements Runnable {
private int mOriginalWindowAttachCount;
public void run() {
Log.i(TAG,"Inside RUN");
if (getParent()!= null) {
Log.i(TAG,"getParent:"+getParent().toString());
}
if ((getParent() != null) && hasWindowFocus()
&& (mOriginalWindowAttachCount == getWindowAttachCount())
&& !mHasPerformedLongPress) {
if (performLongClick()) { // <-- DOESN'T WORK :(
mHasPerformedLongPress = true;
}
}
}
public void rememberWindowAttachCount() {
mOriginalWindowAttachCount = getWindowAttachCount();
}
}
private void postCheckForLongClick() {
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
mPendingCheckForLongPress.rememberWindowAttachCount();
postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
}
@Override
public void cancelLongPress() {
super.cancelLongPress();
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress != null) {
removeCallbacks(mPendingCheckForLongPress);
}
}
上面的代碼不會攔截觸摸事件,當我點擊一個窗口小部件,但它的邏輯似乎旨在攔截(並直接用於進一步的治療)longclicks小部件。我真正需要的是在父視圖內截取一個longclick。
訣竅似乎在於在if (performLongClick())
,其中,據我可以得到,觸發一個事件LongClick到小部件 ...
...所以我想我現在的問題是如何跟蹤父視圖內的一個長按鈕。
對不起,在處理機器人UI事件長(和看似基本的)的問題,但是從我一派這似乎是一個很令人費解的話題..
感謝這個想法,但正如你可以在我的代碼片段中看到的,我正在實現'setOnLongClickListener',並且從我可以看到的情況來看,'AppWidgetHostView'沒有用於跟蹤滾動事件的接口。你能在這裏指出我正確的方向嗎? – Pbal
從你的問題描述來看,它聽起來像你有一個滾動小部件。如果您沒有滾動窗口小部件,則主屏幕可能會將緩慢拖動解釋爲長按,並且您無法做出任何改變。 –
你是對的;小部件,如WhatsApp的未讀列表和印象筆記列表**正在滾動窗口小部件**,並且每當我滾動它們時,似乎都會觸發一個LongClick。我檢查過Google Launcher的源代碼,它使用的邏輯幾乎和我的一樣(除了他們處理多個屏幕,而我的窮人的Launcher是一個「單屏幕」......),並且這種類型的小部件不會生成這種奇怪的行爲......我相信我錯過了一些東西,但我無法弄清楚。 – Pbal