How to use recycler view to list items in a vertically scrollable view

Srinivas Gunti
4 min readApr 30, 2020

--

Here we need 3 main things to list items in recycler view.

  1. Data
  2. Item layout
  3. Adapter

Here we are getting data from the google blogger API endpoint. You can also create a blog using google blogger and use google blogger APIs to retrieve blog posts.

You can read more about it here: https://developers.google.com/blogger/docs/3.0/getting_started

Dependencies to be added in build.gradle (Module: app)

dependencies {
implementation 'com.android.support:recyclerview-v7:28.0.0'
// library for api
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.3.1'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
implementation 'com.google.code.gson:gson:2.7'

// glide image loader
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'com.google.firebase:firebase-database:16.0.4'
implementation 'com.google.firebase:firebase-storage:16.0.4'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation 'org.jsoup:jsoup:1.10.1'
}

First, we will design the XML part of the application.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/parent_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
>

<androidx.recyclerview.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_centerHorizontal="true"
android:id="@+id/recycler_view">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
</ScrollView>

Next, we will create an XML file for the single item that is to be shown in the recycler view.

item_layout.java

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:orientation="horizontal">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="10dp"
android:id="@+id/blog_post_image">
</ImageView>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Crops Stick With Despite Trade War In India With USA"
android:textSize="15dp"
android:textColor="#000000"
android:fontFamily="sans-serif-medium"
android:id="@+id/blog_post_title"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"/>
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" eu neque porta, ultricies leo posuere, tincidunt eros."
android:fontFamily="sans-serif-condensed-light"
android:textStyle="normal"
android:textColor="#0066cc"
android:letterSpacing="0.02"
android:lineSpacingExtra="2.7sp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:id="@+id/blog_post_content"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp"
android:gravity="center_vertical"
android:text="16 August"
android:fontFamily="sans-serif-medium"
android:textStyle="normal"
android:textColor="#003366"
android:letterSpacing="0.02"
android:lineSpacingExtra="0.7sp"
android:id="@+id/blog_post_date"/>


</LinearLayout>


</LinearLayout>
</LinearLayout>



</RelativeLayout>

Next, we need to create a response model that can be used to store the data.

blog_response.java

package com.recyclerviewDemo;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.List;

public class blog_response {

@SerializedName("kind")
@Expose
private String kind;

@SerializedName("items")
@Expose
private List<blog_item> items;

@SerializedName("etag")
@Expose
private String etag;

public String getKind() {
return kind;
}

public void setKind(String kind) {
this.kind = kind;
}

public List<blog_item> getItems() {
return items;
}

public void setItems(List<blog_item> items) {
this.items = items;
}

public String getEtag() {
return etag;
}

public void setEtag(String etag) {
this.etag = etag;
}
}

blog_item.java

package com.recyclerViewDemo;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class blog_item {

@SerializedName("id")
@Expose
private Long id;

@SerializedName("published")
@Expose
private String published;

@SerializedName("url")
@Expose
private String url;

@SerializedName("title")
@Expose
private String title;

@SerializedName("content")
@Expose
private String content;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getPublished() {
return published;
}

public void setPublished(String published) {
this.published = published;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

Next, create an interface named Api.java to store the URL and endpoints

Api.java

package com.recyclerviewDemo;

import com.tripshots.response.blog_item;
import com.tripshots.response.blog_response;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;

public interface api {
String url = "https://www.googleapis.com/blogger/v3/";

@GET("blogs/{Blog_ID}/posts/")
Call<blog_response> getBlogPosts(@Query("key") String key);

@GET("blogs/{Blog_ID}/posts/")
Call<blog_item> getSpecificBlogPost(@Path("postId") Long postId, @Query("key") String key);
}

Here we will be using the retrofit library to access the API end points

MainActivity.java

package com.recyclerViewDemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;


import com.recyclerViewDemo.Adapter.PostAdapter;

import com.recyclerViewDemo.Api;


import com.recyclerViewDemo.blog_item;
import com.recyclerViewDemo.blog_response;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {

RecyclerView blog_recycler_view;


Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(com.tripshots.Api.api.url)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
com.recyclerViewDemo.Api Api = retrofit.create(com.recyclerViewDemo.Api.class);




@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

blog_recycler_view = findViewById(R.id.blog_items);
blog_recycler_view.setLayoutManager(new LinearLayoutManager(this));

getBlogPosts();

}


private void getBlogPosts(){
Call<blog_response> call = Api.getBlogPosts({Api Key});

call.enqueue(new Callback<blog_response>() {
@Override
public void onResponse(Call<blog_response> call, Response<blog_response> response) {
if(response.isSuccessful()){

Log.d("blog retrieval", "success");
blog_response blogResponse = response.body();

List<blog_item> result = blogResponse.getItems();
blog_recycler_view.setAdapter(new blogAdapter(MainActivity.this, blogResponse.getItems()));

}
}

@Override
public void onFailure(Call<blog_response> call, Throwable t) {
Log.d("Blog retrieval failed", t.getCause().toString());
Log.d("blog retrieval", "failure");


}
});
}



}

Now we need to create an adapter for this recycler view

blogAdapter.java

package com.recyclerViewDemo;


import android.content.Context;
import android.content.Intent;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.text.Html;
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 com.bumptech.glide.Glide;
import com.recyclerViewDemo.R;
import com.recyclerViewDemo.blog_item;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

public class blogAdapter extends RecyclerView.Adapter<blogAdapter.ViewHolder> {

private Context context;
private List<blog_item> items;

public blogAdapter(Context context, List<blog_item> items) {
this.context = context;
this.items = items;
}

@NonNull
@Override
public blogAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.item_layout, viewGroup, false);
return new blogAdapter.ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull blogAdapter.ViewHolder viewHolder,final int i) {

final blog_item result = items.get(i);

viewHolder.blog_post_title.setText(result.getTitle());

String s = Html.fromHtml(result.getContent()).toString();
s = s.substring(0, Math.min(s.length(), 80));

viewHolder.blog_post_content.setText(s+"...");

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss-HH:mm",
Locale.ENGLISH);
String s1 = result.getPublished();

try
{
Date d = sdf.parse(s1);
String s2 = (new SimpleDateFormat("dd MMMM YYYY")).format(d);

viewHolder.blog_post_date.setText(s2);
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}

String html = result.getContent();
Document doc = Jsoup.parse(html);
Element link = doc.select("img").first();

String img_url = link.attr("src");

Glide.with(context)
.load(img_url)
//.apply(new RequestOptions().override(140, 140))
.into(viewHolder.blog_post_image);

}

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


public class ViewHolder extends RecyclerView.ViewHolder{

ImageView blog_post_image;
TextView blog_post_title, blog_post_content, blog_post_date;

public ViewHolder(@NonNull View itemView){
super(itemView);

blog_post_image = itemView.findViewById(R.id.blog_post_image);

blog_post_title = itemView.findViewById(R.id.blog_post_title);
blog_post_content = itemView.findViewById(R.id.blog_post_content);
blog_post_date = itemView.findViewById(R.id.blog_post_date);

}

}


}

I hope this tutorial helps you understand how to retrieve items and show them in recycler view.

Happy Coding !!! Cheers.

--

--

Srinivas Gunti
Srinivas Gunti

Written by Srinivas Gunti

Software Engineer | Amateur Writer | Traveller | Tech Enthusiast

No responses yet