此博客通过RecyclerView、TextView等进行界面布局,使用自定义RecyclerView.Adapter、RecyclerViewAdapter.ViewHolder以及自定义RecyclerView.ItemDecoration实现分组列表以及悬浮顶部效果

同时这也是中国大学慕课移动终端应用开发的网课作业13,我会持续更新我的作业,如果有需要关注一下吧

说明

1.非常感谢此篇博文以及博文作者,详细介绍了RecyclerView.ItemDecoration的用法,让我少花了很多时间。
2.自定义RecyclerView.ItemDecoration,即下面代码部分的WordItemDecoration.java类,我补充了许多注释,希望大家看的更轻松
3.如果想了解有关ItemDecoration更多知识,请戳我第一点的链接
4.我在作业要求的基础上进行拓展,做了一个单词查阅目录,我觉得这样作品可能更实用一些。

效果图

代码部分

模型:Word.java
public class Word {private String initial;//此单词的首字母private String english;//单词英文private String chinese;//单词中文public Word(String english, String chinese) {this.english = english;this.chinese = chinese;this.initial = english.substring(0,1).toUpperCase();  //首字母获取}public String getInitial() {return initial;}public void setInitial(String initial) {this.initial = initial;}public String getEnglish() {return english;}public void setEnglish(String english) {this.english = english;}public String getChinese() {return chinese;}public void setChinese(String chinese) {this.chinese = chinese;}
}
自定义适配器:WordAdapter.java
public class WordAdapter extends RecyclerView.Adapter<WordAdapter.ViewHolder> {private Context mContext;//上下文对象private ArrayList<Word> mWords;private LayoutInflater mInflater;public WordAdapter(Context context, ArrayList<Word> words) {mContext = context;mWords = words;mInflater = LayoutInflater.from(mContext);}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = mInflater.inflate(R.layout.word_item, parent, false);ViewHolder holder = new ViewHolder(view);return holder;}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, final int position) {Word word = mWords.get(position);holder.mTextViewWordEnglish.setText(word.getEnglish());holder.mTextViewWordChinese.setText("释义:"+word.getChinese());holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(mContext, "点击的单词是:"+ mWords.get(position).getEnglish()+",中文是:"+mWords.get(position).getChinese(), Toast.LENGTH_SHORT).show();}});}@Overridepublic int getItemCount() {return mWords.size();}class ViewHolder extends RecyclerView.ViewHolder{public TextView mTextViewWordEnglish;public TextView mTextViewWordChinese;public ViewHolder(@NonNull View itemView) {super(itemView);mTextViewWordEnglish = itemView.findViewById(R.id.word_english);mTextViewWordChinese = itemView.findViewById(R.id.word_chinese);}}
}
自定义修饰:WordItemDecoration.java
public class WordItemDecoration extends RecyclerView.ItemDecoration {private ArrayList<Word> mWords;//设置数据private Paint mPaint;//设置画悬浮栏的画笔private Rect mRectBounds;//设置一个矩形,用于画文字private int mTitleHeight;//设置悬浮栏的高度private int mTextSize;//设置文字大小private Context mContext;//设置上下文对象public WordItemDecoration(Context context,ArrayList<Word> words) {mWords = words;mContext = context;//设置悬浮栏高度以及文字大小,为了统一尺寸规格,转换为像素mTitleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45, mContext.getResources().getDisplayMetrics());mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 30, mContext.getResources().getDisplayMetrics());mRectBounds = new Rect();//初始化矩形//初始化画笔mPaint = new Paint();mPaint.setAntiAlias(true);//抗锯齿mPaint.setDither(true);//防抖动mPaint.setTextSize(mTextSize);}/*** Draw any appropriate decorations into the Canvas supplied to the RecyclerView.* Any content drawn by this method will be drawn before the item views are drawn,* and will thus appear underneath the views.** 提供给RecyclerView的画布中绘制任何适当的装饰。* 使用此方法绘制的任何内容都将在绘制项目视图之前绘制,因此将显示在视图下面。** @param c      Canvas to draw into    画布* @param parent RecyclerView this ItemDecoration is drawing into   正在使用装饰的recycle view* @param state  The current state of RecyclerView      即RecyclerView的当前状态*/@Overridepublic void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {/*** 这个方法负责绘制每一个标题,可以实现随着视图移动而移动* */super.onDraw(c, parent, state);//先画出带有背景颜色的矩形条悬浮栏,从哪个位置开始绘制到哪个位置结束,则需要先确定位置,再画文字(即:title)int left = parent.getPaddingLeft();int right = parent.getWidth() - parent.getPaddingRight();//父view(RecyclerView)有padding值,子view有margin值int childCount = parent.getChildCount();//得到的数据其实是一屏可见的item数量并非总item数,再复用for(int i = 0; i < childCount; i++){View child = parent.getChildAt(i);//子view(即:item)有可能设置有margin值,所以需要parms来设置margin值RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();//以及 获取 position 位置int position = params.getViewLayoutPosition();if(position > -1){if(position == 0){//肯定是要绘制一个悬浮栏 以及 悬浮栏内的文字//画矩形悬浮条以及文字drawRectAndText(c, left, right, child, params, position);}else{if(mWords.get(position).getInitial() != null && !mWords.get(position).getInitial().equals(mWords.get(position - 1).getInitial())){//和上一个Tag不一样,说明是另一个新的分组//画矩形悬浮条以及文字drawRectAndText(c, left, right, child, params, position);}else{//说明是一组的,什么也不画,共用同一个首字母}}}}}/*** Draw any appropriate decorations into the Canvas supplied to the RecyclerView.* Any content drawn by this method will be drawn after the item views are drawn* and will thus appear over the views.** 在提供给RecyclerView的画布中绘制任何适当的装饰。* 使用此方法绘制的任何内容都将在绘制项目视图之后绘制,因此将显示在视图上。** @param c      Canvas to draw into* @param parent RecyclerView this ItemDecoration is drawing into* @param state  The current state of RecyclerView.*/@Overridepublic void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {/*** 这个方法可以显示在视图上面,所以可以实现悬浮标题的效果* */super.onDrawOver(c, parent, state);//其实就是获取到每一个可见的位置的item时,执行画顶层悬浮栏int firstPosition = ((LinearLayoutManager)parent.getLayoutManager()).findFirstVisibleItemPosition();View child = parent.findViewHolderForLayoutPosition(firstPosition).itemView;//绘制悬浮栏,其实这里和上面onDraw()绘制方法差不多,只不过,这里面的绘制是在最上层,会悬浮mPaint.setColor(Color.parseColor("#C5E4FD"));c.drawRect(parent.getPaddingLeft(), parent.getPaddingTop(), parent.getRight() - parent.getPaddingRight(), parent.getPaddingTop() + mTitleHeight, mPaint);//绘制文字mPaint.setColor(Color.parseColor("#555555"));mPaint.getTextBounds(mWords.get(firstPosition).getInitial(), 0, mWords.get(firstPosition).getInitial().length(), mRectBounds);c.drawText(mWords.get(firstPosition).getInitial(), child.getPaddingLeft()+40, parent.getPaddingTop() + mTitleHeight - (mTitleHeight/2 - mRectBounds.height()/2), mPaint);}/*** Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies* the number of pixels that the item view should be inset by, similar to padding or margin.* The default implementation sets the bounds of outRect to 0 and returns.** 检索给定项的任何偏移量。outRect<code>outRect</code>的每个字段指定项目视图应插入的像素数,* 类似于填充或边距。默认实现将outRect的边界设置为0并返回** <p>* If this ItemDecoration does not affect the positioning of item views, it should set* all four fields of <code>outRect</code> (left, top, right, bottom) to zero* before returning.* 如果此ItemDecoration不影响项视图的位置,则在返回之前,* 它应将<code>outRect</code>的所有四个字段(左、上、右、下)设置为零。** <p>* If you need to access Adapter for additional data, you can call* {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the* View.* 如果需要访问适配器以获取其他数据,* 可以调用{@link RecyclerView#getChildAdapterPosition(View)}获取查看。*** @param outRect Rect to receive the output.* @param view    The child view to decorate* @param parent  RecyclerView this ItemDecoration is decorating* @param state   The current state of RecyclerView.*/@Overridepublic void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {/*** 这个方法设置预留空间* */super.getItemOffsets(outRect, view, parent, state);//获取position,由本方法的第三段注释可得int position = parent.getChildAdapterPosition(view);if(position > -1){//界面中的所有子viewif(position == 0){//第一个位置,设置悬浮栏//在top留出一段距离outRect.set(0, mTitleHeight, 0, 0);//里面参数表示:左上右下的内边距padding距离}else{//当滑动到某一个item时(position位置)得到首字母,与上一个item对应的首字母不一致( position-1 位置),说明这是下一分组了if(mWords.get(position).getInitial() != null && !mWords.get(position).getInitial().equals(mWords.get(position-1).getInitial())){//在top留出一段距离outRect.set(0, mTitleHeight, 0, 0);}else{//首字母相同说明是同一组的数据,比如都是 A 组下面的数据,那么就不需要再留出空间绘制悬浮栏了,共用同一个 A 组即可outRect.set(0, 0, 0, 0);}}}}/*** 绘制文字和图形* */private void drawRectAndText(Canvas c, int left, int right, View child, RecyclerView.LayoutParams params, int position) {//1、画矩形悬浮栏//item可以有margin值不设置就默认为0,其中child.getTop()表示item距离父recycler view的距离,params.topMargin表示item的外边距,悬浮栏在item上方,那么悬浮栏的bottom就是child.getTop() - params.topMarginmPaint.setColor(Color.parseColor("#C5E4FD"));c.drawRect(left, child.getTop() - params.topMargin - mTitleHeight, right, child.getTop() - params.topMargin, mPaint);//2、画文字mPaint.setColor(Color.parseColor("#555555"));mPaint.getTextBounds(mWords.get(position).getInitial(), 0, mWords.get(position).getInitial().length(), mRectBounds);//将文字放到矩形中,得到Rect的宽高c.drawText(mWords.get(position).getInitial(), child.getPaddingLeft()+40, child.getTop() - params.topMargin - (mTitleHeight / 2 - mRectBounds.height() / 2), mPaint);}}
子布局文件:word_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="60dp"android:background="#E3FAF9"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"><TextViewandroid:id="@+id/word_english"android:text="hello"android:textSize="20dp"android:layout_centerVertical="true"android:layout_marginLeft="20dp"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/word_chinese"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="20dp"android:text="释义:你好"android:layout_width="wrap_content"android:layout_height="wrap_content"/></RelativeLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#BCBCC0"/></LinearLayout>
主Activity:DictionaryActivity.java
public class DictionaryActivity extends Activity {private RecyclerView mRecyclerView;     //定义recycle viewprivate WordAdapter mWordAdapter;       //定义适配器private WordItemDecoration mItemDecoration; //定义装饰private ArrayList<Word> mWords;     //定义数据@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_dictionary);initData();mRecyclerView = findViewById(R.id.dictionary_recycler_view);mRecyclerView.setLayoutManager(new LinearLayoutManager(this));mWordAdapter = new WordAdapter(this,mWords);mRecyclerView.setAdapter(mWordAdapter);mItemDecoration = new WordItemDecoration(this,mWords);mRecyclerView.addItemDecoration(mItemDecoration);}private void initData(){mWords = new ArrayList<>();mWords.add(new Word("absorb","吸收;吸引"));mWords.add(new Word("absurd","荒唐的"));mWords.add(new Word("acceptable","可接受的"));mWords.add(new Word("admit","承认"));mWords.add(new Word("advise","建议"));mWords.add(new Word("advocate","提倡,倡导"));mWords.add(new Word("back","背面,后部"));mWords.add(new Word("bad","坏的,有害的"));mWords.add(new Word("balloon","气球"));mWords.add(new Word("cafe","咖啡馆"));mWords.add(new Word("cake","蛋糕"));mWords.add(new Word("calculation","计算,计算结果"));mWords.add(new Word("calendar","日历,历书"));mWords.add(new Word("cherish","希望"));mWords.add(new Word("damage","损害,毁坏"));mWords.add(new Word("dancer","舞者; 舞女"));mWords.add(new Word("danger","危险"));mWords.add(new Word("each","各,各自"));mWords.add(new Word("earphone","耳机"));mWords.add(new Word("east","东,东方"));mWords.add(new Word("factory","工厂,制造厂"));mWords.add(new Word("fake","假货,膺品"));mWords.add(new Word("garbage",".垃圾,污物,废料"));mWords.add(new Word("gasolene","汽油"));mWords.add(new Word("gather","推测,推断"));}
}
主布局文件:activity_dictionary.xml
<?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="match_parent"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/dictionary_recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"/>
</RelativeLayout>

总结

1.再次感谢这篇博文的帮助
2.码字不易,若有帮助,给个关注和赞呗

安卓作业----慕课移动应用开发作业13之使用自定义RecyclerView.ItemDecoration实现列表悬浮顶部效果相关推荐

  1. 安卓作业----慕课移动应用开发作业15之模仿实现微信界面效果(二)

    此篇综合运用自定义ActionBar.ContextMenu.PopupWindow.Fragment.ViewPager 以及RecyclerView等实现微信页面效果. 同时这也是中国大学慕课移动 ...

  2. HTML期末大作业 ~ 马尔代夫旅游网页设计作业成品 ~ HTML+CSS+JS网页设计期末课程大作业 ~ web前端开发技术 ~ web课程设计网页规划与设计...

    HTML期末大作业 ~ 大学生旅游官网网页设计作业成品 ~ HTML+CSS+JS网页设计期末课程大作业 ~ web前端开发技术 ~ web课程设计网页规划与设计~ 临近期末, 你还在为HTML网页设 ...

  3. HTML+CSS+JS`管理系统网站设计——学生信息管理系统模板 (13页) HTML+CSS+JavaScript html网页设计期末大作业_网页设计平时作业

    HTML5期末大作业:管理系统网站设计--学生信息管理系统模板 (13页) HTML+CSS+JavaScript html网页设计期末大作业_网页设计平时作业 常见网页设计作业题材有 个人. 美食. ...

  4. HTML5期末大作业:管理系统网站设计——学生信息管理系统模板 (13页) HTML+CSS+JavaScript html网页设计期末大作业_网页设计平时作业

    HTML5期末大作业:管理系统网站设计--学生信息管理系统模板 (13页) HTML+CSS+JavaScript html网页设计期末大作业_网页设计平时作业 常见网页设计作业题材有 个人. 美食. ...

  5. 慕课python作业_大学慕课Python编程基础作业答案

    大学慕课Python编程基础作业答案 更多相关问题 A.EnglishnessB.BritishnessC.ScottishnessD.Welshness A.beforeB.followedC.fo ...

  6. educoder平台哪里有答案_作业答案辅导平台下载-作业答案辅导软件下载v2.0 安卓免费版...

    作业答案辅导软件是一款免费搜题的软件,可以帮助大家搜索不会做的题目,不管是哪个年纪哪个科目都可以快速一键拍照搜题,让大家快速获取答案,而且还能给出详细的解题思路和步骤,让大家不光只是抄答案,更能知道如 ...

  7. HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(HTML+CSS)~动漫主题html5网页模板-HTML期末作业课程设计期末大作业动漫主题html5网页模板-html5网页设计源码...

    HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(DIV+CSS) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页要求的总数量太多?没 ...

  8. HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(HTML+CSS)~动漫主题html5网页模板-HTML期末作业课程设计期末大作业动漫主题html5网页模板-html5网页设计源码

    HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(DIV+CSS) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页要求的总数量太多?没 ...

  9. 网页作业HTML+CSS+JS大作业——汽车租赁(47页) 加特效 web期末作业设计网页_汽车大学生网页设计作业成品

    HTML+CSS+JS大作业--汽车租赁(47页) 加特效 web期末作业设计网页_汽车大学生网页设计作业成品 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电商. 宠物. 电器. ...

最新文章

  1. 汇编实验:屏幕窗口程序(代码有较为详细的注释)
  2. 【dll 返回字符串 】2
  3. KVM halt-polling机制分析
  4. csdn下载频道处理公告
  5. 给推荐系统加入先验知识的方法总结
  6. 左岸读书-知识分子的典型
  7. AR涂涂乐⭐三、 C#实现识别图进入扫描框显示绿色,未进入为红色功能
  8. 大话测试数据(二):概念测试数据的获取
  9. consists of 和 is comprised of
  10. 微信小程序 云开发 欢迎登录注册
  11. ARM Cortex-M处理器详解
  12. 什么是开关量,I/O区分详细解答
  13. CSS3选择器-属性选择器
  14. Java程序员最全面的学习路线图
  15. 网易七鱼(杭州)招聘前端
  16. 2742: [HEOI2012]Akai的数学作业
  17. 优先使用TimeUnit类中的sleep()(转自 ImportNew - 刘志军 翻译自 javarevisited)
  18. CAD2010软件安装资料及教程
  19. Linux素描软件,素描学习app-素描学习绘画手机版下载v1.0.0-Linux公社
  20. 输入圆的半径,计算圆的周长与面积

热门文章

  1. 西门子PLC各类通信协议差异对比
  2. SCI与EI收录的外文期刊(计算机类)
  3. python教程是什么课文_python : 新概念英语 课文转为html
  4. sql分组查询的使用
  5. 十二 个经典 Linux 进程管理命令介绍
  6. Linux more 命令使用介绍
  7. 通过青年大学浅析微信x5内核
  8. 数据库乐观锁和悲观锁例子和分析
  9. DFS 简单迷宫及路径打印
  10. 软件行业的技术知识工作者