Android RecyclerView- Images, Text and OnLongClick/OnLongPress


Android RecyclerView Images and Text OnLongClickListener example.

How to show images and text and handle Longclick events in recyclerview in android. We first render text and images in cardview. The cardview then is the item view for the recyclerview. User long clicks to show a Toast message.

What is a RecyclerView

A RecyclerView is an android widget that is used when you need to display a scrolling list of elements based on large data sets (or data that frequently changes).

People sometimes call it a more advanced and flexible version of ListView. RecyclerViews commonly get used alongside cardviews. CardViews basically allow us display cards. Cards themselves don't show data directly. Instead they display TextViews and ImageViews which are what display our text and images respectively.

What is LongClick?

In PC world we are used to two types of events when working with your Microsoft Windows or Apple Macintosh Operating systesm. These are either clicking or right-clicking. Clicking is simply tapping. You click to open or initiate an action. On the other hand we right-click to show a context menu that normally has several options. Then the user can select the action whether is is opening or deleting document or any other file or starting a program.

Mobile devices these days even in the developing world are smartphones. These include samsung, infinix, iPhone, F7, Tecno, Oppo, HTC etc. These have a touch screen and no physical keyboard or mouse. Hence you cannot right click. Instead you can long click. Long click involves tapping but holding it longer than clicks.

Long clicking also most of the time get used to show a context menu. These types of menus normally allow us perform an action related to a given widget. You can also long click to select an item.

How to Work with a RecyclerView

To work with a RecyclerView, normally you start by adding a RecyclerView element in your layout:

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/mRecycler" />

In fact even before this, you want to make sure you had added a support library dependency in your app level build.gradle:

    implementation 'com.android.support:design:23.2.1'

In your RecyclerView you will represent the views to be listed as view holder objects. These objects are instances of a class you define by extending RecyclerView.ViewHolder. Each view holder is in charge of displaying a single item with a view.

The view holder objects are managed by an adapter, which you create by extending RecyclerView.Adapter. The adapter creates view holders as needed. The adapter also binds the view holders to their data

The RecyclerView fills itself with views provided by a layout manager that you provide.

An Example

Let's write a simple RecyclerView example. This recyclerview will comprise cardviews.

  • Android RecyclerView with CardViews.
  • LongClick a cardview and show a simple toast with data item in that card.
  • CardViews shall consist of image and text.
  • We handle onLongPress or onLongClick events and get the OnClick position.
  • We are able to get recyclerview adapter position and show clicked item in a Toast message.

Let's start.

Section 1 : Build.Gradle

First we'll come to our app level build.gradle and:

  • Add dependencies for RecyclerView and CardViews
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:23.2.1'
    implementation 'com.android.support:design:23.2.1'
    implementation 'com.android.support:cardview-v7:23.2.1'
}

We've added implementation statements for AppCompat, Design and CardView support libraries. Design will give us recyclerview.

Section 1 : Movie Class

Then we come to our data object. This is our POJO class and represents a single Movie.

The Movie will have properties like name and image.

package com.tutorials.hp.recyclerlongclick;

public class Movie {

    private String name;
    private int image;

    public Movie(String name, int image) {
        this.name = name;
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public int getImage() {
        return image;
    }
}

We've created a public class called Movie. That class has two fields or properties: name and image. Those fields are private hence cannot be accessed by outside classes. So then how do we assign them values, or even get their values? Well that's where our public constructor and getter accessor methods come in.

Instantiating the Movie class will cause the instantiater to pass us the name and image via constructor. Then the getter methods can return us the name and image.

Section 1 : ItemLongClickListener Interface

We will now come and create a simple interface that will act as the signature for our LongClickListener. Remember we are interested in listening to long click events for our RecyclerView.

The onItemLongClick will be taking a View object and an integer, the position of the clicked item. That method is an abstract one, meaning it doesn't have a body yet. Hence the implementer of the interface will have to provide their implementations.

package com.tutorials.hp.recyclerlongclick;

import android.view.View;

public interface ItemLongClickListener {

    void onItemLongClick(View v,int pos);

}

Section 2 : ViewHolder class

Here's our Viewholder class. This class will

  • Holds our View Items for Recycling.
  • Implements View.OnClickListener.
package com.tutorials.hp.recyclerlongclick;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class MyHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {

    ImageView img;
    TextView nameTxt;
    ItemLongClickListener itemLongClickListener;

    public MyHolder(View itemView) {
        super(itemView);

        img= (ImageView) itemView.findViewById(R.id.movieImage);
        nameTxt= (TextView) itemView.findViewById(R.id.nameTxt);

        itemView.setOnLongClickListener(this);

    }

    public void setItemLongClickListener(ItemLongClickListener ic)
    {
        this.itemLongClickListener=ic;
    }

    @Override
    public boolean onLongClick(View v) {
        this.itemLongClickListener.onItemLongClick(v,getLayoutPosition());
        return false;
    }
}

You can see our MyHolder class is extending the RecycerView.ViewHolder class. This will make our class a view holder class. A view holder class is a class responsible for temporarily holding widgets for the adapter to recycle those views. This dramatically improves performance as inflation then occurs only once. Then subsequently the widgets are recycled. Deriving from that class has forced us to provide a constructor that takes a View object and passing it to the super class.

We've made our MyHolder class implement our View.OnLongClickListener interface. That is the interface that normally has to be implemented suppose you want ti listen to long click events of any view. So we are listening to our MyHolder's long click events.

Section 3 : Adapter class

Then we have our Adapter class as well. As our RecycerView adapter class, this class has to derive from RecyclerView.Adapter<T>.

Moreover it will perform the following tasks:

  • Inflates our Layout.
  • Binds our dataset.
package com.tutorials.hp.recyclerlongclick;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyHolder> {

    Context c;
    ArrayList<Movie> movies;

    public MyAdapter(Context c, ArrayList<Movie> movies) {
        this.c = c;
        this.movies = movies;
    }

    //INITIALIZE PUR HOLDER
    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,parent,false);
        MyHolder holder=new MyHolder(v);
        return holder;
    }

    //BIND DATA TO VIEWS
    @Override
    public void onBindViewHolder(MyHolder holder, int position) {
        holder.nameTxt.setText(movies.get(position).getName());
        holder.img.setImageResource(movies.get(position).getImage());

        holder.setItemLongClickListener(new ItemLongClickListener() {
            @Override
            public void onItemLongClick(View v, int pos) {
                Toast.makeText(c,movies.get(pos).getName(),Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return movies.size();
    }
}

Our MyAdapter class is our adapter class. In this case we specifically use the RecyclerView.Adapter<MyHolder> as we are working with recyclerview. Deriving from that class will force us to override several methods as we've done. Those method include the getCount() which will return the number of movies to be displayed in our recyclerview. Then onCreateViewHolder is where we inflate our model layout into a view object. To inflate we've used the usual culprit, the LayoutInflater class. The inflater view has then been passed to the MyHolder, Eventually that method returns the MyHolder instance.

Then onBindViewHolder is where we bind data. First our View holder is passed to us to allow us to reference the various widgets it is holding. In our case those widgets are an imageview and a textview. Then we've also set the lonclick listener to our MyHolder, then provided the event handler. In our case we simply show a toast message when our recyclerview item is long clicked.

Section 1 : MainActivity

Then we come to our MainActivity. This class is deriving from our AppCompatActivity.

This class is our launcher activity. We will set our RecyclerView layout manager here as well as the RecyclerView adapter.

Moreover we generate our data set.

package com.tutorials.hp.recyclerlongclick;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    RecyclerView rv;
    MyAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        rv= (RecyclerView) findViewById(R.id.mRecycler);
        adapter=new MyAdapter(this,getMovies());

        //SET RV PROPERTIES
        rv.setLayoutManager(new LinearLayoutManager(this));
        rv.setItemAnimator(new DefaultItemAnimator());

        //ADAPTER
        rv.setAdapter(adapter);

    }

    private ArrayList<Movie> getMovies() {
        //COLECTION OF MOVIES
        ArrayList<Movie> movies=new ArrayList<>();

        Movie movie=new Movie("BlackList",R.drawable.red);

        //ADD ITR TO COLLECTION
        movies.add(movie);

        movie=new Movie("Ghost Rider",R.drawable.rider);
        movies.add(movie);

        movie=new Movie("Fruts",R.drawable.fruits);
        movies.add(movie);

        movie=new Movie("Breaking Bad",R.drawable.breaking);
        movies.add(movie);

        movie=new Movie("Crisis",R.drawable.crisis);
        movies.add(movie);

        movie=new Movie("Star Wars",R.drawable.starwars);
        movies.add(movie);

        movie=new Movie("Shuttle Carrier",R.drawable.shuttlecarrier);
        movies.add(movie);

        movie=new Movie("Men In Black",R.drawable.meninblack);
        movies.add(movie);

        movie=new Movie("Game Of Thrones",R.drawable.thrones);
        movies.add(movie);

        return movies;

    }

}

Our main activity has inherited from the AppCompatActivity. That has then turned it into an activity. Hence you have to make sure that it is registered in the android manifest. In our main activity we've maintained a recyclerview as well as an adapter. Then we have two methods, the onCreate() and the getMovies(). onCreate() is a callback method for activity class. It gets raised when the activity is being created. In it we will first set our content view, which basically involves passing our layout to the setContentView method. Then we've referenced our ToolBar via findViewById then used it as our action bar. We've also referenced the Floating Action Button.

Not only that but we've referenced our recyclerview from our layout file, then set it's adapter. That adapter is the instance of MyAdapter class. We've also set the layout manager as well as the item animator to our recyclerview.

Then the getMovies() is responsible for populating an arraylist with some movies and tv shows that can be watched. That arraylist will then be the data source for our recyclerview.

Section 1 : ContentMain.xml

Our content_main.xml layout. We add our RecyclerView here. We'll wrap it with a RelativeLayout. Make sure you assign the recyclerview an id. That id is it's identifier and will be used to reference our recycler in the java code.

  • Holds our RecyclerView.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.tutorials.hp.recyclerlongclick.MainActivity"
    tools:showIn="@layout/activity_main">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/mRecycler" />
</RelativeLayout>

Section 2 : Model Layout

This layout will define the view to be inflated in our RecylerView.Adapter subclass.

Basically this view will be a CardView in our case.

  • To be inflated to a view item.
  • CardView with image and text.

At the root we have a cardview with card corner radius as well as card elevation set. Inside it we will have an imageview, textviews and checkbox.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mCard"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="10dp"
    card_view:cardElevation="10dp"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/movieImage"
            android:padding="10dp"
            android:src="@drawable/ghost" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Name"
            android:id="@+id/nameTxt"
            android:padding="10dp"
            android:textColor="@color/colorAccent"
            android:layout_below="@+id/movieImage"
            android:layout_alignParentLeft="true"
             />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text=" John Doe a former FBI Agent and now Physics teacher .is wrongly accussed of murdering an innocent child.He makes it his business to find the bad guys who did taht.He convinces hacker Aram to join him.....
            "
            android:id="@+id/descTxt"
            android:padding="10dp"
            android:layout_below="@+id/nameTxt"
            android:layout_alignParentLeft="true"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="TV Show"
            android:id="@+id/posTxt"
            android:padding="10dp"

            android:layout_below="@+id/movieImage"
            android:layout_alignParentRight="true" />

        <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/chk"
            android:layout_alignParentRight="true"
            />

    </RelativeLayout>
</android.support.v7.widget.CardView>

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post Next Post