电商开发之商品属性分类
来源:互联网 发布:假短信软件 编辑:程序博客网 时间:2024/05/16 07:11
前一段时间一直在忙其他项目,没有时间发博客,今天闲下来,发一下之前写过的电商开发商品属性分类的功能,借鉴大神的逻辑,适配器的写法和大神的基本你一样
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
- 电商开发之商品属性分类
- 电商Demo商品分类
- 商品分类 商品类型 商品属性
- 【Android开发—电商系列】(二):仿淘宝商品属性标签页
- 【Android开发—电商系列】(二):仿淘宝商品属性标签页
- Android开发—电商系列】(二):仿淘宝商品属性标签页
- ecshop后台商品属性详解之分类页属…
- 商城之商品分类
- Android开发之TextView中间设置横线,适用于电商项目,商品原价之类的功能。
- Android开发之TextView中间设置横线,适用于电商项目,商品原价之类的功能。
- Android开发之TextView中间设置横线,适用于电商项目,商品原价之类的功能。
- 商城开发之商品分类表的设计、使用、管理
- 电商商品爬虫
- 我的产品开发之旅(3) - 设计商品一级、二级分类、推荐商品表
- 电商系统中的分类属性系统设计之我见(抛砖引玉)
- 商城之首页商品分类
- 电商项目笔记之九:商品类别管理
- Solr应用之电商商品搜索备忘
- 关于os的一系列问题:统计当前目录下每个文件类型的文件数
- Oracle修改字段类型方法总结
- 光照和阴影算法该如何优化?
- 控制GPS/WIFI/蓝牙/飞行模式
- 德国:一个中国人在德国生活的真实感受
- 电商开发之商品属性分类
- 图解集合1:ArrayList
- 《iOS移动开发从入门到精通》图书连载11:字符和字符串
- 使用newInstance()来实例化fragment
- 图解集合2:LinkedList
- DPC计时器
- Retrofit2 Cookie管理-按声明决定是否带Cookie请求接口
- java中自定义注解的作用和写法
- Oracle "ORA-00942: 表或视图不存在 "的原因和解决方法