J'essaie d'utiliser RecyclerView avec RecyclerView.Adapter mais voici quelque chose qui ne va pas. Je poste mon code ci-dessous:
Disposition:
<Android.support.v7.widget.RecyclerView
xmlns:tools="http://schemas.Android.com/tools"
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/topic_view"
Android:scrollbars="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
topic_tile.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="@dimen/tile_height">
<com.makeramen.RoundedImageView
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/avatar"
Android:padding="16dp"
app:riv_corner_radius="72dp"
Android:layout_height="72dp"
Android:layout_width="72dp"
/>
<LinearLayout
Android:id="@+id/text_layout"
Android:orientation="vertical"
Android:paddingTop="@dimen/text_padding_top_and_bottom"
Android:paddingBottom="@dimen/text_padding_top_and_bottom"
Android:paddingRight="16dp"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TextView
Android:id="@+id/title"
Android:textSize="@dimen/primary_font"
Android:paddingLeft="@dimen/text_padding_left"
Android:textColor="#000000"
Android:text="Title"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"/>
<TextView
Android:id="@+id/author"
Android:textSize="@dimen/secondary_font"
Android:paddingLeft="@dimen/text_padding_left"
Android:text="author"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
Voici dans onCreate()
public class TitleListActivity extends ActionBarActivity {
private RecyclerView topic_view;
private RecyclerView.LayoutManager mLayoutManager;
private TitlelistAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_title_list);
.....
topic_view = (RecyclerView)findViewById(R.id.topic_view);
adapter = new TitlelistAdapter(topicList);
topic_view.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(TitleListActivity.this);
topic_view.setLayoutManager(mLayoutManager);
topic_view.setItemAnimator(new DefaultItemAnimator());
topic_view.setAdapter(adapter);
l'adaptateur:
public class TitlelistAdapter extends RecyclerView.Adapter<TitlelistAdapter.ViewHolder> {
public List<Topic> topicList;
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView title;
TextView author;
RoundedImageView avatar;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView)itemView.findViewById(R.id.title);
author = (TextView)itemView.findViewById(R.id.author);
avatar = (RoundedImageView)itemView.findViewById(R.id.avatar);
}
}
public TitlelistAdapter(List<Topic> topicList){
this.topicList = topicList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.topic_tile,viewGroup,false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.title.setText(topicList.get(i).title);
viewHolder.author.setText(topicList.get(i).member.username);
}
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
@Override
public int getItemCount() {
return topicList.size();
}
}
Voici l'exception:
Java.lang.NullPointerException
at Android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.Java:1694)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
at Android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.Java:1404)
at Android.widget.LinearLayout.measureVertical(LinearLayout.Java:695)
at Android.widget.LinearLayout.onMeasure(LinearLayout.Java:588)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:310)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
at Android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.Java:453)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:310)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
at Android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.Java:1404)
at Android.widget.LinearLayout.measureVertical(LinearLayout.Java:695)
at Android.widget.LinearLayout.onMeasure(LinearLayout.Java:588)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:310)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.Java:2291)
at Android.view.View.measure(View.Java:16497)
at Android.view.ViewRootImpl.performMeasure(ViewRootImpl.Java:1912)
at Android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.Java:1109)
at Android.view.ViewRootImpl.performTraversals(ViewRootImpl.Java:1291)
at Android.view.ViewRootImpl.doTraversal(ViewRootImpl.Java:996)
at Android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.Java:5600)
at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:761)
at Android.view.Choreographer.doCallbacks(Choreographer.Java:574)
at Android.view.Choreographer.doFrame(Choreographer.Java:544)
at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:747)
at Android.os.Handler.handleCallback(Handler.Java:733)
at Android.os.Handler.dispatchMessage(Handler.Java:95)
at Android.os.Looper.loop(Looper.Java:136)
at Android.app.ActivityThread.main(ActivityThread.Java:5001)
at Java.lang.reflect.Method.invokeNative(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:515)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:785)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:601)
at dalvik.system.NativeStart.main(Native Method)
Est-ce quelque chose que je n'ai pas initié ou quelque chose que je devrais écrire davantage?
J'ai eu cette erreur lorsque mon RecyclerView n'avait pas de LayoutManager. L'ajout de ce code a résolu le problème:
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
Votre XML montre que vous avez deux Android espaces de noms qui devraient réellement vous donner une erreur car dans Android vous êtes autorisé à utiliser l'espace de noms une seule fois. Supprimez le linearLayout à partir de votre mise en page principale, car cela semble inutile. Vérifiez votre mise en page de ligne personnalisée, c'est-à-dire topic_tile
ainsi que toute erreur similaire
<Android.support.v7.widget.RecyclerView
xmlns:tools="http://schemas.Android.com/tools"
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/topic_view"
Android:scrollbars="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
ÉDITER :
dans onCreate()
private RecyclerView.LayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
.
.
.
mLayoutManager = new LinearLayoutManager(this);
recycleView.setLayoutManager(mLayoutManager);
}
Si vous rencontrez le même problème pour RecycleView à l'intérieur d'un fragment, essayez d'utiliser ce code.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_latest, container, false);
// get recycler view
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.novel_item_list);
//mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
String[] abc = {"hi","how are you","this is recycler"};
// specify an adapter (see also next example)
mAdapter = new RecyclerViewAdapter(abc);
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
Pour ceux qui essaient d'utiliser un ViewPager pour les onglets, et à l'intérieur de leurs onglets ont un RecyclerView qui provoque cette erreur folle, je suggère de reporter le gonflage en créant un autre fragment pour inclure uniquement le RecylerView.
Ce fichier xml est l'un de mes onglets qui contiennent une disposition de cadre au lieu d'un recycleur.
shop_most_views_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<FrameLayout
Android:id="@+id/most_view_item_frameLayout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="#f3f3f3" />
</LinearLayout>
sa classe Java
public class MostViews extends Fragment {
private String title;
private int page;
View convertedView;
RecyclerView grids;
public static MostViews newInstance(int page, String title) {
MostViews fragmentFirst = new MostViews();
Bundle args = new Bundle();
args.putInt("someInt", page);
args.putString("someTitle", title);
fragmentFirst.setArguments(args);
return fragmentFirst;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
page = getArguments().getInt("someInt", 0);
title = getArguments().getString("someTitle");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
convertedView = inflater.inflate(R.layout.shop_most_views_fragment, container, false);
transitMasonaryLayoutFragmentIntoFramLayout();
return convertedView;
}
private void transitMasonaryLayoutFragmentIntoFramLayout() {
MasanoryLayout masanoryLayout = new MasanoryLayout();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.most_view_item_frameLayout, masanoryLayout).commit();
}
}
nous avons donc une disposition de cadre pour y mettre notre fragment de recylcer.
shop_most_view_masanory_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical" Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.v7.widget.RecyclerView
Android:id="@+id/mostViewsItem"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</LinearLayout>
sa classe Java
public class MasanoryLayout extends Fragment {
View convertedView;
RecyclerView grids;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
convertedView = inflater.inflate(R.layout.shop_most_view_masanory_fragment, container, false);
grids = (RecyclerView) convertedView.findViewById(R.id.mostViewsItem);
setLayoutManagerOnRecyclerView();
MasonryAdapter adapter = new MasonryAdapter(initializeData());
grids.setAdapter(adapter);
return convertedView;
}
private void setLayoutManagerOnRecyclerView() {
grids.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
}
private List<StoreItem> initializeData() {
List<StoreItem> storeItems = new ArrayList<>();
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.clothstore));
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.clothstore));
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
storeItems.add(new StoreItem("احسان", "احسان", R.drawable.clothstore));
return storeItems;
}
}
comme vous le voyez, votre FragmentPagerAdapter appellerait MostViews pour être gonflé et MostViews lui-même appelerait MasanoryLayout pour être gonflé. nous avons donc échappé au contexte FragmentPagerAdapter;)
Vous devez définir LayoutManager
pour RecycleView
:
Actuellement, Android prend en charge 3 types de mises en page.
Si vous le souhaitez, cela semble normal ListView
, utilisez LinearLayoutManager
.
Si vous voulez que cela ressemble à une grille, utilisez GridLayoutManager
.
Si vous voulez qu'il semble décalé, utilisez StaggeredGridLayoutManager
Constructeurs pour 3 types de dispositions ci-dessus
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 2);
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.HORIZONTAL);
Ensuite, vous définissez LinearLayout
sur RecycleView
(dans ce cas, j'ai utilisé LinearLayoutManager
recyclerView = (RecyclerView) view.findViewById(R.id.saved_recycle_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(linearLayoutManager);
Quoi qu'il en soit, utilisez OttoBus Library pour passer les événements de l'adaptateur à Activity/Fragment contenant le RecycleView
. Bonne chance !