我想为listview中的每个项目创建一个片段,因为我想将一些逻辑分开。我正在为每个项目使用视图持有者。如果视图不存在,我创建一个新片段并将其添加到容器中。
holder.mMyFragment = new MyFragment(mActivity, this);
mActivity.getSupportFragmentManager().beginTransaction().add(R.id.my_container, holder.mMyFragment).commit();
对于每个项目,我都会调用holder.mMyFragment.setUi(dataSource,position)来根据数据源和位置设置片段的UI。
我遇到的问题是我在片段类的onCreateView方法中初始化片段的UI元素,但是当我将片段添加到项目时它不会被调用。所以后来当我调用setUi()使用片段中的一些UI元素时,它会抱怨NullPointerException。有没有人有建议?谢谢!
答案 0 :(得分:8)
我希望列表视图中的每个项目都有一个片段,因为我想将一些逻辑分开。
您不能将片段用作列表项视图,因为API不允许您 - View
和Fragment
甚至没有关联,所以这里有#s}你无法像那样使用它。制作自定义视图并使用适配器getViewTypeCount
和getView
来使用不同的列表项行为。
片段由Activity的FragmentManager或其他Fragments子FragmentManager管理;而列表项视图由ListView&管理。 ListAdapter。您可以在片段中使用ListView,但不能反过来使用。
答案 1 :(得分:8)
“有一个解决方案”。
问题是,您 无法将片段直接添加到容器中 (FrameLayout),并且在listview中具有与上述代码中相同的“id”。
技巧是,创建“LinearLayout”的listview(Recyclerview)。然后动态在适配器中创建FrameLayout,并为每个分配 不同的ID 。将Fragment膨胀为FrameLayout,将此FrameLayout膨胀为LinearLayout。
@Override
protected void onBindBasicItemView(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof VideoHomeViewHolder) {
VideoHomeViewHolder videoHomeViewHolder = (VideoHomeViewHolder) holder;
FrameLayout frameLayout = new FrameLayout(mContext);
frameLayout.setId(position+1); //since id cannot be zero
FragmentHelper.popBackStackAndReplace(mFragmentManager, frameLayout.getId(),
new ShowLatestVideosFragment(mShowLatestVideosItems.get(position)));
videoHomeViewHolder.linearLayout.addView(frameLayout);
}
}
答案 2 :(得分:3)
一个简单的方法。 一个问题:您应该存储添加恢复片段状态。
holder.mMyFragment = new MyFragment(mActivity, this);
int id = View.generateViewId();
findViewByTag("abc").setId(id);
mActivity.getSupportFragmentManager().beginTransaction().add(id, holder.mMyFragment).commit();
答案 3 :(得分:1)
您好,我遇到了同样的问题,我找到了办法 我的问题与你类似:
“我希望列表视图中的每个项目都有一个片段,因为我想将一些逻辑分开”
在我的应用程序中,我必须提供以垂直(listView)和水平(ViewPager)模式显示自定义项目的选项。另外,我必须处理18个自定义项目,每个项目具有不同的逻辑,因此最好的方法是重复使用我在ListView中用于ViewPager的片段。
我得到了它,但不是你想要的方式,我的意思是,我使用了像“ViewHolders”这样的片段:
getViewTypeCount(), getItemViewType(int position), getCount(), getItem(int position) getView(int position, View convertView, ViewGroup parent)
在getView
中,我在“膨胀”各自的XML之前检查了我需要的布局类型,创建一个片段,将小部件从XML分配到片段(使用rootView.findViewById
)并设置“标签”新片段。
你在这一点上可以看到的是ListView中的片段从未附加到Activity但你得到了你想要的东西:逻辑分布在几个部分和ListView的所有好处(重用行,滚动等)。
/>
如果你需要我可以发布我的部分代码,但你必须处理“spanglish”;)。
<强>已更新强>
所有问题都是因为当您创建要与ViewPager一起使用的片段时,通常所有“布局和”设置“代码都在onCreateView
方法内,我的意思是:
View rootView = inflater.inflate(R.layout.fragment_question_horizontal_container, container, false);
)answer = (EditText)rootView.findViewById(R.id.answer_question_text);
)直到这一点,没有什么奇怪的
如果要使用具有上述行为的片段,则必须“模拟”对onCreateView的调用,填充数据并将其附加到listView。
以下是诀窍:在某些方法中将onCreateView
中的代码拆分,而不关心谁在调用它们。我onCreateView
的一个例子:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_pregunta_horizontal_container, container, false);
addAnswerLayout(rootView, R.layout.fragment_pregunta_texto, getActivity());
setUpComponents(rootView);
//those 2 methods are about my app logic so I'm not going to talk much about them
setUpQuestionState(savedInstanceState);
readSavedAnswer();
return rootView;
}
public void addAnswerLayout(View rootView, int optionId, Context context) {
mContext = context;
RelativeLayout relativeLayout = (RelativeLayout)rootView.findViewById(R.id.pregunta_container);
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
View newView = inflater.inflate(optionId, relativeLayout, false);
relativeLayout.addView(newView);
}
public void setUpComponents(View rootView) {
//next line: some heritage that you can ignore
super.setUpComponents(rootView);
respuesta = (EditText)rootView.findViewById(R.id.pregunta_respuesta_texto);
respuesta.setTypeface(UiHelper.getInstance(getActivity()).typeface);
respuesta.setTextColor(mContext.getResources().getColor(R.color.drs_gris));
...
}
现在让我们转到CustomArrayAdapter获取列表视图:
PreguntasVerticalArrayAdapter extends ArrayAdapter<Pregunta>
其中“Pregunta”是具有上述逻辑的通用片段。getViewTypeCount(), getItemViewType(int position), getCount(), getItem(int position) getView(int position, View convertView, ViewGroup parent)
。
getView
遵循相同的行为:获取params中给定位置的对象,重用“viewholder”并填充数据。我的getView
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
Pregunta pregunta = mData.get(position);
if (rowView == null)
rowView = createQuestionUI(pregunta, parent, position);
fillDataInRow((PreguntaUI)rowView.getTag(), pregunta, position);
return rowView;
}
private View createPreguntaUI(Pregunta pregunta, ViewGroup parent, int position) {
View rootView = null;
LayoutInflater inflater = (mPreguntasVerticalFragment.getActivity()).getLayoutInflater();
//you can ignore this part of the code ralted to Bundle.
Bundle args = new Bundle();
args.putLong(PreguntaUI.PREGUNTAUI_ID, pregunta.getIdpregunta());
args.putInt(PreguntaUI.PREGUNTAUI_INDEX, position);
args.putInt(PreguntaUI.PREGUNTAUI_TOTAL_QUESTIONS, getCount());
//internal method of "pregunta" to know what kind of question it is.
String tipo = pregunta.getTipo();
if (tipo.equalsIgnoreCase(PreguntaType.TEXT.toString())) {
rootView = inflater.inflate(R.layout.fragment_pregunta_vertical_container, parent, false);
Pregunta_texto pregunta_texto = new Pregunta_texto();
pregunta_texto.setArguments(args);
//LOOK AT THIS POINT!!!: I'm calling the same methods that I called in onCreateView fragment's method.
pregunta_texto.addAnswerLayout(rootView, R.layout.fragment_pregunta_texto,
mPreguntasVerticalFragment.getActivity());
pregunta_texto.setUpComponents(rootView);
pregunta_texto.setUpQuestionState(null);
pregunta_texto.readSavedAnswer();
//I'm adding the fragment to reuse it when I can
rootView.setTag(pregunta_texto);
}
else if ...
return rootView;
}
这就是......在这一点上,如果你有足够的经验处理CustomArrayAdapters和Fragments,你可能会得到它! :d
答案 4 :(得分:0)
来自Android文档:“片段表示活动中的行为或用户界面的一部分。您可以在单个活动中组合多个片段以构建多窗格UI并重复使用片段在多个活动中。“
对于您的活动,是否要添加2个片段,其中第一个片段显示listView( = ListFragment ,另一个片段在右侧,仅在用户点击某个项目时显示(来自第一个片段或listView)?
答案 5 :(得分:0)
您可以使用RecyclerView而不是使用ListFragment,Android对此具有文档:
https://developer.android.com/training/basics/fragments/creating.html#AddInLayout