Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能

这篇具有很好参考价值的文章主要介绍了Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实现效果

指示器样式第二个gif是用模拟器的,gif有小问题,第三个截图没问题

Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能

二、引入依赖

appbuild.gradle在添加以下代码
1、implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6',这个里面带的适配器,直接调用就即可
这依赖包还需要得到要添加,在Projectbuild.gradle在添加以下代码,不添加就不行

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }//加上
    }
}

三、源码实现

1、指示器样式(自定义类)

自定义RecyclerViewIndicator.kt

package com.example.myapplication3.view

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
import androidx.annotation.Nullable
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication3.R

class RecyclerViewIndicator @JvmOverloads constructor(
    context: Context,
    @Nullable attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    FrameLayout(context, attrs, defStyleAttr) {
//    private val rootView: View
    private val mRootView: View
    private val indView: View
    var indViewWidth = 0
    var indViewHeight = 0
    var rate = 0f

    init {
        val root = inflate(context, R.layout.app_viewpager_indicator, this)
        mRootView = root.findViewById<View>(R.id.root)
        indView = root.findViewById<View>(R.id.ind_view)
    }

    /**
     * 绑定recyclerView
     * @param recyclerView
     * @param orientation 排列方向
     *
     * 这里用到的recyclerView的三个方法
     * computeHorizontalScrollExtent/computeVerticalScrollExtent 当前显示在屏幕上的总长度
     * computeHorizontalScrollOffset/computeVerticalScrollOffset 当前滑动的总长度
     * computeHorizontalScrollRange/computeVerticalScrollRange recylerView内部的总长度
     */
    fun setWithRecyclerView(recyclerView: RecyclerView, orientation: Int) {
        val isHorizontal = orientation == RecyclerView.HORIZONTAL
        mRootView.post(Runnable {
            val scrollRange =
                (if (isHorizontal) recyclerView.computeHorizontalScrollRange() else recyclerView.computeVerticalScrollRange()).toFloat()
            val scrollExtent =
                (if (isHorizontal) recyclerView.computeHorizontalScrollExtent() else recyclerView.computeVerticalScrollExtent()).toFloat()
            val layoutParams = indView.layoutParams as LayoutParams
            if (isHorizontal) {
                //算出比例
                rate = width.toFloat() / scrollRange
                //由显示在屏幕上的总长度算出滑块长度
                indViewWidth = (scrollExtent * rate).toInt()
                layoutParams.height = LayoutParams.MATCH_PARENT
                layoutParams.width = indViewWidth
            } else {
                rate = height.toFloat() / scrollRange
                layoutParams.width = LayoutParams.MATCH_PARENT
                indViewHeight = (scrollExtent * rate).toInt()
                layoutParams.height = indViewHeight
            }
            indView.layoutParams = layoutParams
        })
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val scrollOffset =
                    if (isHorizontal) recyclerView.computeHorizontalScrollOffset() else recyclerView.computeVerticalScrollOffset()
                //由recyclerView滑动距离算出滑块移动距咯
                if (isHorizontal) {
                    val left = (scrollOffset * rate).toInt()
                    indView.layout(left, indView.top, left + indViewWidth, indView.bottom)
                } else {
                    val top = (scrollOffset * rate).toInt()
                    indView.layout(indView.left, top, indView.right, top + indViewHeight)
                }
            }
        })
    }
}

指示器布局app_viewpager_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/shape_indicator_radius_gray">

    <View
        android:id="@+id/ind_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/shape_indicator_radius_yellow"/>
</FrameLayout>

指示器背景灰色shape_indicator_radius_gray.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/gray" />
    <corners android:radius="50dp" />
</shape>

colors.xml中添加的颜色

<color name="gray">#959595</color><!--  灰色  -->
<color name="orange">#F94E18</color><!--  桔色  -->
<color name="translucent_red">#20EA5A5A</color> <!--  半透明红  -->

指示器桔色shape_indicator_radius_orange.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/orange" />
    <corners android:radius="50dp" />
</shape>

2、RecyclerView适配器

RvAdapter.kt

package com.example.myapplication3.adapter

import android.widget.TextView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R

class RvAdapter(layoutResId: Int = R.layout.rv_item) : BaseQuickAdapter<String, BaseViewHolder>(layoutResId) {

    override fun convert(holder: BaseViewHolder, item: String) {
        val itemTv = holder.getView<TextView>(R.id.item_tv)
        itemTv.text = item
    }
}

rv_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/xx"
    android:layout_width="70dp"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_c" />

    <TextView
        android:id="@+id/item_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试"/>
</LinearLayout>

Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能

3、主视图实现

MainActivity.kt

package com.example.myapplication3

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myapplication3.adapter.RvAdapter
import kotlinx.android.synthetic.main.activity_main.indicator
import kotlinx.android.synthetic.main.activity_main.recyclerView

class MainActivity : AppCompatActivity() {

    private val mAdapter by lazy {
        RvAdapter().apply {
//            setOnItemLongClickListener(activity)
        }
    }

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

    private fun init() {

        val itemList: MutableList<String> = ArrayList()
        for (i in 0..12) {
            itemList.add("测试$i")
        }
        val layoutManager = LinearLayoutManager(this@MainActivity)
        layoutManager.orientation = LinearLayoutManager.HORIZONTAL
        recyclerView.layoutManager = layoutManager
        recyclerView.adapter = mAdapter
        mAdapter.setList(itemList)
        indicator.setWithRecyclerView(recyclerView,LinearLayoutManager.HORIZONTAL)
    }
}

activity_main.xml

<?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"
    android:layout_gravity="center"
    android:layout_margin="10dp"
    android:background="@drawable/shape_indicator_radius_white"
    android:orientation="vertical"
    android:padding="10dp">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="15dp"
        android:gravity="center">

        <com.example.myapplication3.view.RecyclerViewIndicator
            android:id="@+id/indicator"
            android:layout_width="55dp"
            android:layout_height="4dp" />
    </LinearLayout>
</LinearLayout>

Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能
布局圆角样式shape_indicator_radius_white.xml文章来源地址https://www.toymoban.com/news/detail-492869.html

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/translucent_red"/>
    <corners android:radius="10dp" />
</shape>

到了这里,关于Android kotlin 实现仿淘宝RecyclerView和对应下的指示器功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b)

    对 Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)-CSDN博客 改进,用Glide批量把Bitmap加载出来,然后在RecyclerView成片成堆的绘制Canvas,此种实现是RecyclerView加载多宫格图片展示,卡顿丢帧最低的一种实现,上下滑动流畅。 Android GridLayoutManager Glide批量

    2024年04月25日
    浏览(44)
  • Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)

    有一个遗留问题,每行加载16张图片,以行为原子单位。后面可以考虑另外一种实现,group分组标签单独占一行,图片可以一大片一大片的占据多行,每行16张。 Android Glide自定义AppCompatImageView切分成若干小格子,每个小格子onDraw绘制Bitmap,Kotlin(1)_android appcompatimageview-CSDN博

    2024年04月17日
    浏览(44)
  • Android Glide in RecyclerView,only load visible item when page return,Kotlin

    base on this article: Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin_zhangphil的博客-CSDN博客 【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用

    2024年02月09日
    浏览(45)
  • Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

    build.gradle文件: 如果手机图片很多,假设已经将全部图片装入宫格的列表,在快速上下滑动过程中,由于glide会累积每一个图片的加载任务,如果图片比较大,上下滑动时间又很长,那么累积任务会很严重,导致异常发生,实现在RecyclerView切入后台(或不可见)时候,然后再

    2024年02月10日
    浏览(49)
  • Android Canvas画布saveLayer与对应restoreToCount,Kotlin

              如果把 全部注释掉,则为                   Android Canvas状态save与restore,Kotlin-CSDN博客 文章浏览阅读218次,点赞3次,收藏3次。文章浏览阅读9.6k次。文章浏览阅读1.8k次。/*Java代码 将Drawable转化为Bitmap */ Bitmap drawableToBitmap(Drawable drawable) { int width = drawable.getIntrins

    2024年02月04日
    浏览(30)
  • Android开发中,JDK版本,Gradle版本,Kotlin插件与Kotlin版本等各自对应关系

    一、Gradle版本和Java版本对应关系 二、Gradle版本和Kotlin版本对应关系 三、Gradle版本和Gradle插件版本匹配关系 可以在Android Studio的 File Project Structure Project 菜单中指定插件版本,也可以在顶级 build.gradle 文件中进行修改

    2024年03月15日
    浏览(68)
  • Android生态下的Kotlin有哪些更新#GoogleIO 2023

    自Android官方宣布Kotlin作为Android开发的第一语言,过去将近6年时间。下面是GoogleIO 2023宣布的Android生态的4项重要更新。 如果你是一位Kotlin开发者,你可能会对听到这个消息感到兴奋,因为Kotlin语言将通过2.0版本得到重大升级。有意思的是,新的Kotlin编译器版本2.0将成为Kotli

    2024年02月09日
    浏览(33)
  • Android Canvas图层saveLayer剪切clipPath原图addCircle绘制对应圆形区域,Kotlin(2)

    在 Android Canvas图层saveLayer剪切clipRect原图对应Rect区域,Kotlin(1)-CSDN博客 的基础上,把矩形切图,换成圆形。             在文章1: https://zhangphil.blog.csdn.net/article/details/135297013 基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大

    2024年02月02日
    浏览(44)
  • Android RecyclerView 实现瀑布流

    Android RecyclerView 使用大全 - 基础使用,item 动画,下拉刷新等 瀑布流也是个常用的显示控件了,但是在使用时经常遇到一些问题,比如滑动回顶部后出现空隙、item在滑动时乱跳等问题。 下面就来说说我怎么实现的瀑布流,并且怎么处理上面所说的这些问题的。 我使用了原生

    2024年02月09日
    浏览(72)
  • Android Studio版本升级后的问题 gradle降级、jdk升级 Compose 与 Kotlin 的兼容性对应关系

    AGPBI: {“kind”:“error”,“text”:“Can’t determine type for tag ‘macro name=“m3_comp_switch_disabled_selected_handle_color”?attr/colorSurface’”,“sources”:[{“file”:“/Users/fausto/.gradle/caches/transforms-3/4948d05d0ff6027d2e3c9f4a6010103b/transformed/material-1.7.0-alpha02/res/values/values.xml”}],“tool”:“Resource and

    2024年02月04日
    浏览(78)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包