Recyclerview in Android . RecyclerView
Useful Blogs :
Layoutinflator & dynamic UI creation -
https://stackoverflow.com/questions/3477422/what-does-layoutinflater-in-android-do#:~:text=LayoutInflater%20is%20a%20class%20used,another%20is%20dynamic%20or%20programmatically.
Useful Videos :
https://www.youtube.com/watch?v=9rcrYFO1ogc
(Recyclerview with Cardview) -
https://www.youtube.com/watch?v=Urpt8m6Uijw&list=PLirRGafa75rSMDp5bORq_eHjMLKqJ2EYO&index=2
--------------------------------------------------------------------------------------------
RecyclerView takes less mememory space to display large amount of data.
Recycler view calculates the size of the ROW size & determines how many rows can be fit inside the screen. Depending on the screen size , recycler view creates only that much of the rows and Nothing more, later it goes on recycling them as needed.
It is somewhat similar to the idea of DATA LOADER in pytorch.
We can create a Custom Layout Manager by extending RecyclerView.LayoutManager Class but RecyclerView Provides three types of in-built Layout Managers.
Linear Layout Manager ,GridLayoutManager , StaggeredGridLayoutManager.
If none of these layout managers suits your needs, you can create your own by extending the RecyclerView.LayoutManager abstract class
--------------------------------------------------------------------
RecyclerView class needs to have a Layout Manager and an Adapter to be instantiated , along with a seperate XML file of the Row you want to show.
The Adapter class is the most important , since it is reponsible for mapping the rows into the Recyclerview.
To create a Adapter you create a new class that extends the RecyclerView.Adapter class .
The adapter class itself also contains a nested class called Viewholder class that extends to the RecyclerView.ViewHolder class.
The ViewHolder class contains the references of all the components of your view.
[The professional apprach is to keep the viewHolder class seperate]
Adapter class that extends to Recyclerview.Adapter , needs to implement 3 imp methods :
1] onCreateViewHolder() :
First methods that get called everytime we need to create a particular row,
Inflates the Individual row & returns the object of viewHolder class.
2] onBindViewHolder() :
It takes the View or row & fills it with data.
The onCreateViewHolder() method returns a viewholder and passes it to this method.
That viewholder object contains all the views inside one Row or the xml you inflated.
You can get the reference and set the data to the views.
3] getItemCount() :
This method must always return the number of Items /rows you want to show.
--------------------------------------------------------------------------------------------
[ LinearLayoutManager( ) takes 3 parameters - first is context , 2nd is the Direction of the recyclerview ,Default direction is Vertical. ]
Using the GridlayoutManager is simple :
// 2nd parameter takes the number of columns per row.
GridLayoutManager gridLayoutManager = new GridLayoutManager(this,2);
recyclerView.setLayoutManager(gridLayoutManager);
-----------------------------------------------------------------------------------------------
RecyclerView with LinearLayoutManager.
(BASIC APPROACH)
JAVA :
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/myrecyclerview"
tools:context=".MainActivity">
</androidx.recyclerview.widget.RecyclerView>
mysinglerow.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:id="@+id/imageview1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="21dp"
android:layout_marginEnd="59dp"
android:layout_marginRight="59dp"
android:layout_marginBottom="21dp"
android:src="@drawable/atom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/textView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="69dp"
android:layout_marginEnd="72dp"
android:layout_marginRight="72dp"
android:text="Username"
android:textSize="25sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageview1"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.myrecyclerview);
//set layoutmanager as per need.
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//Gives divider lines
DividerItemDecoration dividecor = new DividerItemDecoration(recyclerView.getContext(),DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(dividecor);
//set adapter
recyclerView.setAdapter(new myadapter());
}
}
myadapter.java
[Pass your Viewholder class to the Adapter class's < > brackets.]
package com.example.myapplication;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.w3c.dom.Text;
// You must first always name your viewholder class inside <> before implementing any methods
public class myadapter extends RecyclerView.Adapter<myadapter.MyViewHolder> {
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
// 3rd parameter is always false.
View view = layoutInflater.inflate(R.layout.mysinglerow,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// holder contains all the components of your view.
// you can set Data to them here.
holder.textView.setText("Roll number : ");
holder.textView.append(String.valueOf(position));
}
@Override
public int getItemCount() {
return 20;
}
//viewholder class
static class MyViewHolder extends RecyclerView.ViewHolder {
//The viewholder holds or contains all the components of the view.
// initiate all the components of your view or row.
ImageView imageView;
TextView textView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
imageView= itemView.findViewById(R.id.imageview1);
textView=itemView.findViewById(R.id.textView);
}
}
}
KOTLIN :
MainActivity.kt
package com.deepesh.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
lateinit var myrecyclerview:RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
myrecyclerview = findViewById(R.id.recyclerview1)
myrecyclerview.layoutManager= LinearLayoutManager(this)
myrecyclerview.adapter= myadapter()
}
}
myadapter.kt
package com.deepesh.myapplication
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class myadapter : RecyclerView.Adapter<myadapter.myviewholder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): myviewholder {
val inflater:LayoutInflater = LayoutInflater.from(parent.context)
val view: View = inflater.inflate(R.layout.single_row,parent,false)
return myviewholder(view)
}
override fun onBindViewHolder(holder: myviewholder, position: Int) {
holder.textview.setText("Deepeshdm")
}
override fun getItemCount(): Int {
return 20
}
class myviewholder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textview : TextView= itemView.findViewById(R.id.textview_sr)
val imageview: ImageView= itemView.findViewById(R.id.imageview_sr)
}
}
single_row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#4857D8">
<ImageView
android:id="@+id/imageview_sr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="16dp"
android:src="@drawable/ic_launcher_foreground"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview_sr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="33dp"
android:layout_marginEnd="91dp"
android:text="Username"
android:textColor="#fff"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerview1"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
-----------------------------------------------------------------------------------------------
RecyclerView with LinearLayoutManager.
(PROFESSIONAL APPROACH using a Modal class)
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/myrecycleview"
tools:context=".MainActivity">
</androidx.recyclerview.widget.RecyclerView>
MainActivity.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.myrecycleview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
myadapter adapter = new myadapter(dataQueue());
recyclerView.setAdapter(adapter);
}
public ArrayList<MyModal> dataQueue() {
ArrayList<MyModal> list = new ArrayList<>();
MyModal obj1 = new MyModal();
obj1.setMyimageview(R.drawable.atom);
obj1.setMytextview("This is object one");
list.add(obj1);
MyModal obj2 = new MyModal();
obj1.setMyimageview(R.drawable.atom);
obj1.setMytextview("This is object one");
list.add(obj2);
MyModal obj3 = new MyModal();
obj1.setMyimageview(R.drawable.atom);
obj1.setMytextview("This is object one");
list.add(obj3);
MyModal obj4 = new MyModal();
obj1.setMyimageview(R.drawable.atom);
obj1.setMytextview("This is object one");
list.add(obj4);
return list;
}
}
mysinglecard_row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:elevation="5dp"
android:id="@+id/mycardview"
android:layout_height="200dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/myconstraintlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/myimageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="63dp"
android:layout_marginRight="63dp"
android:layout_marginBottom="16dp"
android:src="@drawable/atom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/mytextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/mytextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="66dp"
android:layout_marginEnd="91dp"
android:layout_marginRight="91dp"
android:text="Username"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/myimageView"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
MyViewHolder.java
package com.example.myapplication;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class MyViewHolder extends RecyclerView.ViewHolder {
//This class holds the reference of all the
// views/componants in the mysinglecard_row
ImageView imageView;
TextView textView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
imageView=itemView.findViewById(R.id.myimageView);
textView = itemView.findViewById(R.id.mytextView);
}
}
MyModal.java
package com.example.myapplication;
public class MyModal {
// This class should contain same number of
// memebers as the no, of componants in your view
private String mytextview;
//this will hold image id.
private int myimageview;
public String getMytextview() {
return mytextview;
}
public void setMytextview(String mytextview) {
this.mytextview = mytextview;
}
public int getMyimageview() {
return myimageview;
}
public void setMyimageview(int myimageview) {
this.myimageview = myimageview;
}
}
myadapter.java
package com.example.myapplication;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class myadapter extends RecyclerView.Adapter<MyViewHolder> {
ArrayList<MyModal> data;
public myadapter(ArrayList<MyModal> data) {
this.data = data;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.mysinglecard_row,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.textView.setText(data.get(position).getMytextview());
holder.imageView.setImageResource(data.get(position).getMyimageview());
}
@Override
public int getItemCount() {
return data.size();
}
}
-------------------------------------------------------------------------------------------
Useful video : https://youtu.be/69C1ljfDvl0
SET CLICK LISTENER ON RECYCLERVIEW
(Never use the .setOnClickListener inside the OnBindViewHolder , since it s bad for performance , always create a interface and write the implementation in some other class)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.deepesh.myapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.Toast;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
String[] mylist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mylist = new String[]{"A", "B", "C", "D", "E", "F", "G", "A", "B"};
MyAdapter myadapter= new MyAdapter(Arrays.asList(mylist),listener);
recyclerView.setAdapter(myadapter);
}
// PASS THIS INTERFACE TO THE ADAPTER
// WRITE THE CODE FOR WHAT SHOULD HAPPEN WHEN USER CLICKS THAT COMPONENT INSIDE THE ONCLICK
MyAdapter.OnRowClickListener listener = position -> {
Toast.makeText(this,mylist[position] , Toast.LENGTH_SHORT).show();
};
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black">
<TextView
android:id="@+id/textview_singlerow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:text="Hello World !"
android:textSize="30sp"
android:textColor="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.deepesh.myapp;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
List<String> stringList;
OnRowClickListener onRowClickListener;
public MyAdapter(List<String> stringList,OnRowClickListener listener) {
this.stringList = stringList;
// STEP 2] Maintain a global variable holding the interface.
// We'll implement this interface inside the MainActivity & pass it as parameter to adapter.
this.onRowClickListener=listener;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row,parent,false);
return new MyViewHolder(view,onRowClickListener);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.textview_singlerow.setText(stringList.get(position));
// DO NOT USE .setOnClickListener here.
// BAD FOR PERFORMANCE.
}
@Override
public int getItemCount() {
return stringList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder{
OnRowClickListener rowClickListener;
TextView textview_singlerow;
//STEP 3] Change the Viewholder class parameters &
// pass the Interface that you''ll get from the Adapter constructor.
public MyViewHolder(@NonNull View itemView,OnRowClickListener listener) {
super(itemView);
textview_singlerow=itemView.findViewById(R.id.textview_singlerow);
this.rowClickListener=listener;
// STEP 4] Set the System's OnClickListener to the component
// & call the Interface's methods.
itemView.setOnClickListener(v -> rowClickListener.OnRowClick(getAdapterPosition()));
}
}
// STEP 1] Define an interface
public interface OnRowClickListener{
void OnRowClick(int position);
}
}
-----------------------------------------------------------------------------------------------
ADD LEFT/RIGHT SWIPE FUNCTIONALITY
// Adds Swipable Functionality to Recyclerview
ItemTouchHelper touchHelper = new ItemTouchHelper
(new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
// Gives Position on where swipe is taking place & deletes it.
int viewPosition = viewHolder.getAdapterPosition();
noteViewModel.delete(noteAdapter.getNoteAt(viewPosition));
Toast.makeText(MainActivity.this, "NOTE DELETED", Toast.LENGTH_SHORT).show();
}
});
touchHelper.attachToRecyclerView(notes_recyclerView);;
-------------------------------------------------------

Comments
Post a Comment