仿淘宝京东商品规格属性选择的最简单实现

本文介绍仿淘宝京东商品规格属性选择的简单实现方法。采用常用的RecyclerView控件,性能好且简单。实现主要涉及RecyclerView和流式布局,针对RecyclerView设置最大高度问题,通过重写LayoutManager方法解决,标签用流式布局实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

仿淘宝京东商品规格属性选择的最简单实现

商城里面的规格选择,网上大部分是自定义控件实现的,显得很是麻烦,而我的实现方式是大家最常用的控件RecyclerView,特点是性能好,简单。废话不多说,先看实现的效果图:
在这里插入图片描述
上图效果的实现主要是 RecyclerView和flowlayout(流式布局).

RecyclerView设置最大高度

如图规格多的时候,RecyclerView要有个最大高度,我们设置android:maxHeight="300dp"是没有效果的,因为RecyclerView没有maxHigh这个属性,那怎么实现这个效果呢?通过查看源码,

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
...
if (mLayout.mAutoMeasure) {
    ...
    // now we can get the width and height from the children.
    mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
    if (mLayout.shouldMeasureTwice()) {
        ...        
        // now we can get the width and height from the children.
        mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
    }
} else {
  ...
}
}

当RecyclerView的LayoutManager#isAutoMeasureEnabled()返回true时,RecyclerView高度取决于children view的布局高度,并非取决于RecyclerView自身的测量高度。

下面是setMeasuredDimensionFromChildren(int widthSpec, int heightSpec)源码

 void setMeasuredDimensionFromChildren(int widthSpec, int heightSpec) {
final int count = getChildCount();
if (count == 0) {
    mRecyclerView.defaultOnMeasure(widthSpec, heightSpec);
    return;
}
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for (int i = 0; i < count; i++) {
    View child = getChildAt(i);
    final Rect bounds = mRecyclerView.mTempRect;
    getDecoratedBoundsWithMargins(child, bounds);
    if (bounds.left < minX) {
        minX = bounds.left;
    }
    if (bounds.right > maxX) {
        maxX = bounds.right;
    }
    if (bounds.top < minY) {
        minY = bounds.top;
    }
    if (bounds.bottom > maxY) {
        maxY = bounds.bottom;
    }
}
mRecyclerView.mTempRect.set(minX, minY, maxX, maxY);
setMeasuredDimension(mRecyclerView.mTempRect, widthSpec, heightSpec);
}

该方法计算了RecyclerView当前所有Child View的布局范围mRecyclerView.mTempRect,最后调用了public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec),并将得出的布局范围mRecyclerView.mTempRect、RecyclerView的测量参数widthSpec、heightSpec作为参数传入,以此来决定RecyclerView最终宽高值。

最终解决方法

因此,我们只需要重写LayoutManager的public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec)方法即可为RecyclerView设置最大宽高。

` @Override
public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec) {
    super.setMeasuredDimension(childrenBounds, wSpec, View.MeasureSpec.makeMeasureSpec(DeviceUtil.dp2px(mContext,246), AT_MOST));
}`

属性的标签实现

标签的实现用的是flowlayout,用法很简单,这里就不在描述了。

至此,如图的效果就实现了,还有不懂的可看demo代码。

查看源码

因为demo太大请移步github: https://github.com/shabake/GHAlibabaSpecificationSelectionDemoFeatures初始化确定按钮颜色置灰,不可点击。当 spu 颜色数量大于1个时,显示颜色导航,底部列表可以滚动,反之隐藏,布局自适应。如果有颜色导航,输入或点击 + - 按钮,颜色导航对应的颜色数字同步变化,如果数量大于99显示99+;如果数量小于1不显示。点击> < 底部列表和颜色导航同步滚动。输入或点击 + - 按钮,当按 +到最大库存 + 置灰;当按 - 到0 - 置灰。点击输入框。键盘弹出,规格选择器 上移;点击完成,键盘收回,规格选择器 回到原位。点击颜色导航条的颜色标签,高亮被点击颜色标签并滚动到屏幕中心,底部列表滑动到对应位置,同时切换 sku 图片。当输入或者点击数量大于1,确定按钮可点击,颜色高亮。当库存不足的时候,输入框下显示库存不足标签。输入框不可输入 0 ,. 。列表行自适应高度布局中心对齐。点击背景遮罩或者 x ,收回弹窗。动态输入监听,同步显示,根据输入判定确定状态。数据模型重新组装。适配IPhoneX及以上系列。使用demo 数据是从接口获取,需要连接wifi或蜂窝网络。数据结构 (点击箭头展开/收起)GHSpecificationSelectionTitleModel 颜色导航器模型 GHSpecificationSelectionModel sku 模型 GHSpecificationSelectionImageModel 图片模型初始化对象 GHAlibabaSpecificationSelection继承 GHPopView ,GHPopView 已经封装好弹出/收回动画,外部无需重复处理。- (void)show;- (void)dismiss传入数据/*** 数据源* @param skuList 装skuModel数组* @param colors 颜色数组 非必传,如果为空,不显示颜色导航* @param sectePrice 价格区间字典*/[self.alibabaSpecificationSelection setSkuList:specifications colors:colors sectePrice:sectePrice];​取出用户选择_alibabaSpecificationSelection.getDataBlock = ^(NSArray * _Nonnull dataArray) {NSMutableString *string = [NSMutableString string];for (NSDictionary *dict in dataArray) {[string appendFormat:@"颜色:%@ 数量:%@ id:%@",dict[@"color"],dict[@"skuNum"],dict[@"skuId"]];}KAlert(@"用户选择的数据", string);};重置数据在这个方法内部清除所有count。底部scrollview 滚动到初始化状态。底部确定按钮初始化状态。scrollTitles初始化。- (void) resetData;与我联系45329453@qq.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值