2012-03-17 28 views
22

我有一個應用程序,示出了在ViewPager幾個片段(同一類型的),我有一些麻煩的上下文菜單項。 (我正在使用支持庫)。錯誤片段在ViewPager接收onContextItemSelected調用

當在上下文菜單中選擇了在片段中的一個的上下文菜單項,錯誤的片段接收onContextItemSelected事件呼叫。

例如,如果我在尋呼機的片段#3上,則位置#2上的片段接收它。如果我滑回到片段#2,則片段#3接收到該呼叫。

我有一個樣本here。我現在在我自己的應用程序中通過在每個片段中都有一個mHandleContext變量並在頁面更改時啓用/禁用它,這樣onContextItemSelected調用將會發送到所有片段,直到右邊一個叫。)

我做錯了什麼或者這是一個支持庫的錯誤?作爲一個方面說明,這在我使用ActionBarSherlock 3.5.1時沒有發生,後者擁有自己的支持庫分支。

+1

可能重複的[如何在一個多片段活動手柄onContextItemSelected](http://stackoverflow.com/questions/5297842/how-to-handle-oncontextitemselected-in-a-multi-fragment-activity ) – 2012-04-11 19:48:37

回答

33

所以這是某種由谷歌或東西,剛剛走了完全未經深思熟慮的白癡設計決定的。要解決這個最簡單的方法是這樣的if語句來包裹onContextItemSelected調用:在ActionBarSherlock 3.5

if (getUserVisibleHint()) { 
    // Handle menu events and return true 
} else 
    return false; // Pass the event to the next fragment 

兼容性庫有這樣的黑客。

+1

@一旦出現這種行爲的解釋,答案似乎更準確。我有同樣的問題,並通過使用不同的groupID(如在他的解決方案中)爲不同片段的上下文菜單解決它 – marwinXXII 2012-12-01 11:02:16

+0

Arnt'提示'被認爲是不可靠的? – 2013-01-27 23:36:04

+0

理論上,也許,但ViewPager的兩個片段適配器都會設置提示。 – Veeti 2013-11-18 04:29:38

14

它發生,因爲這樣的:

public boolean dispatchContextItemSelected(MenuItem item) { 
    if (mActive != null) { 
     for (int i=0; i<mAdded.size(); i++) { 
      Fragment f = mAdded.get(i); 
      if (f != null && !f.mHidden) { 
       if (f.onContextItemSelected(item)) { 
        return true; 
       } 
      } 
     } 
    } 
    return false; 
} 

正如你所看到的,FragmentManager呼籲Fragment.onContextItemSelected所有他自己的片段,直到它返回true。在你的榜樣,我可以提供這樣的解決辦法:

public static class TestListFragment extends ListFragment { 

    private int mNumber = 0; 
    private ArrayList<String> mItems; 

    public static TestListFragment newInstance(int number) { 
     Bundle args = new Bundle(); 
     args.putInt("number", number + 1); 

     TestListFragment fragment = new TestListFragment(); 
     fragment.setArguments(args); 

     return fragment; 
    } 

    public TestListFragment() {} 

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

     mNumber = getArguments().getInt("number"); 
     mItems = new ArrayList<String>(); 
     mItems.add("I am list #" + mNumber); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mItems)); 
     registerForContextMenu(getListView()); 
    } 

    @Override 
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { 
     super.onCreateContextMenu(menu, v, menuInfo); 
     menu.add(mNumber, 0, 0, "Hello, World!"); 
    } 

    @Override 
    public boolean onContextItemSelected(MenuItem item) { 
     if(item.getGroupId() == mNumber){ 
      Log.d("ViewPagerContextMenuBug", "onContextItemSelected called for number " + mNumber); 
      Toast.makeText(getActivity(), "onContextItemSelected called for number " + mNumber, Toast.LENGTH_SHORT).show(); 
      return true; 
     } 
     return false; 
    } 

} 
+0

我試過了,它似乎沒有工作。 item.getGroupId()返回0,無論什麼片段被長時間點擊。 – 2016-05-31 01:20:19

+0

爲此目的使用groupID是個好主意。這就是最好的答案。 – YBrush 2017-12-30 19:58:42

0

哦Google,我的意思是WTF?

問題是onContextItemSelected是非常通用的,並且每個片段的每個菜單項都會調用它。

您可以使用MenuItem.OnMenuItemClickListener迫使片段菜單不使用這個片段的所有onContextItemSelected,但只有相同的功能。

使用未來實現:

@Override 
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { 
    super.onCreateContextMenu(menu, v, menuInfo); 
    MenuInflater inflater = getActivity().getMenuInflater(); 
    if (v == btnShare) { 
     inflater.inflate(R.menu.share_menu, menu); 
     for (int i = 0; i < menu.size(); ++i) { 
      MenuItem item = menu.getItem(i); 
      item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { 
       @Override 
       public boolean onMenuItemClick(MenuItem item) { 
        onContextItemSelected(item); 
        return true; 
       } 
      }); 
     } 
    } 
} 

@Override 
public boolean onContextItemSelected(MenuItem item) { 
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); 
    switch (item.getItemId()) { 
     case R.id.print: 
     // ... 
    } 
} 
0

使用每個菜單項的意圖工作很適合我。

@Override 
    public void onCreateContextMenu(ContextMenu menu, View v, ContextmenuInfo menuInfo) { 
     super.onCreateContextMenu(menu, v, menuInfo); 

     MenuInflater inflater = super.getActivity.getMenuInflater(); 

     inflater.infalte(R.menu.list_item, menu); 

     for(int i = 0; i < menu.size(); i++) { 
      MenuItem item = menu.getItem(i); 
      Intent intent = new Intent(); 
      intent.putExtra(KEY_EXTRA_FRAGMENT_ID, this.fragmentId); 
      if (item != null) { 
       item.setIntent(intent); 
      } 
     } 
    } 

    @Override 
    public boolean onContextItemSelected(MeniItem item) { 

     Intent intent = item.getIntent(); 

     if (intent != null) { 
      if (intent.getIntExtra(KEY_EXTRA_FRAGMENT_ID, -1) == this.fragmentId) { 

       // Implement code according the item function. 

       return true; 
      } 
     } 

     return super.onContextItemSelected(item); 
    }