业务需要实现类似京东分类页面的页面效果,原先没有写过类似的这种效果,特此搞个Demo 梳理一下整体的实现流程以及记录下逻辑实现的效果
一,效果
效果.gif二,实现思路 RecycleView+Fragment(RecycleView)+观察
.
1:左侧是RecycleView 为了实现局部刷新 使用了DiffUtil 处理局部刷新问题
2:右侧是一个Fragment 用了 SmartRefreshLayout,RecycleView处理刷新效果
3.数据通讯使用了 ClassificationObservable,ClassificationFinshObservable两个观察者处理开始刷新以及刷新结束的状态
.
三,代码实现
1.首页代码
package com.wu.third.classification
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.wu.base.adapter.KtAdapter
import com.wu.third.R
import com.wu.third.databinding.ActivityClassificationBinding
import java.util.*
import kotlin.collections.ArrayList
class ClassificationActivity : AppCompatActivity(), Observer {
var binding: ActivityClassificationBinding? = null
//右侧内容
var currentFragment: ClassificationContentFragment? = null
//左侧内容适配器
var tagAdapter: ClassificationTagAdapter? = null
//静态图片
var imgs = arrayListOf<String>(
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F16%2F10%2F29%2F2ac8e99273bc079e40a8dc079ca11b1f.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=0b42192b10b6d521d58cd0650a0148e6",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F17%2F09%2F15%2F67351408baad11ce25c9b14166a049a6.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=a6c67c2f08b86a82348b2c87e75ffd9c",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ftupian.qqjay.com%2Fu%2F2018%2F0222%2F2_163119_13.jpg&refer=http%3A%2F%2Ftupian.qqjay.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=995f87498f2d19ab6c885e09904d1ef3",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdpic.tiankong.com%2Ftc%2Feb%2FQJ9124407543.jpg&refer=http%3A%2F%2Fdpic.tiankong.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=c76415814c9c52ae20480a89199a128c",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdpic.tiankong.com%2Ftc%2Feb%2FQJ9124407543.jpg&refer=http%3A%2F%2Fdpic.tiankong.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=c76415814c9c52ae20480a89199a128c",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.pconline.com.cn%2Fimages%2Fupload%2Fupc%2Ftx%2Fitbbs%2F1705%2F10%2Fc35%2F46579542_1494425402317_mthumb.jpg&refer=http%3A%2F%2Fimg.pconline.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=3ddc7531c2a48fd48712346466ebd228",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp01%2F1ZZQ20QJS6-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=5f6463e28700d48143f6be2c554f8a28"
)
//左侧商品分类
var tags = arrayListOf<ClassificationTagInfo>(
ClassificationTagInfo("家电", true),
ClassificationTagInfo("食品", false),
ClassificationTagInfo("服装", false),
ClassificationTagInfo("电子", false),
ClassificationTagInfo("农产品", false),
ClassificationTagInfo("饮料", false),
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityClassificationBinding>(
this,
R.layout.activity_classification
)
ClassificationObservable.addObserver(this)
ClassificationFinshObservable.addObserver(this)
initView()
}
private fun initView() {
tagAdapter = ClassificationTagAdapter(this)
binding!!.rvClassify.layoutManager = LinearLayoutManager(this)
binding!!.rvClassify.adapter = tagAdapter
tagAdapter!!.setAsyncListDatas(tags)
currentFragment = ClassificationContentFragment.newInstance(0)
supportFragmentManager.beginTransaction().replace(R.id.fragment_content, currentFragment!!) .commit()
tagAdapter!!.setOnViewClickListener(object :
KtAdapter.OnAdapterViewClickListener<ClassificationTagInfo> {
override fun onViewClick(v: View?, program: ClassificationTagInfo?) {
var position = tagAdapter!!.getAsyncListItems()!!.indexOf(program)
currentFragment!!.setData(getContentData(position), position)
processFinish(position)
}
})
}
fun getContentData(position: Int): ArrayList<ClassificationContentInfo> {
var contentInfos = ArrayList<ClassificationContentInfo>()
var contentInfo = ClassificationContentInfo()
contentInfo.title = tags.get(position).title
contentInfo.imgs = imgs
contentInfos.add(contentInfo)
return contentInfos
}
override fun onDestroy() {
super.onDestroy()
ClassificationObservable.deleteObserver(this)
ClassificationFinshObservable.deleteObserver(this)
}
//右侧刷新的观察者
private fun processRefreshLoadMoreData(info: ClassificationObservableInfo) {
if ((info.type == 0 && info.position == 0) || (info.type == 1 && info.position >= tags.size - 1)) {
currentFragment!!.finish()
return
}
if (info.type == 0) {
//下拉 刷新
info.position -= 1
} else {
//上拉加载
info.position += 1
}
currentFragment!!.setData(getContentData(info.position), info.position)
}
//刷新完成后改变 左侧标题数据
private fun processFinish(position: Int) {
var newList = ArrayList<ClassificationTagInfo>()
var oldList = tagAdapter!!.getAsyncListItems()
oldList.forEachIndexed { index, classificationTagInfo ->
var info: ClassificationTagInfo? = null
if (index == position) {
info = ClassificationTagInfo(classificationTagInfo.title, true)
} else {
info = ClassificationTagInfo(classificationTagInfo.title, false)
}
newList.add(info)
}
tagAdapter!!.setAsyncListDatas(newList)
}
override fun update(o: Observable?, arg: Any?) {
if (o is ClassificationObservable) {
var info = arg as ClassificationObservableInfo
processRefreshLoadMoreData(info)
} else if (o is ClassificationFinshObservable) {
processFinish(arg as Int)
}
}
}
1.2.layout
<?xml version="1.0" encoding="utf-8"?>
<layout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_classify"
android:layout_width="100dp"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/rv_classify" />
</RelativeLayout>
</layout>
2.右侧Fragment实现
package com.wu.third.classification
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener
import com.wu.third.R
import com.wu.third.databinding.FragmentClassificationContentBinding
/**
* @author wkq
*
* @date 2021年11月18日 16:06
*
*@des
*
*/
class ClassificationContentFragment : Fragment() {
//设置出艰苦
var imgs = arrayListOf<String>(
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F16%2F10%2F29%2F2ac8e99273bc079e40a8dc079ca11b1f.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=0b42192b10b6d521d58cd0650a0148e6",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F17%2F09%2F15%2F67351408baad11ce25c9b14166a049a6.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=a6c67c2f08b86a82348b2c87e75ffd9c",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ftupian.qqjay.com%2Fu%2F2018%2F0222%2F2_163119_13.jpg&refer=http%3A%2F%2Ftupian.qqjay.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=995f87498f2d19ab6c885e09904d1ef3",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ftupian.qqjay.com%2Fu%2F2018%2F0222%2F2_163119_13.jpg&refer=http%3A%2F%2Ftupian.qqjay.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=995f87498f2d19ab6c885e09904d1ef3",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ftupian.qqjay.com%2Fu%2F2018%2F0222%2F2_163119_13.jpg&refer=http%3A%2F%2Ftupian.qqjay.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=995f87498f2d19ab6c885e09904d1ef3",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ftupian.qqjay.com%2Fu%2F2018%2F0222%2F2_163119_13.jpg&refer=http%3A%2F%2Ftupian.qqjay.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=995f87498f2d19ab6c885e09904d1ef3",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdpic.tiankong.com%2Ftc%2Feb%2FQJ9124407543.jpg&refer=http%3A%2F%2Fdpic.tiankong.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=c76415814c9c52ae20480a89199a128c",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.pconline.com.cn%2Fimages%2Fupload%2Fupc%2Ftx%2Fitbbs%2F1705%2F10%2Fc35%2F46579542_1494425402317_mthumb.jpg&refer=http%3A%2F%2Fimg.pconline.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=3ddc7531c2a48fd48712346466ebd228",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp01%2F1ZZQ20QJS6-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639813297&t=5f6463e28700d48143f6be2c554f8a28"
)
var binding: FragmentClassificationContentBinding? = null
var position = 0;
var finisTime: Long = 1000
companion object {
fun newInstance(position: Int): ClassificationContentFragment {
val args = Bundle()
args.putInt("position", position)
val fragment = ClassificationContentFragment()
fragment.arguments = args
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate<FragmentClassificationContentBinding>(
layoutInflater,
R.layout.fragment_classification_content, container, false
)
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
position = arguments!!.getInt("position")
initData()
initView()
}
var mContentInfos = ArrayList<ClassificationContentInfo>()
var contentAdapter: ClassificationContentAdapter? = null
private fun initData() {
var contentInfo = ClassificationContentInfo()
contentInfo.title = "家电"
contentInfo.imgs = imgs
mContentInfos.add(contentInfo)
}
private fun initView() {
contentAdapter = ClassificationContentAdapter(activity!!);
binding!!.rvContent.layoutManager = LinearLayoutManager(activity!!)
binding!!.rvContent.adapter = contentAdapter
contentAdapter!!.addItems(mContentInfos)
binding!!.sfLayout.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
override fun onRefresh(refreshLayout: RefreshLayout) {
postRefreshLoadMore(0)
}
override fun onLoadMore(refreshLayout: RefreshLayout) {
postRefreshLoadMore(1)
}
})
}
//延时执行刷新 为了保留 顶部和顶部的刷新布局
fun postRefreshLoadMore(type: Int) {
binding!!.sfLayout.postDelayed(object : Runnable {
override fun run() {
ClassificationObservable.update(ClassificationObservableInfo(type, position))
}
}, finisTime)
}
fun setData(contentInfos: ArrayList<ClassificationContentInfo>, position: Int) {
this.position = position
mContentInfos = contentInfos
contentAdapter!!.setNewData(mContentInfos)
ClassificationFinshObservable.update(position)
finish()
}
fun finish() {
binding!!.sfLayout.finishLoadMore()
binding!!.sfLayout.finishRefresh()
goTop()
}
//为了兼容一下 sfLayout 的定时问题 做了一下延时
fun goTop() {
binding!!.sfLayout.postDelayed(object : Runnable {
override fun run() {
binding!!.rvContent.scrollToPosition(0);
var mLayoutManager = binding!!.rvContent.getLayoutManager() as LinearLayoutManager
mLayoutManager.scrollToPositionWithOffset(0, 0);
}
}, 100)
}
}
2.2 layout
<?xml version="1.0" encoding="utf-8"?>
<layout>
<com.scwang.smartrefresh.layout.SmartRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sf_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/color_m_red"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="上拉加载上一页"
android:textColor="@color/white" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/color_1aad19"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="下拉加载下一页"
android:textColor="@color/white" />
</RelativeLayout>
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
</layout>
3.左侧适配器
package com.wu.third.classification
import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.RecyclerView
import com.wu.base.adapter.KtAdapter
import com.wu.base.base.adapter.KtDataBindingViewHolder
import com.wu.third.R
import com.wu.third.databinding.LayoutClassficationTagBinding
/**
* @author wkq
*
* @date 2021年11月18日 14:55
*
*@des 左侧标题的Adapter
*
*/
class ClassificationTagAdapter(mContext: Context) : KtAdapter<ClassificationTagInfo>(mContext) {
//DiffUtil 的异步刷新的工具
var diff: AsyncListDiffer<ClassificationTagInfo>? = null
init {
this.mContext = mContext
diff = AsyncListDiffer<ClassificationTagInfo>(this, ClassificationTagDiffItemCallBack())
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var binding = DataBindingUtil.inflate<LayoutClassficationTagBinding>(
LayoutInflater.from(mContext),
R.layout.layout_classfication_tag, parent, false
)
var holder = KtDataBindingViewHolder(binding.root)
holder.binding = binding
return holder
}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
// payloads 为null 整条数据刷新
if (payloads.isEmpty() || payloads.size <= 0) {
super.onBindViewHolder(holder, position, payloads)
} else {
//局部更新 不会更新整个item 更新指定的控件
var bundle = payloads.get(0) as Bundle
if (bundle != null) {
var title = bundle.getString("title")
var isShow = bundle.getBoolean("isShow")
var holder = holder as KtDataBindingViewHolder
var binding = holder.binding as LayoutClassficationTagBinding
if (!TextUtils.isEmpty(title)) {
binding.tvTag.text = title
}
if (isShow) {
binding.rlRoot.setBackgroundColor(mContext.resources.getColor(R.color.color_23d41e))
} else {
binding.rlRoot.setBackgroundColor(mContext.resources.getColor(R.color.white))
}
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var bindingHolder = holder as KtDataBindingViewHolder
var binding = bindingHolder.binding as LayoutClassficationTagBinding
binding.tvTag.text = getAsyncListItem(position)!!.title
if (getAsyncListItem(position)!!.isShow) {
binding.rlRoot.setBackgroundColor(mContext.resources.getColor(R.color.color_23d41e))
} else {
binding.rlRoot.setBackgroundColor(mContext.resources.getColor(R.color.white))
}
binding.rlRoot.setOnClickListener {
if (viewClickListener!=null){
viewClickListener!!.onViewClick( binding.rlRoot,getAsyncListItem(position))
}
}
}
fun setAsyncListDatas(newList: List<ClassificationTagInfo>) {
if (diff == null) return
diff!!.submitList(newList)
}
fun getAsyncListItem(position: Int): ClassificationTagInfo {
return diff!!.currentList.get(position)
}
fun getAsyncListItems(): List<ClassificationTagInfo> {
return diff!!.currentList
}
override fun getItemCount(): Int {
return diff!!.currentList.size
}
}
3.2 ClassificationTagDiffItemCallBack
package com.wu.third.classification
import android.os.Bundle
import android.text.TextUtils
import androidx.recyclerview.widget.DiffUtil
/**
* @author wkq
*
* @date 2021年09月06日 14:33
*
*@des 异步差分对比的监听
*
*/
class ClassificationTagDiffItemCallBack() :
DiffUtil.ItemCallback<ClassificationTagInfo>() {
//是否相同的id
override fun areItemsTheSame(oldItem: ClassificationTagInfo, newItem: ClassificationTagInfo): Boolean {
return oldItem.title!!.equals(oldItem.title)
}
//是否相同的数据
override fun areContentsTheSame(oldItem: ClassificationTagInfo, newItem: ClassificationTagInfo): Boolean {
var oldItem = oldItem.toString()
var newItem = newItem.toString()
return oldItem.equals(newItem)
}
// 局部刷新 返回null 整条数据刷新
override fun getChangePayload(oldItem: ClassificationTagInfo, newItem: ClassificationTagInfo): Any? {
var bundle = Bundle()
// onBindViewHolder 实现三个参数 payloads 第一个数据为 封装的bundle
if (!TextUtils.equals(oldItem.title, newItem.title)) {
bundle.putString("title", newItem.title)
}
if (oldItem.isShow!=newItem.isShow) {
bundle.putBoolean("isShow", newItem.isShow)
}
return bundle
}
}
3.3右侧Adapter
package com.wu.third.classification
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.wu.base.adapter.KtAdapter
import com.wu.base.base.adapter.KtDataBindingViewHolder
import com.wu.third.R
import com.wu.third.databinding.ItemClassificationContentBinding
/**
* @author wkq
*
* @date 2021年11月18日 15:03
*
*@des 右侧内容的Adapter
*
*/
class ClassificationContentAdapter(mContext: Context) :
KtAdapter<ClassificationContentInfo>(mContext) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var binding = DataBindingUtil.inflate<ItemClassificationContentBinding>(
LayoutInflater.from(mContext),
R.layout.item_classification_content, parent, false
)
var holder = KtDataBindingViewHolder(binding.root)
holder.binding = binding
return holder
}
var binding:ItemClassificationContentBinding?=null
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var bindingHolder = holder as KtDataBindingViewHolder
binding = bindingHolder.binding as ItemClassificationContentBinding
binding!!.tvTitle.text = getItem(position)!!.title
binding!!.rvImgs.layoutManager = GridLayoutManager(mContext, 4)
var adapter = ClassificationImgsAdapter(mContext)
binding!!.rvImgs.adapter = adapter
adapter.addItems(getItem(position)!!.imgs)
}
fun setNewData(newDatas:ArrayList<ClassificationContentInfo>){
removeAllItems()
itemList=newDatas
notifyDataSetChanged()
binding!!.rvImgs.scrollToPosition(0)
}
}
新增:自定义LinearLayoutManager左侧分类自动居中逻辑
package com.wu.third.classification;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
/**
* @author wkq
* @date 2021年11月26日 16:57
* @des
*/
public class CenterLinearLayoutManager extends LinearLayoutManager {
public CenterLinearLayoutManager(Context context) {
super(context);
}
public CenterLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public CenterLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private static class CenterSmoothScroller extends LinearSmoothScroller {
public CenterSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
}
//滚动速度
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 400f / displayMetrics.densityDpi;
}
}
}
自动滑动到中间调用
//自动滑动到中间
centerLinearLayoutManager!!.smoothScrollToPosition(binding!!.rvClassify, RecyclerView.State(),position)
总结
大致逻辑代码就是这样,核心实现了 商品分类点击右侧切换数据,右侧商品分类滑动切换左侧商品分类的逻辑.商品右侧的分类实现了上拉 和下拉的一部分动画
网友评论