-
3、创建一个 StarAdapter
-
4、Activity 完整代码
-
二、吸顶功能实现
-
- 1、自定义 ItemDecoration
-
2、StarDecoration 初始化
-
3、重写 getItemOffsets() 方法
-
4、绘制头部预留空间
-
5、重写 onDraw() 绘制头部
-
6、绘制吸顶效果
-
7、StarDecoration 完整代码
-
总结
================================================================
使用纯代码 加 注释的方式,可以更快的理解源码
如果你喜欢,请点个赞,后期会不断的深入讲解
========================================================================
在绘制吸顶效果之前,需要先实现一个RecyclerView功能列表
新建一个item 的Layout 文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”>
<TextView
android:id=“@+id/user_name”
android:text=“姓名”
android:gravity=“center”
android:layout_width=“match_parent”
android:layout_height=“44dp”
android:textSize=“20sp”
tools:ignore=“MissingConstraints” />
在 RecyclerView 中引用item
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
<androidx.recyclerview.widget.RecyclerView
android:id=“@+id/main_rv”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:listitem=“@layout/item”
/>
public class Star {
String userName;
String groupName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public Star(String userName, String groupName) {
this.userName = userName;
this.groupName = groupName;
}
}
在StarAdapter 中实现 RecyclerView 功能
public class StarAdapter extends RecyclerView.Adapter<StarAdapter.StarViewHolder> {
private Context mContext;
private List starList;
private LayoutInflater inflater;
public StarAdapter(Context context, List stars){
this.mContext = context;
this.starList = stars;
this.inflater = LayoutInflater.from(mContext);
}
@NonNull
@Override
public StarViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.item, null);
return new StarViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull StarViewHolder holder, int position) {
holder.textView.setText(starList.get(position).getUserName());
if (position %2 == 0){
holder.textView.setBackgroundColor(Color.YELLOW);
}else {
holder.textView.setBackgroundColor(Color.RED);
}
}
@Override
public int getItemCount() {
return starList.size();
}
public class StarViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public StarViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.user_name);
}
}
}
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private StarAdapter starAdapter;
private List starList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
recyclerView = findViewById(R.id.main_rv);
starAdapter = new StarAdapter(this, starList);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(starAdapter);
}
private void init(){
starList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 20; j++) {
if (i % 2 ==0){
starList.add(new Star(“小明” + j, “快乐家族” + i));
}else {
starList.add(new Star(“王美丽” + j, “嗨嗨家族” + i));
}
}
}
}
}
上面源码中,我写了一个嵌套的for 循环,用来实现数据的赋值,显示为4组,每组组20条数据。代码运行效果如下:
======================================================================
在 StarDecoration 中,我写了一个分辩率的转换方法
public class StarDecoration extends RecyclerView.ItemDecoration {
/**
-
分辩率
-
@param context
-
@param dpValue
-
@return
*/
private int dp2px(Context context, float dpValue){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue,
context.getResources().getDisplayMetrics());
}
}
// 分组栏的高度
private int headerHeight;
private int valueHeight = 50;
private Paint headPaint;
private Paint drawTextPaint;
private Rect textRect;
public StarDecoration(Context context){
// 顶部吸顶栏的高度
headerHeight = dp2px(context, valueHeight);
// 每一组的头部的Paint
headPaint = new Paint();
headPaint.setColor(Color.RED);
drawTextPaint = new Paint();
drawTextPaint.setColor(Color.YELLOW);
drawTextPaint.setTextSize(50);
textRect = new Rect();
}
ItemDecoration 想要绘制的话,就必须得重写 getItemOffsets()
方法。代码如下
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
@NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// 绑定自己的 Adapter
if (parent.getAdapter() instanceof StarAdapter){
StarAdapter starAdapter = (StarAdapter) parent.getAdapter();
// 当前item 的位置
int position = parent.getChildLayoutPosition(view);
// 分割线预留的空间
outRect.set(10, 10, 0, 0);
}
}
上面的代码中,我们给ItemDecoration 预留了一个划线的空间
运行如下:
- 在Adapter 中判断当前组的第一个item 是不是头部
// 是否是组的第一个Item
public boolean isFirstItemOfGroup(int position) {
if (position == 0) {
return true;
} else {
// 拿到当前位置的和前一个位置的 组名
String currentItemGroupName = getGroupName(position);
String preItemGroupName = getGroupName(position - 1);
// 如果相等,则表示position 的 item 不是第一个,否则是
if (currentItemGroupName.equals(preItemGroupName)) {
return false;
} else {
return true;
}
}
}
- 在 获取到头部 item 之后,预留一个绘制空间
// 判断 Item 是头部
boolean isGroupHeader = starAdapter.isFirstItemOfGroup(position);
if (isGroupHeader){
// headerHeight 是头部 Item 的高度
outRect.set(0, headerHeight, 0, 0);
}else {
// decorationTop 分割线的高度
outRect.set(0, decorationTop, 0, 0);
}
在 getItemOffsets()
中添加上面代码后,预留的 item 的头部空间就出来了,运行如下
// 绘制自己
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
if (parent.getAdapter() instanceof StarAdapter){
StarAdapter starAdapter = (StarAdapter) parent.getAdapter();
// 当前屏幕上展示的
int count = parent.getChildCount();
// 实现 itemView 的宽度和分割线的宽度一样
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingLeft();
最后
针对于上面的问题,我总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
(StarAdapter) parent.getAdapter();
// 当前屏幕上展示的
int count = parent.getChildCount();
// 实现 itemView 的宽度和分割线的宽度一样
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingLeft();
最后
针对于上面的问题,我总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
[外链图片转存中…(img-wWcpLW7h-1714329322085)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!