Reputation: 422
I have the following app I'm working on, where I am trying to make it so whenever an image in the RecyclerView is clicked, its two corresponding buttons from the row xml will become visible (they are invisible by default).
Here's my code...
MainAcitivity.Java
package com.mdadi.animals2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.ArrayList;
import static android.view.View.VISIBLE;
public class MainActivity extends AppCompatActivity implements MyAdapter.OnImageListener {
private RecyclerView list; //RecyclerView instance
private RecyclerView.Adapter mAdapter; //Adapter
private RecyclerView.LayoutManager mLayoutManager;
private ArrayList<ListData> data = new ArrayList<>();
ListData lastPosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initialize data
data = ListData.initData();
final EditText editText = findViewById(R.id.editTxt);
list = findViewById(R.id.recyclerView); //Lookup RecyclerView in activity layout
list.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
list.setLayoutManager(mLayoutManager); //Set layout manager to position items/rows
//Attach adapter to RecyclerView to pop items
mAdapter = new MyAdapter(data, this);
list.setAdapter(mAdapter);
/* findViewById(R.id.delBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String newFact = editText.getText().toString();
mAdapter.notifyItemInserted(listData.size() - 1);
}
});*/
}
@Override
public void onImageClick(int position) {
int lastPos = position;
Button delBtn = findViewById(R.id.delBtn);
Button nextBtn = findViewById(R.id.nextBtn);
data.remove(R.id.delBtn);
delBtn.setVisibility(VISIBLE);
mAdapter.notifyItemChanged(R.id.delBtn);
nextBtn.setVisibility(VISIBLE);
mAdapter.notifyItemChanged(R.id.nextBtn);
Log.d("MyActivity", position + " clicked");
}
}
MyAdapter.Java
package com.mdadi.animals2;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
//ViewHolder defined above
private ArrayList<ListData> data; //ArrayList member var for ListData
private OnImageListener mOnImageListener;
//Pass in data array for constructor
public MyAdapter(ArrayList<ListData> data, OnImageListener onImageListener) {
this.data = data;
this.mOnImageListener = onImageListener;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//Inflate custom layout
View rootView = LayoutInflater.from(parent.getContext()).inflate
(R.layout.recycler_view_item, parent, false);
//Return new holder instance
return new MyViewHolder(rootView, mOnImageListener);
}
//Pop data into item through holder
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
//Get data model based on position
ListData listData = data.get(position);
//String message = data.get(position).getDesc();
//holder.textView.setText(message);
//Set item views based on created views and data
holder.textView.setText(listData.getDesc());
holder.img.setImageResource(listData.getImgURL());
}
//Return total item count of list
@Override
public int getItemCount() {
if (data != null)
return data.size();
else
return 0;
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView textView;
private ImageView img;
private Button next;
private Button delete;
OnImageListener onImageListener;
public MyViewHolder(View v, OnImageListener onImageListener) {
super(v);
textView = v.findViewById(R.id.fact);
img = v.findViewById(R.id.image);
next = v.findViewById(R.id.nextBtn);
delete = v.findViewById(R.id.delBtn);
this.onImageListener = onImageListener;
v.setOnClickListener(this);
}
public void onClick(View view) {
onImageListener.onImageClick(getAdapterPosition());
}
}
public interface OnImageListener {
void onImageClick(int position);
}
}
ListData.Java
package com.mdadi.animals2;
import java.util.ArrayList;
public class ListData {
private String desc;
private int imgURL;
public ListData(String desc, int imgURL) {
this.desc = desc;
this.imgURL = imgURL;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
public int getImgURL() {
return imgURL;
}
public static ArrayList<ListData> initData() {
ArrayList<ListData> list = new ArrayList<>();
list.add(new ListData("bird\n",R.drawable.bird)); //1
list.add(new ListData("cat\n",R.drawable.cat)); //2
list.add(new ListData("dog\n",R.drawable.dog)); //3
list.add(new ListData("fish\n",R.drawable.fish)); //4
list.add(new ListData("kangaroo\n",R.drawable.kangaroo)); //5
list.add(new ListData("monkey\n",R.drawable.monkey)); //6
list.add(new ListData("turtle\n",R.drawable.turtle)); //7
list.add(new ListData("horse\n",R.drawable.horse)); //8
list.add(new ListData("elephant\n",R.drawable.elephant)); //9
list.add(new ListData("turkey\n",R.drawable.turkey)); //10
return list;
}
}
The problem here is that while it returns the correct position of the clicked image in logd, buttons will often be displayed for the wrong row.
Upvotes: 1
Views: 1068
Reputation: 62841
You didn't post the XML for each RecyclerView
item but I assume that each row would have its own buttons, delBtn
and nextBtn
, and it is these that you want to set the visibility for.
The problem is how you look up these buttons. When you do the following in the click handler:
Button delBtn = findViewById(R.id.delBtn);
Button nextBtn = findViewById(R.id.nextBtn);
You are searching for those ids from the top of the view hierarchy and outside the bounds of the item that was clicked. You actually want to do the search inside the item that is clicked.
Button delBtn = itemView.findViewById(R.id.delBtn);
Button nextBtn = itemView.findViewById(R.id.nextBtn);
Here itemView
is the view layout for the row which you could pass into onImageClick()
from onClick()
. (Actually, take a look at your ViewHolder
constructor for how to do this.)
There are a couple of other things that look unusual in your code such as
mAdapter.notifyItemChanged(R.id.delBtn);
The argument should be a position in the data
array.
Upvotes: 2