I have created a RecyclerView, and in the Adapter I am hoping to create a ClickListener. I want each item in the RecyclerView to send a unique response after click. In other words, a click is loading a different fragment for each specific RecyclerView item. Right now, the RecyclerView is not responding, as I have logged it and even added a Toast without any luck:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<LatestPoll> mDataSet;
int lastPosition = -1;
// 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 implements View.OnClickListener {
// each data item is just a string in this case
protected TextView pollQuestion;
protected ImageView pollImage;
protected RelativeLayout individualItem;
public ViewHolder(View v) {
super(v);
pollQuestion = (TextView) v.findViewById(R.id.latest_item_question);
pollImage = (ImageView) v.findViewById(R.id.pollThumbNailImage);
individualItem = (RelativeLayout) v.findViewById(R.id.individual_item);
individualItem.setOnClickListener(this);
}
#Override
public void onClick(View v) {
v.getId();
int itemPosition = getLayoutPosition();
String item = String.valueOf(mDataSet.get(itemPosition));
Toast.makeText(getActivity().getApplicationContext(), item, Toast.LENGTH_LONG).show();
Log.v("TESTING", "ITEM CLICKED!");
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<LatestPoll> myDataset) {
mDataSet = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
// set the view's size, margins, paddings and layout parameters
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
//The OutOfBoundsException is pointing here
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.v("ON_BIND", "ON_BINDVIEWHOLDER CALLED");
LatestPoll latestPoll = mDataSet.get(position);
holder.pollQuestion.setText(latestPoll.getQuestion());
Picasso.with(getActivity())
.load(latestPoll.getPollImage())
.fit()
.placeholder(R.drawable.loading_spinnter_white)
.into(holder.pollImage);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataSet.size();
}
}
private void onLoad() {
if (mFragmentListener != null) {
mFragmentListener.onFragmentLoaded();
}
}
public interface FragmentListener {
void onFragmentLoaded();
}
}
You need to set onclick listener to the parent layout inside the onBindViewHolder .
holder.parentID.setOnClickListener(mRecyclerViewListener);
In your View holder
parentID = iteView.findViewById(R.id.parent);
Related
I want to use admob with recyclerview but there is a problem. I need to hide some elements that are belong to viewholder. I need to hide the imageview in which position the ImageView belongs. When i click holder.btnReklamIzle the picture in that position must be hid in onRewardedVideoAdLoaded method. How can i transmit the position to onRewardedVideoAdLoaded method?
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_kuponlar, container, false);
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(KuponlarFragment.this.getActivity());
mRewardedVideoAd.setRewardedVideoAdListener(this);
tahminlerRecyclerView = root.findViewById(R.id.tahminlerRecyclerView);
linearLayoutManager = new LinearLayoutManager(this.getActivity());
tahminlerRecyclerView.setLayoutManager(linearLayoutManager);
tahminlerRecyclerView.setHasFixedSize(true);
loadRewardedVideoAd();
fetch();
return root;
}
private void loadRewardedVideoAd() {
mRewardedVideoAd.loadAd(getString(R.string.admob_ads_id),
new AdRequest.Builder().build());
}
private void fetch() {
Query query = FirebaseDatabase.getInstance()
.getReference()
.child("tahminler");
FirebaseRecyclerOptions<Mac> options =
new FirebaseRecyclerOptions.Builder<Mac>()
.setQuery(query, new SnapshotParser<Mac>() {
#NonNull
#Override
public Mac parseSnapshot(#NonNull DataSnapshot snapshot) {
return new Mac((double)snapshot.child("oran").getValue(),
snapshot.child("tahmin").getValue().toString(),
);
}
})
.build();
adapter = new FirebaseRecyclerAdapter<Mac, ViewHolder>(options) {
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tahmin_tasarim_recyclerview, parent, false);
return new ViewHolder(view);
}
#Override
protected void onBindViewHolder(final ViewHolder holder, final int position, Mac mac) {
holder.btnReklamIzle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}
}});
}
};
tahminlerRecyclerView.setAdapter(adapter);
}
#Override
public void onRewardedVideoAdLoaded() {
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView image;
public ViewHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.image);
}
}
onRewardedVideoAdLoaded is a callback method for an asynchronous operation hence you cannot pass values to it as arguments but use referenced variables.
For your case do the following:
Firstly
Create a global variable to hold the list of views to hide
ArrayList<View> views_to_hide = new ArrayList<>();
Secondly
Create a helper function to hide the views
function hideViews(ArrayList<View> views){
for(View v : views) v.setVisibility(View.GONE);
}
Thirdly
Inside onBindViewHolder Add to the list the views you want to hide under your button onClick
public void onClick(View v) {
//...
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
// Ads already shown you may want to manually hide other images here
}else{
// We only need to add to list when ads not loaded
// We also want to make sure we don't add same view to the list twice
if(!views_to_hide.contains(holder.image))
views_to_hide.add(holder.image);
}});
//...
Finally
Call your helper function inside onRewardedVideoAdLoaded
#Override
public void onRewardedVideoAdLoaded() {
//This hides the views that was added to the list before now
hideViews(views_to_hide);
}
As I'm new to android, I'm struggling to highlight Recyclerview clicked or current item. I have tried some workarounds but nothing helps. Basically I want to highlight selected item even after it is coming back from respective Fragment. Please check my code and help me to get done. Thanks.
public class ContentaAdapter extends RecyclerView.Adapter<ContentaAdapter.MyViewHolder> {
Context context;
ArrayList<String> ItemTitle;
ArrayList<String> ItemSource;
public ContentaAdapter(Context context, ArrayList<String> ItemTitle, ArrayList<String> ItemSource) {
this.context = context;
this.ItemTitle = ItemTitle;
this.ItemSource = ItemSource;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_items_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.ItemTitle.setText(ItemTitle.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment contentdisplay = new ViewContentFragment();
Bundle bundle=new Bundle();
bundle.putStringArrayList("ItemTitle",ItemTitle);
bundle.putStringArrayList("ItemSource",ItemSource);
bundle.putInt("position",position);
bundle.putInt("ItemCounts",ItemTitle.size());
contentdisplay.setArguments(bundle);
((MainActivity)context).replaceFragment(contentdisplay);
}
});
}
#Override
public int getItemCount() {
return ItemTitle.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView ItemTitle;
public MyViewHolder(View itemView) {
super(itemView);
ItemTitle = (TextView) itemView.findViewById(R.id.item_title);
}
}
}
you need to to add isSelected state in to your list item data model and change it onClick.
And when you know state you can change background in ViewHolder
if (isSelected) {
// set selected background here
} else {
// set not selected background here
}
And instead of keeping two lists in adapter you should create one with model ArrayList<DataModel> similar to this:
class DataModel {
String ItemTitle;
String ItemSource;
Boolean isSelected;
}
also you shouldn't pass both list to other fragment, instead take only what you need, for example yourList.get(position);
I'm using Recycleview with Cardview in Gridlayout for Books app which will be fetched from Json . I'm looking to open different url which will download a separate books on for each item. How do I create this...??
Below is my adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Model> mDataset;
private ImageLoader mImageLoader;
// 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 ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView nameText;
public TextView phoneText;
public NetworkImageView image;
#SuppressLint("WrongViewCast")
public ViewHolder(View v) {
super(v);
nameText = v.findViewById(R.id.name_text);
phoneText = v.findViewById(R.id.phone_text);
image = v.findViewById(R.id.imgAvatar);
image.setDefaultImageResId(R.mipmap.ic_launcher);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Position: "+getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Model> myDataset, Context mCOntext) {
Log.d("TEST",myDataset.get(0).getName());
mDataset = myDataset;
mImageLoader = MySingleton.getInstance(mCOntext).getImageLoader();
}
// 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.card_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
//holder.mTextView.setText(mDataset.get(position).getName());
Log.d("TEST","Printing Names onBindView Holder"+mDataset.get(position).getName());
holder.nameText.setText(mDataset.get(position).getName());
holder.phoneText.setText(mDataset.get(position).getPhone());
holder.image.setImageUrl(mDataset.get(position).getImage(),mImageLoader);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
Below is the screenshot of my Grid layout
Thanks in advance.
Do you have an URL for each Book ? If so, you can store it in your Model. Then, you can store it in the ViewHolder and retrieve it in the OnClickListener.
It means
Model.java
public class Model {
// your model
private String mUrl;
String getUrl() {
return mUrl;
}
}
MyAdapter.java
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView nameText;
public TextView phoneText;
public NetworkImageView image;
public String url;
#SuppressLint("WrongViewCast")
public ViewHolder(View v) {
super(v);
nameText = v.findViewById(R.id.name_text);
phoneText = v.findViewById(R.id.phone_text);
image = v.findViewById(R.id.imgAvatar);
image.setDefaultImageResId(R.mipmap.ic_launcher);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Position: "+getAdapterPosition(), Toast.LENGTH_SHORT).show();
// you can use url here
}
});
}
}
// ...
// 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
Model model = mDataset.get(position);
// - replace the contents of the view with that element
//holder.mTextView.setText(model.getName());
Log.d("TEST","Printing Names onBindView Holder"+mDataset.get(position).getName());
holder.nameText.setText(model.getName());
holder.phoneText.setText(model.getPhone());
holder.image.setImageUrl(model.getImage(),mImageLoader);
holder.url = model.getUrl();
}
I have Adapter in my project and few fragments where I populate fragments with celebrity names and date of birth as it is given in below image
I will like to call a different url to launch for each item
For First Item
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.stackoverflow.com")));
For Second Item
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.youtube.com")));
and so on
Below is my Adapter Class
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Model> mDataset;
private ImageLoader mImageLoader;
// 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 ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView nameText;
public TextView phoneText;
public NetworkImageView image;
#SuppressLint("WrongViewCast")
public ViewHolder(View v) {
super(v);
nameText = v.findViewById(R.id.name_text);
phoneText = v.findViewById(R.id.phone_text);
image = v.findViewById(R.id.imgAvatar);
image.setDefaultImageResId(R.mipmap.ic_launcher);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Position: "+getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Model> myDataset, Context mCOntext) {
Log.d("TEST",myDataset.get(0).getName());
mDataset = myDataset;
mImageLoader = MySingleton.getInstance(mCOntext).getImageLoader();
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
public interface ItemClickListener {
void onItemClick(View view, int position);
}
// 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
//holder.mTextView.setText(mDataset.get(position).getName());
Log.d("TEST","Printing Names onBindView Holder"+mDataset.get(position).getName());
holder.nameText.setText(mDataset.get(position).getName());
holder.phoneText.setText(mDataset.get(position).getPhone());
holder.image.setImageUrl(mDataset.get(position).getImage(),mImageLoader);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
and my Fragment is
public class english extends Fragment implements Response.Listener , Response.ErrorListener {
View view;
RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private Context context;
private List<Model> contactList = new ArrayList<>();
private String url ="https://api.androidhive.info/json/contacts.json";
Button btn;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.home_fragment,container,false);
context = getContext();
mLayoutManager = new GridLayoutManager(context,2);
mRecyclerView = (RecyclerView)view.findViewById(R.id.my_recycler_view);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManager);
getContactList();
return view;
}
private void getContactList(){
Log.d("TEST","Getting Contact list");
Controller.getInstance(context).makeNetworkCalls(Request.Method.GET,url,this,this);
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
Toast.makeText(context, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Object response) {
Log.d("TEST","Got The response" +response);
if (response == null) {
Toast.makeText(context, "Couldn't fetch the contacts! Pleas try again.", Toast.LENGTH_LONG).show();
return;
}
List<Model> items = new Gson().fromJson(response.toString(), new TypeToken<List<Model>>(){}.getType());
contactList.addAll(items);
MyAdapter rcAdapter = new MyAdapter(contactList,context);
mRecyclerView.setAdapter(rcAdapter);
}
}
Please Help.
its Simple
First Create URL Array
in The Adapter Classs
ArrayList<String> UrlsToTran=new ArrayList<>();
in The Adapter Class Constructor
MyAdapter(Context mContext)
{
//Assing Context
//Assign The Urls
UrlsToTran.add("www.stackoverflow.com");
UrlsToTran.add("www.facebook.com");
//And Add More Values As U need
}
Then Add OnClick Listener
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
//holder.mTextView.setText(mDataset.get(position).getName());
Log.d("TEST","Printing Names onBindView
Holder"+mDataset.get(position).getName());
holder.nameText.setText(mDataset.get(position).getName());
holder.phoneText.setText(mDataset.get(position).getPhone());
holder.image.setImageUrl(mDataset.get(position).getImage(),mImageLoader);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(UrlsToTran.get(position).toString())));
}
});
}
First, for every item in your adapter create an OnClickListener like this:
holder.image.setOnClickListener(v->{
});
Now Create an interface between the adapter and the fragment/activity that shows the list
public interface ModelListener {
void onModelClicked(Model model);
}
In your activity/fragment listen to an item click and send the intent
new ModelListener(){
public void onModelClicked(Model model){
startActivity(new Intent(.., model.getUrl()));
}
}
I'm using this CarouselView library.
I have used Recycler View and Card View to create the following UI.
In each card view, I have added this carousel view and contains images inside carousel.
This library has the setImageClickListener that gives the index of each clicked image in each card view.
customCarouselView.setImageClickListener(new ImageClickListener() {
#Override
public void onClick(int position) {
Toast.makeText(SampleCarouselViewActivity.this, "Clicked item: "+ position, Toast.LENGTH_SHORT).show();
}
});
I want to know which image is clicked and from which card that image belongs since there are multiple card-views.
I tried to register the click event in the ImageView and get the adapterPosition of clicked cardview using getAdapterPosition().
fruitImageView.setOnClickListener(new View.OnClickListener() { /*Hits only when another click event (setImageClickListner) is not registered*/
#Override
public void onClick(View view) {
int a = getAdapterPosition(); //gives the index of clicked cardview position.
}
});
When both of the events are registered then only click on ImageView (fruitImageView.setOnClickListener) gets hit, which gives the position of the adapter. I also want to know which image is clicked.
When I remove this ImageView Click listener, then carousel view click customCarouselView.setImageClickListener gets hit which gives the postion of image clicked but not the adapter position.
Are there any work around for this? Please help.
My Adapter Class complete code:
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {
private ArrayList<HomeSalesModel> salesLists;
int[] sampleImages = {R.drawable.album1, R.drawable.album2, R.drawable.album3, R.drawable.album4, R.drawable.album5};
String[] sampleTitles = {"A", "B", "C", "D", "E"};
Context myContext = null;
public GridAdapter(ArrayList<HomeSalesModel> salesLists) {
this.salesLists = salesLists;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
myContext = parent.getContext();
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(GridAdapter.ViewHolder viewHolder, int i) {
viewHolder.tv_country.setText(salesLists.get(i).getTitle());
}
#Override
public int getItemCount() {
return salesLists.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private CarouselView customCarouselView;
private TextView tv_country;
private CardView cardView;
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.grid_card_row, parent, false));
tv_country = (TextView) itemView.findViewById(R.id.tv_country);
customCarouselView = (CarouselView) itemView.findViewById(R.id.customCarouselView);
cardView = (CardView) itemView.findViewById(R.id.card);
customCarouselView.setPageCount(sampleImages.length);
//customCarouselView.setSlideInterval(4000);
customCarouselView.setViewListener(viewListener);
customCarouselView.setImageClickListener(imageClickListner);
}
ViewListener viewListener = new ViewListener() {
#Override
public View setViewForPosition(int position) {
LayoutInflater li = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View customView = li.inflate(R.layout.view_custom, null);
TextView labelTextView = (TextView) customView.findViewById(R.id.labelTextView);
ImageView fruitImageView = (ImageView) customView.findViewById(R.id.fruitImageView);
fruitImageView.setImageResource(sampleImages[position]);
labelTextView.setText(sampleTitles[position]);
fruitImageView.setOnClickListener(new View.OnClickListener() { /*Works when another click event (imageClickListner) is not registered*/
#Override
public void onClick(View view) {
int a = getAdapterPosition(); //gives the index cardview position.
}
});
//labelTextView.setText(salesLists.get(position).getProducts().get(position).getSlug());
return customView;
}
};
ImageClickListener imageClickListner = new ImageClickListener() {
#Override
public void onClick(int position) {
Toast.makeText(myContext, "Clicked item: " + position, Toast.LENGTH_SHORT).show(); //gives index the clicked image.
}
};
}
}
Simply you can get the adapter position inside ImageClickListener.
int postion = getAdapterPosition();