此博客通过RecyclerView、TextView等进行界面布局,使用自定义RecyclerView.Adapter、RecyclerViewAdapter.ViewHolder以及自定义RecyclerView.ItemDecoration实现分组列表以及悬浮顶部效果 同时这也是中国大学慕课移动终端应用开发的网课作业13,我会持续更新我的作业,如果有需要关注一下吧 1.非常感谢此篇博文以及博文作者,详细介绍了RecyclerView.ItemDecoration的用法,让我少花了很多时间。 1.再次感谢这篇博文的帮助说明
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 @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = mInflater.inflate(R.layout.word_item, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public 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() { @Override public void onClick(View v) { Toast.makeText(mContext, "点击的单词是:"+ mWords.get(position).getEnglish()+",中文是:"+mWords.get(position).getChinese(), Toast.LENGTH_SHORT).show(); } }); } @Override public 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的当前状态 */ @Override public 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. */ @Override public 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. */ @Override public 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){//界面中的所有子view if(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.topMargin mPaint.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="https://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="60dp" android:background="#E3FAF9"> <RelativeLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > <TextView android: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"/> <TextView android: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> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#BCBCC0"/> </LinearLayout>
主Activity:DictionaryActivity.java
public class DictionaryActivity extends Activity { private RecyclerView mRecyclerView; //定义recycle view private WordAdapter mWordAdapter; //定义适配器 private WordItemDecoration mItemDecoration; //定义装饰 private ArrayList<Word> mWords; //定义数据 @Override protected 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="https://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/dictionary_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
总结
2.码字不易,若有帮助,给个关注和赞呗
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算