RecycleView实现首页复杂布局效果(横向和竖向)

1.设计思想
其实当你看到一个布局或界面时,你首先要想怎么实现,用什么控件,当时我第一个想到的就是listview,但listview没有办法实现横向滑动,所以决定用RecycleView,最开始想的是用2个RecycleView(一个横向和一个竖向)。其实这里有一个问题,当滑动竖向RecycleView时,横向RecycleView是不会跟着一起动的,这从用户的角度来看体验肯定不好(开发者可以以用户的角度去开发,这样产品会有更多的用户体验)
在这里插入图片描述
最后的设计是,外面有一个顶层竖向RecycleView,横向RecycleView是其中一个Item。
在这里插入图片描述
1.准备横向RecycleView的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/hrecycleview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"/>

</LinearLayout>

2.准备横向RecycleView的Item的布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="169dp">
    <TextView
        android:id="@+id/text5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/imagemap"
        android:layout_marginLeft="4dp"
        android:layout_marginTop="16dp"
        android:text="精选栏目"
         />

    <ImageView
        android:id="@+id/imagemap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:src="@drawable/shape"
        />

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="239dp"
        android:layout_height="143dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="46dp"
        android:src="#ad226bff" />

    <TextView
        android:id="@+id/text1"
        android:layout_width="215dp"
        android:layout_height="36dp"
        android:layout_alignTop="@id/imageview"
        android:layout_marginLeft="12dp"
        android:layout_alignStart="@id/imageview"
        android:layout_marginTop="54dp"
        android:text="RecycleView实现首页复杂布局效果(横向和竖向)…"
        android:textColor="#ffffffff"/>
    <TextView
        android:id="@+id/text2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/text1"
        android:layout_marginTop="16dp"
        android:layout_alignStart="@id/text1"
        android:layout_marginLeft="2dp"
        android:text="05-04 15:20 | 9999阅"
        android:textColor="#ffffffff"/>

    <View
        android:layout_width="3dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/imageview"/>

</RelativeLayout>

3.设置横向RecycleView的适配器

class SecondAdapter(val datalist1: List<DateMessage>) :
    RecyclerView.Adapter<SecondAdapter.MyViewHolder>() {

    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val text1 = view.findViewById<TextView>(R.id.text1)
        val text2 = view.findViewById<TextView>(R.id.text2)
        val text5 = view.findViewById<TextView>(R.id.text5)
        val imagemap = view.findViewById<ImageView>(R.id.imagemap)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item2, parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        when (position) {
            0 -> {
                holder.text5.visibility = View.VISIBLE
                holder.imagemap.visibility = View.VISIBLE
            }
            else -> {
                holder.text5.visibility = View.GONE
                holder.imagemap.visibility = View.GONE
            }

        }

        val data = datalist1[position]
        holder.apply {
            text1.text = data.title
            text2.text = data.desc
        }

    }


    override fun getItemCount(): Int {
        return datalist1.size
    }


}

这里都是适配器的正常步骤,主要讲解下下面这段代码
when (position) {
0 -> {
holder.text5.visibility = View.VISIBLE
holder.imagemap.visibility = View.VISIBLE
}
else -> {
holder.text5.visibility = View.GONE
holder.imagemap.visibility = View.GONE
}

    }

这是通过判断数据的数组下标,如果是第一个数据,就让2个控件为显示状态,相当于标识这是第一个数据(达到置顶效果),以后的数据不显示这2个控件。

4.写一个数据类

data class MultiItem(
    //用于标识传入的数据是横向RecycleView还是竖向RecycleView的
    var itemType: Int,
    //横向 rv
    var listData: List<DateMessage>? = null,
    //竖向
    var data: DateMessage? = null
)

5.总布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <ImageView
        android:id="@+id/image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="8dp"
        android:src="@mipmap/map1"
        tools:ignore="MissingConstraints"
        />

    <EditText
        android:id="@+id/edittext1"
        android:layout_width="259dp"
        android:layout_height="30dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="7dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="60dp"
        android:background="@null"
        tools:ignore="MissingConstraints" />
    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        app:layout_constraintTop_toTopOf="@id/edittext1"
        app:layout_constraintLeft_toLeftOf="@id/edittext1"
        android:layout_marginTop="7dp"
        android:layout_marginLeft="8dp"
        android:src="@mipmap/map2"/>

    <TextView
        android:id="@+id/text2"
        android:layout_width="116dp"
        android:layout_height="17dp"
        app:layout_constraintTop_toTopOf="@id/edittext1"
        app:layout_constraintLeft_toLeftOf="@id/edittext1"
        android:layout_marginTop="7dp"
        android:layout_marginLeft="30dp"
        android:text="点击搜索精彩内容"
        android:textSize="14sp"/>
    <ImageView
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:src="@mipmap/map3"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="16dp"
       />


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/mainRecycleView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/edittext1"
        android:layout_marginTop="54dp"
        app:layout_constraintBottom_toTopOf="@id/view"
        tools:ignore="MissingConstraints" />


    <View
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="48dp"
         />

    <ImageView
        android:id="@+id/image2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/bottommap1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="25dp"
        android:layout_marginBottom="21dp"
        tools:ignore="MissingConstraints" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="@id/image2"
        app:layout_constraintTop_toBottomOf="@id/image2"
        android:text="首页"
        android:textSize="11sp"
        tools:ignore="MissingConstraints" />

    <ImageView
        android:id="@+id/image3"
         android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:src="@mipmap/boottommap2"
        tools:ignore="MissingConstraints"
        app:layout_constraintLeft_toRightOf="@id/image2"
        android:layout_marginLeft="49dp"
        app:layout_constraintTop_toTopOf="@id/image2"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="@id/image3"
        app:layout_constraintTop_toBottomOf="@id/image3"
        android:text="今日头条"
        android:textSize="11sp"
        tools:ignore="MissingConstraints" />

    <ImageView
        android:id="@+id/image4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/bottommap3"
        app:layout_constraintLeft_toRightOf="@id/image3"
        android:layout_marginLeft="49dp"
        app:layout_constraintTop_toTopOf="@id/image3" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="@id/image4"
        app:layout_constraintTop_toBottomOf="@id/image4"
        android:text="选择"
        android:textSize="11sp"/>
    <ImageView
        android:id="@+id/image5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@id/image4"
        android:layout_marginLeft="49dp"
       app:layout_constraintTop_toTopOf="@id/image4"
        android:src="@mipmap/bottommap4"
        tools:ignore="MissingConstraints" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="@id/image5"
        app:layout_constraintTop_toBottomOf="@id/image5"
        android:text="行情分析"
        android:textSize="11sp"
        tools:ignore="MissingConstraints" />

    <ImageView
        android:id="@+id/image6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:ignore="MissingConstraints"
        android:src="@mipmap/bottommap5"
        app:layout_constraintLeft_toRightOf="@id/image5"
        android:layout_marginLeft="49dp"
        app:layout_constraintTop_toTopOf="@id/image5"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="@id/image6"
        app:layout_constraintTop_toBottomOf="@id/image6"
        android:text="好友会"
        android:textSize="11sp"
        tools:ignore="MissingConstraints" />


</androidx.constraintlayout.widget.ConstraintLayout>

6.顶层RecycleView的适配器

class HeadRefactorAdapter(private val dataList: ArrayList<MultiItem>) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        private const val BANNER = 1
        private const val HORIZONTAL = 2
        private const val VERTICAL = 3
    }


    class HorizontalViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        private val rvContentList = view.findViewById<RecyclerView>(R.id.hrecycleview)

        fun bind(data: List<DateMessage>?) {
            if (data.isNullOrEmpty()) {
                return
            }
            rvContentList.apply {
                layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
                adapter = SecondAdapter(data)
            }
        }
    }

    class VerticalViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        private val text1: TextView = view.findViewById(R.id.text1)
        private val text2: TextView = view.findViewById(R.id.text2)
        private val text3: TextView = view.findViewById(R.id.text3)
        private val image: ImageView = view.findViewById(R.id.image)

        fun bind(listData: DateMessage?) {

            if (listData == null) {
                return
            }

            if (adapterPosition == 0) {
                text2.visibility = View.VISIBLE
            } else {
                text2.visibility = View.GONE
            }

            text1.text = listData.title
            text3.text = listData.desc
            image.setImageResource(listData.image)
        }
    }

    override fun getItemViewType(position: Int): Int {
        return when (dataList[position].itemType) {
            2 -> HORIZONTAL
            else -> VERTICAL
           
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            HORIZONTAL -> HorizontalViewHolder(
                layoutInflater.inflate(
                    R.layout.hrecycleview,
                    parent,
                    false
                )
            )
            VERTICAL -> VerticalViewHolder(
                layoutInflater.inflate(
                    R.layout.item1,
                    parent,
                    false
                )
            )
            else -> {}
        }
    }


    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is HorizontalViewHolder -> {
                holder.bind(dataList[position].listData)
            }
            is VerticalViewHolder -> {
                holder.bind(dataList[position].data)
            }
        }
    }


    override fun getItemCount(): Int {
        return dataList.size
    }

}

这里主要说下 getItemViewType方法,根据传入数据的itemType可以判断出是横向还是竖向的RecycleVIew的数据
override fun getItemViewType(position: Int): Int {
return when (dataList[position].itemType) {
2 -> HORIZONTAL
else -> VERTICAL
}
}

最后在 onCreateViewHolder方法中根据viewType来解析不同的布局,这里如果对 LayoutInflater有疑惑可以看我的另一篇博客LayoutInflater详解
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return when (viewType) {
HORIZONTAL -> HorizontalViewHolder(
layoutInflater.inflate(
R.layout.hrecycleview,
parent,
false
)
)
VERTICAL -> VerticalViewHolder(
layoutInflater.inflate(
R.layout.item1,
parent,
false
)
)
else -> {}
}
}
最后通过onBindViewHolder判断ViewHolder的类型进行数据展示
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is HorizontalViewHolder -> {
holder.bind(dataList[position].listData)
}
is VerticalViewHolder -> {
holder.bind(dataList[position].data)
}
}
}

7.MainActivity的代码

class MainActivity : AppCompatActivity() {
    //RecycleView 数据
    private val mDataList = ArrayList<MultiItem>()
 

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        //add hor
        mDataList.add(MultiItem(1, listData = listOf(
            DateMessage(title = "1RecycleView实现首页复杂布局效果(横向和竖向)…", desc = "05-04 15:20 | 9999阅", image = R.drawable.ic_launcher_background),
            DateMessage(title = "2RecycleView实现首页复杂布局效果(横向和竖向)…", desc = "05-04 15:20 | 9999阅", image = R.drawable.ic_launcher_background),
            DateMessage(title = "11RecycleView实现首页复杂布局效果(横向和竖向)…", desc = "05-04 15:20 | 9999阅", image = R.drawable.ic_launcher_background),
        )))

        //add ver
        repeat(10){
            mDataList.add(MultiItem(1, data = DateMessage(title = "${it}RecycleView实现首页复杂布局效果(横向和竖向)…", desc = "05-04 15:20 | 9999阅", image = R.drawable.ic_launcher_background)))
        }

        val recyclerview = findViewById<RecyclerView>(R.id.mainRecycleView)
        recyclerview.layoutManager = LinearLayoutManager(this)
        recyclerview.adapter = HeadRefactorAdapter(mDataList)
    }

你没有看错,当你把前面的准备好了,其实主代码不多。
这里解释下,MultiItem的第一个参数就是item,用来区分数据
mDataList.add(MultiItem(1, listData = listOf(
DateMessage(title = “1RecycleView实现首页复杂布局效果(横向和竖向)…”, desc = “05-04 15:20 | 9999阅”, image = R.drawable.ic_launcher_background),
DateMessage(title = “2RecycleView实现首页复杂布局效果(横向和竖向)…”, desc = “05-04 15:20 | 9999阅”, image = R.drawable.ic_launcher_background),
DateMessage(title = “11RecycleView实现首页复杂布局效果(横向和竖向)…”, desc = “05-04 15:20 | 9999阅”, image = R.drawable.ic_launcher_background),

最后祝大家周末快乐!

  • 1
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论

打赏作者

橘子先生z

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值