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

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

引言

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

效果图

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

然后看看动态的效果图

实现思路

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

布局代码实现

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

<?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的话,会导致界面显示不完全,而且还可以滑动,这是不允许的。

<?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

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。

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的数据填充

/**
 * 左边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的点击事件

/**
  * 左边列表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

实现代码

       /**
         * 右边滑动的监听事件
         */
        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出现,预计这个礼拜六把思路和代码整理出来分享给大家

    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();
       }
   });
    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();
        }
    });

原文发布于微信公众号 - codelang(codelang)

原文发表时间:2017-11-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android干货

Android项目实战(十四):TextView显示html样式的文字

4528
来自专栏Android学习之路

ViewDragHelper使用笔记及侧滑菜单实践

3566
来自专栏项勇

笔记20 | 学习整理开源APP(BaseAnimation)程序源码“中的通讯录效果(一)

1725
来自专栏三好码农的三亩自留地

打造Android微信朋友圈下拉刷新控件

我们初步分析下,界面上主要有二个控件,一个彩虹状的圆形LoadingView,一个是ListView,那么我大致可以有下面三个步骤:

3202
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-25(01)图形用户界面编程GUI

1:如何让Netbeans的东西Eclipse能访问。 在Eclipse中创建项目,把Netbeans项目的src下的东西给拿过来即可。 注意:修改项目编码...

5065
来自专栏androidBlog

自定义Behavior —— 仿知乎,FloatActionButton隐藏与展示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

1281
来自专栏学海无涯

Android开发之ListView使用经验分享

在Android开发中,ListView是使用最广泛的组件之一,虽然谷歌推出了RecycleView,但是很多项目中依旧在使用ListView,本文将总结一下使...

3236
来自专栏xingoo, 一个梦想做发明家的程序员

【插件开发】—— 7 SWT布局详解,不能再详细了!

前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 5 SWT简单控件的使用与布局搭...

23410
来自专栏向治洪

Android Material Design之Toolbar与Palette实践

前言 我们都知道Marterial Design是Google推出的全新UI设计规范,如果对其不太了解的可以看下:Material design非官方中文指导手...

2318
来自专栏学海无涯

Android开发之自定义View(二)

在 Android开发之自定义View(一)中,讲解了最复杂的一种自定义View,本次将剩下的两种讲完~~~ go,go,go 继承原有的控件,在原有控件基础上...

3388

扫码关注云+社区

领取腾讯云代金券