您的位置:首页 > 移动开发 > Android开发

电商开发之商品属性分类

2017-01-03 12:15 661 查看
前一段时间一直在忙其他项目,没有时间发博客,今天闲下来,发一下之前写过的电商开发商品属性分类的功能,借鉴大神的逻辑,适配器的写法和大神的基本你一样
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐