Android美团购物车效果
效果就是gif展⽰的,效果图有了,还是要⽤⽂字介绍下的。
效果就是左右两个列表,左侧列表点击时,右侧的标题⾃动显⽰到列表的顶部,标题是悬浮吸顶的,没组的标题固定悬浮在顶部,当右侧列表滑动时,左侧列表⾃动定位⾄和左侧相同的分类保持统⼀,底部的弹出购物车区域,购物车的⾼度是在屏幕的70%以下是⾃适应的⾼度,最⼤⾼度是当前屏幕的70%,下边是部分代码和实现思路。
这⾥提到了scrollToPositionWithOffset()⽅法,就顺便说⼀下scrollToPosition和scrollToPositionWithOffset的区别
scrollToPosition 会把不在屏幕的 Item 移动到屏幕上,原来在上⽅的 Item 移动到可见 Item 的第⼀项,在下⽅的移动到屏幕可见 Item 的最后⼀项。已经显⽰的 Item 不会移动。
scrollToPositionWithOffset 会把 Item 移动到可见 Item 的第⼀项,即使它已经在可见 Item 之中。另外它还有 offset 参数,表⽰ Item 移动到第⼀项后跟 RecyclerView 上边界或下边界之间的距离(默认是 0)
要实现这个效果还就得使⽤scrollToPositionWithOffset()这个⽅法,我也没有重写⼀个Manager,就这样直接使⽤了
数据源准备完之后就开始下⾯的实现了
###设置adapter
```
//设置数据源,数据绑定展⽰
leftAdapter = new LeftProductTypeAdapter(MainActivity.this, productListEntities);
rightAdapter = new RightProductAdapter(MainActivity.this, productListEntities, shopCart);
rightMenu.setAdapter(rightAdapter);
leftMenu.setAdapter(leftAdapter);
//左侧列表单项选择
leftAdapter.addItemSelectedListener(this);
rightAdapter.setShopCartImp(this);
/
/设置初始头部
initHeadView();
```
刚才从图上也看到了右侧列表⼜⼀个标题,这个标题就是为了占位和显⽰使⽤
```
/**
* 初始头部
*/
private void initHeadView() {
headMenu = MenuOfMenuByPosition(0);
headerLayout.setContentDescription("0");
headerView.TypeName());
}
```
别忘了设置LayoutManager,这⾥为什么使⽤LinearLayoutManager在上边也说了,主要是使⽤LinearLayoutManager的scrollToPositionWithOffset()⽅法
```
leftMenu.setLayoutManager(new LinearLayoutManager(this));
rightMenu.setLayoutManager(new LinearLayoutManager(this));
```
数据绑定之后,就是列表的滑动了,先说右侧列表数据滑动,然后让左侧选中
###右侧列表滑动监听
```
rightMenu.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (recyclerView.canScrollVertically(1) == false) {//⽆法下滑
showHeadView();
return;
}
View underView = null;
if (dy > 0) {
underView = rightMenu.X(), MeasuredHeight() + 1);
} else {
underView = rightMenu.X(), 0);
}
if (underView != null && ContentDescription() != null) {
int position = Integer.ContentDescription().toString());
ProductListEntity menu = MenuOfMenuByPosition(position);
if (leftClickType || !TypeName().TypeName())) {
if (dy > 0 && TranslationY() <= 1 && TranslationY() >= -1 * MeasuredHeight() * 4 / 5 && !leftClickType) {// Top()>9
int dealtY = Top() - MeasuredHeight();
headerLayout.setTranslationY(dealtY);
} else if (dy < 0 && TranslationY() <= 0 && !leftClickType) {
headerView.TypeName());
int dealtY = Bottom() - MeasuredHeight();
headerLayout.setTranslationY(dealtY);
} else {
headerLayout.setTranslationY(0);
headMenu = menu;
headerView.TypeName());
for (int i = 0; i < productListEntities.size(); i++) {
if ((i) == headMenu) {
leftAdapter.setSelectedNum(i);
break;
}
}
if (leftClickType) leftClickType = false;
}
}
}
}
});
```
```
private void showHeadView() {
headerLayout.setTranslationY(0);
View underView = rightMenu.X(), 0);
if (underView != null && ContentDescription() != null) {
int position = Integer.ContentDescription().toString());
ProductListEntity entity = MenuOfMenuByPosition(position + 1);
headMenu = entity;
headerView.TypeName());
for (int i = 0; i < productListEntities.size(); i++) {
if ((i) == headMenu) {
leftAdapter.setSelectedNum(i);
break;
}
}
}
}
```
以上代码就是两个列表滑动交互右侧的主要代码,以上实现的是右侧滑动分组置顶的效果
接下来就是
###右侧滑动,左侧选中
选中的主要代码是LeftProductTypeAdapter中的setSelectedNum();
```
/**
* 选中左侧区域
*
* @param selectedNum
*/
public void setSelectedNum(int selectedNum) {
if (selectedNum < getItemCount() && selectedNum >= 0) {
this.mSelectedNum = selectedNum;
notifyDataSetChanged();
}
}
```
然后adapter中设置选中的样式就可以
```
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ProductListEntity dishMenu = (position);
LeftMenuViewHolder viewHolder = (LeftMenuViewHolder) holder;
if (mSelectedNum == position) {
} else {
}
```
说完了右侧滑动让左侧选中,那么接下来就是左侧点击让右侧对应的分组显⽰出来
###左侧列表点击,右侧分组显⽰在顶部
在LeftProductTypeAdapter中暴露接⼝
```
public interface onItemSelectedListener {
public void onLeftItemSelected(int postion, ProductListEntity menu);
}
public void addItemSelectedListener(onItemSelectedListener listener) {
if (mSelectedListenerList != null)
mSelectedListenerList.add(listener);
}
```
在Activity中实现,这⾥直接使⽤scrollToPositionWithOffset⽅法就可以了,相对来说⽐较简单
```
/**
* 左侧列表单项选中
*
* @param position
* @param menu
*/
@Override
public void onLeftItemSelected(int position, ProductListEntity menu) {
int sum = 0;
for (int i = 0; i < position; i++) {
sum += (i).getProductEntities().size() + 1;
}
// StickyHeaderLayoutManager layoutManager = (StickyHeaderLayoutManager) Layou
tManager(); LinearLayoutManager layoutManager = (LinearLayoutManager) LayoutManager(); rightMenu.scrollToPosition(position);
layoutManager.scrollToPositionWithOffset(sum, 0);
leftClickType = true;
}
```
⽬前为⾄,左右两个列表就可以实现交互了,左侧点击右侧显⽰指定数据,右侧滑动左侧选中对应的内容
列表的联动处理完成,接下来就是右侧列表商品加减操作了
###右侧列表加减处理
右侧列表的加减操作这⾥没有暴露到Activity中操作,是在Adapter中设置的
####RightProductAdapter
```
//加减点击时间
dishholder.iv_group_list_item_count_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e("posss", "-------------------posss:" + posss);
if (shopCart.addShoppingSingle(dish)) {
// notifyItemChanged(position);
//当前数字变化刷新
notifyDataSetChanged();
if (shopCartImp != null) {
shopCartImp.add(view, position,dish);
}
}
}
});
dishholder.iv_group_list_item_count_reduce.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (shopCart.subShoppingSingle(dish)) {
// notifyItemChanged(position);
//当前数字变化刷新
notifyDataSetChanged();
if (shopCartImp != null)
}
}
});
```
这⾥没有使⽤notifyItemChanged()⽅法刷新,因为这个⽅法,完成操作之后刷新,商品图⽚有闪烁效果,所以这⾥使⽤的notifyDataSetChanged()⽅法替代
在上边adapter中的处理中,我们看到了shopCart.addShoppingSingle(dish) 的判读
这⾥的shopCart 是⼀个购物车实体,可以理解为中转处
看下ShopCart的内容
```
public class ShopCart {
private int shoppingAccount;//数量
private double shoppingTotalPrice;//购物车总价格
private Map<ProductListEntity.ProductEntity, Integer> shoppingSingle;//保存数量
private Map<String, Integer> parentCountMap;//⽗保存数量
public ShopCart() {
this.shoppingAccount = 0;
this.shoppingTotalPrice = 0.0;
this.shoppingSingle = new HashMap<>();
this.parentCountMap = new HashMap<>();
}
public boolean addShoppingSingle(ProductListEntity.ProductEntity dish) {
double remain = ProductCartMoney();
// if (remain <= 0)
// return false;
//商品的价格,减操作直接--
dish.setProductCartMoney(--remain);
int num = 0;
if (ainsKey(dish)) {
num = (dish);
}网页购物车代码
num += 1;
/***/
dish.setProductCount(num);
shoppingSingle.put(dish, num);
//如果这个map存在这个⽗ID的值
int parentNum = 0;
if (ParentId())) {
parentNum = (ParentId());
parentNum += 1;
} else {//如果第⼀次存储
parentNum = 1;
}
parentCountMap.ParentId(), parentNum);
Log.e("TAG", "addShoppingSingle: " + (dish));
shoppingTotalPrice += ProductMoney();//加商品的正常价格
shoppingAccount += num;
return true;
}
public boolean subShoppingSingle(ProductListEntity.ProductEntity dish) {
int num = 0;
if (ainsKey(dish)) {
num = (dish);
}
if (num <= 0) return false;
num--;
double remain = ProductCartMoney();
dish.setProductCartMoney(++remain);
dish.setProductCount(num);
shoppingSingle.put(dish, num);
if (num == 0) {
}
//如果这个map存在这个⽗ID的值
int parentNum = 0;
if (ParentId())) {
parentNum = (ParentId());
parentNum -= 1;
parentCountMap.ParentId(), parentNum);
}
shoppingTotalPrice -= ProductMoney();
shoppingAccount -= num;
return true;
}
public int getShoppingAccount() {
return shoppingSingle.size();
}
public void setShoppingAccount(int shoppingAccount) {
this.shoppingAccount = shoppingAccount;
}
public double getShoppingTotalPrice() {
return shoppingTotalPrice;
}
public void setShoppingTotalPrice(double shoppingTotalPrice) {
this.shoppingTotalPrice = shoppingTotalPrice;
}
public Map<ProductListEntity.ProductEntity, Integer> getShoppingSingle() {
return shoppingSingle;
}
public void setShoppingSingle(Map<ProductListEntity.ProductEntity, Integer> shoppingSingle) { this.shoppingSingle = shoppingSingle;
}
public Map<String, Integer> getParentCountMap() {
return parentCountMap;
}
public void setParentCountMap(Map<String, Integer> parentCountMap) {
this.parentCountMap = parentCountMap;
}
public void clear() {
this.shoppingAccount = 0;
this.shoppingTotalPrice = 0;
this.shoppingSingle.clear();
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。