1

我有一個活動,A,和兩個片段,B和C.片段選項菜單 - 在片段堆棧

在這兩種片段B和C創建多個實例,我請在onCreate()方法setHasOptionsMenu(true)

此外,對於每個我使用下列方法:

@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
    super.onCreateOptionsMenu(menu, inflater); 

    getActivity().invalidateOptionsMenu(); // Doesn't help much... 
    menu.clear(); 
    inflater.inflate(R.menu.menu_act_detail, menu); 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    if (item.getItemId() == R.id.action_favorite_act) { 
     Log.d(TAG, title); 
     return true; 
    } else if (item.getItemId() == R.id.action_visit_site_act) { 
     Intent i = new Intent(Intent.ACTION_VIEW); 
     i.setData(Uri.parse(url)); 
     startActivity(i); 
     return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 

所以片段的每個實例B和C具有標題和URL。但是,當我向片段堆棧添加多個不同的B和C實例時,當我觸發action_favorite_act選項菜單項時,它會記錄第一個實例的標題。

這是我使用到B或C的一個實例添加到所述片段棧的代碼:

FragmentManager fragmentManager = getSupportFragmentManager(); 
Fragment fragment = ActDetailFragment.newInstance(id); 
fragmentManager.beginTransaction() 
      .add(R.id.flContent, fragment, id) 
      .addToBackStack(null) 
      .commit(); 

在這種情況下,id是相同屬於每個實例的url域。

實施例的行爲:

  • 我添加B的一個實例與標題的片段堆棧= 「你好」 和url = 「test.com」

  • 我觸發action_favorite_act菜單項和它記錄hello

  • 我加一個C的實例與標題=「世界」的片段堆棧和URL =「site.com」

  • 我觸發action_favorite_act菜單項,並將其記錄world

  • 我添加B的另一個實例與標題=「再見」的片段堆和url =「another.com」

  • 我觸發action_favorite_act菜單項,它記錄hello而不是goodbye

無論我添加了多少個B或C實例,菜單項似乎都會追溯到第一個實例。因此,helloworld會獲得日誌記錄,而不是位於堆棧頂部的B和C實例的標題。我如何獲得堆棧頂部的菜單項以響應操作?

+1

由於您使用的是'addToBackStack()',您是否可以確認在添加完例如B,C,B,C,B,C,B,C你可以按下後退按鈕並查看同一片段的多個實例?我很好奇,如果add()實際上並沒有添加片段,因爲已經添加了具有該ID的另一個片段。 –

+0

@ BenP。是的,當我按下後退按鈕時,我會返回到添加到後端堆棧的每個片段。 – wayway

+1

當你不調用menu.clear()時會發生什麼,它是否顯示每個Fragment副本的菜單? – lionscribe

回答

1

我寫了一個小應用程序來嘗試複製您的問題,我可以。通過一種好運,我用一個透明背景爲我的片段,這是有益的,因爲這意味着我看到我所有的片段是活一次:

enter image description here

和你一樣,我注意到,當我選擇選項菜單項時,我總是記錄相同的消息(來自第一個片段)。

問題的根源似乎是您的片段類的每個實例對其菜單項使用相同的R.id常量。所以你有在您的活動中有三個Fragment B實例,但全部三個都可以處理R.id.action_favorite_act的點擊。據推測,該活動只是遍歷其片段,並將菜單事件傳遞給每個人直到有人處理它,因此第一個總是獲勝。

您可以通過使用replace()而不是add()來解決此問題,以便任何時候只有一個給定片段類的實例處於活動狀態並附加。

如果這不符合您的要求,我相信您必須爲您的菜單項使用動態生成的ID,以便每個片段都有其自己的項目ID。

+0

感謝您的詳細回覆和驗證行爲!我想避免使用'replace()',因爲當我按下後退按鈕時會導致我的片段重新加載。我會研究動態生成的菜單ID。 – wayway

+1

@WayWay動態設置菜單項ID可能會導致菜單中出現重複條目​​。如果你調用menu.clear(),那麼你將只有最後添加的菜單的菜單ID,所以你仍然有問題。 – lionscribe

+1

@WayWay另一種可能的解決方案是以某種方式在活動中存儲對「當前」片段的引用(可能通過'id'或'tag'),然後在'onOptionsItemSelected()'中檢查是否是當前如果不是,則返回false。 –