26
loading...
This website collects cookies to deliver better user experience
This series is going to be dedicated to the basic of Android development. Join me and let us try to build and understand some cool stuff. All the resources I used to create this post can be found on ticketnote or HERE.
I also want to mention one final thing that I except from you the reader. Before reading this you should have a solid understanding of Android Fragments and the RecyclerView. I mention this because I will not be going over fragment transactions or how to implement a RecyclerView. Check out HERE for my fragments tutorial and HERE for my RecyclerView tutorial. If you do not understand these fundamentals then you may find it hard to follow along in this tutorial.
public class ExampleFragment extends Fragment implements CustomAdapter.OnNoteListener{
private List<String> data;
public ExampleFragment(){
super(R.layout.example_fragment);
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//This is where we initialize the data. Normally this would be from a remote server
dataCall();
}
@Override
public void onViewCreated(View view,Bundle savedInstanceState){
// this is where we are going to set the RecyclerView
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.example_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(new CustomAdapter(this.data,this));
}
public void dataCall(){
ArrayList<String> data = new ArrayList<>();
for(int i = 0; i< 49; i ++){
data.add("NAME # " +i);
}
this.data = data;
}
@Override
public void onNoteClick(int position) {
Toast toast = Toast.makeText(getActivity(),"CLICKED",Toast.LENGTH_SHORT);
toast.show();
}
}
Fragment Manager
(fragment manager is responsible for organizing and calling methods in fragments) it enters the CREATED
state of its lifecycle. This transition into the state triggers the onCreate() method. The method receives a Bundle
which contains any previously saved state but initially the value is null. This method is also called before onCreateView()(which we do not have, more on that later) and called before onViewCreated()public ExampleFragment(){
super(R.layout.example_fragment);
}
super(R.layout.example_fragment)
we are invoking an alternative constructor within the Fragment class which will take the View that we provided it and automatically call onCreateView() for us.@Override
public void onViewCreated(View view,Bundle savedInstanceState){
// this is where we are going to set the RecyclerView
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.example_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(new CustomAdapter(this.data,this));
}
This method gets called immediately after onCreateView() has returned and receives the inflated view from it. We can use that inflated view to set up our RecyclerView.
Now we can move on to creating the method that will get passed to our adapter and eventually the ViewHolder object.
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private List<String> data;
private OnNoteListener onNoteListener;
public CustomAdapter(List<String> data,OnNoteListener onNoteListener){
this.data = data;
this.onNoteListener = onNoteListener;
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private final TextView textView;
OnNoteListener onNoteListener;
public ViewHolder(View view,OnNoteListener onNoteListener){
super(view);
this.textView = (TextView) view.findViewById(R.id.text_view_id);
view.setOnClickListener(this);
this.onNoteListener = onNoteListener;
}
@Override
public void onClick(View v) {
this.onNoteListener.onNoteClick(getAdapterPosition());
}
}
@Override
public CustomAdapter.ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
//inflate the indiv item
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.indiv_viewholder_item,parent,false);
return new ViewHolder(view, this.onNoteListener);
}
@Override
public void onBindViewHolder( CustomAdapter.ViewHolder holder, int position) {
holder.textView.setText(this.data.get(position));
}
@Override
public int getItemCount() {
return this.data.size();
}
public interface OnNoteListener{
void onNoteClick(int position);
}
}
OnNoteListener
:
public interface OnNoteListener{
void onNoteClick(int position);
}
public class ExampleFragment extends Fragment implements CustomAdapter.OnNoteListener
implements
an interface, we have to use CustomAdapter.onNoteListener
because our interface is nested inside of our CustomAdapter class. Once we have implements
our interface we must implement all of the interfaces methods, for us it is onNoteClick.
public void onNoteClick(int position) {
Toast toast = Toast.makeText(getActivity(),"CLICKED",Toast.LENGTH_SHORT);
toast.show();
}
This method is the method that we have been talking about. It is the method that we are going to pass around until it gets passed to the ViewHolder object. This method that is getting called when we click on the individual ViewHolder objects. We pass it an int to show that each method can call it with its own values. However, we are only using it to create and show a toast when clicked. Toast.makeText()
is used to create a Toast, it takes 3 parameters: the context, the text to be shown and the duration that the toast will be viewed. toast.show()
must be called in order for the toast to be shown.
Now remember that our goal is to simply pass a method to our ViewHoder object so that it gets called on every click. In order to do that we must to pass access to our method to the CustomAdapter object and then to the onCreateViewHolder() method and then finally to the ViewHolder object its self.
recyclerView.setAdapter(new CustomAdapter(this.data,this));
this
? Well, any time that 'this' is used inside of an instance method or constructor it references the current object. So when use this
we are referencing public class ExampleFragment extends Fragment implements CustomAdapter.OnNoteListener
.OnNoteListener
and setting a global instance variable inside or our CustomAdapter class, see below:
private OnNoteListener onNoteListener;
public CustomAdapter(List<String> data,OnNoteListener onNoteListener){
this.data = data;
this.onNoteListener = onNoteListener;
}
public CustomAdapter.ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
//inflate the indiv item
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.indiv_viewholder_item,parent,false);
return new ViewHolder(view, this.onNoteListener);
}
this.onNoteListener
to the new ViewHolder() object. The ViewHolder instance will now get an inflated view as well as access to our onNoteClick method. Our viewHolder object now has access to the method that we defined earlier:
public void onNoteClick(int position) {
Toast toast = Toast.makeText(getActivity(),"CLICKED",Toast.LENGTH_SHORT);
toast.show();
}
implements
View.OnClickListener:
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private final TextView textView;
OnNoteListener onNoteListener;
public ViewHolder(View view,OnNoteListener onNoteListener){
super(view);
this.textView = (TextView) view.findViewById(R.id.text_view_id);
view.setOnClickListener(this);
this.onNoteListener = onNoteListener;
}
@Override
public void onClick(View v) {
this.onNoteListener.onNoteClick(getAdapterPosition());
}
}
Notice the constructor and how we have an instance of onNoteListener and we are assigning it to a global reference variable inside of the ViewHolder class: this.onNoteListener = onNoteListener;
. This will allow us to reference it later.
The most important part of this is the view.setOnClickListener(this)
, without this method your ViewHolder objects will not be clickable. this
is referring to the actual ViewHolder object. It is basically us saying that when the individual view is clicked we want the onClick
method to be called.
public void onClick(View v) {
this.onNoteListener.onNoteClick(getAdapterPosition());
}
The code above is the last part of the puzzle. onClick() will get called whenever a ViewHolder object is called and with it we are calling our own method that we defined this.onNoteListener.onNoteClick(getAdapterPosition())
with the current position in the adapter.
That concludes how to make your RecyclerView clickable.