当前位置: 首页 > news >正文

View->LinearLayout中动态添加多行多列的ItemView(来源RecyclerView中的ViewHodler)

XML文件

  • ItemView布局R.layout.layout_item_view
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"><FrameLayoutandroid:id="@+id/fl"android:layout_width="46dp"android:layout_height="46dp"android:background="@drawable/shape_dmt_bg"android:layout_margin="3dp"><ImageViewandroid:id="@+id/iv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"/></FrameLayout>
</FrameLayout>
  • Activity布局R.layout.activity_main
<?xml version="1.0" encoding="utf-8"?>
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/holo_red_light"><LinearLayoutandroid:id="@+id/list"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:paddingLeft="22dp"android:paddingRight="22dp"android:background="@color/black"android:orientation="vertical"></LinearLayout>
</FrameLayout>

RecyclerView的相关类

  • ViewHolder代码
class MyViewHolder(itemView: View, private val mListener: OnItemSelectListener?) : RecyclerView.ViewHolder(itemView) , MyListViewHelper.ISelectable {private var mIv: ImageView? = nullprivate var mFl: FrameLayout? = nullfun bind(index: Int, type: MyType) {mIv = itemView.findViewById(R.id.iv)mFl = itemView.findViewById(R.id.fl)mIv?.setImageResource(type.icon)itemView.setOnClickListener {mListener?.onItemSelect(index, type)}}override fun select() {mFl?.setBackgroundResource(R.drawable.shape_dmt_bg_on)mIv?.setColorFilter(Color.parseColor("#FFFFD800"))}override fun unselect() {mFl?.setBackgroundResource(R.drawable.shape_dmt_bg)mIv?.colorFilter = null}interface OnItemSelectListener {fun onItemSelect(index: Int, type: MyType)}
}data class MyType (val icon: Int, val type: TYPE) {enum class TYPE {A, B, C,}
}
  • Adapter代码
class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {private val mData = ArrayList<MyType>().apply {add(MyType(R.drawable.ic_rect, MyType.TYPE.A))add(MyType(R.drawable.ic_crop_free, MyType.TYPE.B))add(MyType(R.drawable.ic_icon_crop_rotate, MyType.TYPE.C))add(MyType(R.drawable.ic_rect, MyType.TYPE.A))add(MyType(R.drawable.ic_crop_free, MyType.TYPE.B))add(MyType(R.drawable.ic_icon_crop_rotate, MyType.TYPE.C))add(MyType(R.drawable.ic_rect, MyType.TYPE.A))add(MyType(R.drawable.ic_crop_free, MyType.TYPE.B))add(MyType(R.drawable.ic_icon_crop_rotate, MyType.TYPE.C))add(MyType(R.drawable.ic_crop_free, MyType.TYPE.B))add(MyType(R.drawable.ic_icon_crop_rotate, MyType.TYPE.C))}private var mSelectedListener: MyViewHolder.OnItemSelectListener? = nullfun setOnItemSelectListener(listener: MyViewHolder.OnItemSelectListener) {mSelectedListener = listener}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_item_view, parent, false)return MyViewHolder(itemView, mSelectedListener)}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {holder.bind(position, mData[position])}override fun getItemCount(): Int {return mData.size}
}

动态添加ItemView的工具类

  • 传入RecyclerViewAdapter,在父View中动态添加RecyclerView的每个ItemView(依次调用AdapteronCreateViewHolder方法和onBindViewHolder方法)
class MyListViewHelper(private val mContext : Context, private val mColumns : Int = 5, private val mMarginBottom : Float = 20f) {private val mViews = HashMap<Int, RecyclerView.ViewHolder>()private var mSelectedIndex = -1fun <T : RecyclerView.ViewHolder> setAdapter(parentView: ViewGroup, adapter: RecyclerView.Adapter<T>){// 确定要添加的行数val rows = Math.ceil(((adapter.itemCount / (mColumns * 1f)).toDouble())).toInt() // 向上取整,确定最大行数Log.d("yang", "adapter.itemCount = ${adapter.itemCount}, rows = $rows")for (row in 0 until rows) {val childLinearLayout = LinearLayout(parentView.context).apply {orientation = LinearLayout.HORIZONTAL}val params = ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT).apply {bottomMargin = dpToPx(mContext, mMarginBottom).toInt()}// 每一行的Linearlayout开始添加ItemViewfor (column in 0 until mColumns) {val index = row * mColumns + columnval viewHolder: RecyclerView.ViewHolderif (index < adapter.itemCount) {viewHolder = adapter.createViewHolder(childLinearLayout, adapter.getItemViewType(index))adapter.bindViewHolder(viewHolder, index)mViews[index] = viewHolder} else {// 如果不足一行,补充空白的占位ItemViewviewHolder = adapter.createViewHolder(childLinearLayout, 0)viewHolder.itemView.visibility = View.INVISIBLE}val itemViewParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {leftMargin = 50rightMargin = 50}childLinearLayout.addView(viewHolder.itemView, itemViewParams)}// 添加到父布局的LinearLayout中childLinearLayout.gravity = Gravity.CENTER_HORIZONTALparentView.addView(childLinearLayout, params)}}fun performSelect(index: Int) {if (index == mSelectedIndex) {return}val vh = mViews[index] ?: returnvh.itemView.performClick()}fun select(index: Int) {if (index == mSelectedIndex) {return}val vh = mViews[index] ?: returnval oldVH = mViews[mSelectedIndex](oldVH as ISelectable?)?.unselect()(vh as ISelectable).select()mSelectedIndex = index}interface ISelectable {fun select()fun unselect()}
}

Activity代码

class MainActivity : AppCompatActivity() {private lateinit var mList: ViewGroupprivate lateinit var mListHelper: MyListViewHelperprivate lateinit var mAdapter : MyAdapteroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)mList = findViewById(R.id.list)mAdapter = MyAdapter()mAdapter.setOnItemSelectListener(object : MyViewHolder.OnItemSelectListener {override fun onItemSelect(index: Int, type: MyType) {mListHelper.select(index)}})mListHelper = MyListViewHelper(this, 3)mListHelper.setAdapter(mList, mAdapter)mListHelper.performSelect(0)}
}

效果图

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Docker-compose】搭建php 环境
  • stm32h743 阿波罗v2 NetXduo http server CubeIDE+CubeMX
  • ABeam News | FY25 ABeam德硕大中华区入社式,飞往崭新航向!
  • MD5加密和注册页面的编写
  • 【Vue3】export, import, export default
  • 编程语言及系统发展:探索计算世界的演进之旅
  • 模板方法模式的实现
  • 昇思25天学习打卡营第17天|基于MobileNetv2的垃圾分类
  • 标签印刷检测,如何做到百分百准确?
  • mysql中select语句的执行顺序
  • 全网最炸裂的5款SD涩涩模型!身体真的是越来越不好了!建议收藏,晚上自己偷偷打开看!
  • p14数组(2)
  • CSS 【实用教程】(2024最新版)
  • 电商出海第一步,云手机或成重要因素
  • 本地部署私人知识库的大模型!Llama 3 + RAG!
  • [译]如何构建服务器端web组件,为何要构建?
  • gops —— Go 程序诊断分析工具
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • javascript 哈希表
  • javascript 总结(常用工具类的封装)
  • 构建二叉树进行数值数组的去重及优化
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 如何使用 JavaScript 解析 URL
  • 我这样减少了26.5M Java内存!
  • 限制Java线程池运行线程以及等待线程数量的策略
  • ​渐进式Web应用PWA的未来
  • #QT(QCharts绘制曲线)
  • $NOIp2018$劝退记
  • (160)时序收敛--->(10)时序收敛十
  • (2)(2.10) LTM telemetry
  • (3)nginx 配置(nginx.conf)
  • (42)STM32——LCD显示屏实验笔记
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (WSI分类)WSI分类文献小综述 2024
  • (zt)最盛行的警世狂言(爆笑)
  • (八)Flask之app.route装饰器函数的参数
  • (十)Flink Table API 和 SQL 基本概念
  • (五)关系数据库标准语言SQL
  • (一)python发送HTTP 请求的两种方式(get和post )
  • .NET CLR Hosting 简介
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .Net环境下的缓存技术介绍
  • .sh
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • @Transient注解
  • [ solr入门 ] - 利用solrJ进行检索
  • [Algorithm][综合训练][体育课测验(二)][合唱队形][宵暗的妖怪]详细讲解
  • [boost]使用boost::function和boost::bind产生的down机一例
  • [BZOJ4337][BJOI2015]树的同构(树的最小表示法)
  • [c++] 自写 MyString 类
  • [CareerCup] 6.1 Find Heavy Bottle 寻找重瓶子
  • [CLIP-VIT-L + Qwen] 多模态大模型源码阅读 - 语言模型篇(4)
  • [DDR5 Jedec 4-1] 预充电命令 Precharge
  • [element-ui] el-dialog 中的内容没有预先加载,因此无法获得内部元素的ref 的解决方案
  • [Go 微服务] Kratos 验证码业务