Open In App

Expandable News Feed in Android with Example

Last Updated : 30 Apr, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Many news applications use the Expandable type of view for displaying the news along with the categories. This type of feature will help to make the UI look better and also provides additional content in the same UI. This type of UI is used when you display different types of content inside your application and filtering it with different categories. In this article, we will take a look at creating a similar type of expandable News Feed Example in our Android App. 

What we are going to build in this article? 

We will be building a simple application in which we will be displaying a Recycler View in which we will show news categories and clicking on the news category we will display the news for that specific category in the recycler view inside that. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Java language. 

Step by Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.

Step 2: Working with the activity_main.xml file

Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. 

XML




<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/idRLView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <!--recycler view for displaying news categories. -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/idRVNewsCategories"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  
</RelativeLayout>


Step 3: Creating a modal class for storing our news 

Navigate to the app > java > your app’s package name > Right-click on it > New > Java class and name it as NewsModal and add the below code to it. 

Java




public class NewsModal {
    
    // string for news title and description.
    private String newsTitle;
    private String newsDesc;
  
    // on below line we have created a constructor.
    public NewsModal(String newsTitle, String newsDesc) {
        this.newsTitle = newsTitle;
        this.newsDesc = newsDesc;
    }
  
    // creating a getter and setter.
    public String getNewsTitle() {
        return newsTitle;
    }
  
    public void setNewsTitle(String newsTitle) {
        this.newsTitle = newsTitle;
    }
  
    public String getNewsDesc() {
        return newsDesc;
    }
  
    public void setNewsDesc(String newsDesc) {
        this.newsDesc = newsDesc;
    }
  
}


Step 4: Creating a modal class for storing our News Categories 

Similarly, create another Java class and name it as CategoriesModal and add the below code to it. 

Java




import java.util.ArrayList;
  
public class CategoriesModal {
      
    // creating variable for our category, 
    // news array list and expanded boolean.
    private String newsCategory;
    private ArrayList<NewsModal> newsModalArrayList;
    private boolean expanded;
  
    // creating a constructor.
    public CategoriesModal(String newsCategory, ArrayList<NewsModal> newsModalArrayList) {
        this.newsCategory = newsCategory;
        this.newsModalArrayList = newsModalArrayList;
          
        // default we are setting expanded as false.
        this.expanded = false;
    }
  
    // getter and setter methods.
    public boolean isExpanded() {
        return expanded;
    }
  
    public void setExpanded(boolean expanded) {
        this.expanded = expanded;
    }
  
    public String getNewsCategory() {
        return newsCategory;
    }
  
    public void setNewsCategory(String newsCategory) {
        this.newsCategory = newsCategory;
    }
  
    public ArrayList<NewsModal> getNewsModalArrayList() {
        return newsModalArrayList;
    }
  
    public void setNewsModalArrayList(ArrayList<NewsModal> newsModalArrayList) {
        this.newsModalArrayList = newsModalArrayList;
    }
      
}


Step 5: Creating a layout file for our news item 

Navigate to the app > res > layout > Right-click on it > New > Layout Resource File and name it as news_rv_item and add the below code to it. 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="3dp"
    android:backgroundTint="@color/purple_200"
    app:cardCornerRadius="1dp">
  
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
  
        <!--text view for displaying news title-->
        <TextView
            android:id="@+id/idTVNewsTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:layout_marginTop="8dp"
            android:padding="4dp"
            android:text="News Title"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textStyle="bold" />
  
        <!--text view for displaying news description-->
        <TextView
            android:id="@+id/idTVNewsDesc"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/idTVNewsTitle"
            android:layout_marginStart="4dp"
            android:layout_marginTop="4dp"
            android:padding="4dp"
            android:text="News Desc"
            android:textColor="@color/white"
            android:textSize="12sp" />
          
    </RelativeLayout>
      
</androidx.cardview.widget.CardView>


Step 6: Creating a new layout file for news categories 

Similarly, create another Layout resource File and name it as news_categories_rv_item and add the below code to it. 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="3dp"
    app:cardCornerRadius="4dp">
  
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
  
        <!--text view for displaying news category-->
        <TextView
            android:id="@+id/idTVCategory"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="Category"
            android:textSize="15sp" />
  
        <androidx.cardview.widget.CardView
            android:id="@+id/idCVCategory"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:elevation="0dp"
            app:cardElevation="0dp">
  
            <!--recycler view for displaying news recycler view-->
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/idRVNews"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
  
        </androidx.cardview.widget.CardView>
  
    </LinearLayout>
  
</androidx.cardview.widget.CardView>


Step 7: Creating a new Adapter class for setting data in news RecyclerView

Create another Java class and name it as NewsRVAdapter and add the below code to it. Comments are added in the code to get to know in more detail. 

Java




import android.content.Context;
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.ArrayList;
  
public class NewsRVAdapter extends RecyclerView.Adapter<NewsRVAdapter.ViewHolder> {
      
    // variables for array list and context.
    private ArrayList<NewsModal> newsModalArrayList;
    private Context context;
  
    // creating a constructor.
    public NewsRVAdapter(ArrayList<NewsModal> newsModalArrayList, Context context) {
        this.newsModalArrayList = newsModalArrayList;
        this.context = context;
    }
  
    @NonNull
    @Override
    public NewsRVAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // passing our layout file for displaying our card item
        return new NewsRVAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.news_rv_item, parent, false));
  
    }
  
    @Override
    public void onBindViewHolder(@NonNull NewsRVAdapter.ViewHolder holder, int position) {
        // on below line we are setting data to our ui components.
        NewsModal modal = newsModalArrayList.get(position);
        holder.newsDescTV.setText(modal.getNewsDesc());
        holder.newsTitleTV.setText(modal.getNewsTitle());
    }
  
    @Override
    public int getItemCount() {
        // returning the size of array list
        return newsModalArrayList.size();
    }
  
    public class ViewHolder extends RecyclerView.ViewHolder {
          
        // creating variables for our text view.
        private TextView newsTitleTV, newsDescTV;
  
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            // initializing our text view
            newsTitleTV = itemView.findViewById(R.id.idTVNewsTitle);
            newsDescTV = itemView.findViewById(R.id.idTVNewsDesc);
        }
    }
}


Step 8: Creating an adapter class for our categories RecyclerView 

Create another Java class name it as CategoriesRVAdapter and add below code to it. Comments are added in the code to get to know in more detail. 

Java




import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
  
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.ArrayList;
  
public class CategoriesRVAdapter extends RecyclerView.Adapter<CategoriesRVAdapter.ViewHolder> {
      
    // variables for array list and context.
  
    private ArrayList<CategoriesModal> categoriesModalArrayList;
    private Context context;
  
    // creating a constructor.
    public CategoriesRVAdapter(ArrayList<CategoriesModal> categoriesModalArrayList, Context context) {
        this.categoriesModalArrayList = categoriesModalArrayList;
        this.context = context;
    }
  
    @NonNull
    @Override
    public CategoriesRVAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // passing our layout file for displaying our card item
        return new CategoriesRVAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.news_categories_rv_item, parent, false));
    }
  
    @Override
    public void onBindViewHolder(@NonNull CategoriesRVAdapter.ViewHolder holder, int position) {
          
        // setting data to our views on below line.
        CategoriesModal modal = categoriesModalArrayList.get(position);
        holder.categoryTV.setText(modal.getNewsCategory());
        NewsRVAdapter adapter = new NewsRVAdapter(modal.getNewsModalArrayList(), context);
        holder.newsRV.setLayoutManager(new LinearLayoutManager(context));
        holder.newsRV.setAdapter(adapter);
          
        // on below line we are getting our expanded boolean.
        boolean expanded = modal.isExpanded();
        if (expanded) {
            // if it is true then we have to make our recycler view card visible.
            holder.newsCV.setVisibility(View.VISIBLE);
        } else {
            // if it is false then we have to make 
            // recycler view card invisible
            // we will be using a visibility gone.
            holder.newsCV.setVisibility(View.GONE);
        }
         
        // adding click listener to our category tv.
        holder.categoryTV.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // inside on click we are 
                // setting our expanded boolean
                modal.setExpanded(!modal.isExpanded());
                // after updating data we are calling 
                // a notify item changed method.
                notifyItemChanged(position);
            }
        });
    }
  
    @Override
    public int getItemCount() {
        // returning the size of array list on below line.
        return categoriesModalArrayList.size();
    }
  
    public class ViewHolder extends RecyclerView.ViewHolder {
        // creating new variables for our views.
        private RecyclerView newsRV;
        private TextView categoryTV;
        private CardView newsCV;
  
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            // initializing our views.
            newsCV = itemView.findViewById(R.id.idCVCategory);
            categoryTV = itemView.findViewById(R.id.idTVCategory);
            newsRV = itemView.findViewById(R.id.idRVNews);
        }
    }
}


Step 9: Working with the MainActivity.java file

Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.

Java




import android.os.Bundle;
  
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.ArrayList;
  
public class MainActivity extends AppCompatActivity {
  
    // creating array list for our categories, 
    // different news and category recycler view.
    private ArrayList<CategoriesModal> categoriesModalArrayList;
    private ArrayList<NewsModal> popularNewsArrayList, sportsNews, techNews;
    private RecyclerView catRV;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
          
        // initializing our variables.
        catRV = findViewById(R.id.idRVNewsCategories);
        categoriesModalArrayList = new ArrayList<>();
          
        // popular news array list.
        popularNewsArrayList = new ArrayList<>();
        popularNewsArrayList.add(new NewsModal("Bihar Board 10th Result 2021: Bihar matric result announced; 78.17% passed", "Bihar Board Result: The Bihar education board on Monday declared the class 10 results. The Bihar Board has made the BSEB 10th result and scores available on the Board's website — biharboardonline.bihar.gov.in — for public access. Candidates are recommended to stay connected with the Times of India Education for latest updates on BSEB 10th Result 2021."));
        popularNewsArrayList.add(new NewsModal("IPL 2021: Full squad, players list of all eight teams", "In the IPL 2021 Player Auction, South African all-rounder Chris Morris made headlines by becoming IPL's most expensive buy of all time. Morris was fetched by Rajasthan Royals for a mammoth Rs. 16.25 crore. Meanwhile Krishnappa Gowtham became the highest uncapped Indian buy of all time. He was bought by Chennai Super Kings for Rs. 9.25"));
        popularNewsArrayList.add(new NewsModal("Bihar Board 10th Result 2021: Bihar matric result announced; 78.17% passed", "Bihar Board Result: The Bihar education board on Monday declared the class 10 results. The Bihar Board has made the BSEB 10th result and scores available on the Board's website — biharboardonline.bihar.gov.in — for public access. Candidates are recommended to stay connected with the Times of India Education for latest updates on BSEB 10th Result 2021."));
        popularNewsArrayList.add(new NewsModal("IPL 2021: Full squad, players list of all eight teams", "In the IPL 2021 Player Auction, South African all-rounder Chris Morris made headlines by becoming IPL's most expensive buy of all time. Morris was fetched by Rajasthan Royals for a mammoth Rs. 16.25 crore. Meanwhile Krishnappa Gowtham became the highest uncapped Indian buy of all time. He was bought by Chennai Super Kings for Rs. 9.25"));
         
        // on below line we are adding our first category.
        categoriesModalArrayList.add(new CategoriesModal("Popular News", popularNewsArrayList));
  
        // sports news.
        sportsNews = new ArrayList<>();
        sportsNews.add(new NewsModal("AB de Villiers loves RCB, he and Maxwell made the difference: Kohli", "AB de Villiers loves RCB, he and Maxwell made the difference: Kohli"));
        sportsNews.add(new NewsModal("Glenn Maxwell made it easier: AB de Villiers after scripting RCB win vs KKR", "Glenn Maxwell made it easier: AB de Villiers after scripting RCB win vs KKR"));
        sportsNews.add(new NewsModal("PBKS vs DC: Steve Smith makes Delhi Capitals debut in Mumbai", "PBKS vs DC: Steve Smith makes Delhi Capitals debut in Mumbai"));
        sportsNews.add(new NewsModal("DC vs PBKS IPL 2021 Match 11: Live story and ball-by-ball commentary", "DC vs PBKS IPL 2021 Match 11: Live story and ball-by-ball commentary"));
          
        // on below line we are creating our second category.
        categoriesModalArrayList.add(new CategoriesModal("Sports", sportsNews));
  
        // technology news.
        techNews = new ArrayList<>();
        techNews.add(new NewsModal("PlayStation 5’s latest update brings storage expansion, new social features", "PlayStation 5’s latest update brings storage expansion, new social features"));
        techNews.add(new NewsModal("OnePlus 9R gets first major OxygenOS update, here are the details\n" + "The Oxygen 11.2.1.", "OnePlus 9R gets first major OxygenOS update, here are the details\n" + "The Oxygen 11.2.1."));
        techNews.add(new NewsModal("Domino's India database likely hacked, 1 million credit card details leaked", "Domino's India database likely hacked, 1 million credit card details leaked"));
        techNews.add(new NewsModal("iPhone 13 Product Red appears in renders, show design changes", "iPhone 13 Product Red appears in renders, show design changes"));
          
        // on below line we are adding our third category.
        categoriesModalArrayList.add(new CategoriesModal("Technology", techNews));
          
        // on below line we are setting layout manager to our recycler view.
        catRV.setLayoutManager(new LinearLayoutManager(this));
          
        // on below line we  are creating and setting adapter to our recycler view.
        CategoriesRVAdapter adapter = new CategoriesRVAdapter(categoriesModalArrayList, this);
        catRV.setAdapter(adapter);
          
    }
}


Now run your app and see the output of the app. 

Output:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads