HeadLine仿今日头条项目
一、项目概述
1.1项目背景
在移动应用开发中,列表展示是最常见的需求之一。无论是社交应用的时间线、电商应用的商品列表,还是新闻应用的资讯流,都离不开高效的列表实现。本项目《仿今日头条》是一个典型的新闻资讯类应用,通过实现一个包含多种卡片类型的新闻列表,展示了 Android 平台高级列表开发的最佳实践。
1.2项目整体架构
仿今日头条项目:
1、MainActivity.java 主活动,数据初始化和列表配置
2、NewsAdapter.java RecyclerView适配器
3、NewsBean.java 数据模型
4、activity_main.xml 主界面布局
5、list_item_one.xml 单图新闻布局
6、list_item_two.xml 三图新闻布局
7、title_bar.xml 标题栏布局
二、RecyclerView核心概念详解
2.1 RecyclerView的工作机制
RecyclerView 的工作机制可以概括为"创建-复用-绑定"三部曲:
用户滑动列表
↓
RecyclerView 检测到需要显示新条目
↓
调用 Adapter.onCreateViewHolder() 创建新视图
↓
调用 Adapter.onBindViewHolder() 绑定数据
↓
条目滑出屏幕时,视图进入回收池
↓
新条目需要显示时,从回收池复用视图
2.2核心组件说明
2.2.1 LayoutManager(布局管理器)
LayoutManager 负责决定条目如何排列和显示。本项目使用LinearLayoutManager实现垂直列表:
LinearLayoutManager 内部维护了条目位置的缓存,能够高效地计算哪些条目应该显示在屏幕上。
2.2.2 Adapter(适配器)
适配器是 RecyclerView 和数据之间的桥梁,本项目的 NewsAdapter 继承自 RecyclerView.Adapter <RecyclerView.ViewHolder>:
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// 三个必须重写的方法
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 根据视图类型创建不同的 ViewHolder
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// 将数据绑定到 ViewHolder
}
@Override
public int getItemCount() {
// 返回数据总数
return NewsList.size();
}
}
2.2.3 ViewHolder(视图持有者)
ViewHolder是RecyclerView性能优化的核心。它缓存了子视图的引用,避免了重复的findViewById()调用:
2.3视图类型机制
RecyclerView 支持多种视图类型,这是通过getItemViewType方法实现的:
@Override
public int getItemViewType(int position) {
//返回当前位置的视图类型
return NewsList.get(position).getType();
}
本项目中,getType() 返回的值决定了使用哪种布局:
type = 1:使用 list_item_one.xml(单图新闻)
type = 2:使用 list_item_two.xml(三图新闻)
三、项目数据模型设计
3.1 NewsBean 类详解
NewsBean是新闻的数据模型,定义了新闻包含的所有属性:
public class NewsBean {
private int id; //新闻id
private String title; //新闻标题
private List<Integer> imgList; //新闻图片
private String name; //用户名
private String comment; //用户评论
private String time; //新闻发布时间
private int type; //新闻类型
// Getter 和 Setter 方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
//其他 getter/setter
3.2使用List存储图片的优势
private List<Integer> imgList; // 使用 List 存储图片资源ID
这种设计非常灵活:
单图新闻:imgList.size() == 1
三图新闻:imgList.size() == 3
置顶新闻:imgList.size() == 0 //无图片
如果未来需要支持两图、四图等布局,只需要添加对应的布局文件和判断逻辑即可。
3.3数据初始化流程
在MainActivity.setData()方法中,创建了6条新闻数据:
private void setData() {
//数组组装逻辑 为每条新闻创建 NewsBean 对象
//根据不同的位置(0-5)设置不同的图片列表
NewsList = new ArrayList<NewsBean>();
NewsBean bean;
for (int i = 0; i < titles.length; i++) {
bean = new NewsBean();
bean.setId(i + 1);
bean.setTitle(titles[i]);
bean.setName(names[i]);
bean.setComment(comments[i]);
bean.setTime(times[i]);
bean.setType(types[i]);
switch (i) {
case 0: //置顶新闻的图片设置
List<Integer> imgList0 = new ArrayList<>();
bean.setImgList(imgList0);
break;
case 1://设置第2个条目的图片数据
List<Integer> imgList1 = new ArrayList<>();
imgList1.add(icons1[i - 1]);
bean.setImgList(imgList1);
break;
case 2://设置第3个条目的图片数据
List<Integer> imgList2 = new ArrayList<>();
imgList2.add(icons2[i - 2]);
imgList2.add(icons2[i - 1]);
imgList2.add(icons2[i]);
bean.setImgList(imgList2);
break;
case 3://设置第4个条目的图片数据
List<Integer> imgList3 = new ArrayList<>();
imgList3.add(icons1[i - 2]);
bean.setImgList(imgList3);
break;
case 4://设置第5个条目的图片数据
List<Integer> imgList4 = new ArrayList<>();
imgList4.add(icons2[i - 1]);
imgList4.add(icons2[i]);
imgList4.add(icons2[i + 1]);
bean.setImgList(imgList4);
break;
case 5://设置第6个条目的图片数据
List<Integer> imgList5 = new ArrayList<>();
imgList5.add(icons1[i - 3]);
bean.setImgList(imgList5);
break;
}
NewsList.add(bean);
}
四、多视图类型适配器实现
4.1 NewsAdapter 完整代码分析
视图绑定逻辑:
4.2视图类型判断的技巧
在 onBindViewHolder 中使用 instanceof 判断 ViewHolder 类型:
if (holder instanceof MyViewHolder1) {
// 处理单图视图
} else if (holder instanceof MyViewHolder2) {
// 处理三图视图
}
4.3置顶标识的特殊处理
if (position == 0) {
holder.iv_top.setVisibility(View.VISIBLE); // 显示"置顶"图标
holder.iv_img.setVisibility(View.GONE); // 置顶新闻没有图片
} else {
holder.iv_top.setVisibility(View.GONE); // 其他新闻不显示置顶
holder.iv_img.setVisibility(View.VISIBLE); // 显示右侧图片
}
五、布局资源文件深度剖析
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/light_gray_color"
android:orientation="vertical">
<!-- 包含标题栏 -->
<include layout="@layout/title_bar" />
<!-- 频道标签栏 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@android:color/white"
android:orientation="horizontal">
<TextView
style="@style/tvStyle"
android:text="推荐"
android:textColor="@android:color/holo_red_dark" />
<TextView
style="@style/tvStyle"
android:text="抗疫"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="小视频"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="北京"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="视频"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="热点"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="娱乐"
android:textColor="@color/gray_color" />
</LinearLayout>
<!-- 分割线 -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#eeeeee" />
<!-- RecyclerView 列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
布局解析:
1.使用 LinearLayout 垂直排列所有元素
2.include 标签用于复用标题栏布局
3.频道标签栏使用水平 LinearLayout 实现
4.1dp 高的 View 作为分割线
5.RecyclerView 占据剩余空间(layout_height="match_parent")
5.2 title_bar.xml 标题栏布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#d33d3c"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<!-- 标题栏-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="仿今日头条"
android:textColor="@android:color/white"
android:textSize="22sp" />
<EditText
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="15dp"
android:background="@drawable/search_bg"
android:gravity="center_vertical"
android:textColor="@android:color/black"
android:hint="搜你想搜的"
android:textColorHint="@color/gray_color"
android:textSize="14sp"
android:paddingLeft="30dp" />
</LinearLayout>
设计特点:
1.高度 50dp,红色背景(#d33d3c)
2.左侧显示"仿今日头条"标题,白色文字,22sp
3.右侧搜索框带搜索图标背景(通过 android:background="@drawable/search_bg" 实现)
4.搜索框提示文字"搜你想搜的"
5.3 list_item_one.xml - 单图新闻布局
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_marginBottom="8dp"
android:background="@android:color/white"
android:padding="8dp">
<LinearLayout
android:id="@+id/ll_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:maxLines="2"
android:textColor="#3c3c3c"
android:textSize="16sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_top"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:src="@drawable/top" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/iv_top"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_name"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_comment"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_time"
style="@style/tvInfo" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
<ImageView
android:id="@+id/iv_img"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_toRightOf="@id/ll_info"
android:padding="3dp" />
</RelativeLayout>
布局详解:
1.外层 RelativeLayout:
高度固定 90dp
白色背景
底部外边距 8dp(与下一条新闻间距)
内边距 8dp
2.左侧信息区域:
使用 LinearLayout 垂直排列
宽度 280dp(固定宽度,为右侧图片留出空间)
3.标题 TextView:
maxLines="2":最多显示2行,超出自动截断
颜色 #3c3c3c,字号 16sp
4.底部信息栏:
包含置顶图标和作者/评论/时间信息
置顶图标默认隐藏(visibility="gone")
使用 layout_alignParentBottom="true" 将信息栏固定在底部
5.右侧图片:
layout_toRightOf="@id/ll_info":位于信息区域右侧
高度 90dp,宽度自适应(match_parent)
内边距 3dp,形成图片边框效果
5.4 list_item_two.xml - 三图新闻布局
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@android:color/white">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:padding="8dp"
android:textColor="#3c3c3c"
android:textSize="16sp" />
<LinearLayout
android:id="@+id/ll_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_img1"
style="@style/ivImg"/>
<ImageView
android:id="@+id/iv_img2"
style="@style/ivImg"/>
<ImageView
android:id="@+id/iv_img3"
style="@style/ivImg"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ll_img"
android:orientation="vertical"
android:padding="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_name"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_comment"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_time"
style="@style/tvInfo" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
布局详解:
1.外层 RelativeLayout:
高度自适应(wrap_content)
白色背景,底部外边距 8dp
2.标题区域:
位于顶部,全宽
最多显示2行,内边距 8dp
3.图片区域:
位于标题下方(layout_below="@id/tv_title")
水平排列的三张图片
使用样式统一图片尺寸
4.底部信息:
位于图片区域下方
显示作者、评论数、时间
5.5 样式文件分析
<!-- tvInfo 样式 - 用于底部信息文字 -->
<style name="tvInfo">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">12sp</item>
<item name="android:textColor">#9c9c9c</item>
<item name="android:layout_marginRight">8dp</item>
</style>
<!-- ivImg 样式 - 用于三图新闻的图片 -->
<style name="ivImg">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">80dp</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_margin">3dp</item>
<item name="android:scaleType">centerCrop</item>
</style>
样式优势:
1.代码复用:多处使用相同属性时只需引用样式
2.易于维护:修改样式定义即可全局生效
3.布局清晰:减少布局文件中的重复代码
六、ViewHolder 模式与性能优化
6.1 ViewHolder 模式原理
ViewHolder 模式的核心思想是缓存视图引用。在传统的 ListView 中,getView() 方法会被频繁调用,如果每次都通过 findViewById() 查找控件,会造成严重的性能问题。
没有使用 ViewHolder 的代码:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.list_item, null);
TextView title = convertView.findViewById(R.id.title); // 每次都查找
TextView content = convertView.findViewById(R.id.content); // 每次都查找
title.setText(titles[position]);
content.setText(contents[position]);
return convertView;
}
使用 ViewHolder 的代码:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.title = convertView.findViewById(R.id.title);
holder.content = convertView.findViewById(R.id.content);
convertView.setTag(holder); // 缓存 ViewHolder
} else {
holder = (ViewHolder) convertView.getTag(); // 复用 ViewHolder
}
holder.title.setText(titles[position]);
holder.content.setText(contents[position]);
return convertView;
}
static class ViewHolder {
TextView title;
TextView content;
}
6.2 RecyclerView 的强制 ViewHolder
RecyclerView 在设计上强制使用 ViewHolder 模式,无法绕过:
// RecyclerView 要求必须继承 ViewHolder
class MyViewHolder extends RecyclerView.ViewHolder {
TextView title;
ImageView image;
public MyViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
image = itemView.findViewById(R.id.image);
}
}
这种设计保证了:
1.性能最优:不会出现忘记使用 ViewHolder 的情况
2.代码规范:统一的视图缓存机制
3.类型安全:泛型支持
6.3 视图复用机制详解
RecyclerView 的视图复用比 ListView 更加高效:
屏幕可见区域(显示5个条目)
↓
用户向下滑动,第1个条目滑出屏幕
↓
第1个条目的视图进入 RecyclerView 的回收池
↓
用户继续滑动,需要显示第6个条目
↓
RecyclerView 从回收池中取出第1个条目的视图
↓
调用 onBindViewHolder() 更新数据
↓
第6个条目显示,复用了第1个条目的视图
回收池层级:
- Scrap:临时分离的视图,用于布局过程
- Cache:缓存最近使用的视图,默认大小2
- RecycledViewPool:共享视图池,可以跨 RecyclerView 复用
七、数据绑定与界面更新机制
7.1数据绑定流程:
数据源更新
↓
调用 notifyDataSetChanged() 或更细粒度的通知方法
↓
RecyclerView 重新布局
↓
Adapter 重新绑定可见区域的数据
↓
界面更新完成
八、RecyclerView 在仿今日头条项目中的使用详解
8.2.1 RecyclerView 的初始化流程
第一步:在布局文件中定义 RecyclerView
位置:activity_main.xml
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
第二步:在 Activity 中初始化
位置:MainActivity.java 的 onCreate() 方法
mRecyclerView = findViewById(R.id.rv_list); // 找到控件
mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); // 设置布局管理器
mAdapter = new NewsAdapter(MainActivity.this, NewsList); // 创建适配器
mRecyclerView.setAdapter(mAdapter); // 设置适配器
代码解析:
findViewById(R.id.rv_list):通过 ID 找到 RecyclerView 控件setLayoutManager():设置布局管理器,这里使用 LinearLayoutManager 实现垂直列表NewsAdapter:自定义适配器,负责创建视图和绑定数据setAdapter():将适配器设置给 RecyclerView
8.2.2 多视图类型的实现机制
核心代码1:定义视图类型
// 在 NewsBean 中定义 type 字段
private int type; // 1=单图新闻,2=三图新闻
核心代码2:返回视图类型
@Override
public int getItemViewType(int position) {
return NewsList.get(position).getType(); // 根据数据返回类型
}
核心代码3:根据类型创建不同的视图
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 1) {
// 加载单图新闻布局
View itemView = LayoutInflater.from(mContext)
.inflate(R.layout.list_item_one, parent, false);
return new MyViewHolder1(itemView);
} else if (viewType == 2) {
// 加载三图新闻布局
View itemView = LayoutInflater.from(mContext)
.inflate(R.layout.list_item_two, parent, false);
return new MyViewHolder2(itemView);
}
return null;
}
核心代码4:分别绑定数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
NewsBean bean = NewsList.get(position);
if (holder instanceof MyViewHolder1) {
// 绑定单图新闻数据
((MyViewHolder1) holder).title.setText(bean.getTitle());
((MyViewHolder1) holder).name.setText(bean.getName());
// ... 其他数据绑定
} else if (holder instanceof MyViewHolder2) {
// 绑定三图新闻数据
((MyViewHolder2) holder).title.setText(bean.getTitle());
((MyViewHolder2) holder).name.setText(bean.getName());
// ... 其他数据绑定
}
}
8.2.3 ViewHolder 的实现
单图新闻 ViewHolder:
class MyViewHolder1 extends RecyclerView.ViewHolder {
// 声明控件
ImageView iv_top, iv_img;
TextView title, name, comment, time;
public MyViewHolder1(View view) {
super(view);
// 在构造函数中查找并缓存控件
iv_top = view.findViewById(R.id.iv_top);
iv_img = view.findViewById(R.id.iv_img);
title = view.findViewById(R.id.tv_title);
name = view.findViewById(R.id.tv_name);
comment = view.findViewById(R.id.tv_comment);
time = view.findViewById(R.id.tv_time);
}
}
三图新闻 ViewHolder:
class MyViewHolder2 extends RecyclerView.ViewHolder {
// 声明控件
ImageView iv_img1, iv_img2, iv_img3;
TextView title, name, comment, time;
public MyViewHolder2(View view) {
super(view);
// 在构造函数中查找并缓存控件
iv_img1 = view.findViewById(R.id.iv_img1);
iv_img2 = view.findViewById(R.id.iv_img2);
iv_img3 = view.findViewById(R.id.iv_img3);
title = view.findViewById(R.id.tv_title);
name = view.findViewById(R.id.tv_name);
comment = view.findViewById(R.id.tv_comment);
time = view.findViewById(R.id.tv_time);
}
}
九、控件使用总结
9.1 项目中使用的所有控件
9.1.1 RecyclerView(1个)
作用: 新闻列表展示控件,是整个项目的核心列表控件
使用位置: activity_main.xml
关键属性:
android:id="@+id/rv_list":控件唯一标识android:layout_width="match_parent":宽度填满父容器android:layout_height="match_parent":高度填满父容器
代码示例:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
9.1.2 LinearLayout(6个)
作用: 线性布局容器,用于垂直或水平排列子控件
使用位置:
activity_main.xml:外层容器(垂直排列)、频道标签栏(水平排列)title_bar.xml:标题栏容器(水平排列)list_item_one.xml:左侧信息区域(垂直排列)、底部信息栏(水平排列)list_item_two.xml:图片容器(水平排列)、底部信息容器(水平排列)
关键属性:
android:orientation="vertical":子控件垂直排列android:orientation="horizontal":子控件水平排列android:layout_width:宽度android:layout_height:高度
代码示例:
<!-- 垂直排列 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView ... />
<ImageView ... />
</LinearLayout>
<!-- 水平排列 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView ... />
<TextView ... />
</LinearLayout>
9.1.3 RelativeLayout(3个)
作用: 相对布局容器,子控件可以相对于父容器或其他控件定位
使用位置:
list_item_one.xml:整个条目的外层容器list_item_one.xml:底部信息栏的内层容器list_item_two.xml:整个条目的外层容器
关键属性:
android:layout_below="@id/xxx":位于指定控件下方android:layout_toRightOf="@id/xxx":位于指定控件右侧android:layout_alignParentBottom="true":对齐父容器底部android:layout_centerVertical="true":垂直居中
代码示例:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/iv_img"
android:layout_width="100dp"
android:layout_height="80dp"
android:layout_below="@id/tv_title"
android:layout_toRightOf="@id/tv_title" />
</RelativeLayout>
9.1.4 TextView(多个)
作用: 显示文字内容,包括新闻标题、作者名、评论数、发布时间
使用位置:
activity_main.xml:频道标签(推荐、抗疫、小视频等)list_item_one.xml:标题、作者、评论、时间list_item_two.xml:标题、作者、评论、时间title_bar.xml:标题栏文字
关键属性:
android:text:显示的文本内容android:textSize:文字大小(sp单位)android:textColor:文字颜色android:maxLines:最大行数android:ellipsize:超出时省略号位置android:gravity:文字对齐方式
代码示例:
<!-- 标题 TextView -->
<TextView
android:id="@+id/tv_title"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:maxLines="2"
android:textSize="16sp"
android:textColor="#3c3c3c"
android:text="各地餐企齐行动,杜绝餐饮浪费" />
<!-- 作者 TextView(使用样式) -->
<TextView
android:id="@+id/tv_name"
style="@style/tvInfo"
android:text="央视新闻客户端" />
<!-- 评论数 TextView -->
<TextView
android:id="@+id/tv_comment"
style="@style/tvInfo"
android:text="9884评" />
<!-- 时间 TextView -->
<TextView
android:id="@+id/tv_time"
style="@style/tvInfo"
android:text="6小时前" />
9.1.5 ImageView(多个)
作用: 显示图片,包括新闻图片和置顶图标
使用位置:
list_item_one.xml:右侧新闻图片、置顶图标list_item_two.xml:三张新闻图片
关键属性:
-
android:src:图片资源(如@drawable/top) -
android:scaleType:图片缩放类型centerCrop:居中裁剪,填满控件fitCenter:居中显示,保持比例fitXY:拉伸填满
-
android:visibility:可见性(visible/gone/invisible)
代码示例:
<!-- 置顶图标 -->
<ImageView
android:id="@+id/iv_top"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/top"
android:visibility="gone" />
<!-- 右侧新闻图片 -->
<ImageView
android:id="@+id/iv_img"
android:layout_width="match_parent"
android:layout_height="90dp"
android:padding="3dp"
android:scaleType="centerCrop" />
<!-- 三图新闻图片(使用样式) -->
<ImageView
android:id="@+id/iv_img1"
style="@style/ivImg"
android:scaleType="centerCrop" />
9.1.6 EditText(1个)
作用: 搜索输入框,接收用户输入的关键字
使用位置: title_bar.xml
关键属性:
android:hint:输入提示文字("搜你想搜的")android:textColorHint:提示文字颜色android:background:背景(搜索框背景样式)android:paddingLeft:左内边距(为搜索图标留出空间)android:gravity="center_vertical":垂直居中
代码示例:
<EditText
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:hint="搜你想搜的"
android:textColorHint="@color/gray_color"
android:background="@drawable/search_bg"
android:paddingLeft="30dp"
android:textSize="14sp"
android:gravity="center_vertical" />
9.1.7 View(1个)
作用: 作为分割线,分隔频道标签栏和新闻列表
使用位置: activity_main.xml
关键属性:
android:layout_width="match_parent":宽度填满android:layout_height="1dp":高度1像素android:background="#eeeeee":浅灰色背景
代码示例:
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#eeeeee" />
9.1.8 include(1个)
作用: 引入其他布局文件,实现布局复用
使用位置: activity_main.xml
关键属性:
layout="@layout/title_bar":指定要引入的布局文件
代码示例:
<!-- 引入标题栏布局 -->
<include layout="@layout/title_bar" />
优势:
- 代码复用:标题栏只需定义一次,多处使用
- 易于维护:修改标题栏只需改一个文件
- 结构清晰:主布局文件更简洁
十、总结
10.1项目执行结果:
HeadLine:
ListView:
RecyclerView:
10.2项目核心内容回顾:
1. RecyclerView 的使用
- 初始化:
findViewById()→setLayoutManager()→setAdapter() - 适配器:必须实现
onCreateViewHolder()、onBindViewHolder()、getItemCount()三个方法 - 多视图类型:通过
getItemViewType()返回不同类型,在onCreateViewHolder()中创建不同布局
2. 布局资源
- activity_main.xml:主布局,包含标题栏、频道标签、RecyclerView
- title_bar.xml:标题栏布局,包含标题文字和搜索框
- list_item_one.xml:单图新闻布局,左侧文字+右侧图片
- list_item_two.xml:三图新闻布局,标题+三张图片+底部信息
3. 核心控件
- RecyclerView:列表控件
- TextView:显示文字(标题、作者、评论、时间)
- ImageView:显示图片(新闻图、置顶图标)
- LinearLayout:垂直或水平排列控件
- RelativeLayout:相对位置定位