电商开发之商品属性分类

前一段时间一直在忙其他项目,没有时间发博客,今天闲下来,发一下之前写过的电商开发商品属性分类的功能,借鉴大神的逻辑,适配器的写法和大神的基本你一样

http://blog.csdn.net/u010924834/article/details/50353955

基本看起来,实在不明白activity或者fragment里边该怎么写,思路断断续续,太难掌控了,没办法,谁让我是菜鸟呢,只能慢慢想,慢慢整理逻辑了,用了将近三天时间终于吧这个弄出来了,先看下数据吧

{
  "data": [
    {
      "content": "红色,黑色,白色,蓝色,粉色,紫色,彩色,花白色,藏青色,黑白色,卡其色,粉红色,亮白色,浅灰色,玫瑰红,黄色,蓝色,绿色,金色,嫩黄色",
      "title": "颜色"
    },
    {
      "content": "34,34,39,41,10,49,43,48,12,42,68",
      "title": "尺码"
    },
    {
      "content": "M,L,S,XL,XXL,XXXL,X,XX,XXX,XXXXL,XXXX,LL,SS,MM",
      "title": "样式"
    }
  ]
}
这是分类的json数据

然后再看下适配器吧

package com.demo.demo_gridview;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 小明 on 2016/11/1.
 */
public class GoodSelectAdapter extends MyBaseAdapter<List<Map<String, Object>>> {

    //用于保存用户的属性集合
    private Map<String, String> selectProMap = new HashMap();
    private int index = 1;
    private ArrayList<HashMap<String, TextView[]>> mViewList;

    private OnTextClickListener listener;

    public GoodSelectAdapter(OnTextClickListener listener, Context context, List<Map<String, Object>> datas, Map<String, String> hashmap) {
        super(context, datas);
        this.selectProMap = hashmap;
        mViewList = new ArrayList<>();
        this.listener = listener;
    }

    @Override
    public View getViewDatas(int position, View convertView, ViewGroup parent) {

        index++;
        Log.i("aaa", index + "");
        ViewHolder holder = null;
        if (convertView == null) {
            // 获取list_item布局文件的视图
            convertView = LayoutInflater.from(context).inflate(R.layout.tag_item, null, true);
            holder = new ViewHolder();
            // 获取控件对象
            holder.tvPropName = (TextView) convertView.findViewById(R.id.tv_property_name);
            holder.vgPropContents = (MyViewGroup) convertView.findViewById(R.id.myviewgroup);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        if (this.datas != null) {
            ArrayList<String> lables = (ArrayList<String>) datas.get(position).get("lable");
            String type = (String) datas.get(position).get("type");
            holder.tvPropName.setText(type);//规格名称
            //动态加载标签
            //判断布局中的子控件是否为0,如果不为0,就不添加了,防止ListView滚动时重复添加
            if (holder.vgPropContents.getChildCount() == 0) {
                TextView[] textViews = new TextView[lables.size()];
                //设置每个标签的文本和布局
                for (int i = 0; i < lables.size(); i++) {
                    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                    params.setMargins(15, 15, 15, 0);
                    TextView textView = new TextView(context);
                    textView.setGravity(17);
                    textView.setPadding(25, 15, 25, 15);
                    textView.setLayoutParams(params);
                    textViews[i] = textView;
                    textViews[i].setBackgroundResource(R.color.white);
                    textViews[i].setText(lables.get(i));
                    textViews[i].setTag(i);
                    holder.vgPropContents.addView(textViews[i]);
                }
                //绑定标签的Click事件
                for (int j = 0; j < textViews.length; j++) {
                    textViews[j].setTag(textViews);
                    textViews[j].setOnClickListener(new LableClickListener(type));
                }
            }
            /**判断之前是否已选中标签*/
            if (selectProMap.get(type) != null) {
                for (int h = 0; h < holder.vgPropContents.getChildCount(); h++) {
                    TextView v = (TextView) holder.vgPropContents.getChildAt(h);
                    if (selectProMap.get(type).equals(v.getText().toString())) {
                        v.setBackgroundColor(Color.parseColor("#EE5500"));
                        v.setTextColor(Color.parseColor("#FFFFFF"));
                        selectProMap.put(type, v.getText().toString());
                    }
                }
            }
        }
        return convertView;
    }

    /*定义item对象*/
    public class ViewHolder {

        TextView tvPropName;
        MyViewGroup vgPropContents;
    }

    class LableClickListener implements View.OnClickListener {
        private String type;

        public LableClickListener(String type) {
            this.type = type;
        }

        @Override
        public void onClick(View v) {
            TextView[] textViews = (TextView[]) v.getTag();
            TextView tv = (TextView) v;
            for (int i = 0; i < textViews.length; i++) {
                //让点击的标签背景变成橙色,字体颜色变为白色
                if (tv.equals(textViews[i])) {
                    textViews[i].setBackgroundColor(Color.parseColor("#EE5500"));
                    textViews[i].setTextColor(Color.parseColor("#FFFFFF"));
                    selectProMap.put(type, textViews[i].getText().toString());
                    listener.onClick(type, textViews[i].getText().toString());
                } else {
                    //其他标签背景变成白色,字体颜色为黑色
                    textViews[i].setBackgroundResource(R.color.white);
                    textViews[i].setTextColor(Color.parseColor("#000000"));
                }
            }

        }

    }

    public interface OnTextClickListener{
        void onClick(String title, String text);
    }

}
基本上就是照搬大神的源码了,说明一下,之所以写一个回调接口

    public interface OnTextClickListener{
        void onClick(String title, String text);
    }
是因为我这边的服务器是仿照京东写的,在开始进来的时候需要给服务器的分类数据必须是
颜色:白色,尺码,23,演示:xxl
所以需要拼接了,而大神写出来的,点击之后显示的只是一个类别,比如点击红色,他就会显示红色,而viewgroup则不是是用的他写出来的,而是是用的鸿洋大神的自定义viewgroup

http://blog.csdn.net/lmj623565791/article/details/38352503/

子所以不是用他写的,相信体验过的程序员已经测试过了,他写出来的viewgroup显示的分类一个是不全,还需要改动viewgroup里边的代码,我记得是在onMeasure()里边计算viewgroup的高度的时候需要在他计算的高度上再加上75,这样看起来还算是可以吧,不过属性名和属性分类的间距太大了,至于怎么修改,我完全懵逼了,没办法本菜只能再去找去他的viewgroup了,

package com.demo.demo_gridview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by 小明 on 2016/12/7.
 */

public class MyViewGroup extends ViewGroup {

    private static final String TAG = "FlowLayout";


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

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(
            ViewGroup.LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT);
    }

    /**
     * 负责设置子控件的测量模式和大小 根据所有子控件设置自己的宽和高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 获得它的父容器为它设置的测量模式和大小
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

        Log.e(TAG, sizeWidth + "," + sizeHeight);

        // 如果是warp_content情况下,记录宽和高
        int width = 0;
        int height = 0;
        /**
         * 记录每一行的宽度,width不断取最大宽度
         */
        int lineWidth = 0;
        /**
         * 每一行的高度,累加至height
         */
        int lineHeight = 0;

        int cCount = getChildCount();

        // 遍历每个子元素
        for (int i = 0; i < cCount; i++) {
            View child = getChildAt(i);
            // 测量每一个child的宽和高
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            // 得到child的lp
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            // 当前子空间实际占据的宽度
            int childWidth = child.getMeasuredWidth() + lp.leftMargin
                    + lp.rightMargin;
            // 当前子空间实际占据的高度
            int childHeight = child.getMeasuredHeight() + lp.topMargin
                    + lp.bottomMargin;
            /**
             * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行
             */
            if (lineWidth + childWidth > sizeWidth) {
                width = Math.max(lineWidth, childWidth);// 取最大的
                lineWidth = childWidth; // 重新开启新行,开始记录
                // 叠加当前高度,
                height += lineHeight;
                // 开启记录下一行的高度
                lineHeight = childHeight;
            } else
            // 否则累加值lineWidth,lineHeight取最大高度
            {
                lineWidth += childWidth;
                lineHeight = Math.max(lineHeight, childHeight);
            }
            // 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较
            if (i == cCount - 1) {
                width = Math.max(width, lineWidth);
                height += lineHeight;
            }

        }
        setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth
                : width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight
                : height);

    }

    /**
     * 存储所有的View,按行记录
     */
    private List<List<View>> mAllViews = new ArrayList<List<View>>();
    /**
     * 记录每一行的最大高度
     */
    private List<Integer> mLineHeight = new ArrayList<Integer>();

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mAllViews.clear();
        mLineHeight.clear();

        int width = getWidth();

        int lineWidth = 0;
        int lineHeight = 0;
        // 存储每一行所有的childView
        List<View> lineViews = new ArrayList<View>();
        int cCount = getChildCount();
        // 遍历所有的孩子
        for (int i = 0; i < cCount; i++) {
            View child = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            // 如果已经需要换行
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width) {
                // 记录这一行所有的View以及最大高度
                mLineHeight.add(lineHeight);
                // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView
                mAllViews.add(lineViews);
                lineWidth = 0;// 重置行宽
                lineViews = new ArrayList<View>();
            }
            /**
             * 如果不需要换行,则累加
             */
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin
                    + lp.bottomMargin);
            lineViews.add(child);
        }
        // 记录最后一行
        mLineHeight.add(lineHeight);
        mAllViews.add(lineViews);

        int left = 0;
        int top = 0;
        // 得到总行数
        int lineNums = mAllViews.size();
        for (int i = 0; i < lineNums; i++) {
            // 每一行的所有的views
            lineViews = mAllViews.get(i);
            // 当前行的最大高度
            lineHeight = mLineHeight.get(i);

            Log.e(TAG, "第" + i + "行 :" + lineViews.size() + " , " + lineViews);
            Log.e(TAG, "第" + i + "行, :" + lineHeight);

            // 遍历当前行所有的View
            for (int j = 0; j < lineViews.size(); j++) {
                View child = lineViews.get(j);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }
                MarginLayoutParams lp = (MarginLayoutParams) child
                        .getLayoutParams();

                //计算childView的left,top,right,bottom
                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc = lc + child.getMeasuredWidth();
                int bc = tc + child.getMeasuredHeight();

                Log.e(TAG, child + " , l = " + lc + " , t = " + t + " , r ="
                        + rc + " , b = " + bc);

                child.layout(lc, tc, rc, bc);

                left += child.getMeasuredWidth() + lp.rightMargin
                        + lp.leftMargin;
            }
            left = 0;
            top += lineHeight;
        }

    }

}
这就是鸿洋大神的代码了,至于怎么去计算的,别来问我,因为我也不会,怎么自定义viewgroup,还是推荐鸿洋大神的博客

http://blog.csdn.net/lmj623565791/article/details/38339817

感兴趣的刻意去看看,很不错的

废话不多说了。上activity代码,其他的都可以找打,唯独activity里边的代码是没有的,可怜的我搞了三天才能完全运行啊,本菜好可怜,你们也不给我个赞哭

package com.demo.demo_gridview;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 小明 on 2016/12/6.
 */

public class StartActivity extends AppCompatActivity implements GoodSelectAdapter.OnTextClickListener {

    //数据实体类
    private ShopDeialResponseDto responseDto;
    //数据集合
    private List<ShopDeialResponseDto.DataEntity> datas;
    private Context context;
    //父布局
    private LinearLayout activity_main;
    //需要上传服务器  请求图片属性的集合
    private Map<String, String> hashmap = new HashMap<>();;
    //适配器
    private GoodSelectAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = this;
        setContentView(R.layout.activity_main);
        //沉浸式   请忽略
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
        }
        //绑定控件
        activity_main = (LinearLayout) findViewById(R.id.activity_main);
        datas = new ArrayList<>();
        //解析json
        String json = FileUtils.getJson("commodity.json", this);
        responseDto = new Gson().fromJson(json, ShopDeialResponseDto.class);
        //数据添加
        setDatas();
    }

    private void setDatas() {
        //得到数据
        datas = responseDto.getData();
        String content[] = new String[datas.size()];
        //吧数据拆分成三个数据 因为只有三条json数据
        for (int i = 0; i < datas.size(); i++) {
            content[i] = datas.get(i).getContent();
        }
        //对数组进行拆分
        for (int j = 0; j < content.length; j++) {
            Map<String, Object> map = new HashMap<>();
            //添加属性标题
            map.put("type", datas.get(j).getTitle());
            //拆分字符串  得到一个新的数组
            String str[] = (content[j].split(","));
            List<String> list1 = new ArrayList();
            //循环数组  得到一个新的listview需要的集合
            for (int i = 0; i < str.length; i++) {
                list1.add(str[i]);
                //添加属性集合
                parameter.put(datas.get(j).getTitle(), datas.get(j).getTitle() + ":" + list1.get(0));
            }
            //添加属性内容
            map.put("lable", list1);
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(map);
//            RecyclerView recyclerView = new RecyclerView(context);
//            adapter1 = new HomeAdapter(context, list, hashmap);
            ListView listView = new ListView(context);
            adapter = new GoodSelectAdapter(this, context, list, hashmap);
            listView.setAdapter(adapter);
            activity_main.addView(listView);
        }

        String property = null;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < parameter.size(); i++) {
            if (i == parameter.size() - 1) {
                property = sb.append(parameter.get(datas.get(i).getTitle())).toString();
            } else {
                property = sb.append(parameter.get(datas.get(i).getTitle()) + ",").toString();
            }
        }
        Toast.makeText(context, property.toString(), Toast.LENGTH_SHORT).show();
    }

    /**
     * 服务器需要的数据是一个string字符串
     * 颜色:白色,尺码,23,演示:xxl
     * @param title
     * @param text
     */
    //属性集合
    private Map<String, String> parameter = new HashMap<>();
    @Override
    public void onClick(String title, String text) {
        parameter.put(title, title + ":" + text);
        StringBuffer property = new StringBuffer();
        for (int i = 0; i < parameter.size(); i++) {
            if (i == parameter.size() - 1) {
                property.append(parameter.get(datas.get(i).getTitle()));
            } else {
                property.append(parameter.get(datas.get(i).getTitle()) + ",");
            }
        }
        Toast.makeText(context, property.toString(), Toast.LENGTH_SHORT).show();
    }
}
因为是单独写出来的一个项目,所以吧json数据写在了assets里边,里边有一段这样的代码
        //沉浸式   请忽略
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
        }
这是本菜在测试沉浸式,请忽略就好,如果有人也想试试沉浸式,建议吧build.gradle里边的v7包改成22.2.。0以上的
    compile 'com.android.support:appcompat-v7:22.2.1'
其中的一个方法
    /**
     * 服务器需要的数据是一个string字符串
     * 颜色:白色,尺码,23,演示:xxl
     * @param title
     * @param text
     */
    //属性集合
    private Map<String, String> parameter = new HashMap<>();
    @Override
    public void onClick(String title, String text) {
        parameter.put(title, title + ":" + text);
        StringBuffer property = new StringBuffer();
        for (int i = 0; i < parameter.size(); i++) {
            if (i == parameter.size() - 1) {
                property.append(parameter.get(datas.get(i).getTitle()));
            } else {
                property.append(parameter.get(datas.get(i).getTitle()) + ",");
            }
        }
        Toast.makeText(context, property.toString(), Toast.LENGTH_SHORT).show();
    }
则是适配器的回调接口里边重写的方法了,返回数据,在activity里边进行操作。当然activity要实现adapter里边的ontextClickListener接口了。

基本上就是这样了,如果还有不明白的,或者更好地方法,请告诉我,谢谢,顺便求点赞,谢谢!!

项目地址:http://download.csdn.net/detail/sinat_29874521/9708583

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
电商小程序后端开发的功能点包括但不限于以下几个方面: 1. 用户管理: 实现用户的注册、登录、个人信息管理等功能,包括用户身份验证和权限控制。 2. 商品管理: 实现商品的添加、编辑、删除、查询等功能,包括商品分类属性、库存管理等。 3. 订单管理: 实现订单的创建、支付、取消、发货、退款等功能,包括订单状态的管理和订单与商品的关联。 4. 购物车管理: 实现购物车中商品的添加、删除、数量修改等功能,包括购物车与用户和商品的关联。 5. 支付管理: 实现与第三方支付平台的对接,处理用户支付请求,生成支付订单等。 6. 物流管理: 实现订单的物流跟踪功能,包括订单发货、物流信息查询等。 7. 评价管理: 实现用户对商品的评价功能,包括评价的提交、查看、回复等。 8. 促销管理: 实现促销活动的创建、管理、展示等功能,包括满减、折扣、优惠券等。 9. 数据统计与分析: 实现对用户、商品、订单等数据的统计和分析,提供数据报表和可视化展示。 10. 客服与反馈: 实现用户与客服的实时通讯功能,包括在线咨询、投诉建议等。 以上只是电商小程序后端开发中的一些常见功能点,具体的功能需求还会根据实际业务需求而有所差异。123 #### 引用[.reference_title] - *1* *3* [从零开始,开发一个电商微信小程序[前端+后端(c#)]](https://blog.csdn.net/weixin_42794881/article/details/109178368)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* [搭建JAVA电商平台——后端](https://blog.csdn.net/Akira_Rexlee/article/details/81144817)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值