Android recyclerview adding duplicate elements on each activity creation - android

When I launch a new fragment from my navigation drawer, it's meant to take me to a home page with a cardView of matching profiles. It works great the first time and every profile I want to show up is there. However, when I navigate away from the fragment and then click on it again, the elements are duplicated, and each subsequent time I refresh the page the items are duplicated once more. I believe this problem lies somewhere in my RecyclerView adapter not clearing on an activity create, but I have't been able to pinpoint it. Here's my fragment class
public class HomeFragment extends Fragment {
private CustomListAdapter listAdapter;
private static final String profileUrl = "http://10.0.2.2:3000/apip/buyers/profiles";
private static final String TAG = selectBuyerProfile.class.getSimpleName();
private ProgressDialog pDialog;
private ListView listView;
private List<BuyerProfile> buyersProfiles = new ArrayList<BuyerProfile>();
private View root;
//private RVAdapter recyclerAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_home, container, false);
return root;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
RecyclerView rv = (RecyclerView) getActivity().findViewById(R.id.rv);
//rv.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
rv.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
rv.setItemAnimator(new DefaultItemAnimator());
final RVAdapter recyclerAdapter = new RVAdapter(buyersProfiles);
rv.setAdapter(recyclerAdapter);
RequestQueue mRequestQueue;
Cache cache = new DiskBasedCache(getActivity().getCacheDir(), 1024 * 1024);
Network network = new BasicNetwork(new HurlStack());
mRequestQueue = new RequestQueue(cache, network);
mRequestQueue.start();
JsonArrayRequest profileRequest = new JsonArrayRequest(profileUrl,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// Parsing json
for(int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
BuyerProfile parsedProfile = new BuyerProfile();
parsedProfile.setBuyerProfTitle(obj.getString("title"));
parsedProfile.setDescription(obj.getString("description"));
parsedProfile.setLocations(obj.getString("locations"));
parsedProfile.setAssetTypes(obj.getString("asset_type"));
parsedProfile.setPropertyStatuses(obj.getString("property_status"));
//parsedProfile.setBuyerId("Select");
buyersProfiles.add(parsedProfile);
} catch (Exception e) {
e.printStackTrace();
}
}
recyclerAdapter.notifyDataSetChanged();
// notifying list adapter about data changes
// so that it renders the list view with updated data
//hidePDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Toast.makeText(selectBuyerProfile.this,"Error",Toast.LENGTH_LONG).show();
}
});
mRequestQueue.add(profileRequest);
}
}
And here is my RVAdapter class
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {
private Activity activity;
private LayoutInflater inflater;
private List<BuyerProfile> profileItems;
private static boolean itemFavorited;
RVAdapter(List<BuyerProfile> profiles) {
this.profileItems = profiles;
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView description;
TextView locations;
TextView id;
TextView investmentRangeMin;
TextView investmentRangeMax;
TextView assetTypes;
TextView propertyStatuses;
ImageView favoriteButton;
CardView cardView;
PersonViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.titleText);
description = (TextView) itemView.findViewById(R.id.descriptionText);
investmentRangeMin = (TextView) itemView.findViewById(R.id.investmentRangeMin);
investmentRangeMax = (TextView) itemView.findViewById(R.id.investmentRangeMax);
locations = (TextView) itemView.findViewById(R.id.locations);
id = (TextView) itemView.findViewById(R.id.profileNumber);
assetTypes = (TextView) itemView.findViewById(R.id.assetTypes);
propertyStatuses = (TextView) itemView.findViewById(R.id.propertyStatuses);
favoriteButton = (ImageView) itemView.findViewById(R.id.favorite_select);
cardView = (CardView) itemView.findViewById(R.id.cv);
//User selects favorite on a matched profile
itemFavorited = false;
favoriteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!itemFavorited) {
favoriteButton.setImageResource(R.drawable.ic_favorite);
//cardView.setCardBackgroundColor(R.color.colorPrimary);
itemFavorited = true;
} else {
favoriteButton.setImageResource(R.drawable.ic_favorite_border);
itemFavorited = false;
}
}
});
}
}
#Override
public int getItemCount() {
return profileItems.size();
}
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
PersonViewHolder pvh = new PersonViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
personViewHolder.name.setText(profileItems.get(i).getBuyerProfTitle());
personViewHolder.description.setText(profileItems.get(i).getDescription());
personViewHolder.locations.setText(profileItems.get(i).getLocations());
personViewHolder.assetTypes.setText(profileItems.get(i).getAssetTypes());
personViewHolder.propertyStatuses.setText(profileItems.get(i).getPropertyStatuses());
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
/*
#Override
public Object getItem(int location) {
return profileItems.get(location);
}
*/
#Override
public long getItemId(int position) {
return position;
}
}
Finally here is my fragments 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="wrap_content"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:padding="0dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Matches"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="false"
android:id="#+id/matchesText"
android:textAlignment="center"
android:textSize="20dp"
android:textColor="#color/navigationBarColor"
android:layout_alignParentStart="false"
android:layout_alignParentBottom="false"
android:layout_alignParentLeft="false"
android:layout_alignParentRight="true"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rv"
android:layout_below="#id/matchesText"
/>
<!-- Thumbnail Image -->
<ImageView
android:id="#+id/imgBillionaire"
android:src="#drawable/ic_perm_identity"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentLeft="true"
android:layout_marginRight="8dp"
android:layout_alignParentEnd="false"
android:layout_alignParentStart="true"
android:nestedScrollingEnabled="false"
android:visibility="invisible"/>
<!-- Name of Asset -->
<TextView
android:id="#+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/imgBillionaire"
android:layout_toRightOf="#+id/imgBillionaire"
android:textSize="#dimen/Title"
android:textStyle="bold" />
<!-- Description -->
<TextView
android:id="#+id/descriptionText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/titleText"
android:layout_marginTop="1dip"
android:layout_toRightOf="#+id/imgBillionaire"
android:textSize="#dimen/Description" />
<!-- Source -->
<TextView
android:id="#+id/locations"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/descriptionText"
android:layout_marginTop="5dp"
android:layout_toRightOf="#+id/imgBillionaire"
android:textColor="#color/wealthsource"
android:textSize="#dimen/InvestmentRange" />
<!-- Source -->
<TextView
android:id="#+id/assetTypes"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/locations"
android:layout_marginTop="5dp"
android:layout_toRightOf="#+id/imgBillionaire"
android:textColor="#color/wealthsource"
android:textSize="#dimen/InvestmentRange" />
<!-- Source -->
<TextView
android:id="#+id/propertyStatuses"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/assetTypes"
android:layout_marginTop="5dp"
android:layout_toRightOf="#+id/imgBillionaire"
android:textColor="#color/wealthsource"
android:textSize="#dimen/InvestmentRange" />
<!-- Year -->
<TextView
android:id="#+id/profileNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="false"
android:layout_alignParentRight="true"
android:textColor="#color/year"
android:textSize="#dimen/Date" />
</RelativeLayout>
</LinearLayout>
Any ideas why the items in my recyclerview would keep duplicating on each page refresh?

What can possibly be happening is that each time the network request returns, it tries to add every new item to an already existing list inside the fragment.
Depending on how you implement your navigation logic, your fragment won't be destroyed by the system once you navigate away from it, instead calling a series of lifecycle callbacks:
onPause() -> onStop() -> onDestroyView()
And when you return to the fragment, all required lifecycle callbacks will be called until it reaches the active state.
onCreateView() -> onActivityCreated() -> onStart() -> onResume()
More information on fragment's lifecycle works can be found here: https://developer.android.com/guide/components/fragments.html
Since your fragment is not getting destroyed and recreated, your buyersProfiles reference may hold the previous data when you return. Since the network call is not overwriting the original list, it will append the new data fetched from the network next to the existing data each time it calls it's onResponse callback.
This may also affect use cases where you implement some kind of pull-to-refresh logic or refresh button, as the new network call will not clean the list.
One thing you could try to avoid this repetition is adding
buyersProfiles = new ArrayList<BuyerProfile>();
to the top of your onResponse() callback.
Hope it helps.

Related

Null pointer exception on setOnClickListener()

I want to access from this fragment a view from another layout which is not part of the fragment. That is why i get NullPointerException.
How can i solve this?
Fragment code
public class Pacijenti_fragment extends Fragment {
//this is the JSON Data URL
public final static String MESSAGE_KEY= "com.example.android.app";
//a list to store all the products
List<Pacijent> pacijentList;
String id="";
String ID="";
//the recyclerview
RecyclerView recyclerView;
private SearchView searchView;
private PacijentiAdapter adapter;
Button btnPogled;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view=inflater.inflate(R.layout.pacijenti_fragment, container, false);
//getting the recyclerview from xml
recyclerView = (RecyclerView)view.findViewById(R.id.recylcerView);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new MyDividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL, 36));
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
//initializing the productlist
pacijentList = new ArrayList<>();
btnPogled=(Button)findViewById(R.id.btnDodaj); //here i make my button
Bundle b=getArguments();
this.id=b.getString("id");
System.out.println(id);
ID = this.id;
btnPogled.setOnClickListener(new View.OnClickListener(){ //here i get null pointer
#Override
public void onClick(View v) {
OnPogled();
}
});
//this method will fetch and parse json
//to display it in recyclerview
loadPacijenti();
return view;
}
This is another xml where I located my button
<?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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/GornjiLayout"
>
<TextView
android:id="#+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="Jane"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
android:textColor="#000000" />
<TextView
android:id="#+id/textViewSurname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_toRightOf="#id/textViewName"
android:text="Doe"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
android:textColor="#000000"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/SredjiLayout"
android:layout_below="#id/GornjiLayout"
>
<TextView
android:id="#+id/textViewDateOfBirth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textViewName"
android:layout_marginLeft="5dp"
android:layout_marginRight="150dp"
android:layout_marginTop="5dp"
android:text="21.05.1989"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
android:textStyle="bold" />
<Button
android:id="#+id/buttonDodaj"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="Otvori" />
</LinearLayout>
<TextView
android:id="#+id/textViewAdress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/SredjiLayout"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:text="Some street 45, UnknownVille"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
android:textStyle="bold" />
</RelativeLayout>
</LinearLayout>
I don't know how to access other xml from fragment. And this xml is separate file because it goes inside recyclerview with specific adapter that i wrote. and this button needs to be inside that recycler view because every button should pass id of every person from db.
Okay i got your point so basically what you're trying to do is access a button from another xml in your recycler view for that simply refer this code and do all changes in your adapter class here inside your oncreate view holder specify the xml file from which you'll be accessing the button:
public class ManagerTaskListAdapter extends RecyclerView.Adapter<ManagerTaskListAdapter.ProjectViewHolder> {
private ArrayList<Taskmsg> dataList;
private ArrayList<Project> projects;
Context mContext;
public ManagerTaskListAdapter(ArrayList<Taskmsg> dataList, Context mContext) {
this.dataList = dataList;
this.mContext=mContext;
}
#Override
public ProjectViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.man_task_list_item, parent, false);
return new ProjectViewHolder(view);
}
#Override
public void onBindViewHolder(ProjectViewHolder holder, int position) {
String fname=dataList.get(position).getEmpFirstName();
String lname=dataList.get(position).getEmpLastName();
String prdesc=dataList.get(position).getTaskDescription();
String pid= dataList.get(position).getProjectId().toString();
String em=dataList.get(position).getTaskCreatedBy();
String taskid=dataList.get(position).getTaskId().toString();
prdesc = prdesc.replaceAll("\\<.*?\\>", "");
holder.txttname.setText(dataList.get(position).getTaskName());
holder.txttdesc.setText(prdesc);
holder.txttaskcrt.setText(dataList.get(position).getTaskCreatedBy());
holder.txtempname.setText(fname +" "+ lname);
holder.itemView.setOnClickListener(v -> {
Intent in=new Intent(mContext,TaskDetails.class);
in.putExtra("tid",taskid);
in.putExtra("pid",pid);
in.putExtra("email",em);
mContext.startActivity(in);
});
}
#Override
public int getItemCount() {
return dataList.size();
}
class ProjectViewHolder extends RecyclerView.ViewHolder {
TextView txttname,txttdesc,txtempname,txttaskcrt;
ProjectViewHolder(View itemView) {
super(itemView);
txttname = (TextView) itemView.findViewById(R.id.tv_taskname);
txttaskcrt=itemView.findViewById(R.id.tv_taskcreatedby);
txttdesc = (TextView) itemView.findViewById(R.id.tv_taskdescription);
txtempname = (TextView) itemView.findViewById(R.id.tv_empname);
}
}
}
Just change one line of findviewById.
btnPogled=(Button)findViewById(R.id.btnDodaj)
to
btnPogled=(Button)view.findViewById(R.id.btnDodaj)

Recycler view not rendering view

I am not getting any view from the recycler, I did some debug and the constructor of the adapter is called with items on its list, also the method
getItemCount()
but none of the rest seem to be executed.
I´ve been wandering around stack looking for this problem and i found different approaches to a solution, problem is none worked out for me, maybe I am just missing something i can´t see.
I read somewhere that it could be because the recycler view is inside an scroll view, but the solution given did not worked for me
my custom adapter:
public class CircumstancesAdapter extends RecyclerView.Adapter<CircumstancesAdapter.CircumstancesViewHolder> {
List<CatalogRespModel> circumList;
Context mContext;
public CircumstancesAdapter(List<CatalogRespModel> list, Context context) {
this.circumList = list;
this.mContext = context;
}
#Override
public CircumstancesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.row_item_circumstances, parent, false);
return new CircumstancesViewHolder(view);
}
#Override
public void onBindViewHolder(CircumstancesViewHolder holder, int position) {
holder.tvCircum.setText(circumList.get(position).get_Descripcion());
}
#Override
public int getItemCount() {
if(circumList != null) return circumList.size();
else return 0;
}
public class CircumstancesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
RadioButton rbCircum;
TextView tvCircum;
private Context context;
public CircumstancesViewHolder(View itemView) {
super(itemView);
rbCircum = (RadioButton) itemView.findViewById(R.id.rb_circ);
rbCircum.setOnClickListener(this);
tvCircum = (TextView) itemView.findViewById(R.id.tv_circ);
this.context = itemView.getContext();
}
#Override
public void onClick(View v) {
}
}
}
my container layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- TODO: Update blank fragment layout -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:id="#+id/text2"
android:text="#string/text_circ"
android:textSize="20sp"
android:textColor="#color/colorPrimaryshadow"/>
<RelativeLayout
android:id="#+id/placa"
android:layout_width="180dp"
android:layout_height="120dp"
android:layout_gravity="center"
android:background="#drawable/placa">
<TextView
android:id="#+id/tv_plate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:layout_centerInParent="true"
android:text="#string/dummy"
android:textSize="40sp"
android:textColor="#android:color/black"/>
</RelativeLayout>
<ImageView
android:id="#+id/iv_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="true"
android:src="#drawable/conductora" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rview_circumstances"
android:layout_width="match_parent"
android:background="#fff"
android:orientation="vertical"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/boton_continuar_circustanciasa"
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/continuar"
android:layout_marginBottom="10dp"
android:elevation="30dp"
android:layout_gravity="center"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</FrameLayout>
my row layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:background="#fff"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:layout_height="wrap_content">
<RadioButton
android:id="#+id/rb_circ"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:buttonTint="#color/colorAccentDark"
android:gravity="center_vertical"
android:textSize="14sp" />
<TextView
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="#+id/tv_circ"
android:textSize="14sp"
android:text="texto de prueba"
android:textColor="#color/colorAccentDark"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
and in my onCreateView inside the fragment:
recyclerView = (RecyclerView) rootView.findViewById(R.id.rview_circumstances);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
if(Catalogs.circumstancesArray.size() > 0){
adapter = new CircumstancesAdapter(Catalogs.circumstancesArray, getContext());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
}
Note: I checked the List size and is greater than 0
Fragment code as requested:
public class CircumstancesFragment extends Fragment {
Button btnContinue;
TextView tvPlate;
private ImageView ivIndicator;
private static int iNumDevices;
IFragmentListener iFragmentListener;
private RecyclerView recyclerView;
RecyclerView.Adapter adapter;
private final static String TAGMap = CircumstancesFragment.class.getSimpleName();
public static final String TAG = "CircumstancesFragment.java";
public static CircumstancesFragment getInstance(Bundle bundle){
if(bundle != null){
iNumDevices = bundle.getInt("numDevices");
}
return new CircumstancesFragment();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if(context != null){
if(context instanceof IFragmentListener){
iFragmentListener = (IFragmentListener) context;
} else
throw new RuntimeException("el contexto no esta implementando la interfaz");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View rootView = inflater.inflate(R.layout.fragment_circustancias_, container, false);
btnContinue = (Button) rootView.findViewById(R.id.boton_continuar_circustanciasa);
tvPlate = (TextView) rootView.findViewById(R.id.tv_plate);
recyclerView = (RecyclerView) rootView.findViewById(R.id.rview_circumstances);
ivIndicator = (ImageView) rootView.findViewById(R.id.iv_indicator);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
if(Catalogs.circumstancesArray.size() > 0){
adapter = new CircumstancesAdapter(Catalogs.circumstancesArray, getContext());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
btnContinue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
try
{
iFragmentListener.notify(null, TAG);
} catch (Exception ex)
{
Log.d("error", ex.getMessage());
}
}
});
setLayout(iNumDevices);
return rootView;
}
private void setLayout(int i){
tvPlate.setText(FdccoreConstants.insuredArray.get(0).get_Placa_Vehiculo());
if(i== FdccoreConstants.ONE_DEVICE){
ivIndicator.setImageResource(R.drawable.conductora);
}else if(i== FdccoreConstants.TWO_DEVICE){
ivIndicator.setImageResource(R.drawable.only_conductor);
}
}
private void resetView(){
}
}
Please provide more code because Your layout and adapter is working fine.
I only changed Your model list to String.
Maybe in place when You checked list size and list.size() > 0 add
adapter.notifyDataSetChanged();
=====
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rview_circumstances);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
list = new ArrayList<>();
list.add("asd");
list.add("sasf");
list.add("asasfasf");
list.add("asgagsad");
list.add("asgas");
list.add("asagasgd");
list.add("asreyeryd");
list.add("asgsheyd");
CircumstancesAdapter adapter = new CircumstancesAdapter(list, this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
solution: somehow in order to work with the scroll view i must add this line
compile 'com.android.support:recyclerview-v7:25.3.1'
compiling only appcompat-v7 wont work

Fragment replacing in RecyclerView item

In my RecyclerView I need replace part of my item to my fragment. But replacing only first item in recycler view. What I am doing is wrong?
My container (in recycler view item):
...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container" />
...
My update code in RecyclerView adapter:
...
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
...
MyFragment fragment = MyFragment.newInstance("fragment1");
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
...
}
...
I finnaly found solution. The problem is I set a common container id. But in recycler view need to set unique container id for each item.
So, my code now this:
MyFragment fragment = MyFragment.newInstance("fragment1");
fragmentManager.beginTransaction().replace(UNIQUE_CONTAINER_ID, fragment).commit();
If someone will be useful, here is my complete code (implementation fragment in recycler view):
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
...
// Delete old fragment
int containerId = holder.mediaContainer.getId();// Get container id
Fragment oldFragment = fragmentManager.findFragmentById(containerId);
if(oldFragment != null) {
fragmentManager.beginTransaction().remove(oldFragment).commit();
}
int newContainerId = View.generateViewId();// Generate unique container id
holder.mediaContainer.setId(newContainerId);// Set container id
// Add new fragment
MyFragment fragment = MyFragment.newInstance("fragment1");
fragmentManager.beginTransaction().replace(newContainerId, fragment).commit();
...
}
Upd.: Instead of using your own method to generate a unique id, it is recommended to use View.generateViewId()
Thanks to Mikhali, I'm able to provide to you a complete running example.
Pay special attention on the comments in onBindViewHolder()
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewLedgerAdapter.ViewHolder>{
private final String TAG = RecyclerViewAdapter.class.getSimpleName();
private final float FINAL_OPACITY = 0.3f;
private final float START_OPACITY = 1f;
private final int ANIMATION_TIME = 500;
private final int TYPE_ITEM = 0;
private final int TYPE_DATE = 1;
private final int TYPE_TRANSACTION = 2;
private final int TYPE_PENDING = 3;
private HashMap<Integer, Integer> mElementTypes;
private List<Operation> mObjects;
private Context mContext;
private Utils.CURRENCIES mCurrencySelected; // Which currency is already selected
private boolean mCurrencyFilter; // Defines if a currency is already selected to apply filter
private Animation mAnimationUp;
private Animation mAnimationDown;
public RecyclerViewLedgerAdapter(List<Operation> objects, Context context) {
mElementTypes = new HashMap<Integer, Integer>();
mObjects = objects;
mContext = context;
mCurrencyFilter = false;
mCurrencySelected = null;
mAnimationUp = AnimationUtils.loadAnimation(context, R.anim.slide_up);
mAnimationDown = AnimationUtils.loadAnimation(context, R.anim.slide_down);
}
...
...
Not needed methods
...
...
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_element_ledger, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
Operation operation = mObjects.get(position);
holder.setAppUserActivity(userActivityOperation);
// Remember that RecyclerView does not have onClickListener, you should implement it
holder.getView().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Hide details
// iDetailsContainer object could be checked on inner class ViewHolder
if(holder.iDetailsContainer.isShown()){
holder.iDetailsContainer.setVisibility(View.GONE);
}else{
// Show details
// Get fragment manager inside our fragment
FragmentManager fragmentManager = ((UserActivity)mContext).getSupportFragmentManager();
// Delete previous added fragment
int currentContainerId = holder.iDetailsContainer.getId();
// Get the current fragment
Fragment oldFragment = fragmentManager.findFragmentById(currentContainerId);
if(oldFragment != null) {
// Delete fragmet from ui, do not forget commit() otherwise no action
// is going to be observed
ragmentManager.beginTransaction().remove(oldFragment).commit();
}
// In order to be able of replacing a fragment on a recycler view
// the target container should always have a different id ALWAYS
int newContainerId = getUniqueId();
// Set the new Id to our know fragment container
holder.iDetailsContainer.setId(newContainerId);
// Just for Testing we are going to create a new fragment according
// if the view position is pair one fragment type is created, if not
// a different one is used
Fragment f;
if(position%2 == 0) {
f = new FragmentCard();
}else{
f=new FragmentChat();
}
// Then just replace the recycler view fragment as usually
manager.beginTransaction().replace(newContainerId, f).commit();
// Once all fragment replacement is done we can show the hidden container
holder.iDetailsContainer.setVisibility(View.VISIBLE);
}
}
// Method that could us an unique id
public int getUniqueId(){
return (int)SystemClock.currentThreadTimeMillis();
}
});
}
public class ViewHolder extends RecyclerView.ViewHolder{
private View iView;
private LinearLayout iContainer;
public LinearLayout iDetailsContainer;
private ImageView iOperationIcon;
private ImageView iOperationActionImage;
private TextView iOperation;
private TextView iAmount;
private TextView iTimestamp;
private TextView iStatus;
private UserActivityOperation mUserActivityOperation;
public ViewHolder(View itemView) {
super(itemView);
iView = itemView;
iContainer = (LinearLayout) iView.findViewById(R.id.operation_container);
iDetailsContainer = (LinearLayout) iView.findViewById(R.id.details_container);
iOperationIcon = (ImageView) iView.findViewById(R.id.ledgerOperationIcon);
iOperationActionImage = (ImageView) iView.findViewById(R.id.ledgerAction);
iOperation = (TextView) iView.findViewById(R.id.ledgerOperationDescription);
iAmount = (TextView) iView.findViewById(R.id.ledgerOperationCurrencyAmount);
iTimestamp = (TextView) iView.findViewById(R.id.ledgerOperationTimestamp);
iStatus = (TextView) iView.findViewById(R.id.ledgerOperationStatus);
// This linear layout status is GONE in order to avoid the view to use space
// even when it is not seen, when any element selected the Adapter will manage the
// behavior for showing the layout - container
iDetailsContainer.setVisibility(View.GONE);
}
...
...
Not needed methods
...
...
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/operation_container_maximum"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="11dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="11dp"
android:orientation="vertical">
<LinearLayout
android:id="#+id/operation_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="14dp">
<ImageView
android:id="#+id/ledgerOperationIcon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/fondear" />
<ImageView
android:id="#+id/ledgerAction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="#drawable/operation_trade" />
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:weightSum="2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="#+id/ledgerOperationDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Descripcion"
android:textColor="#color/ledger_desc" />
<TextView
android:id="#+id/ledgerOperationCurrencyAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="2dp"
android:text="5000 BTC" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="#+id/ledgerOperationTimestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Fecha/Hora"
android:textColor="#color/ledger_timestamp" />
<TextView
android:id="#+id/ledgerOperationStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Status" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/details_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Something hidden" />
<ImageView
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/user_btc"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
</LinearLayout>
Fragment
// This is one of the fragments used in the RecyclerViewAdapterCode, and also makes a HTTPRequest to fill the
// view dynamically, you could laso use any of your fragments.
public class FragmentCard extends Fragment {
TextView mTextView;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_card, container, false);
mTextView = (TextView) view.findViewById(R.id.tv_fragment_two);
new UserActivityAsyncTask().execute();
return view;
}
private UserActivityOperation[] asyncMethodGetPendingWithdrawals(){
BitsoWithdrawal[] userWithdrawals = HttpHandler.getUserWithdrawals(getActivity());
int totalWithDrawals = userWithdrawals.length;
UserActivityOperation[] appUserActivities = new UserActivityOperation[totalWithDrawals];
for(int i=0; i<totalWithDrawals; i++){
appUserActivities[i] = new UserActivityOperation(userWithdrawals[i], getActivity());
}
return appUserActivities;
}
private class UserActivityAsyncTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(String... strings) {
// Precess Compound balance
UserActivityOperation[] compoundBalanceProcessed = asyncMethodGetPendingWithdrawals();
return compoundBalanceProcessed.length;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
mTextView.setText(result.toString());
}
}
}

How to get two different imageview in Recyclerview row

how do i get two different imageview and textviews in each row of recyclerview
and i want to make each imageview clickable .... i have done this in list view but don't know how to do it in recycler view .... so help me to acheive this ... thanks in advance
here is my layout file recyclerview row
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:weightSum="2">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="250dp"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="2">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="6dp"
android:scaleType="fitXY" />
/>
<TextView
android:id="#+id/category_title_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/thumbnail"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:ellipsize="end"
android:maxLines="1"
android:text="Title"
android:textColor="#android:color/black"
android:textSize="10dp" />
<TextView
android:id="#+id/tv_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/category_title_one"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:ellipsize="end"
android:maxLines="1"
android:text="Price"
android:textColor="#android:color/black"
android:textSize="10dp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/thumbnail2"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="6dp"
android:scaleType="fitXY" />
/>
<TextView
android:id="#+id/category_title_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/thumbnail2"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:ellipsize="end"
android:maxLines="1"
android:text="Title"
android:textColor="#android:color/black"
android:textSize="10dp">
</TextView>
<TextView
android:id="#+id/tv_price2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/category_title_two"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:ellipsize="end"
android:maxLines="1"
android:text="Price"
android:textColor="#android:color/black"
android:textSize="10dp">
</TextView>
</RelativeLayout>
</LinearLayout>
here is my adapterclass
public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ViewHolder> {
private Context context;
public ImageLoader mImageLoader;
//List of superHeroes
List<ListOfData> superHeroes;
public RecyclerViewDataAdapter(List<ListOfData> superHeroes, Context context) {
super();
//Getting all the superheroes
this.superHeroes = superHeroes;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_row, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ListOfData superHero = superHeroes.get(position);
mImageLoader = MyApplication.getInstance().getImageLoader();
mImageLoader.get(superHero.getImageUrl(), ImageLoader.getImageListener(holder.imageView1, R.mipmap.ic_launcher, android.R.drawable.ic_dialog_alert));
mImageLoader.get(superHero.getImageUrl(), ImageLoader.getImageListener(holder.imageView2, R.mipmap.ic_launcher, android.R.drawable.ic_dialog_alert));
holder.imageView1.setImageUrl(superHero.getImageUrl(), mImageLoader);
holder.imageView2.setImageUrl(superHero.getImageUrl(), mImageLoader);
holder.textViewName1.setText(superHero.getName());
holder.textViewName2.setText(superHero.getName());
//holder.textViewRank.setText(String.valueOf(superHero.getRank()));
//holder.textViewRealName.setText(superHero.getRealName());
//holder.textViewCreatedBy.setText(superHero.getCreatedBy());
//holder.textViewFirstAppearance.setText(superHero.getFirstAppearance());
String powers = "";
/* for(int i = 0; i<superHero.getPowers().size(); i++){
powers+= superHero.getPowers().get(i);
}*/
//holder.textViewPowers.setText(powers);
}
#Override
public int getItemCount() {
return superHeroes.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
public NetworkImageView imageView1;
public NetworkImageView imageView2;
public TextView textViewName1;
public TextView textViewName2;
public TextView textViewRank;
public TextView textViewRealName;
public TextView textViewCreatedBy;
public TextView textViewFirstAppearance;
public TextView textViewPowers;
public ViewHolder(View itemView) {
super(itemView);
imageView1 = (NetworkImageView) itemView.findViewById(R.id.thumbnail);
imageView2 = (NetworkImageView) itemView.findViewById(R.id.thumbnail2);
textViewName1 = (TextView) itemView.findViewById(R.id.category_title_one);
textViewName2 = (TextView) itemView.findViewById(R.id.category_title_two);
/* textViewRank= (TextView) itemView.findViewById(R.id.textViewRank);
textViewRealName= (TextView) itemView.findViewById(R.id.textViewRealName);
textViewCreatedBy= (TextView) itemView.findViewById(R.id.textViewCreatedBy);
textViewFirstAppearance= (TextView) itemView.findViewById(R.id.textViewFirstAppearance);
textViewPowers= (TextView) itemView.findViewById(R.id.textViewPowers);
*/
}
}
}
here is Json part
public class Pants extends Fragment {
//Creating a List of superheroes
public Context context;
public List<ListOfData> listSuperHeroes;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
public Pants() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.tshirts_pants_shirts, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
//Calling method to get data
getData();
return view;
}
private void getData() {
//Showing a progress dialog
final ProgressDialog loading = ProgressDialog.show(getActivity(), "Loading Data", "Please wait...", false, false);
//Creating a json array request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ProductConfig.DATA_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Dismissing progress dialog
loading.dismiss();
//calling method to parse json array
parseData(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
//Adding request to the queue
requestQueue.add(jsonArrayRequest);
}
//This method will parse json data
private void parseData(JSONArray array) {
listSuperHeroes = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
ListOfData superHero = new ListOfData();
JSONObject json = null;
try {
json = array.getJSONObject(i);
superHero.setImageUrl(json.getString(ProductConfig.TAG_IMAGE_URL));
superHero.setName(json.getString(ProductConfig.TAG_NAME));
/*superHero.setRank(json.getInt(ProductConfig.TAG_RANK));
superHero.setRealName(json.getString(ProductConfig.TAG_REAL_NAME));
superHero.setCreatedBy(json.getString(ProductConfig.TAG_CREATED_BY));
superHero.setFirstAppearance(json.getString(ProductConfig.TAG_FIRST_APPEARANCE));
*/
ArrayList<String> powers = new ArrayList<String>();
JSONArray jsonArray = json.getJSONArray(ProductConfig.TAG_POWERS);
for (int j = 0; j < jsonArray.length(); j++) {
powers.add(((String) jsonArray.get(j)) + "\n");
}
superHero.setPowers(powers);
} catch (JSONException e) {
e.printStackTrace();
}
listSuperHeroes.add(superHero);
}
adapter = new RecyclerViewDataAdapter(listSuperHeroes, context);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
//Initializing our superheroes list
}
}
Do the images of the same row belong to the same hero or are they from different heroes?
If they are from different heroes:
1) Change your recyclerview row layout to have only 1 imageview and 2 textviews (remove the second relativelayout)
2) Change the LayoutManager of your recyclerview to GridLayoutManager with 2 columns:
GridLayoutManager glm = new GridLayoutManager(getContext(), 2);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return 2;
}
});
recyclerView.setLayoutManager(glm);
3) Change your onBindViewHolder meethod and ViewHolder class accordingly (remove the second imageview and the third and fourth textviews)
4) Make the image clickable adding the following to the onBindViewHolder method:
holder.imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
If I understand your issue correctly, in onBindViewHolder you're setting both of your TextViews and ImageViews using the same data. Which is why you're getting the same image twice. What you should do is pass Map<int, List<Object>> superHeroes into your RecyclerView. The key would be the row item number and the list would contain objects for both your superheroes with a title and image uri.
To make your individual ImageViewsclickable, set anonClickListeneron eachonBindViewHolder` and handle their respect logic.
From this code I can see that you set the same image to imageView1 and imageView2 and the same text for textViewName1 and textViewName2
holder.imageView1.setImageUrl(superHero.getImageUrl(), mImageLoader);
holder.imageView2.setImageUrl(superHero.getImageUrl(), mImageLoader);
holder.textViewName1.setText(superHero.getName());
holder.textViewName2.setText(superHero.getName());
If you would like to have two different images, you have to set two different images and not the same one.
For the click handling you have to set the onClickListener on the image/text/button/view that you want making clickable, for example if you want that your imageView1 is clickable you have to do
holder.imageView1.setOnClickListener(this);
than you have to implements the interface
public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ViewHolder> implements View.OnClickListener {
and after that you can handle the onClick event in the overrided method
#Override
public void onClick(View v) {
}
I hope that helps.
Even though the question is 4 years old. I going to post an answer so other people can see it.
Since you are providing an array, the position is getting the values ( image and text) item from each index of the array.
What you need to do is provide the array as you did but make sure each index of the array contain image1, text1, image2 and text2.

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