2012-07-17 78 views
5

所以我幾天來一直在玩這個遊戲,而且似乎無法讓它起作用。我有一個顯示片段的活動,並且該片段是我使用ViewPager進行頁面瀏覽的片段列表的成員。片段本身由一個TextView和一個ListView組成。 ListView從自定義適配器填充自身。OnItemSelectedListener在使用自定義適配器的片段中

我想要做的是將一個OnItemSelected事件傳遞迴它處理的片段。對我來說,繼續前進並在此處顯示代碼可能會更好。

這是活動

public class DialogInventory extends FragmentActivity implements OnItemSelectedListener { 

ViewPager viewPager; 
Pager pager; 

@Override 
protected void onCreate(Bundle bundle) { 
    super.onCreate(bundle); 
    setContentView(R.layout.dialog_inventory); 

    List<Fragment> fragList = new Vector<Fragment>(); 
    fragList.add(Fragment.instantiate(this, FragmentOne.class.getName())); 
    fragList.add(Fragment.instantiate(this, FragmentTwo.class.getName())); 
    pager = new Pager(getSupportFragmentManager(), fragList); 

    viewPager = (ViewPager) findViewById(R.id.pagerMain); 
    viewPager.setAdapter(pager); 

    listMain = (ListView) findViewById(R.id.listMain); 
    listMain.setOnItemSelectedListener(this); 
} 

public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { 
    switch (viewPager.getCurrentItem()) { 
     case 0: 
      FragmentOne fragOne = new FragmentOne(); 
      fragOne.onItemSelected(parent, view, pos, id); 
      break; 
     case 1: 
      FragmentTwo fragTwo = new FragmentTwo(); 
      fragTwo.onItemSelected(parent, view, pos, id); 
      break; 
    } 
} 
public void onNothingSelected(AdapterView<?> arg0) { 
} 

這是片段:

public class FragmentOne extends Fragment implements OnItemSelectedListener { 

View view; 
ListView listMain; 
ArrayList<String> invItems = new ArrayList<String>(); 

public FragmentOne() { 
} 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) { 
    view = inflater.inflate(R.layout.fragment_one, viewGroup, false); 

    listMain = (ListView) v.findViewById(R.id.listMain); 
    listMain.setAdapter(new AdapterItem(getActivity().getApplicationContext(), 
     R.layout.tile_item, invItems)); 
    listMain.setOnItemSelectedListener(this); 
    return view; 
} 
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { 
    Log.i("Test", "hit"); 
} 

某些線條爲簡潔起見省略。讓我們假設片段得到正確顯示並且一切正常。唯一不能正常工作的是Activity中的OnItemSelected事件根本沒有觸發......更不用說片段中的OnItemSelected事件。我在這裏做錯了什麼?

編輯:ListViews必須在它們各自的片段中(因爲它們將單獨顯示在不同的活動以及上面列出的活動中)。這裏最大的問題是我無法在我的Activity中設置OnItemSelectedListener,因此事件永遠不會被觸發。我已經完成了所有的代碼,並且正在運行,只是OnItemSelectedListener不起作用。

編輯2:明天我會給這個問題增加一筆賞金。鑑於此,我認爲我會更正確地回答正確答案的範圍。正確的答案不會對UI佈局或演示文稿發生任何重大變化。正確的答案會將OnItemSelected事件傳遞給Fragment並在那裏處理。答案不會讓我在代碼行之後加載我的Activity,以實現我認爲只需幾行就可以完成的事情。更優雅的答案顯然更具吸引力。感謝任何看過這個的人。

這裏的問題是,我在我的活動中得到了NPE。我如何將它指向一個ListView,其佈局不同於它所在類的佈局。

+2

運行打破你的「我不想改變UI」規則的風險,有你沒有使用'ListFragment'它默認給你一個方法,'理由覆蓋',捕獲點擊'ListView',因此你可以做我認爲你正在嘗試做的事情,即處理片段中本地的列表項點擊... http://developer.android.com /reference/android/app/ListFragment.html#onListItemClick(android.widget.ListView,android.view.View,int,long) – 2012-07-20 22:27:55

+0

是的,因爲ListFragment會填滿整個屏幕。在這種情況下,我將在底部有按鈕,並在頂部有一個標題TextView – user1449018 2012-07-21 10:20:41

+2

您似乎有事情背對背:您不應該嘗試捕獲活動中的列表項單擊並將它們傳播到片段( s),而是直接在相關片段中接收它們。基本上@SalilPandit已經給出了正確的方法。你是否使用'ListFragment'取決於你,但是你認爲它「填滿整個屏幕」的假設是不正確的;它只是處理列表的一個便利片段,但您可以使它看起來像任何您想要的,只要您至少用'@android:id/list'聲明瞭一個'ListView'。 – 2012-07-21 23:32:08

回答

2

你在哪裏使用listView.setOnItemSelectedListener(this)?你需要明確告知您的活動應該控制UI行爲ListView控件...

而在你的片段添加:

listMain.setOnItemSelectedListener(this); 
+0

Ooops。離開了。編輯op – user1449018 2012-07-17 17:22:39

+0

好吧,現在你需要在Activity中找到你的ListView(用'(ListView)findViewById(R.id.listView)'),設置適配器並執行相同的操作。 – Sam 2012-07-17 17:24:39

+0

我剛試了一下。現在我正在讓NPE將偵聽器設置爲活動中的列表視圖。我將更新代碼更改的OP – user1449018 2012-07-17 17:39:22

0

我也一直在努力做一些類似的。問題在於,您在活動中沒有實例來設置一個onitemselected偵聽器。我親自嘗試了所有我能想到的方法來實現這一目標。其中包括:

list = (ListView) vp.getRootView().findViewById(R.id.listMain); 
list.setOnItemSelectedListener(this); 

其中list是listview的實例,然後設置爲片段中的列表。這種方法的問題在於,當您嘗試將偵聽器設置爲此時,您會得到一個NPE。如果您發現此問題的答案,請在此處發佈。它會幫助我一噸。

我有人建議我採取一種新方法,並且每次調用viewpager時重新創建列表(沒有實際分頁......創建實際上視圖永遠不會改變的滑動錯覺)我有人建議使用ListFragment ...ListFragment會很好,但除了ListFragment之外,您不能在佈局中包含任何其他內容。

+0

感謝您的意見。薩姆(上圖)和我一起研究了這一點,並嘗試了幾個解決方案,但似乎沒有任何工作。我幾乎認爲Android不支持這樣的功能。我的頭腦冷靜告訴我,我錯了,這可以做到。 – user1449018 2012-07-17 22:03:54

0

在你的FragmentActivity,而不是使用OnItemSelectedListener,也許你可以使用靜態方法來完成這項工作。並在onItemSelected()(在片段中)調用此方法。

1

創建自己的界面和回調可能是最好的解決方案。在我的應用我做了這樣的事情:

public class ModuleFragment extends ListFragment { 
    //... 
    private OnModuleSelectedListener mdListener; 

// this method makes sure my activity implements my interface. If not I show an error 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      mdListener = (OnModuleSelectedListener) activity; 
      Log.d(TAG, "OnModuleSelectedListener Implemented !"); 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
       + " must implement OnSqSelectedListener"); 
     } 
    } 
// This is the standard onListItemClick, I use it to get data I need and give them to the Listener 
    public void onListItemClick(ListView l, View v, int position, long id) { 
     super.onListItemClick(l, v, position, id); 
     l.getItemAtPosition(position); 
     HashMap<String, String> map = (HashMap<String, String>) l 
      .getItemAtPosition(position); 
     mdId = map.get("id"); 
     mdName = map.get("name"); 
     mdListener.onModuleSelected(mdId,mdName); 

    } 

    public interface OnModuleSelectedListener { 
     public void onModuleSelected(String mdId, String mdName); 
    } 
} 

這裏是我現在的活動:

public class Main extends Activity implements OnModuleSelectedListener{ 
//... 
    public void onModuleSelected(String mdId, String mdName) { 
      //.. I do whatever I want with what I get from the list 
    } 
} 

希望它可以幫助你一點。這是我可以給你的問題的最接近的答案。

0

在片段的父活動中實現接口將解決您的問題。例如。 TestFragment包含一個名爲TestFragmentListener的接口。在您的父級活動中實現此偵聽器接口,並在Fragment中保存接口的引用以執行回調.OnItemSelectedListener方法對父級活動執行回調,並按正常方式處理其餘部分。請參閱下面的示例代碼。

public final class TestFragment extends Fragment { 

    TextView title; 
    ListView listView; 
    TestFragmentListener mActivity; 
    TestAdapter adapter; 

    public interface TestFragmentListener { 
     public void onItemSelected(Object o); 
    } 

    public static TestFragment newInstance(String content) { 
     TestFragment fragment = new TestFragment(); 
     return fragment; 
    } 

    @Override 
    public void onAttach(Activity activity) { 

     try { 
      mActivity = (TestFragmentListener) activity; 

     } catch (ClassCastException e) { 
      Log.e("Invalid listerer", e.getMessage()); 
     } 

     super.onAttach(activity); 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mActivity = null; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     View vw = inflater.inflate(R.layout.layout, container, false); 

     title = (TextView) vw.findViewById(R.id.textView1); 
     listView = (ListView) vw.findViewById(R.id.listView1); 

     return vw; 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 

     TestAdapter adapter = new TestAdapter(); 

     listView.setAdapter(adapter); 

     listView.setOnItemClickListener(new OnItemClickListener() { 

      public void onItemClick(AdapterView<?> arg0, View arg1, 
        int position, long arg3) { 
      } 
     }); 

     listView.setOnItemSelectedListener(new OnItemSelectedListener() { 

      @Override 
      public void onItemSelected(AdapterView<?> arg0, View arg1, 
        int arg2, long arg3) { 
       mActivity.onItemSelected(arg2); 

      } 

      @Override 
      public void onNothingSelected(AdapterView<?> arg0) { 
       // TODO Auto-generated method stub 

      } 
     }); 
     super.onActivityCreated(savedInstanceState); 
    } 

private class TestAdapter extends BaseAdapter { 

     @Override 
     public int getCount() { 
      return 100; 
     } 

     @Override 
     public Object getItem(int arg0) { 
      return null; 
     } 

     @Override 
     public long getItemId(int arg0) { 
      return arg0; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup container) { 

      TextView tv = new TextView((Activity) mActivity); 
      tv.setText(Integer.toString(position)); 
      return tv; 
     } 
    } 

}