android - Android在每10个项目(如tumblr)的recyclerview下方添加背景视图
问题描述
我正在尝试制作像 tumblr 应用程序这样的回收站视图。你可以在这里看到:https ://streamable.com/s/gpyec/kxvjnz
我的问题是如何在 recyclerview 下方添加视频(或任何可点击的)?我添加了一个项目装饰实现,如下所示:
class RecyclerViewAdItemDecoration(private val func:() -> Unit) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
val position = parent.getChildLayoutPosition(view)
val mLayoutManager = parent.layoutManager
if (mLayoutManager is GridLayoutManager) {
setGridParams(view, position, parent)
} else if (mLayoutManager is LinearLayoutManager) {
setLinearParams(view, position, parent)
}
}
private fun setGridParams(view: View, position: Int, parent: RecyclerView) {
val p = view.layoutParams as ViewGroup.MarginLayoutParams
if (position == 0) {
p.setMargins(0,0,0, 0)
} else if (position >= 10 && (position % 10 == 0 || position % 11 == 0)) {
p.setMargins(0,0,0, parent.height)
func()
} else {
p.setMargins(0,0,0, 0)
}
}
private fun setLinearParams(view: View, position: Int, parent: RecyclerView) {
val p = view.layoutParams as ViewGroup.MarginLayoutParams
if (position == 0) {
p.setMargins(0,0,0, 0)
} else if (position >= 10 && (position % 10 == 0)) {
p.setMargins(0,0,0, parent.height)
func()
} else {
p.setMargins(0,0,0, 0)
}
}
}
这样我可以为背景视图添加足够的空间,但它现在不可点击。我也找不到任何用于这种实现的库。感谢任何帮助。
编辑:为了澄清,我想在回收站视图中的每 10 个项目之后显示背景视频(或任何视图)。就像在链接中的视频中看到的那样,在回收站视图中每 10 个项目之间有一个空格,这也会触发在后台播放视频(在回收站视图下方)
解决方案
在回收站视图中每 10 个项目后立即显示背景视频(或任何视图)。
如果背景视频在每 10 项之后,则表示有一项(第 11 项),它是透明的。
您真正想要的是具有多种视图类型的 recyclerview。
使用RelativeLayout
允许activity_main.xml
将视图放置在其他视图之上(在 Z 轴上)。
例如:RecyclerView
是这里的最高视图。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:focusable="true">
<View
android:id="@+id/ad"
android:background="@color/colorAccent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_posts"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
为两种类型的回收站视图类型创建两个项目布局
前任:
item_normal.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:id="@+id/tv_post"
tools:text="Post"
android:background="@android:color/white"
android:textSize="32sp"
android:gravity="center_horizontal|center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
item_transparent.xml(其中布局背景是透明的,可以看到表面区域下方的视图)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"/>
item_transparent中的设置android:clickable=false
不会停止触发透明项目上的点击事件,因此使用接口的通信流,当点击透明项目时将另一个视图(广告)带到前面。
MainActivity.kt
class MainActivity : AppCompatActivity(), RvAdpater.OnItemClick {
private lateinit var adView: View
private lateinit var rvPosts: RecyclerView
override fun onClick() {
bringAdFront()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
rvPosts = findViewById(R.id.rv_posts)
rvPosts.layoutManager = LinearLayoutManager(this)
val rvAdpater = RvAdpater()
rvAdpater.setListener(this)
rvPosts.adapter = rvAdpater
}
private fun bringAdFront() {
adView = findViewById<View>(R.id.ad)
adView.bringToFront()
}
override fun onBackPressed() {
// to go back to the normal recycler view when back button is pressed
val parent = rvPosts.parent as ViewGroup
parent.removeAllViews()
parent.addView(adView, 0)
parent.addView(rvPosts, 1)
}
}
RvAdapter.kt
const val TAG = "RvAdpater"
class RvAdpater : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private lateinit var listener:OnItemClick
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val viewNormal = LayoutInflater.from(parent.context).inflate(R.layout.item_normal, parent, false)
val viewTransparent = LayoutInflater.from(parent.context).inflate(R.layout.item_transparent, parent, false)
return when(viewType){
0 -> NormalViewHolder(viewNormal)
2 -> TransparentViewHolder(viewTransparent)
else -> NormalViewHolder(viewNormal)
}
}
override fun getItemCount(): Int = 10
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(getItemViewType(position)){
0 -> {
val normalHolder = holder as NormalViewHolder
normalHolder.tv.text = "Post"
normalHolder.itemView.setOnClickListener {
Log.d(TAG, "Clicked on Normal item")
}
}
2 -> {
val transparentHolder = holder as TransparentViewHolder
transparentHolder.itemView.setOnClickListener {
listener.onClick()
}
}
}
}
fun setListener(onItem:OnItemClick){
listener = onItem
}
interface OnItemClick{
fun onClick()
}
override fun getItemViewType(position: Int): Int = position % 2 * 2
class NormalViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val tv:TextView = itemView.findViewById(R.id.tv_post)
}
class TransparentViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
}
查看repo以获取工作示例
为了处理多种视图类型,您可以使用Epoxy库。
推荐阅读
- ios - AVAudioSession 与 WKWebview 混合
- c++ - 通过不同线程读写QTcpSockets抛出QSocketNotifier警告
- powershell - 关于 Powershell DSC 和节点的新手问题
- scala - Spark如何传递Scala对象进行映射转换
- android - 如何将托管在我的服务器上的 OpenMapTiles 用于 android kotlin
- typescript - 如何在并发测试中获得独特的玩笑间谍?
- android - 使用 Braintree SDK 在 Android 中支付 PayPal
- python - 使用多个单词作为不和谐前缀,中间有空格
- c# - 最小起订量设置使用构造函数参数获取 dbContext
- javascript - 如何从 JS 数组中过滤数据并创建另一个 JS 数组