I have a progress bar in viewHolder class inside adapter class. I need to update that bar from another activity UpdateActivity when the method onPause that activity is implemented. I have tried using the interface but it does not update the progress bar, the bar remains as before with no error as well. Is there any way I can update the bar from given activity? Any help would be appreciated.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
public static class MyViewHolder extends RecyclerView.ViewHolder
implements MyCallBack {
ProgressBar progressBar;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
progressBar = itemView.findViewById(R.id.progress_bar);
}
#Override
public void updateMyText(int integer) {
progressBar.setProgress(integer);
}
}
}
interface MyCallBack {
public void updateMyText(int integer);
}
}
public class UpdateActivity extends AppCompatActivity {
MyCallBack myCallBack;
int final_value;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//
#Override
protected void onPause() {
super.onPause();
/* myCallBack = new MyCallBack() {
#Override
public void updateMyText(int integer) {
progressBar.setProgress(100);
}
}; */
final_value = position.getValue(); // final_value != null
progressBar.setProgress(final_value);
}
}
Where is your recyclerview for which you implemented the adapter?
I do not have a clear understanding of the task, what do you want to do here in the activity, it looks like it is a progress bar for loading a splash screen or something similar, then why do you need a recycler for this?
If the logic is that each item in the recyclerview (or another view) contains a progress bar, then in order to manage each specific progress bar you need:
Public method for set progress value in the MyViewHolder.
Reference to the concrete which view contains progressbar (for example, you can use some listener for this inside adapter constructor).
For interaction between activities you can use method startActivityForResult.
Related
The application has a BottomNavigationView for navigating between fragments. One of the Fragments related to the BottomNavigationView has a Fragment as a child containing a RecyclerView and each RecyclerView Item has a Button attached to it.
I would need to navigate the BottomNavigationView to another Fragment with an OnClick of the Button (Highlighted with the red) inside the RecyclerView Item. I have tried different ways but I have not gotten it to work so far.
The Click is handled inside the Adapter of the RecyclerView. (The code inside the OnClickListener is just to clarify what I am trying to do.)
#Override
public void onBindViewHolder(#NonNull LocationsViewHolder holder, int position) {
...
holder.showMarkerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BottomNavigationView navigation = (BottomNavigationView)v.findViewById(R.id.nav_view);
navigation.setSelectedItemId(R.id.navigation_map);
}
});
}
The easiest way is created an interface implemented by your Activity
First create an interface that i called OnItemClick :
public interface OnItemClick{
void onItemClick();
}
Following on your activity implement this interface like below :
public class MainActivity extends AppCompatActivity implements OnItemClick{
/*
rest of your code
*/
#Override
public void onItemClick() {
navigation.setSelectedItemId(R.id.navigation_map);
}
}
On your Fragment you need to pass the Activity into your Adapter
YourAdapter adapter = new YourAdapter(requireActivity());
And on your adapter you need to initialize the interface like below :
OnItemClick listener;
public YourAdapter(Activity activity) {
listener= ((MainActivity) activity);
}
And finaly to call the method on your activity just call it like below
#Override
public void onBindViewHolder(#NonNull LocationsViewHolder holder, int position) {
...
holder.showMarkerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick();
}
});
}
I have a layout where I use two RecyclerViews, each with its own Adapter.
On the Activity class of the layout I have the references of the RVs and I create them there. Then I dynamically create the buttons and insert them on one of the RecyclerViews.
The current problem I'm facing is that I'm setting the onClick listener inside the adapter itself but I want to hopefully set it through the activity class.
That's because the activity class has references to all the things I need to know when an object inside the recycler view is clicked and I want them to move between the RVs when clicked. From first RV to go to second and vice versa.
To create the view inside the first adapter I use.
for (Iterator<String> it = setList.iterator();it.hasNext();)
{
String str = it.next();
Object1 o = new Object1 (str, R.drawable.testicon);
objectList.add(o);
}
firstRVAdapter.notifyDataSetChanged();
Inside my adapter I set the onclick listener inside the OnBindViewHolder as such:
#Override
public void onBindViewHolder(LeftViewHolder holder,final int position) {
holder.imageView.setImageResource(verticalLeftList.get(position).getLogo());
holder.textView.setText(verticalLeftList.get(position).getName());
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String productName =
verticalLeftList.get(position).getName().toString();
Toast.makeText(context, productName + " is selected",
Toast.LENGTH_SHORT).show();
}
});
}
Any recommendations or help how to change this to allow me to do what I want would be really appreciated. Either searching for a way to access the second adapter through the first one or a way to set the listener for each item inside RV from the activity class.
You can create a callback for your adapter to pass data back to your activity.
public interface AdapterCallback {
void itemClicked(int position);
}
see Juan's answer for example
Pass the Activity to the adapter in the constructor as a callback listener, and then, in the onClick() method call a callback on the activity.
(...) means there is more code not relevant to the answer.
In the RV Adapter class:
public MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
Listener listener;
public MyAdapter(Listener listener, ...){
this.listener = listener;
...
}
#Override
public void onBindViewHolder(LeftViewHolder holder,final int position) {
holder.imageView.setImageResource(verticalLeftList.get(position).getLogo());
holder.textView.setText(verticalLeftList.get(position).getName());
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String productName =
verticalLeftList.get(position).getName().toString();
Toast.makeText(context, productName + " is selected",
Toast.LENGTH_SHORT).show();
listener.onClick(productName);
}
});
}
...
public static interface Listener{
public void onRVClick(String aParamToIdWhatWasClicked);
}
}
And make the Activity implement the Listener interface and pass its instance to the RV Adapter constructor.
public class MyActivity extends AppCompatActivity implements MyAdapter.Listener {
private MyAdapter myRvAdapter;
#Override
public void onCreate(Bundle savedInstanceState){
...
myRvAdapter = new MyAapter(this, ...);
...
}
...
#Override
public void onRVClick(String what){
System.out.println(what + " was selected");
}
...
}
Note that the parameter of the onRVClick() interface method can be whatever you want. It could even be the data list item backing the selected recycler view item.
May i know why is it showing me the error of "Cannot resolve symbol ItemClickListener"? Do i need to add library or something in order to solve this issue or i shouldn't declare it in here?
public static class FoodViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ItemClickListener itemClickListener;
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
View view;
public FoodViewHolder (View v){
super(v);
view= v;
}
public void setName(String title){
TextView post_title = (TextView)view.findViewById(R.id.Menu_Name);
post_title.setText(title);
}
public void setImage(Context ctx, String image){
ImageView menuImage = (ImageView) view.findViewById(R.id.Menu_Image);
Picasso.with(ctx).load(image).into(menuImage);
}
#Override
public void onClick(View v) {
}
}
In General for RecyclerView we create an Interface for handling the click events. Unlike a normal Button Click, the RecyclerView Click events cannot be handled directly. As the RecyclerView is the Adapter(Data Provider to the View), You cannot directly handle the item clicks from here and update the view. For this you need an Separate Interface which is ItemClickListener in your case (Create an Interface file separately in your project). In that Interface you need to declare a method for example something like this
public Interface ItemClickListener{
void onRecyclerViewItemClicked(int position);
}
Create a OnClickListener for your View(which is present over single row. Eg: image, text, etc);#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.myText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
itemClickListener.onRecyclerViewItemClicked(position);
//itemClickListener is the Interface Reference Variable
}
});
}
And in your Activity you need to implement this Interface like
public class YourActivity extends AppCompatActivity implements ItemClickListener {
....
....
protected void onCreate(Bundle savedInstanceState) {
...
...
}
#Override
public void onRecyclerViewItemClicked(int position) {
//You will get the position of the Item Clicked over recycler view
//You can handle as per your requirement
}
}
Upon doing this you will listen the click event of recyclerview to the activity. Then you can handle it accordingly.
If you have further doubt follow the references:
https://stackoverflow.com/a/40584425/8331006
https://stackoverflow.com/a/28304164/8331006
you can set the click listener to any view you want you don't need to declare it as a seperate
yourView.setOnClickListener(this);
and in your onClick(View v) add the code that you want whenever you click the view you want for example :
if(v==imageView){
//write your code here
}
I have an image adapter which is taking images from instagram and putting them in a grid layout. I want to be able to click on the image and enlarge it to full screen.
I looked at an online tutorial similar tto this and I made the following changes to my code...
I made an interface...
public interface ImageClickListener{
void onClick(int position);
}
I made sure my main activity implemented this interface by adding implement at the top like so...
public class MainActivity extends AppCompatActivity implements ImageClickListener
lastly I made changes to the holder class in my adapter like so...
public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView mPhoto1, mPhoto2;
public Holder(View itemView) {
super(itemView);
mPhoto1 = (ImageView)itemView.findViewById(R.id.image1);
//mPhoto2 = (ImageView)itemView.findViewById(R.id.image2);
}
#Override
public void onClick(View v) {
ImageClickListener.onClick(getLayoutPosition()); //*** problem here
}
}
the issue is quite clear and I dont know how to resolve it... What I thought was ill do something like...
imageclicklistener listener = new imageclick... so on and so forth in the holder but that didnt work so well. When I make the onclick method in the interface static then I obviously wont be able to use it in my main.
Your MainActivity is the one you want to act as the ImageClickListener. You can pass it in as an argument to the constructor when creating your customer adapter and then keep a reference to it.
public class MyAdapter extends RecyclerView.Adapter<Holder> {
private ImageClickListener imageClickListener;
public MyAdapter(ImageClickListener imageClickListener, other params...) {
this.imageClickListener = imageClickListener;
...
}
...
}
If your Holder is an inner class of your adapter you can then do:
public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView mPhoto1, mPhoto2;
public Holder(View itemView) {
super(itemView);
mPhoto1 = (ImageView)itemView.findViewById(R.id.image1);
}
#Override
public void onClick(View v) {
imageClickListener.onClick(getLayoutPosition());
}
}
In MainActivity where you create the adapter it will look like this:
private MyAdapter myAdapter; // class field
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// this refers to the MainActivity being passed in as the ImageClickListener
myAdapter = new MyAdapter(this, restOfArgs...);
...
}
Suppose I have a MyTextView class that extends TextView. The myTextView Objects should be clickable.
On one hand, it seems that the OnClickListener should be in the MyTextView class since I will be using a few of those, and I don't want to set an OnClickListener to each one. If the OnClickListener is in the MyTextView class, it will only be written once. Moreover, all myTextView objects perform the same thing when clicked.
On the other hand, these objects need to update the UI and some variables in the activity they're in. I don't have access to these variables and UI objects from within MyTextView class and it doesn't feel right to send reference to all of them via the costructor.
What would be the right thing to do OOP-wise ?
you can do so
class MyTextView extends TextView implements View.OnClickListener{
public MyTextView(Context context) {
super(context);
this.setOnClickListener(this);
}
public static interface MyTextListener{
public void updateUI();
}
#Override
public void onClick(View v) {
if(getContext() instanceof MyTextListener){
((MyTextListener)getContext()).updateUI();
}
}
}
continue to implement the interface in activity
public class MainActivity extends Activity implements MyXextView.MyTextListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void updateUI() {
//update here
}
}