前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >仿电商商品分类的思路实现

仿电商商品分类的思路实现

作者头像
codelang
发布2018-06-26 16:08:40
1.5K0
发布2018-06-26 16:08:40
举报
文章被收录于专栏:codelangcodelang

仿电商商品分类的思路实现

引言

按照以前的习惯,本来是每周一篇,因为昨天去逛街买了条169的裤子给耽误了,周一早上来补上。 丑豆很早就让我给他写一下这个demo,每次都有点忙没给他写,趁着昨天晚上睡前一小时来搞定。

效果图

我参照的是拼多多商品分类的界面来写的,先看看样图

然后看看动态的效果图

实现思路

这个页面用了两个并排的列表,右边列表每个item都有一个type对应左边的列表item的每一个type,右边的列表在滑动的时候,左边的列表选择也会跟着变化,在右边的列表一直往上滑或是往下滑的时候,左边的列表item对应的type并没有显示在界面的话,我们还需要左边的列表进行一个滚动到对应的item的位置上,知道思路了,然后我们开始敲代码

布局代码实现

1、 主布局是两个列表,这两个列表我通过LineaLayout的weight进行了一个平分

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="dingshi.com.tworecycleview.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/main_left_recycle"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/main_right_recycle"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="7" />
</LinearLayout>

2、左边列表的layout我就不贴了,就是一个TextView和ImageView的事 3、右边列表的layout我重写了RecycleView的onMeasure方法,使其能扩展到最大,如果直接使用RecycleView的话,会导致界面显示不完全,而且还可以滑动,这是不允许的。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#fff"
    android:padding="10dp">

    <TextView
        android:id="@+id/item_main_right_type"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="鞋包"
        android:textColor="#333"
        android:textSize="17dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查看更多 >"
        android:textColor="#999"
        android:textSize="13dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <dingshi.com.tworecycleview.AbsoluteRecycleView
        android:id="@+id/item_main_right_recycle"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/item_main_right_type" />

</android.support.constraint.ConstraintLayout>

重写的RecycleView

代码语言:javascript
复制
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;

public class AbsoluteRecycleView extends RecyclerView {
    public AbsoluteRecycleView(Context context) {
        super(context);
    }

    public AbsoluteRecycleView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

主界面代码实现

1、参数的定义 WQRecycleAdapter是自己封装的一个通用的Adapter,让你的项目只存在一个adapter。

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {  
    RecyclerView leftRecycle;
    RecyclerView rightRecycle;
    WQRecycleAdapter leftAdapter;
    WQRecycleAdapter rightAdapter;
    /**
     * 存储左边列表内容
     */
    List<String> leftList = new ArrayList<>();
    /**
     * 存储右边列表对应左边列表的type
     */
    List<String> rightList = new ArrayList<>();
    /**
     * 右边列表item的内容
     */
    List<String> detailsList = new ArrayList<>();
    /**
     * 记录当前在哪个position位置
     */
    int currentPosition = 0;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();

        leftRecycle = (RecyclerView) findViewById(R.id.main_left_recycle);
        rightRecycle = (RecyclerView) findViewById(R.id.main_right_recycle);
        leftRecycle.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        rightRecycle.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

        leftAdapter = new WQRecycleAdapter(this, R.layout.item_main_left, leftList);
        leftRecycle.setAdapter(leftAdapter);

        rightAdapter = new WQRecycleAdapter(this, R.layout.item_main_right, rightList);
        rightRecycle.setAdapter(rightAdapter);
        ...
     }
     /**
     * 初始化数据源
     */
    private void initData() {
        for (int i = 0; i < 20; i++) {
            leftList.add("" + i);
            rightList.add("" + i);
        }
        for (int i = 0; i < 9; i++) {
            detailsList.add("");
        }
    }

}

2、设置两个adapter的数据填充

代码语言:javascript
复制
/**
 * 左边item填充数据
 */
leftAdapter.setCallBack(new WQRecycleAdapter.CallBack() {
@Override
public <T> void convert(WQViewHolder holder, T bean, int position) {
    LinearLayout layout = (LinearLayout) holder.getView(R.id.item_main_left_layout);
    extView type = (TextView) holder.getView(R.id.item_main_left_type);
    type.setText((String) bean);
    if (position == currentPosition) {
        layout.setBackgroundColor(0xffffffff);
        type.setTextColor(getResources().getColor(R.color.colorAccent));
    } else {
        layout.setBackgroundColor(0xffeeeeee);
        type.setTextColor(0xff444444);
    }
 }
});

 /**
   * 右边item填充数据
   */
rightAdapter.setCallBack(new WQRecycleAdapter.CallBack() {
            @Override
            public <T> void convert(WQViewHolder holder, T bean, int position) {
       holder.setText(R.id.item_main_right_type, (String) bean);
       RecyclerView detailsRecycle = (RecyclerView) holder.getView(R.id.item_main_right_recycle);
       updateDetailsRecycle(detailsRecycle);
    }
});

/**
 * 右边列表的详情
 * 使用GridLayoutManager来生成3列的网格布局
 * @param detailsRecycle
 */
public void updateDetailsRecycle(RecyclerView detailsRecycle) {
    WQRecycleAdapter detailsAdapter = new WQRecycleAdapter(this, R.layout.item_main_details, detailsList);
    detailsRecycle.setLayoutManager(new GridLayoutManager(this, 3));
    detailsRecycle.setAdapter(detailsAdapter);
}

3、设置左边adapter的点击事件

代码语言:javascript
复制
/**
  * 左边列表item的点击事件
  * 拿到左边item的position让右边的item跳转到指定的position
  */
leftAdapter.setOnItemClickListner(new WQRecycleAdapter.OnItemClickListner() {
    @Override
    public void onItemClickListner(View v, int position) {
        LinearLayoutManager llm = ((LinearLayoutManager) rightRecycle.getLayoutManager());
        llm.scrollToPositionWithOffset(position, 0);

    }
});

4、右边RecycleView的滑动监听 这个部分是重中之中,我们先来想想右边滑动我们需要做哪些事:

  • 获取右边列表第一个item处于在第几个position,将这个position设置到左边的列表,控制左边列表的变化
  • 上面的条件会有一个弊端,如果左边列表只显示10个类型,右边的列表已经滑动到第11个item了,那左边的列表因为被隐藏而看不到效果,这时候,我们需要去滚动左边的列表
  • 判断处理: ①、如果左边列表的第一个item的position大于右边列表滚动的position的话,我们需要左边的列表进行向上滚动处理,这个处理很简单,只需要让左边的列表scrollToPositionWithOffset到右边列表的position, ②、如果左边列表的最后一个item的position小于右边列表滚动的position的话,我们需要左边的列表进行向下滚动处理,这个处理跟上面一样,拿到右边的position,是左边的列表scrollToPositionWithOffset到对应的位置
  • 滑动到底部的处理: 因为我只判断右边第一个item出现来设置左边的position,如果右边列表的type过于拥挤的话,滑动到底部的时候,左边的列表并不会选中到最后一个item,这时候,我们需要判断,如果右边列表滑动到底部的话,则设置左边选中的position为数据集合的长度减1
实现代码
代码语言:javascript
复制
       /**
         * 右边滑动的监听事件
         */
        rightRecycle.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                LinearLayoutManager rightManager = (LinearLayoutManager) rightRecycle.getLayoutManager();

                LinearLayoutManager leftManager = ((LinearLayoutManager) leftRecycle.getLayoutManager());

                /**
                 * 获取第一个item为第几个position
                 */
                currentPosition = rightManager.findFirstVisibleItemPosition();


                /**
                 * 这地方需要进行判断,如果右边的Recycle在移动的时候,左边的RecycleView也是需要进行移动的
                 * 左边的recycleview有可能会不可见,这时候,我们必须去判断一下,左边最后的一个item是不是
                 * 小于右边滑动的位置,或左边第一个item是不是大于右边滑动的位置
                 */
                if (leftManager.findFirstVisibleItemPosition() > currentPosition) {
                    leftManager.scrollToPositionWithOffset(currentPosition, 0);
                } else if (leftManager.findLastVisibleItemPosition() < currentPosition) {
                    leftManager.scrollToPositionWithOffset(currentPosition, 0);
                }

                /**
                 * 判断右边是否滑动到最后一个item,是的话,也将左边移动到最后一个item
                 * canScrollVertically(1)表示是否能向上滚动,false表示已经滚动到底部
                 */
                if (!rightRecycle.canScrollVertically(1)) {
                    currentPosition = rightList.size() - 1;
                }

                /**
                 * 更新左边列表
                 */
                leftAdapter.notifyDataSetChanged();
            }
        });

总结

代码量并不多,实现思路也很简单,都是平常使用到的方法,最后还要提一个,在我们项目实施的过程中,不能一味的寻找框架和copy来解决问题,学会思考问题才是关键,项目已经上传到github,下载链接:https://github.com/MRwangqi/Mall_classify


最近项目有接上微信分享、登录、支付和支付宝支付,由于微信的结果处理都必须在指定类里面去处理,为了使开放方便,刚开发了一套特别Easy化的封装,先贴一小段使用代码,由于没投入到生产环境,先不把代码共享出来,我先看看会不会有bug出现,预计这个礼拜六把思路和代码整理出来分享给大家

代码语言:javascript
复制
    PayWeixin payWeixin = new PayWeixin();
    payWeixin.setAppid("");
    payWeixin.setNoncestr("");
    payWeixin.setPackag("");
    payWeixin.setPartnerid("");
    payWeixin.setPrepayid("");
    payWeixin.setSign("");
    payWeixin.setTimestamp("");
    payWeixin.setOrdercode("");

    EasyPayShare.getInstance().doPayWx(mActivity, payWeixin, new ShareCallBack() {
       @Override
       public void onSuccess(String result) {
            Toast.makeText(activity, "支付成功", Toast.LENGTH_SHORT).show();
       }

       @Override
       public void onCanceled(String result) {
            Toast.makeText(activity, "支付取消", Toast.LENGTH_SHORT).show();
       }

       @Override
       public void onFailed(String result) {
           Toast.makeText(activity, "支付失败", Toast.LENGTH_SHORT).show();
       }
   });
代码语言:javascript
复制
    ShareParams params = new ShareParams.Build()
                        .withDescribe("aa")
                        .withTitle("hahah")
                        .withUrl("http://www.baidu.com")
                        .withShareType(IWeixin.WXSceneSession)
                        .build();
    EasyPayShare.getInstance().doShareWx(mActivity, params, new ShareCallBack() {
        @Override
        public void onSuccess(String result) {
              Toast.makeText(activity, "分享成功", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onCanceled(String result) {
              Toast.makeText(activity, "取消分享", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onFailed(String result) {
              Toast.makeText(activity, "分享失败", Toast.LENGTH_SHORT).show();
        }
    });
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 扣浪 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 仿电商商品分类的思路实现
    • 我参照的是拼多多商品分类的界面来写的,先看看样图
      • 然后看看动态的效果图
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档