How to use recycler view to list items in a vertically scrollable view
Here we need 3 main things to list items in recycler view.
- Data
- Item layout
- 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.