在 Fragment 中显示 RecyclerView
Posted
技术标签:
【中文标题】在 Fragment 中显示 RecyclerView【英文标题】:Display a RecyclerView in Fragment 【发布时间】:2014-12-24 14:36:54 【问题描述】:我正在 android Lollipop 中试用新的 RecyclerView
,但我卡住了。
我正在尝试接收一个列表,其中包含一个图标和一个 TextView
图标右侧的 Fragment
内。
I found this great tutorial 了解如何设置RecyclerView
。我遵循了每一点,只更改了item_layout.xml
以满足我的需要。
项目构建时没有任何错误,但是当它在我的设备上启动时出现此错误:
java.lang.RuntimeException:无法启动活动 ComponentInfocom.fredrikaldgard.materialcolors/com.fredrikaldgard.materialcolors.MainActivity:java.lang.NullPointerException:尝试调用虚拟方法 'void android.support.v7.widget .RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' 在空对象引用上
我尝试用谷歌搜索这个问题,但我对 Android 开发非常业余。
这是我的MainActivity
:
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// this is data fro recycler view
ItemData itemsData[] = new ItemData("Indigo",R.drawable.circle),
new ItemData("Red",R.drawable.color_ic_launcher),
new ItemData("Blue",R.drawable.indigo),
new ItemData("Green",R.drawable.circle),
new ItemData("Amber",R.drawable.color_ic_launcher),
new ItemData("Deep Orange",R.drawable.indigo);
// 3. create an adapter
MyAdapter mAdapter = new MyAdapter(itemsData);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
// 5. set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());
还有我的MyAdapter
:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>
private ItemData[] itemsData;
public MyAdapter(ItemData[] itemsData)
this.itemsData = itemsData;
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType)
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position)
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
viewHolder.txtViewTitle.setText(itemsData[position].getTitle());
viewHolder.imgViewIcon.setImageResource(itemsData[position].getImageUrl());
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder
public TextView txtViewTitle;
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView)
super(itemLayoutView);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount()
return itemsData.length;
编辑:这是Fragment
public class ColorsFragment extends Fragment
public ColorsFragment()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_colors, container, false);
return rootView;
可能出了什么问题?
【问题讨论】:
您的 xml 布局文件中是否还有带有 id 列表的 RecyclerView?如果不是,recyclerView 变量将在步骤 2 中为空。 是的,我的 xml 中有一个 RecyclerView,ID 为“list”。 应该更清楚:在activity_main.xml
文件中,对吧?
@stkent 好吧,我使用导航抽屉,当我单击抽屉中的一个项目时,它会打开一个活动。我的 activity_main.xml 包含一个 FrameLayout,里面有抽屉。我的 RecyclerView 位于名为 fragment_color.xml 的 XML 文件中。
【参考方案1】:
这是不久前提出的问题,但根据@nacho_zona3 提供的答案以及以前的片段经验,问题是在您尝试使用@987654321 查找视图时尚未创建视图onCreate()
中的 @ 方法来解决这个问题,移动以下代码:
// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// this is data from recycler view
ItemData itemsData[] = new ItemData("Indigo",R.drawable.circle),
new ItemData("Red",R.drawable.color_ic_launcher),
new ItemData("Blue",R.drawable.indigo),
new ItemData("Green",R.drawable.circle),
new ItemData("Amber",R.drawable.color_ic_launcher),
new ItemData("Deep Orange",R.drawable.indigo);
// 3. create an adapter
MyAdapter mAdapter = new MyAdapter(itemsData);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
// 5. set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());
您的片段的onCreateView()
调用。需要进行少量重构,因为从此方法调用的所有变量和方法都必须是静态的。最终代码应如下所示:
public class ColorsFragment extends Fragment
public ColorsFragment()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_colors, container, false);
// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.list);
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// this is data from recycler view
ItemData itemsData[] =
new ItemData("Indigo", R.drawable.circle),
new ItemData("Red", R.drawable.color_ic_launcher),
new ItemData("Blue", R.drawable.indigo),
new ItemData("Green", R.drawable.circle),
new ItemData("Amber", R.drawable.color_ic_launcher),
new ItemData("Deep Orange", R.drawable.indigo)
;
// 3. create an adapter
MyAdapter mAdapter = new MyAdapter(itemsData);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
// 5. set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());
return rootView;
所以这里的主要内容是,无论您在哪里调用findViewById()
,都需要使用rootView.findViewById()
【讨论】:
用 getActivity() 替换它。 你也可以从片段'onCreateView'返回recyclerview,因为基本上片段现在是一个RecyclerView 我收到MyAdapter mAdapter = new MyAdapter(itemsData);
的错误,它说 MyAdapter 中的 MyAdapter(android.context.Context, List) 无法应用于 (List)
谢谢兄弟。在几年前针对 v2.3.3 创建了我的第一个应用程序之后,我刚刚回到原生 Android 开发,是的……让我们说一两件事发生了变化。哦,劳德【参考方案2】:
您应该在使用该视图膨胀核心视图后在Fragment
中检索RecyclerView
。也许它找不到你的 recycler 因为它不是 Activity 的一部分
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
final View view = inflater.inflate(R.layout.fragment_artist_tracks, container, false);
final FragmentActivity c = getActivity();
final RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(c);
recyclerView.setLayoutManager(layoutManager);
new Thread(new Runnable()
@Override
public void run()
final RecyclerAdapter adapter = new RecyclerAdapter(c);
c.runOnUiThread(new Runnable()
@Override
public void run()
recyclerView.setAdapter(adapter);
);
).start();
return view;
【讨论】:
非常感谢!我试图用你的代码替换我的 Fragment 中的代码,但我遇到了“final FragmentActivity c = getActivity();”的问题它给了我一个错误:需要“android.support.v4.app.FragmentActitvity”找到“android.app.Activity”。我已经在我的项目中编译了 v4 支持库。 你可以使用任何activity,如果不需要,你不必使用支持库 “使用任何活动”是什么意思?无论如何,我正在使用支持库作为导航抽屉。 我的意思是活动类的任何子类。抱歉没有说清楚。 对不起,我不太擅长碎片之类的复杂事物。我应该写什么而不是“final FragmentActivity c = getActivity();”?当我用 Activity 替换 FragmentActivity 时,错误消失了,但我仍然有这个错误:imgur.com/amSWNWc【参考方案3】:确保您有正确的布局,并且 RecyclerView id 在布局内。否则,您将收到此错误。我有同样的问题,然后我注意到布局错误。
public class ColorsFragment extends Fragment
public ColorsFragment()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
==> make sure you are getting the correct layout here. R.layout...
View rootView = inflater.inflate(R.layout.fragment_colors, container, false);
【讨论】:
【参考方案4】:我遇到了同样的问题。当我使用此代码调用上下文时得到了解决方案。我使用网格布局。如果你使用另一个,你可以改变。
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),1));
如果您有要设置的适配器。所以你可以按照这个。只需调用 getContext
adapter = new Adapter(getContext(), myModelList);
如果要显示 Toast,请使用上面相同的内容
Toast.makeText(getContext(), "Error in "+e, Toast.LENGTH_SHORT).show();
希望这会奏效。
快乐编码
【讨论】:
以上是关于在 Fragment 中显示 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章