OnItemSelectedListener在使用自定义适配器的片段中
所以我几天来一直在玩这个游戏,而且似乎无法让它起作用。我有一个显示片段的活动,并且该片段是我使用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,其布局不同于它所在类的布局。
你在哪里使用listView.setOnItemSelectedListener(this)
?你需要明确告知您的活动应该控制UI行为ListView控件...
而在你的片段添加:
listMain.setOnItemSelectedListener(this);
Ooops。离开了。编辑op – user1449018 2012-07-17 17:22:39
好吧,现在你需要在Activity中找到你的ListView(用'(ListView)findViewById(R.id.listView)'),设置适配器并执行相同的操作。 – Sam 2012-07-17 17:24:39
我刚试了一下。现在我正在让NPE将侦听器设置为活动中的列表视图。我将更新代码更改的OP – user1449018 2012-07-17 17:39:22
我也一直在努力做一些类似的。问题在于,您在活动中没有实例来设置一个onitemselected侦听器。我亲自尝试了所有我能想到的方法来实现这一目标。其中包括:
list = (ListView) vp.getRootView().findViewById(R.id.listMain);
list.setOnItemSelectedListener(this);
其中list是listview的实例,然后设置为片段中的列表。这种方法的问题在于,当您尝试将侦听器设置为此时,您会得到一个NPE。如果您发现此问题的答案,请在此处发布。它会帮助我一吨。
我有人建议我采取一种新方法,并且每次调用viewpager时重新创建列表(没有实际分页......创建实际上视图永远不会改变的滑动错觉)我有人建议使用ListFragment ...ListFragment会很好,但除了ListFragment之外,您不能在布局中包含任何其他内容。
感谢您的意见。萨姆(上图)和我一起研究了这一点,并尝试了几个解决方案,但似乎没有任何工作。我几乎认为Android不支持这样的功能。我的头脑冷静告诉我,我错了,这可以做到。 – user1449018 2012-07-17 22:03:54
在你的FragmentActivity,而不是使用OnItemSelectedListener,也许你可以使用静态方法来完成这项工作。并在onItemSelected()(在片段中)调用此方法。
创建自己的界面和回调可能是最好的解决方案。在我的应用我做了这样的事情:
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
}
}
希望它可以帮助你一点。这是我可以给你的问题的最接近的答案。
在片段的父活动中实现接口将解决您的问题。例如。 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;
}
}
}
运行打破你的“我不想改变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
是的,因为ListFragment会填满整个屏幕。在这种情况下,我将在底部有按钮,并在顶部有一个标题TextView – user1449018 2012-07-21 10:20:41
您似乎有事情背对背:您不应该尝试捕获活动中的列表项单击并将它们传播到片段( s),而是直接在相关片段中接收它们。基本上@SalilPandit已经给出了正确的方法。你是否使用'ListFragment'取决于你,但是你认为它“填满整个屏幕”的假设是不正确的;它只是处理列表的一个便利片段,但您可以使它看起来像任何您想要的,只要您至少用'@android:id/list'声明了一个'ListView'。 – 2012-07-21 23:32:08