文章目录

  • 1. 前言
  • 2. 基础环境——实现RecyclerView的网格布局
  • 3. 自定义ImageView
  • 3. 后记

1. 前言

拟定实现效果部分为下图的歌单列表部分,也就是图中红线框出来的部分。为了方便这里使用RecyclerView来进行实现,对于图中所需要的正方形图片显示控件,这里就考虑使用自定义的ImageView

2. 基础环境——实现RecyclerView的网格布局

首先在xml文件中定义RecyclerView

<androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/fx_music_song_list_below_time"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="8dp"android:paddingRight="8dp"/>

然后定义每个item的布局显示样式的布局文件,这里我定义为fx_music_song_list_below_time_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"xmlns:app="http://schemas.android.com/apk/res-auto"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><!-- 自定义ImageView--><com.weizu.mymusicdemo.customcomponents.RoundEqualWidthImageViewandroid:id="@+id/fx_music_song_list_below_time_item_img"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@drawable/fx_music_rmdt_play"android:background="@drawable/fx_music_round_bg"android:scaleType="centerCrop"app:radius="8dp"/><LinearLayoutandroid:layout_width="200dp"android:layout_height="25dp"android:gravity="center"android:orientation="horizontal"android:layout_alignBottom="@id/fx_music_song_list_below_time_item_img"><ImageViewandroid:layout_width="0dp"android:layout_height="20dp"android:layout_weight="1"android:src="@drawable/fx_music_song_list_below_time_item_play"/><TextViewandroid:id="@+id/fx_music_song_list_below_time_item_play_number"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"android:text="123万"android:textColor="@color/white"android:gravity="left|center_vertical"android:textSize="12sp"/></LinearLayout></RelativeLayout><TextViewandroid:id="@+id/fx_music_song_list_below_time_item_intro"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="8dp"android:text="123万"android:textSize="12sp"android:textColor="@color/black"/></LinearLayout>

最后进行定义一个适配器,用来加载数据到具体的item项:

public class FxPageMusicSongListBelowTimeRecycleViewAdapter<T extends FxPageSongListItemBean> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {private Context mContext;private int mRescourseId;private List<T> mData;public FxPageMusicSongListBelowTimeRecycleViewAdapter(Context context, int rescourseId, List<T> data) {this.mContext = context;this.mRescourseId = rescourseId;this.mData = data;}@NonNull@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {// 实例化对应的子项xml文件View rootView = LayoutInflater.from(mContext).inflate(mRescourseId, parent, false);return new MyViewHolder(rootView);}@Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {MyViewHolder myViewHolder = (MyViewHolder) holder;// 设置数据到每个子项FxPageSongListItemBean bean = (FxPageSongListItemBean) mData.get(position);Glide.with(mContext).load(bean.getCoverImageUrl()).into(myViewHolder.coverImageView);myViewHolder.playNumber.setText(bean.getPlayNumber());myViewHolder.introduce.setText(bean.getIntroduceInfo());}@Overridepublic int getItemCount() {return mData.size();}static class MyViewHolder extends RecyclerView.ViewHolder{private ImageView coverImageView;private TextView playNumber;private TextView introduce;public MyViewHolder(@NonNull View itemView) {super(itemView);coverImageView = itemView.findViewById(R.id.fx_music_song_list_below_time_item_img);playNumber = itemView.findViewById(R.id.fx_music_song_list_below_time_item_play_number);introduce = itemView.findViewById(R.id.fx_music_song_list_below_time_item_intro);}}
}

当然最后一步就是使用了,就是实例化适配器对象,得到RecyclerView实例。然后设置网格布局管理器,并简单设置一下间距:

FxPageMusicSongListBelowTimeRecycleViewAdapter<FxPageSongListItemBean> adapter =new FxPageMusicSongListBelowTimeRecycleViewAdapter<>(getContext(), R.layout.fx_music_song_list_below_time_item, beans);GridLayoutManager manager = new GridLayoutManager(getContext(), 3);
recyclerView.setLayoutManager(manager);
// 设置Item的间距
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {@Overridepublic void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {super.getItemOffsets(outRect, view, parent, state);outRect.left = 8;outRect.right = 8;outRect.top = 16;outRect.bottom = 16;}
});
recyclerView.setAdapter(adapter);

效果:

但是很容易发现一点就是,每个图片的底部的显示的人数部分这里看不清。其实观看原图可以发现在酷狗音乐中其实是使用了一个暗色的背景在底部。所以这里我将在自定义ImageView的时候,加上一层暗色的背景渐变。那么,接下来就进入本篇博客的正题,即:自定义ImageView控件。

3. 自定义ImageView

其实在前面的xml布局文件中可以看见,这里自定义的ImageViewcom.weizu.mymusicdemo.customcomponents.RoundEqualWidthImageView类,且圆角半径radius为自定义属性。

  • 圆角可以使用canvas的裁剪工具来实现;
  • 遮罩层的暗色渐变可以使用在其上再绘制一张图片;
  • 在测量的时候设置宽度一样,就可以得到正方形;
  • 设置缩放类型,使它中心裁剪,填充满;

那么可以定义为:

public class RoundEqualWidthImageView extends AppCompatImageView {private int width;private int height;private int roundDp;public RoundEqualWidthImageView(Context context) {super(context);}public RoundEqualWidthImageView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);initData(context, attrs);}private void initData(Context context, AttributeSet attrs) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.roundEqualWidthImageView);// 默认为直角,没有弧度roundDp = array.getDimensionPixelOffset(R.styleable.roundEqualWidthImageView_radius, 0);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);width = getWidth();height = getHeight();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, widthMeasureSpec);  // 设置宽度一样}@Overrideprotected void onDraw(Canvas canvas) {// 设置缩放类型setScaleType(ScaleType.CENTER_CROP);if (width < roundDp || height < roundDp) roundDp = 5;Path path = new Path();// 四个圆角裁剪path.moveTo(roundDp, 0);path.lineTo(width - roundDp, 0);path.quadTo(width, 0, width, roundDp);path.lineTo(width, height - roundDp);path.quadTo(width, height, width - roundDp, height);path.lineTo(roundDp, height);path.quadTo(0, height, 0, height - roundDp);path.lineTo(0, roundDp);path.quadTo(0, 0, roundDp, 0);canvas.clipPath(path);super.onDraw(canvas);// 绘制暗色渐变Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fx_music_song_list_below_time_item_cover_bg, null);canvas.drawBitmap(bitmap, 0, 0, null);}
}

对于另一个圆角半径属性,这里新建一个values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="roundEqualWidthImageView"><attr name="radius" format="dimension"/></declare-styleable></resources>

那么在使用的时候,就简单指定基本属性和圆角半径即可:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"xmlns:app="http://schemas.android.com/apk/res-auto"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><com.weizu.mymusicdemo.customcomponents.RoundEqualWidthImageViewandroid:id="@+id/fx_music_song_list_below_time_item_img"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@drawable/fx_music_rmdt_play"app:radius="8dp"/>...</RelativeLayout>
</LinearLayout>

现在效果:

同样的为了记录,这部分代码我上传到了github:mymusicdemo-03。

3. 后记

在加载图片的时候使用的Glide的加载 ,突然想起了之前自己写的部分单/多线程断点下载的简单封装,感觉空了可以研究下如何继续深入下去。


References

  • mymusicdemo-03

Android插件化开发指南——实践之仿酷狗音乐首页(自定义ImageView控件)相关推荐

  1. Android插件化开发指南——实践之仿酷狗音乐首页

    文章目录 1. 前言 2. 布局分析 3. 底部导航栏的实现 4. 顶部导航栏和ViewPager+Fragment的关联 1. 前言 在Android插件化开发指南--2.15 实现一个音乐播放器A ...

  2. Android插件化开发指南——实践之Activity转场效果(仿酷狗音乐启动页)

    文章目录 1. 前言 2. Activity退出动画 2.1 简单使用 2.2 overridePendingTransition 3. 后记 1. 前言 在Android插件化开发指南--2.15 ...

  3. Android插件化开发指南——Hook技术(一)【长文】

    文章目录 1. 前言 2. 将外部dex加载到宿主app的dexElements中 3. 插件中四大组件的调用思路 4. Hook 2.1 对startActivity进行Hook 2.1.1 AMS ...

  4. Android插件化开发指南——Hook技术(二)

    文章目录 1. 前言 2. 分析 3. 加载外部资源文件代码 4. References 1. 前言 在上篇Android插件化开发指南--Hook技术(一)[长文]中提到最终的效果其实在插件中的Ma ...

  5. Android插件化开发指南——插件化技术简介

    文章目录 1. 为什么需要插件化技术 2. 插件化技术的历史 3. 插件化实现思路 3.1 InfoQ:您在 GMTC 中的议题叫做<Android 插件化:从入门到放弃>,请问这个标题代 ...

  6. Android插件化开发之解决OpenAtlas组件在宿主的注冊问题

    Android插件化开发之解决OpenAtlas组件在宿主的注冊问题 OpenAtlas有一个问题,就是四大组件必须在Manifest文件里进行注冊,那么就必定带来一个问题,插件中的组件都要反复在宿主 ...

  7. Android插件化开发之动态加载本地皮肤包进行换肤

    Android插件化开发之动态加载本地皮肤包进行换肤 前言: 本文主要讲解如何用开源换肤框架 android-skin-loader-lib来实现加载本地皮肤包文件进行换肤,具体可自行参考框架原理进行 ...

  8. 【游戏开发创新】手把手教你使用Unity制作一个高仿酷狗音乐播放器,滨崎步,旋律起,爷青回(声音可视化 | 频谱 | Audio)

    文章目录 一.前言 二.获取UI素材 三.使用UGUI制作界面 1.界面布局 2.账号圆形头像 3.搜索框 4.调节UI层 5.黑色按钮悬浮高亮效果 6.纯文字按钮 7.滚动列表自适应 8.歌名与视频 ...

  9. 仿酷狗音乐播放器开发日志二十一 开发动态调色板控件(附源码)

    转载请说明原出处,谢谢~~ 上一篇仿酷狗日志结束后,整个换肤功能就只剩下调色板功能没有做了,我本以为会很简单,但是研究了酷狗的调色板功能后发现不是那么简单的事情.首先看一下酷狗的调色板的样子: 我原本 ...

最新文章

  1. 【廖雪峰python入门笔记】list删除元素_pop()
  2. 【免费】网易开卖CTO啦——开发者踩坑专场
  3. 隐藏文件真实下载地址(支持超大文件)源码
  4. NIPS2018 Workshop一览
  5. MicroNets:更小更快更好的MicroNet,三大CV任务都秒杀MobileNetV3
  6. 如何不重启服务,把编译类放入正在运行的服务中去
  7. 各层作用_OSI模型中各层在通信中的作用
  8. [Python] 探索性编程与idleX
  9. jQuery基础集锦——插件开发
  10. matlab动态图阿基米德螺旋,魔兽世界M基尔加丹阿基米德螺旋线之Matlab动图!国服加油...
  11. 2019区块链概念股龙头
  12. 第一课:句子成分与基本句型
  13. 计算机应用技术计算问题,汉语组块计算的若干分析-计算机应用技术专业论文.docx...
  14. IBM MQ运维常用命令
  15. linux下tar.gz、tar、bz2、zip等命令小结
  16. Vscode——编辑setting.json,但显示“无法在只读编辑器中编辑”的一种解决方法
  17. HTML5中的canvas(画布)
  18. spark报Got an error when resolving hostNames. Falling back to /default-rack for all
  19. android重签名闪退,360加固保加固完之后重新签名的包运行闪退,求大神帮忙解答...
  20. 精选教程!从iTunes备份中恢复QQ聊天记录的详细操作

热门文章

  1. 计算机专业大学排名评估,计算机专业全国高校排名top100出炉,根据第四轮学科评估...
  2. 2021年广东省电力市场运行现状分析:累计交易电量2951.7亿千瓦时[图]
  3. 乔治梅森大学计算机工程博士,乔治梅森大学计算机工程硕士排名第62(2020年TFE Times排名)...
  4. 曲柄滑块机构运动分析和参数优化
  5. 【3D商城】添加商品产品模型
  6. 服装3D商城虚拟企业展厅解决方案
  7. js 每隔2秒循环调用
  8. 机械设计软件CAD系统—文件格式基础知识
  9. 勒索软件:帮派联手,拍卖被盗数据
  10. 靠做期货挣钱不切实际?那为什么有这么多人靠这个行业挣钱养家?