RecyclerView OnClick Event Does Not Work - android

I got some trouble while setting an onclicklistener to my recyclerview. I saw that similar question has been asked, I tryed all the ways I can find but I got no result. Here is how I implement it:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Question> values;
private Context context;
public class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener{
public TextView txtHeader;
public View layout;
public ViewHolder(View v) {
super(v);
layout = v;
txtHeader = (TextView) v.findViewById(R.id.header);
}
#Override
public void onClick(View view) {
Log.d("Tag:", "Here");
int position = getLayoutPosition();
String question = values.get(position).getQuestion();
String choiceA = values.get(position).getChoiceA();
String choiceB = values.get(position).getChoiceB();
String choiceC = values.get(position).getChoiceC();
Integer questionID = values.get(position).getQuestionID();
Intent intent = new Intent(context,SingleQuestionActivity.class);
intent.putExtra("question", question);
intent.putExtra("choiceA", choiceA);
intent.putExtra("choiceB", choiceB);
intent.putExtra("choiceC", choiceC);
intent.putExtra("questionID", questionID);
QuestionActivity questionActivity =
(QuestionActivity) context;
questionActivity.goToSingleQuestionScreen(intent);
}
}
...
As you can see I put an Log.d to see if it comes to onClick method it did not. And I set this adapter in my QuestionActivity class like below:
public class QuestionActivity extends AppCompatActivity{
...
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question);
initializeComponents();
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setBackgroundColor(Color.YELLOW);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
QuestionRepository questionRepository =
QuestionRepository.getInstance(getApplicationContext());
Intent intent = getIntent();
questions = questionRepository
.getCategorizedQuestions(intent.getIntExtra("category", 1));
mAdapter = new MyAdapter(questions, this);
recyclerView.setAdapter(mAdapter);
...
Where am I doing wrong?

Try :
public ViewHolder(View v) {
super(v);
layout = v;
txtHeader = (TextView) v.findViewById(R.id.header);
v.setOnClickListener(this);
}
Hope this helps

This can be easily and cleanly done using Butterknife.
Add to your gradle file dependencies and sync project.
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
Now it is easier to set listeners and bind views. You could do the following:
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.header)
TextView header;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
#OnClick
void onClick(View view) {
Log.d("pos", getAdapterPosition());
Intent intent ...
...
view.getContext().startActivity(intent);
}
}
By using #BindView annotation you don't have to call findViewById()every time - Butterknife does that for you. Also you don't have to implement listeners - just add #OnClick annotation.
Also there is no need to get QuestionActivity and call its method from adapter (which I assume is starting another activity). Context can be obtained from view.getContext() as every view holds a reference to context and then you can call e.g. startActivity(intent)
For further reading I recommend
https://medium.com/#pranaypatel/butterknife-a-viewbinding-library-for-android-beginner-guide-fd92caf8e505
http://www.vogella.com/tutorials/AndroidButterknife/article.html

Related

How to display more than one website on a webView

I have a Recycler View and I want my webView to display different website when different items on the Recycler View is clicked.
I have implemented a recycler view which has An ImageView, and two text views. I want a website to be opened in the webview anytime an item on the recycler view is clicked. I want different websites to be opened anytime an item from different rows on the recycler view is clicked.
I have tried different methods but its still not working.
These are my codes
RecyclerViewAdapter:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{
private static final String TAG = "RecyclerViewAdapter";
private ArrayList<String> mImageViews = new ArrayList<>();
private ArrayList<String> mBlogDescriptions = new ArrayList<>();
public ArrayList<String> mBlogNames = new ArrayList<>();
private Context mContext;
public RecyclerViewAdapter mViewAdapter;
public RecyclerViewAdapter(ArrayList<String> imageViews, ArrayList<String> blogDescriptions,ArrayList<String> blogNames, Context context) {
mImageViews = imageViews;
mBlogDescriptions = blogDescriptions;
mBlogNames = blogNames;
mContext = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_list_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
Log.d(TAG, "onBindViewHolder: called.");
String currentItem = mBlogNames.get(position);
Glide.with(mContext)
.asBitmap()
.load(mImageViews.get(position))
.into(holder.mImageView);
holder.mBlogDescription.setText(mBlogDescriptions.get(position));
holder.mBlogName.setText(mBlogNames.get(position));
holder.mBlogName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Bundle extras = new Bundle();
extras.putStringArray("url", new String[]{"www.goal.com","www.facebook.com","www.twitter.com","www.youtube.com"});
extras.get(String.valueOf(position));
Intent intent = new Intent(mContext,WebViewActivity.class);
intent.putExtras(extras);
}
});
}
#Override
public int getItemCount() {
return mBlogDescriptions.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
CircleImageView mImageView;
TextView mBlogDescription;
TextView mBlogName;
RelativeLayout mRelativeLayout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mImageView =itemView.findViewById(R.id.circular_image);
mBlogDescription = itemView.findViewById(R.id.blog_description);
mBlogName = itemView.findViewById(R.id.blog_name);
mRelativeLayout = itemView.findViewById(R.id.parent_layout);
}
}
}
WebViewActivity
public class WebViewActivity extends AppCompatActivity {
private WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
mWebView = findViewById(R.id.web_view);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient());
Bundle extras = this.getIntent().getExtras();
String[] array = extras.getStringArray("url");
mWebView.loadUrl("array");
}
#Override
public void onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
}
please help me with a solution.
Thanks
From my understanding you are trying to create different webviews in your recycler view.
If that is the case i would suggest
creating an android resource file containing the webview
creating an array with the different urls you would like to see in the webview.
Creating a recyclerview adapter that inflates the recource file with the data inside your array.
Pass the adapter into the recycler view.
If you have the urls set with the views inside your recyclerview. What you need to do is
You should implement onTouchEventLister to your recycler view
Then get the view that was touched by getting the view in the position of the touch.
Get the data from that view e.g. if the view that was touched was a textview with text as url. You can get the text from it.
Update the webview url with the url you got from the textview.
Since the two views are on the same context, you can call them from within the ontoucheventlistener
I hope this answers your question.
implementation 'androidx.browser:browser:1.0.0'
CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();
intentBuilder.setToolbarColor(getColor(context, R.color.colorPrimary));
intentBuilder.setSecondaryToolbarColor(getColor(context, R.color.colorPrimaryDark));
intentBuilder.build().launchUrl(context, Uri.parse(url));
I hope this will help you:)

How to use Butterknife with onClickListener in Activity?

I'm looking the answer how to make onClickListener button located in Recycleview Item using Butterknife. I know how to do it without Butterknife, but I can't find anything with Bt.
Does Bt supports this?
' class ViewHolder {
#BindView(R.id.title) TextView name;
#BindView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
#OnClick(R.id.submit)
public void submit(View view) {
// TODO submit data to server...
}
}'
Try to learn from the sample code at official site
If you want to implement the click logic in the activity then here are the steps.
1 Create an interface
public interface ClickHandler{
void onClick(int position);
}
2 Implement CLickHandler in activity
MainActivity extends AppCompatActivity implements ClickHandler{
...
public void onclick(int position){
Log.d("Check","Clicked at" + position);
}
...
adapter = new MyAdapter(this);//Pass the reference to activity as it implements the clickhandler.
...
}
3 Now your adapter has the reference for clickhandler. Similarly pass it to the viewholder and call the onCLick method from there.
class ViewHolder {
#BindView(R.id.title) TextView name;
#BindView(R.id.job_title) TextView jobTitle;
ClickHandler clickHandler;
public ViewHolder(View view, ClickHandler) {
ButterKnife.bind(this, view);
this.clickHandler = clickHandler;
}
#OnClick(R.id.submit)
public void submit(View view) {
if(clickHandler(!=null){
clickHandler.onClick(getAdapterPosition());
}
}
}

How to create a RecyclerView of Buttons

I am creating an AlertDialog custom class, called ActionDialog, which will contains a RecyclerView containing Buttons. I have a List of Button that I populate in the custom class ActionDialog (for now i just populate with useless Button just to try to use it, except one which I create in another class).
The problem is that when i create the AlertDialog, all buttons are showing empty, they are showed but with no text/no clicklistener (as you can see in the image below).
(I have added a custom ActionListener to a Button in another class and then give it as parameter in ActionDialog class. Will it lose the ActionListener?)
Here is the result.
I will leave here my ActionDialog class code, and the adapter class.
This is ActionDialog class:
public class ActionDialog extends AlertDialog{
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private Button actionButtons;
private List<Button> buttons;
private Activity context;
public ActionDialog(#NonNull Activity context, Button actionButtons) {
super(context);
this.context = context;
this.actionButtons = actionButtons;
buttons = new ArrayList<>();
initButton();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//requestWindowFeature(Window.FEATURE_NO_TITLE);
}
private void initButton(){
initZoneButton();
//TODO init all buttons
Button b1 = new Button(context);
b1.setText("ExampleButton1");
Button b2 = new Button(context);
b2.setText("ExampleButton2");
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String a;
}
});
buttons.add(b1);
buttons.add(b2);
}
private void initZoneButton(){
buttons.add(actionButtons); //this button is created in another class and give as parameter in this class
}
public void createDialog(){
Builder mBuilder = new Builder(context);
View view = context.getLayoutInflater().inflate(R.layout.dialog_actionbuttons_layout, null);
mRecyclerView = view.findViewById(R.id.dialog_actionbuttons_rv);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(context);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new ActionButtonsAdapter(buttons);
mRecyclerView.setAdapter(mAdapter);
mBuilder.setView(view);
mBuilder.create().show();
}
}
Here is the RecyclerView adapter class:
public class ActionButtonsAdapter extends RecyclerView.Adapter<ActionButtonsAdapter.ViewHolder>{
private List<Button> dataButtons;
static class ViewHolder extends RecyclerView.ViewHolder {
Button actionButton;
ViewHolder(View v) {
super(v);
actionButton = v.findViewById(R.id.action_button_rv);
}
}
public ActionButtonsAdapter(List<Button> dataButtons){
this.dataButtons = dataButtons;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.actionButton = dataButtons.get(position);
//i think the problem is here, maybe
}
#Override
public ActionButtonsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_actionbutton_layout, parent, false);
return new ViewHolder(v);
}
#Override
public int getItemCount() {
return dataButtons.size();
}
}
I think in the onBindViewHolder method you should do what ever you want to do with your button.
Also there is no need for the list of buttons here. Make a list the data you need to be held in the Buttons RecyclerView.
I have a RecyclerView that will display Genres for restaurants lets say, So I will create a List of strings to hold these genres names (chickens, meats, etc,..)
Setting its text
holder.actionButton.setText(// Make use of position here);
Or Click Listeners.
Update
You can check google samples for recyclerview here
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
// Get element from your dataset at this position and replace the contents of the view
// with that element
viewHolder.getTextView().setText(mDataSet[position]);
}
wheres mDataset is Array of Strings.

Disable item click and enable onclick of recyclerview

here is my layout xml.If relativelayout click works that is also fine.Not getting any click events other than item clicks.
<RelativeLayout
android:id="#+id/layoutItems"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/viewDivider">
<android.support.v7.widget.RecyclerView
android:id="#+id/item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:padding="8dp"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
There are some different ways to do it. The first way is to do like this:
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// do whatever
}
#Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);
Or you can do it in a ViewHolder.
We will need a listener interface.
public interface OnItemClickListener {
public void onClick(View view, int position);
}
In your ViewHolder class in your RecyclerView adapter, implement View.OnClickListener, bind the listener to the view. In the onClick method, call the onClick method of the interface OnItemClickListener. This should be passed in from your RecycyclerView’s constructor. The actual implementation of the onclick event will be from an activity or fragment that contains this RecyclerView. The important line here is clickListener.onClick(view, getPosition()); where clickListener is a global variable in your RecyclerView class, again it should’ve passed in from your RecyclerView’s constructor.
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView cityName;
public ViewHolder(View view) {
super(view);
cityName = (TextView) view.findViewById(R.id.city_name);
itemView.setOnClickListener(this); // bind the listener
}
#Override
public void onClick(View view) {
clickListener.onClick(view, getPosition()); // call the onClick in the OnItemClickListener
}
}
The onClick implementation in the Activity class, the important line here is mAdapter.setClickListener(this); and the onClick method. The onClick method gets triggered from the ViewHolder’s onClick method in your RecyclerView class, which passes the view and position of the clicked item.
public class CityActivity extends Activity implements ItemClickListener {
private RecyclerView mRecyclerView;
private CityAdapter mAdapter;
private List<City> cities;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_city);
cities = CityManager.getInstance(this.getApplicationContext()).getCites();
mRecyclerView = (RecyclerView)findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mAdapter = new CityAdapter(cities, R.layout.row_city, this);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setClickListener(this); // Bind the listener
}
#Override
public void onClick(View view, int position) {
// The onClick implementation of the RecyclerView item click
final City city = cities.get(position);
Intent i = new Intent(this, CityviewActivity.class);
i.putExtra("city", city.name);
i.putExtra("desc", city.description);
i.putExtra("image", city.imageName);
Log.i("hello", city.name);
startActivity(i);
}
}

Working with Long Click Listener with recycler-android

i am working on a notapad like android app project. i which i have implemented recycler.
My project contains NotedAdaper class that extends RecyclerView.Adapter<NotesAdapter.ViewHolder>
in that class using the below code i used click listener,
public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.ViewHolder> {
private List<Notes> mNotes;
private Context mContext;
public NotesAdapter(Context context, List<Notes> notes) {
mNotes = notes;
mContext = context;
}
#Override
public NotesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View notesView = inflater.inflate(R.layout.items_notes, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(notesView);
return viewHolder;
}
// Easy access to the context object in the recyclerview
private Context getContext() {
return mContext;
}
#Override
public void onBindViewHolder(NotesAdapter.ViewHolder viewHolder, final int position) {
// Get the data model based on position
Notes notes = mNotes.get(position);
// Set item views based on your views and data model
TextView textView = viewHolder.preTitle;
textView.setText(notes.getTitle());
TextView textView1 = viewHolder.preText;
textView1.setText(notes.getText());
String color=notes.getColor();
CardView preCard=viewHolder.preCard;
preCard.setBackgroundColor(Color.parseColor(color));
ImageView img = viewHolder.preImage;
img.setVisibility(View.GONE);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Notes notes = mNotes.get(position);
Intent intent = new Intent(view.getContext(),EditNote.class);
Bundle bundle = new Bundle();
bundle.putSerializable("DATA",notes);
intent.putExtras(bundle);
getContext().startActivity(intent);
Toast.makeText(getContext(), "Recycle Click" + position+" ", Toast.LENGTH_SHORT).show();
}
});
}
// Returns the total count of items in the list
#Override
public int getItemCount() {
return mNotes.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
// Your holder should contain a member variable
// for any view that will be set as you render a row
public RobotoTextView preTitle, preText;
public ImageView preImage;
public CardView preCard;
public ViewHolder(View itemView) {
super(itemView);
preTitle = (RobotoTextView) itemView.findViewById(R.id.preTitle);
preText = (RobotoTextView) itemView.findViewById(R.id.preText);
preImage=(ImageView) itemView.findViewById(R.id.preImage);
preCard=(CardView) itemView.findViewById(R.id.preCard);
}
}}
And its absolutely working find. on clicking of a item in recycler, it retrieves the data using position of that item. and showing in another activity.
just like, suppose a activity shows the list of notes created by user. and clicking on any note, it shows the full content of that note.
but now i want to implement Long click listener on the item. and get the position.
so that, i used the following code ...
viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
Notes notes = mNotes.get(position);
Toast.makeText(getContext(), "long Click" + position+" ", Toast.LENGTH_SHORT).show();
return false;
}
});
so, its also working.
but what i want is, on long click, it should only show that Toast.
but its not only showing the long click toast. but also recognising click listener and after showing the toast>> "Long click: ..." it executing the the code written for single click event.
n i dont want it.
both listeners should work separately.
but why its executing single click after long click??? any idea???
Am i making mistake anywhere?
So, the following changes in my code, help me to achieve my output.
1) The method onBindViewHolder is called every time when you bind your view with data. So there is not the best place to set click listener. You don't have to set OnClickListener many times for the one View. Thats why, i wrote click listeners in ViewHolder, (actually that was not my question, but i read somewhere that it would be the best practice, thats why i am following it)
like this,
public static class ViewHolder extends RecyclerView.ViewHolder {
// Your holder should contain a member variable
// for any view that will be set as you render a row
public ImageView preImage;
public CardView preCard;
// We also create a constructor that accepts the entire item row
// and does the view lookups to find each subview
public ViewHolder(final View itemView) {
// Stores the itemView in a public final member variable that can be used
// to access the context from any ViewHolder instance.
super(itemView);
itemView.findViewById(R.id.preTitle);
preImage=(ImageView) itemView.findViewById(R.id.preImage);
preCard=(CardView) itemView.findViewById(R.id.preCard);
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
int p=getLayoutPosition();
System.out.println("LongClick: "+p);
return true;// returning true instead of false, works for me
}
});
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int p=getLayoutPosition();
Notes notes = mNotes.get(p);
Toast.makeText(getContext(), "Recycle Click" + p +" ", Toast.LENGTH_SHORT).show();
}
});
}
}
You may notice that, in onLongClick, i have returned "true", bydefault it was "false".
and this change works for me.
just make onLongClick(View v) returns return true instead of return false
this solved my problem it should solve yours too
i think you should set both the listeners from ViewHolder class.
itemView.setOnClickListener(...);
itemView.setOnLongClickListener(...);
And call getAdapterPosition() from ViewHolder to get the adapter position of the item.
You can checkout the following resource.
https://www.bignerdranch.com/blog/recyclerview-part-1-fundamentals-for-listview-experts/
I think this is an easier way to implement onClick and longClickListeners to RecyclerViews. Here's my code snippet. I've cut out unnecessary codes from here.
public class PrescriptionAdapter extends RecyclerView.Adapter<PrescriptionAdapter.ViewHolder> {
static final String TAG = "RecyclerViewAdapterMedicineFrequency";
ArrayList<Prescription> pdata;
Context context;
OnItemClickListener onItemClickListener;
OnItemLongClickListener onItemLongClickListener;
public PrescriptionAdapter(Context context, ArrayList<Prescription> presData, OnItemClickListener onItemClickListener, OnItemLongClickListener onItemLongClickListener) {
this.pdata = presData;
this.context = context;
this.onItemClickListener = onItemClickListener;
this.onItemLongClickListener = onItemLongClickListener;
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView pName, totalMeds;
ImageView pImage;
OnItemClickListener onItemClickListener;
OnItemLongClickListener onItemLongClickListener;
public ViewHolder(View itemView, OnItemClickListener onItemClickListener, OnItemLongClickListener onItemLongClickListener) {
super(itemView);
pName = (TextView) itemView.findViewById(R.id.prescriptionName);
totalMeds = (TextView) itemView.findViewById(R.id.totalMeds);
pImage = (ImageView) itemView.findViewById(R.id.prescriptionImage);
this.onItemClickListener = onItemClickListener;
this.onItemLongClickListener = onItemLongClickListener;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
#Override
public void onClick(View v) {
onItemClickListener.onItemClick(getAdapterPosition());
}
#Override
public boolean onLongClick(View v) {
onItemLongClickListener.onItemLongClick(getAdapterPosition());
return true;
}
}
public interface OnItemClickListener {
void onItemClick(int i);
}
public interface OnItemLongClickListener {
void onItemLongClick(int i);
}
}

Categories

Resources