安卓高仿京东分类页
前言
网购已经成为我们生活的一般,经常用的京东、淘宝等app,接到一个需求,开发电商app的分类页,这里写了个demo,高仿京东的分类页,我们看下效果
思路
顶部: 封住一个组件,这里不介绍
左侧: 一个RecyclerView即可,比较简单,这里也不介绍,想了解的直接看源码
右侧: TabLayout + RecyclerView 布局, 难点: tabLayout滚动RecyclerView到指定位置,滚动RecyclerView时,默认选中tabLayout
右侧布局
android:id="@+id/rightLinearLayoutCompat" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="scrollable" app:tabIndicatorHeight="0dp" app:tabMaxWidth="120dp" app:tabMinWidth="60dp" app:tabRippleColor="@color/transparent" app:tabTextAppearance="@style/tab_title" app:tabTextColor="@color/color_404040" app:tabSelectedTextColor="@color/color_E33A3C" app:tabBackground="@drawable/selector_tab_indicator2"/> android:id="@+id/categoryRecyclerView" android:layout_width="match_parent" android:layout_height="match_parent"/>
R.layout.main_right_grid_header
android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> android:id="@+id/textHeader" android:padding="@dimen/dp_4" android:textColor="#181818" android:textSize="14dp" android:textStyle="bold" android:text="专属推荐" android:layout_width="match_parent" android:layout_height="wrap_content" />
R.layout.main_right_grid
android:orientation="vertical" android:layout_width="match_parent" android:layout_height="100dp" android:gravity="center"> android:id="@+id/thirdCategoryIcon" android:layout_width="60dp" android:layout_height="60dp" android:scaleType="fitXY"/> android:id="@+id/text_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dp" android:textColor="#898989" android:text="男装馆" android:layout_marginTop="10dp"/>
TabLayout addTab
tabLayout.removeAllTabs()
data.cateList.forEach { v -> tabLayout.addTab(tabLayout.newTab().setText(v.categoryName)) }
RecyclerView的adapter
package com.aries.category.ui.adapter
import android.widget.ImageView
import coil.load
import com.chad.library.adapter.base.BaseSectionQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.aries.category.R
import com.aries.category.ui.modal.CategoryModal
import com.aries.common.util.CoilUtil
class SectionQuickAdapter(sectionHeadResId: Int, layoutResId: Int, data: MutableList
BaseSectionQuickAdapter
private var imageLoader = CoilUtil.getImageLoader()
override fun convertHeader(helper: BaseViewHolder, item: CategoryModal) {
helper.setText(R.id.textHeader, item.categoryName)
}
override fun convert(holder: BaseViewHolder, item: CategoryModal) {
holder.getView
crossfade(true)
placeholder(R.drawable.default_img)
error(R.drawable.default_img)
}
holder.setText(R.id.text_content, item.categoryName)
}
}
设置RecyclerView的 adapter 和 layoutManager
gridLayoutManager = GridLayoutManager(context, 3)
sectionQuickAdapter = SectionQuickAdapter(R.layout.main_right_grid_header, R.layout.main_right_grid, arrayListOf())
val thisTabLayout = tabLayout
categoryRecyclerView.run {
layoutManager = gridLayoutManager
adapter = sectionQuickAdapter
}
设置数据
val list: ArrayList
data.cateList.forEach { v ->
run {
list.add(CategoryModal(v.iconUrl, v.categoryName, v.categoryCode, true))
v.cateList?.forEach { m -> list.add(CategoryModal(m.iconUrl, m.categoryName, m.categoryCode, false))}
}
}
sectionQuickAdapter.setList(list)
重点: 设置 tabLayout 和 RecyclerView 联动关系
categoryRecyclerView.run {
setOnTouchListener { _, p1 ->
if (p1.action == MotionEvent.ACTION_DOWN) {
isRecyclerScroll = true
}
false
}
addOnScrollListener(object : RecyclerView.OnScrollListener(){
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (isRecyclerScroll) {
val position = findHeaderPositionByTab(gridLayoutManager.findFirstVisibleItemPosition())
if (position != lastPos) {
thisTabLayout.setScrollPosition(position, 0F, true)
}
lastPos = position
}
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (mShouldScroll) {
mShouldScroll = false
scrollTop(mToPosition)
}
}
})
}
tabLayout.run {
addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener{
override fun onTabSelected(tab: TabLayout.Tab?) {
val position = tab?.position
if (position != null) {
scrollRecycleView2Top(position)
}
isRecyclerScroll = false
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabReselected(tab: TabLayout.Tab?) {}
})
}
private fun scrollTop(position: Int) {
val firstPosition = gridLayoutManager.findFirstVisibleItemPosition()
val lastPosition = gridLayoutManager.findLastVisibleItemPosition()
if (position < firstPosition) {
// 如果跳转位置在第一个可见位置之前,就smoothScrollToPosition可以直接跳转
categoryRecyclerView.smoothScrollToPosition(position)
} else if (position <= lastPosition){
// 跳转位置在第一个可见项之后,最后一个可见项之前
// smoothScrollToPosition根本不会动,此时调用smoothScrollBy来滑动到指定位置
val movePosition = position - firstPosition
if (movePosition >=0 && movePosition < categoryRecyclerView.childCount) {
val scrollY = categoryRecyclerView.getChildAt(position - firstPosition).top
categoryRecyclerView.smoothScrollBy(0, scrollY)
}
} else {
// 如果要跳转的位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
// 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法
categoryRecyclerView.smoothScrollToPosition(position)
mToPosition = position
mShouldScroll = true
}
}
private fun scrollRecycleView2Top(position: Int) {
val currentItem = dataCopy.cateList[position]
val currentPosition = sectionQuickAdapter.data.indexOfFirst { v -> v.categoryCode == currentItem.categoryCode }
scrollTop(currentPosition)
}
结束语
目前专注于前端⚙️ 在react、react-native开发方面有丰富的经验 最近在学习安卓,有自己的开源安卓项目,集成react-native热更新功能我❤️ 思考、学习、编码和健身如果文章对您有帮助,三连支持一下~O(∩_∩)O谢谢!
相关链接
发表评论