Migrating RecyclerView from Activity to Fragment - can't use findViewById - android

I copied the following code from the MainActivity to a separate fragment, but I can't get findViewById to work:
I get "cannot resolve method findViewById(int)"
these are the related files:
**Also as a beginner, could you let me know if there's a general problem with my code that needs to fixed?
MyFragment.java:
public class MyFragment extends Fragment {
public myFragment() {
// Required empty public constructor
}
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_my, container, false);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
//placeholder data
String[] myDataset = new String[16];
myDataset[0] = "Data0";
myDataset[1] = "Data1";
myDataset[2] = "Data2";
myDataset[3] = "Data3";
myDataset[4] = "Data4";
myDataset[5] = "Data5";
myDataset[6] = "Data6";
myDataset[7] = "Data7";
myDataset[8] = "Data8";
myDataset[9] = "Data9";
myDataset[10] = "Data10";
myDataset[11] = "Data11";
myDataset[12] = "Data12";
myDataset[13] = "Data13";
myDataset[14] = "Data14";
myDataset[15] = "Data15";
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}
}
MyAdapter.java:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView upTv;
public TextView downTv;
public View layout;
public MyViewHolder(View v) {
super(v);
layout = v;
upTv = (TextView)v.findViewById(R.id.upTv);
downTv = (TextView)v.findViewById(R.id.downTv);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.upTv.setText(mDataset[position]);
holder.downTv.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
}
fragment_my.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:scrollbars="vertical"/>
</android.support.constraint.ConstraintLayout>
my_text_view.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:contentDescription="TODO"
android:src="#drawable/ic_launcher_background" />
<TextView
android:id="#+id/downTv"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="#id/icon"
android:text="downTv"
android:textSize="12sp" />
<TextView
android:id="#+id/upTv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toRightOf="#id/icon"
android:gravity="center_vertical"
android:text="upTv"
android:textSize="16sp" />
</RelativeLayout>

Here's your problem:
return inflater.inflate(R.layout.fragment_my, container, false);
You cannot add more code after the return statement. You will need to take the reference of the inflated view and use it to find the reference of child views.
View rootView = inflater.inflate(R.layout.fragment_my, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
// other code
return rootView;

A really good way to use fragments is to initialize certain variables(e.g- activity,context,root view etc) associated with the parent activity when you switch to a fragment.
for example you can do sth like,
private Context context;
private MainActivity activity; //Let MainActivity is your parent activity
private View view; //fields kept inside the fragment class,now we need to keep them initialized
//initialize activity/context from onAttach
#Override
public void onAttach(Context c) {
super.onAttach(c);
Activity a;
context=c;
if (c instanceof Activity){
a=(Activity) c;
if(a instanceof MainActivity)
activity=(MainActivity) a;
}
}
//initialize view from onViewCreated
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.view=view;
}
now you can use them wherever u want inside the fragment class without triggering any nullptrs and other stuff
e.g- you can go
this.view.findViewById(your_resId);
this.activity.getSupportFragmentManager();
etc and a lot of other stuffs when you need ,using these fields you initialized
also specifically in this case of using recyclerView dont forget to call,
adapter.notifyDataSetChanged() whenever you think the list you are showing in the recyclerView went through some change.

I do not have enough reputation to comment so i am writing this as answer to your comment.
You need to notify adapter using below code.
mAdapter.notifyDataSetChanged();

Related

adapter for recyclerview in android

currently i am working on a android project.
where i have two String[], now i want to display the data of bothe String[] on my activity.but with my code i am only able to display the data of one String[].
plz check my code.
file name:MyAdapter4.java
public class MyAdapter4 extends RecyclerView.Adapter<MyAdapter4.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView cardview4;
public EditText edit4;
public TextView title4;
public MyViewHolder(View v) {
super(v);
cardview4=(CardView) v.findViewById(R.id.card_view4);
edit4=(EditText) v.findViewById(R.id.otherEdit);
title4=(TextView) v.findViewById(R.id.otherTitle);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter4(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter4.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.other_file_layout, parent, false);
// set the view's size, margins, paddings and layout parameters
MyAdapter4.MyViewHolder vh = new MyAdapter4.MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyAdapter4.MyViewHolder holder, int position) {
holder.title4.setText(mDataset[position]);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
with this code i am only able to display Textview.... but editText is not showing data
and this is the code which i used to attach the adapter
public class FourFragment extends Fragment {
public static String[] arrayOtherTitle, arrayOtherData;
public FourFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_four, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view4);
rv.setHasFixedSize(true);
MyAdapter2 adapter = new MyAdapter2(arrayOtherTitle);
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
The layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:elevation="4dp"
android:id="#+id/card_view4"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:textStyle="bold"
android:layout_weight="1"
android:id="#+id/otherTitle"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/copy"
android:layout_margin="4dp"/>
</LinearLayout>
<EditText
android:layout_width="match_parent"
android:id="#+id/otherEdit"
android:enabled="false"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
As you can see,
1)in my layout file, there are one textview and one edittext.
2)and in the class, FourFragment.java there are two String[] arrayOtherTitle, and arrayOtherData.
3)so, i want to display them on my activity.
where textview will contain data of arrayOtherTitle,
and editext will contain data of arrayOtherData.
but according to my code, currently i am only able to display data of arrayOtherTitle on textview.
and i am new in this topic,plz anyone help me to display the other arrayOtherData data on edittext.
please

getView() method of custom adapter never gets called

I've read various SO threads on the topic but none of them seem to apply to my code.
I'm trying to populate a fragment with a ListView with my custom NearbyAdapter. However, my getView() method never gets called (as demonstrated by my logs not showing up). The view itself seems to be appropriately attached to my fragment, as demonstrated by the button in the view showing up, but not the ListView.
Relevant NearbyListFragment.java code:
public class NearbyListFragment extends ListFragment {
private int mImageSize;
private boolean mItemClicked;
private NearbyAdapter mAdapter;
private List<Place> places;
private LatLng mLatestLocation;
private static final String TAG = "NearbyListFragment";
public NearbyListFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "NearbyListFragment created");
View view = inflater.inflate(R.layout.fragment_nearby, container, false);
return view;
}
//TODO: Do asynchronously?
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
//Load from data source (NearbyPlaces.java)
mLatestLocation = ((NearbyActivity) getActivity()).getmLatestLocation();
//FIXME: Hardcoding mLatestLocation to Michigan for testing
//mLatestLocation = new LatLng(44.182205, -84.506836);
places = loadAttractionsFromLocation(mLatestLocation);
mAdapter = new NearbyAdapter(getActivity(), places);
ListView listview = (ListView) view.findViewById(R.id.listview);
//setListAdapter(mAdapter);
listview.setAdapter(mAdapter);
Log.d(TAG, "Adapter set to ListView");
mAdapter.notifyDataSetChanged();
}
private class NearbyAdapter extends ArrayAdapter {
public List<Place> placesList;
private Context mContext;
public NearbyAdapter(Context context, List<Place> places) {
super(context, R.layout.item_place);
mContext = context;
placesList = places;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Place place = (Place) getItem(position);
//FIXME: This never gets called
Log.d(TAG, "Place " + place.name);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_place, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
TextView tvDesc = (TextView) convertView.findViewById(R.id.tvDesc);
// Populate the data into the template view using the data object
tvName.setText(place.name);
tvDesc.setText(place.description);
// Return the completed view to render on screen
return convertView;
}
#Override
public long getItemId(int position) {
return position;
}
The layout file of the fragment, fragment_nearby.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/btn_New">
</ListView>
<Button
android:id="#+id/btn_New"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginBottom="20dp"
android:text="Button"
android:width="170dp"
android:layout_alignParentBottom="true" />
</RelativeLayout>
And the layout file of the item, item_place.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name" />
<TextView
android:id="#+id/tvDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Desc" />
</LinearLayout>
Edit: Does anyone want to actually include a reason for the downvote? Especially when something like Custom Adapter for List View has 129 upvotes?
The issue is that ArrayAdapter does not know about List places:
Use this to fix it:
private static class NearbyAdapter extends ArrayAdapter<Place> {
public NearbyAdapter(Context context, List<Place> places) {
super(context, R.layout.item_place, places);
mContext = context;
placesList = places;
}
}
P/s: in this case, I think you need more control to set your place data to your view. Consider using BaseAdapter instead of ArrayAdapter.
Add following to your adapter:
#Override
public int getCount() {
return placesList.size();
}
After this you most likely encounter error with getItem so you will need to override that as well to return your object from the list.
You have to override getCount() method in ArrayAdapter to initialized listview like this:
#Override
public int getCount() {
return placesList.size();
}

RecyclerView inside ViewPager Fragment don't show

So i have a fragment, which have a viewpager with tablayout, which consist of two tabs-two fragments.
The thing is, recyclerview shows empty, and i have no idea why.,
Tab Fragment LAyout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Tag Fragment:
List<OrderListItem> orderList = new ArrayList<>();
orderList.add(new OrderListItem(333, "ABCDE", new Date(), new Date(), false, true));
adapter = new OrderListAdapter(orderList, this.getActivity());
layoutManager = new LinearLayoutManager(this.getActivity(), LinearLayoutManager.VERTICAL, false);
myRecyclerView.setLayoutManager(layoutManager);
myRecyclerView.setAdapter(adapter);
Adapter:
public class OrderListAdapter extends RecyclerView.Adapter<OrderListAdapter.ViewHolder>{
private List<OrderListItem> orderList;
#LayoutRes
private final int layoutRes;
private Context context;
private final LayoutInflater inflater;
public OrderListAdapter(List<OrderListItem> orderList, Context context){
this.orderList = orderList;
this.layoutRes = R.layout.order_list_item_layout;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(layoutRes, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final OrderListItem item = orderList.get(position);
}
public void setItems(List<OrderListItem> orderList){
this.orderList.clear();
this.orderList.addAll(orderList);
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return orderList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
RecycleView Item some colorful layouts insider, so i know if the child layout is there or not, which it isnt. any idea why recyclerview is empty?
edit1: i know the recyclerview is there, because its in a lolipop phone, and if i make a movement at the recycler place it shows me the ripple top and bottom scroll border. but the child layouts are empty and blank, and should be colorful as i specificed in the child layout.
eit2. just used a listview with a simpleAdapter and it is showing. there must be something buggy with the rv
edit3: row layout (i should clearly see an empty textview with a color, besides not any value setted.)
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#color/black"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/material_deep_teal_200"
android:text="New Text"
android:id="#+id/textView" />
</LinearLayout>
Change:
android:layout_width="match_parent"
android:layout_height="match_parent"
to
android:layout_width="50dp" // set yourself
android:layout_height="50dp" // set yourself
Where is the logic in which you set OrderListItem properties to ui?
You have first to set ViewHolder components:
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView mTitleTv;
public ViewHolder(View itemView) {
super(itemView);
mTitle = itemView.findViewById(R.id.textview_id_in_your_xml_file);
}
}
And then set them in onBindViewHolder:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final OrderListItem item = orderList.get(position);
holder.mTitleTv.setText(item.getReplaceThisWithAStringProperty);
}
EDIT
If you have to use default LinearLayoutManager properties use this constructor:
layoutManager = new LinearLayoutManager(getActivity());
Instead of this:
layoutManager = new LinearLayoutManager(this.getActivity(), LinearLayoutManager.VERTICAL, false);
Add also fixed size property for RecyclerView:
recyclerView.setHasFixedSize = true;

RecyclerView not scrolling to the bottom

I followed the recyclerview guidelines and built one for the app I am making, but it does not scroll to the bottom for some reason. I compared it with google code snippets, as well as other code snippets online and can't see the difference. I have posted a picture and the code I am using. I am using tabs, therefore the recyclerview is populated in a fragment.
What the app looks like:
http://imgur.com/H5uOLFR
the adapter class:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Group> groups;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView groupName;
public TextView groupDate;
public TextView groupLocation;
public TextView className;
public ViewHolder(View v) {
super(v);
groupName = (TextView) v.findViewById(R.id.groupName);
groupDate = (TextView) v.findViewById(R.id.groupDate);
groupLocation = (TextView) v.findViewById(R.id.groupLocation);
className = (TextView) v.findViewById(R.id.className);
}
}
/*
* TODO: finish this method
*/
public void add(int position, String item) {
notifyItemInserted(position);
}
public void remove(String item) {
int position = groups.indexOf(item);
groups.remove(position);
notifyItemRemoved(position);
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Group> groupsList) {
groups = groupsList;
Log.d("TEST", "Number of Groups: " +
Integer.toString(groups.size()));
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.group_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final Group group = groups.get(position);
// holder.groupName.setText(group.getName());
holder.groupName.setText(group.getName());
holder.groupDate.setText(group.getFormattedDate());
holder.groupLocation.setText(group.getLocation());
holder.className.setText(group.getParent().getName());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return groups.size();
}
}
The Fragment class:
public class groupsFragment extends Fragment implements GroupLeaver, GroupRetriever {
private RecyclerView rv;
private List<Group> groups;
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
Log.d("TEST", "Entered onCreate");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AppMain.getController().retrieveGroups(groupsFragment.this);
Log.d("TEST", "Entered onCreateView");
View rootView = inflater.inflate(R.layout.groups_fragment, container, false);
rv = (RecyclerView) rootView.findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
Log.d("TEST", "Size of LIST: " + Integer.toString(groups.size()));
MyAdapter adapter = new MyAdapter(groups);
rv.setAdapter(adapter);
return rootView;
}
#Override
public void onMyGroupsFound(List<Group> groups) {
Log.d("TEST", "Entered onMyGroupsFound");
Logg.info(this.getClass(), "Found %d groups for member %s", groups.size(), User.getCurrentUser().getDisplayName());
this.groups = groups;
}
#Override
public void onGroupLeft(Group oldGroup) {
}
#Override
public void onGroupLeftFailed(Group group, ParseException e) {
}
}
The xml layout for the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null"/>
</FrameLayout>
The xml layout for the recyclerview items:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="horizontal">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="3"
android:orientation="vertical">
<TextView
android:id="#+id/groupName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Name"
/>
<TextView
android:id="#+id/groupDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Date"
/>
<TextView
android:id="#+id/groupLocation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Group Location"
/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/className"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="right"
android:text="Class Name"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
You can use these lines to scroll recyclerview to:
list.add(0, group);
adapter.notifyItemInserted(0);
recyclerview.scrollToPosition(0);
Thanks to everyone who responded, but turns out the problem was the version of RecyclerView I was compiling.
Previously I was compiling this
compile 'com.android.support:recyclerview-v7:22.0.0'
But I changed it to this and it worked
compile 'com.android.support:recyclerview-v7:22.2.0'
Credits to #roi divon for the answer: CoordinatorLayout with RecyclerView & CollapsingToolbarLayout
Maybe adding these lines to the recyclerView will do:
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
This is my recyclerView which is working:
<android.support.v7.widget.RecyclerView
android:id="#+id/menuRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"/>
I am not sure but I think problem might be Framelayout You can try with Linearlayout instead of Framelayout in your xml layout for the recyclerview items

RecyclerView onListItemClick to create new intent

so, before latest update, I use onListItemClick listener and it works fine, but now I tried to use RecyclerView, and I'm not sure how to implement onClick for each item, that will open up a new activity..
this is what I used to have
public class SermonsFragment extends Fragment {
#Override
public void onListItemClick(ListView list, View v, int position, long id) {
Intent mediaStreamIntent = new Intent(getActivity(), MediaStreamPlayer.class);
mediaStreamIntent.putExtra("sermon_details", (android.os.Parcelable) list.getItemAtPosition(position));
startActivity(mediaStreamIntent);
}
}
but now, instead of using listview I create a sermon adapter and it looks like this
public class SermonListAdapter extends RecyclerView.Adapter<SermonListAdapter.ViewHolder>{
private ArrayList<Sermon> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
//Note: need to remove static class no idea why
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// each data item is just a string in this case
public View mView;
public ViewHolder(View v) {
super(v);
v.setOnClickListener(this);
mView = v;
}
#Override
public void onClick(View v) {
Log.d("SermonsListAdapter.java.debug", "itemClick " + mDataset.get(getPosition()).getName());
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public SermonListAdapter(ArrayList<Sermon> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public SermonListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.sermon_cardview, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
TextView title = (TextView) holder.mView.findViewById(R.id.sermon_title);
TextView series = (TextView) holder.mView.findViewById(R.id.sermon_series);
TextView pastor = (TextView) holder.mView.findViewById(R.id.sermon_pastor);
TextView sermonDate = (TextView) holder.mView.findViewById(R.id.sermon_date);
title.setText(mDataset.get(position).getName());
series.setText(mDataset.get(position).getSeries());
pastor.setText(mDataset.get(position).getPastor());
sermonDate.setText(mDataset.get(position).getSermonDate());
}
and the fragment is more or less the same, it's just I can't use onListItemClick anymore
public class SermonsFragment extends Fragment {
private static final int MAX_SERMONS_LIST = 20;
private ArrayAdapter<Sermon> listAdapter;
private String imageUrl;
private static String sermonListJSONUrl = “http://someurl”;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
//Check if there is internet, if yes call JSONParser
ConnectionDetector myConnection = new ConnectionDetector(getActivity().getApplicationContext());
Boolean isInternetOnline = false;
isInternetOnline = myConnection.isConnectingToInternet();
if(isInternetOnline) {
//Call JSONParser Asynchronously to get sermonList in JSON Format
new callJSONParserAsync().execute(sermonListJSONUrl);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sermons, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//Just an Empty Class
ArrayList<Sermon> mySermon = new ArrayList<Sermon>();
//specify an adapter
mAdapter = new SermonListAdapter(mySermon);
mRecyclerView.setAdapter(mAdapter);
}
I have the cardview xml look like this
<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_margin="5dp"
android:layout_width="match_parent"
android:layout_height="100dp"
card_view:cardCornerRadius="1dp">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/sermon_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="#+id/sermon_series" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="#+id/sermon_pastor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="#+id/sermon_date" />
</LinearLayout>
</android.support.v7.widget.CardView>
I've got this error when try to create new intent
12-18 22:31:48.469 31887-31887/org.ifgfseattle.ifgfseattle E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: org.ifgfseattle.ifgfseattle, PID: 31887
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ContextImpl.startActivity(ContextImpl.java:1232)
at android.app.ContextImpl.startActivity(ContextImpl.java:1219)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:322)
at org.ifgfseattle.ifgfseattle.adapter.SermonListAdapter$1.onClick(SermonListAdapter.java:81)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
You could implement an onClick on the view in the onBindViewHolder method of yours inside the adpater.
Assign an id to the view that holds the item cell
Get the view just the way you have for the textviews
set an onClick to the root inside the method like this:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
viewHolder.relLayout.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// perform your operations here
}
});
}
EDIT:
This is how you assign an id in the xml
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/lnrLayout" ---------->> This is new
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/sermon_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="#+id/sermon_series" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="#+id/sermon_pastor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="#+id/sermon_date" />
</LinearLayout>
This is how you define the views (or probably instantiate them)
public ViewHolder(View mView) {
super(view);
title = (TextView) holder.mView.findViewById(R.id.sermon_title);
series = (TextView) holder.mView.findViewById(R.id.sermon_series);
pastor = (TextView) holder.mView.findViewById(R.id.sermon_pastor);
sermonDate = (TextView) holder.mView.findViewById(R.id.sermon_date)
lnrLayout = (LinearLayout)holder.mView.findViewById(R.id.lnrLayout);
}
That's your custom viewholder, so declare the TextViews just the way we declare variables.. your onBindView method wil therefore look like this now:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(mDataset.get(position).getName());
holder.series.setText(mDataset.get(position).getSeries());
holder.pastor.setText(mDataset.get(position).getPastor());
holder.sermonDate.setText(mDataset.get(position).getSermonDate());
holder.lnrLayout.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// on click action here
//-- use context to start the new Activity
Intent mediaStreamIntent = new Intent(mContext, MediaStreamPlayer.class);
mediaStreamIntent.putExtra("sermon_details", (android.os.Parcelable) mDataset.get(position));
mContext.startActivity(mediaStreamIntent);
}
});
}
I really have no idea why there is difference between the two, may be its because you are intializing the views inside onbind instead of the viewholder constructor.
You could also refer to this
EDIT 2: (2nd method)
Change you adapter to the following:
// Provide a suitable constructor (depends on the kind of dataset)
public SermonListAdapter(ArrayList<Sermon> myDataset, Fragment fragment) {
mDataset = myDataset;
mFragment = fragment;
}
In the onClick do this:
if(mFragment != null && mFragment instanceof SermonFragment) {
((SermonFragment)mFragment).sendToNextActivity(position); -> you can pass any data you wsh to
}
In the fragment class create a public method with the name sendToNextAcitivity with the same param definition and then call the next intent.
3rd method
Create an interface in the adapter, create a set method for the interface, implement the interface in the fragment and then initialize it, and then pass it to the set method of the adapter.
then use this:
if(mListener!= null) {
mListener.sendToNextActivity(position); -> you can pass any data you wsh to
}

Categories

Resources