Android 中的可扩展新闻提要示例
许多新闻应用程序使用可扩展类型的视图来显示新闻和类别。这种类型的功能将有助于使 UI 看起来更好,并在同一 UI 中提供额外的内容。当您在应用程序中显示不同类型的内容并使用不同类别对其进行过滤时,将使用这种类型的 UI。在本文中,我们将看看在我们的 Android 应用程序中创建类似类型的可扩展新闻提要示例。
我们将在本文中构建什么?
我们将构建一个简单的应用程序,在该应用程序中我们将显示一个 Recycler 视图,我们将在其中显示新闻类别并单击新闻类别,我们将在其中的回收者视图中显示该特定类别的新闻。下面给出了一个示例视频,以了解我们将在本文中做什么。请注意,我们将使用Java语言来实现这个项目。
分步实施
第 1 步:创建一个新项目
要在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目。请注意,选择Java作为编程语言。
步骤 2:使用 activity_main.xml 文件
导航到app > res > layout > activity_main.xml并将以下代码添加到该文件中。下面是activity_main.xml文件的代码。
XML
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;
}
}
Java
import java.util.ArrayList;
public class CategoriesModal {
// creating variable for our category,
// news array list and expanded boolean.
private String newsCategory;
private ArrayList newsModalArrayList;
private boolean expanded;
// creating a constructor.
public CategoriesModal(String newsCategory, ArrayList 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 getNewsModalArrayList() {
return newsModalArrayList;
}
public void setNewsModalArrayList(ArrayList newsModalArrayList) {
this.newsModalArrayList = newsModalArrayList;
}
}
XML
XML
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 {
// variables for array list and context.
private ArrayList newsModalArrayList;
private Context context;
// creating a constructor.
public NewsRVAdapter(ArrayList 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);
}
}
}
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 {
// variables for array list and context.
private ArrayList categoriesModalArrayList;
private Context context;
// creating a constructor.
public CategoriesRVAdapter(ArrayList 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);
}
}
}
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 categoriesModalArrayList;
private ArrayList 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);
}
}
第 3 步:创建一个模态类来存储我们的新闻
导航到应用程序 > Java > 您应用程序的包名称 > 右键单击它 > 新建 > Java类并将其命名为NewsModal并将以下代码添加到其中。
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;
}
}
第 4 步:创建一个模态类来存储我们的新闻类别
同样,创建另一个Java类并将其命名为CategoriesModal并向其添加以下代码。
Java
import java.util.ArrayList;
public class CategoriesModal {
// creating variable for our category,
// news array list and expanded boolean.
private String newsCategory;
private ArrayList newsModalArrayList;
private boolean expanded;
// creating a constructor.
public CategoriesModal(String newsCategory, ArrayList 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 getNewsModalArrayList() {
return newsModalArrayList;
}
public void setNewsModalArrayList(ArrayList newsModalArrayList) {
this.newsModalArrayList = newsModalArrayList;
}
}
第 5 步:为我们的新闻项目创建布局文件
导航到应用程序 > res > 布局 > 右键单击它 > 新建 > 布局资源文件并将其命名为news_rv_item并将以下代码添加到其中。
XML
第 6 步:为新闻类别创建新的布局文件
同样,创建另一个布局资源文件并将其命名为news_categories_rv_item并将以下代码添加到其中。
XML
第七步:新建一个Adapter类,用于在新闻RecyclerView中设置数据
创建另一个Java类并将其命名为NewsRVAdapter并向其添加以下代码。代码中添加了注释,以便更详细地了解。
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 {
// variables for array list and context.
private ArrayList newsModalArrayList;
private Context context;
// creating a constructor.
public NewsRVAdapter(ArrayList 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);
}
}
}
第 8 步:为我们的类别 RecyclerView 创建一个适配器类
创建另一个Java类,将其命名为CategoriesRVAdapter并向其添加以下代码。代码中添加了注释,以便更详细地了解。
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 {
// variables for array list and context.
private ArrayList categoriesModalArrayList;
private Context context;
// creating a constructor.
public CategoriesRVAdapter(ArrayList 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);
}
}
}
第 9 步:使用MainActivity。 Java文件
转到主活动。 Java文件,参考如下代码。下面是MainActivity的代码。 Java文件。代码中添加了注释以更详细地理解代码。
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 categoriesModalArrayList;
private ArrayList 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);
}
}
现在运行您的应用程序并查看应用程序的输出。
输出: