2012-07-17 77 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; 
     } 
    } 

}