Android 多商品订单评价(类似淘宝)
前几日一商城类项目,有一需求,需要对一份订单的里面几个商品进行分别评价(图片,文字内容,星级);以前都是对一份订单所有商品一起评价,那种简单的多;
后来,承蒙老大细心指导,终于弄出来个看起来还算凑活的,还是先贴一下效果图吧。。。
抖动的有点卡,gif图的问题
图片的相关操作展示.gif 具体评价实现
*上面这张图是订单列表,可以看到有几个商品,要对这几个商品进行分条评价;
*这个gif图是具体的对每一个商品进行上传图片,内容,星级评价操作
好了,下面就来分析一下怎么写出这玩意,先从布局开始:
布局很好写,一看就可看出是一个listview,外加一个提交评论的按钮,给listview设置layout_weight属性,固定一下提交按钮的位置。
android:layout_weight="1"
然后就是listview的item,主要说下上传图片那一块,我添了三个imgview,比较low,做了一些判断,选择图片的控件是单选的,只好一个一个选,这样也好,比较简单清楚。
画了张草图,大家可以看一下,方便理解;
评价示意图.png
着重说一下代码实现:
1,首先,从上个订单页面传过来每个商品的id,图片,图片用于显示,商品id用来判定评价的是哪个商品,id 和图片用两个数组存起来;
//demo中在Mainactivity.java
private List<String> img = new ArrayList<>();
private List<String> ids = new ArrayList<>();
2,要给listview 填充数据,和获得item里面的每条数据,我们就先建一个实体类GoodsAssessBean.java,数据是下面几个,里面有几个方法,列出来(因为这是每条item的数据,所以,拿到相应的东西和方法相对好实现);
private String id;//商品id
private String icon;//商品图片
private String content ="";//商品评价内容
private ArrayList<String> imgList = new ArrayList<>();//七牛返回的图片url
private ArrayList<Bitmap> bitmapList = new ArrayList<>();//本地的bitmap
private String starts="0";//商品星级评定
/**
* 添加或更换图片
* @param bitmap 本地 bitmap
* @param index 图片的二级位置 0 或 1 或 2;初始值为0 需要加1与 bitmapList.size()比较
* @param url 七牛返回的图片地址
*/
public void addOrSetImage(Bitmap bitmap, int index, String url){
//如果小于等于证明需要更换图片;
if(index + 1 <= bitmapList.size()){
imgList.set(index, url);
bitmapList.set(index, bitmap);
}else{
//大于的话新增图片;
addBitMap(bitmap);
save(url);
}
}
/**
* 添加Bitmap
* @param bitmap
*/
public void addBitMap(Bitmap bitmap){
if(bitmapList.size()<3){
bitmapList.add(bitmap);
}
}
/**
*
* @param url 每个item里面的URL
*/
public void save(String url){
imgList.add(url);
}
/**
* 这个方法是把七牛返回的图片地址进行拼接,用“;”隔开
* @return
*/
public String getItemUrl(){
String urls="";
if(imgList.size() > 0){
for(int i=0;i<imgList.size();i++){
urls+= imgList.get(i)+";";
}
return urls.substring(0,urls.length()-1);
}else {
return " ";
}
}
/**
* 删除第几张图片
* @param index 第二层位置
*/
public void deleteImg(int index){
if(imgList.size()>index){
imgList.remove(index);
bitmapList.remove(index);
}
}
/**
* 把每个 item(每个商品)的评价内容,星级,图片等转成json格式;
* @return
*/
public String toSString(){
String str = "";
ReturnBean rb = new ReturnBean();
rb.setContent(getContent());
rb.setComment_img(getItemUrl());
rb.setGoods_num(getStarts());
rb.setOrdergoods_id(getId());
try {
str = JsonUtil.toJsonString(rb);
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
public ReturnBean getReturnBean(){
ReturnBean rb = new ReturnBean();
rb.setContent(getContent());
rb.setComment_img(getItemUrl());
rb.setGoods_num(getStarts());
rb.setOrdergoods_id(getId());
return rb;
}
3,在自己写一个图片帮助类AssessImgHelp。在这个类里,我们把写一个方法,把拿到的商品id,和商品图片存到实体类里,在这里面也有些方法,列出来。
public ArrayList<GoodsAssessBean> mBeanList = new ArrayList<>();
public AssessImgHelp(List<String> ids,List<String> icon){
for(int i=0;i<ids.size();i++){
mBeanList.add(new GoodsAssessBean(ids.get(i), icon.get(i)));
}
}
public ArrayList<GoodsAssessBean> getBeanList(){
return mBeanList;
}·
/**
*
* @param outIndex item的位置 相当于position
* @param bitmap bitmap用于本地显士
* @param url 七牛返回地址
* @param inIndex 图片位置
*/
public void doQiNiuDone(int outIndex, Bitmap bitmap, String url,int inIndex){
//哪个item调用GoodsAssessBean.java里的方法,也就是添加更换图片
mBeanList.get(outIndex).addOrSetImage(BitmapUtils.compressImage(bitmap), inIndex, url);
}
//长按删除图片
public void longDelete(int outIndex,int inIndex){
//调用GoodsAssessBean.java里的删除方法
mBeanList.get(outIndex).deleteImg(inIndex);
}
//生成json串
public String jsonSString(){
String str="";
ArrayList<ReturnBean> beanList = new ArrayList<>();
for(int i=0; i< getBeanList().size(); i++){
str += getBeanList().get(i).toSString();
beanList.add(getBeanList().get(i).getReturnBean());
}
Log.e("123", "beanList" + JsonUtil.object2JSON(beanList));
return JsonUtil.object2JSON(beanList);
}
4,最后一个帮助类AssessBeanUtils.java;存入list的position和每个item里面图片的位置,贴一下;
private int outIndex;
private int inIndex;
public void setBean(int outIndex,int inIndex){
this.outIndex = outIndex;
this.inIndex = inIndex;
}
public int getOutIndex() {
return outIndex;
}
public int getInIndex() {
return inIndex;
}
5,好的,现在到目前为止,我们所有的数据都能拿的到,还有一些图片的删除,更换,添加等等方法全部准备完毕,剩下的只是在MainActivity中调用即可(demo中的MainActivity),着重看几个地方;
//list之外的星级判定,物流,描述等获取可以用setOnRatingBarChangeListener()方法;
mRatingBarMiaoshu.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
miaoshu = rating + "";
}
});
/*
* 填充数据
* */
private void showData() {
//长按图片抖动效果
final Animation anim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.myanim);
mAdapter = new CommonAdapter<GoodsAssessBean>(MainActivity.this, assessImgHelp.getBeanList(), R.layout.item_assess) {
@Override
public void convert(ViewHolder helper, final GoodsAssessBean item, final int position) {
//加载商品图片
ImageLoad.loadImgDefault(MainActivity.this, (ImageView) helper.getView(R.id.m_assess), item.getIcon());
//获取商品星级评价
((RatingBar) helper.getView(R.id.m_ratingBar_shop)).setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
item.setStarts(rating + "");
}
});
//获取评价内容
((EditText) helper.getView(R.id.m_assess_edt)).addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
item.setContent(s + "");
}
});
//三个imageView和三个删除按钮
final ImageView img1 = helper.getView(R.id.m_menmian1_icon);
final ImageView img2 = helper.getView(R.id.m_menmian2_icon);
final ImageView img3 = helper.getView(R.id.m_menmian3_icon);
final ImageView imgclose1 = helper.getView(R.id.m_image_one);
final ImageView imgclose2 = helper.getView(R.id.m_image_two);
final ImageView imgclose3 = helper.getView(R.id.m_image_three);
img1.setScaleType(ImageView.ScaleType.CENTER_CROP);//CENTER_CROP FIT_XY
img2.setScaleType(ImageView.ScaleType.CENTER_CROP);//CENTER_CROP FIT_XY
img3.setScaleType(ImageView.ScaleType.CENTER_CROP);//CENTER_CROP FIT_XY
//获取本地图片数量。分别对应相应的显示
int size = item.getBitMapListSize();
if (size == 0) {
setImageViewVisibility(img1, true, img2, false, img3, false);
img1.setImageResource(R.mipmap.pj_tj);//默认图片
} else if (size == 1) {
setImageViewVisibility(img1, true, img2, true, img3, false);
img1.setImageBitmap(item.getBitmapList().get(0));
img2.setImageResource(R.mipmap.pj_tj);
} else if (size == 2) {
setImageViewVisibility(img1, true, img2, true, img3, true);
img1.setImageBitmap(item.getBitmapList().get(0));
img2.setImageBitmap(item.getBitmapList().get(1));
img3.setImageResource(R.mipmap.pj_tj);
} else if (size == 3) {
setImageViewVisibility(img1, true, img2, true, img3, true);
img1.setImageBitmap(item.getBitmapList().get(0));
img2.setImageBitmap(item.getBitmapList().get(1));
img3.setImageBitmap(item.getBitmapList().get(2));
}
//点击事件
img1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("123", "img: " + img1.getId());
mAssessBean.setBean(position, 0);//存储一级二级位置
new PopupWindows(MainActivity.this);//弹出选择头像,相册
}
});
img2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAssessBean.setBean(position, 1);
new PopupWindows(MainActivity.this);
}
});
img3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAssessBean.setBean(position, 2);
new PopupWindows(MainActivity.this);
}
});
img1.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//一些小细节判断,如果第一张没有图片,长按提示请选择图片
if (assessImgHelp.getBeanList().get(position).getImgListSize() > 0) {
img1.startAnimation(anim);//抖动效果
imgclose1.setVisibility(View.VISIBLE);//显示删除按钮
} else {
toast("请添加图片");
}
return true;
}
});
//删除按钮点击事件
imgclose1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
assessImgHelp.longDelete(position, 0);//调用删除方法
mAdapter.notifyDataSetChanged();
imgclose1.setVisibility(View.GONE);
toast("删除成功");
}
});
img2.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (assessImgHelp.getBeanList().get(position).getImgListSize() > 1) {
img2.startAnimation(anim);
imgclose2.setVisibility(View.VISIBLE);
} else {
toast("请添加图片");
}
return true;
}
});
imgclose2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
assessImgHelp.longDelete(position, 1);
mAdapter.notifyDataSetChanged();
imgclose2.setVisibility(View.GONE);
toast("删除成功");
}
});
img3.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (assessImgHelp.getBeanList().get(position).getImgListSize() > 2) {
img3.startAnimation(anim);
imgclose3.setVisibility(View.VISIBLE);
} else {
toast("请添加图片");
}
return true;
}
});
imgclose3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
assessImgHelp.longDelete(position, 2);
mAdapter.notifyDataSetChanged();
imgclose3.setVisibility(View.GONE);
toast("删除成功");
}
});
}
};
mAssessList.setAdapter(mAdapter);
}
//图片的显示与隐藏
public void setImageViewVisibility(ImageView img1, boolean boo1, ImageView img2, boolean boo2, ImageView img3, boolean boo3) {
img1.setVisibility(boo1 ? View.VISIBLE : View.GONE);
img2.setVisibility(boo2 ? View.VISIBLE : View.GONE);
img3.setVisibility(boo3 ? View.VISIBLE : View.GONE);
}
后面的就是一些调用相册,相机,选取图片,上传七牛,还有就是6.0权限问题也有判断。
七牛上传成功之后,调这个方法:
//第一个是position,第三个是七牛返回的图片地址,第四个是图片位置;
assessImgHelp.doQiNiuDone(mAssessBean.getOutIndex(), bitmap, key, mAssessBean.getInIndex());
具体看Demo吧,足够详细,绝对能看懂,以上;
https://github.com/WKaKa/Assess
PS:图片提示失败是应为七牛Token接口失效了,需要换成自己项目里的。
2017,5,19.png拍完照或者选择完图片后,之前填写的星级和内容会刷新掉。解决方法就是弄两个hashMap暂时存一下,只是用来显示。。。。。。
HashMap<Integer, String> saveMap = new HashMap<Integer, String>();;//这个集合用来存储对应位置上Editext中的文本内容
HashMap<Integer, Float> saveMapStart = new HashMap<Integer, Float>();;//这个集合用来存储对应位置上评价星级
((RatingBar) helper.getView(R.id.m_ratingBar_shop)).setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
item.setStarts(rating + "");
Integer tag= (Integer) helper.getView(R.id.m_assess_edt).getTag();
saveMapStart.put(tag, rating);//在这里根据position去保存文本内容
}
});
((EditText) helper.getView(R.id.m_assess_edt)).addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
item.setContent(s + "");
Integer tag= (Integer) helper.getView(R.id.m_assess_edt).getTag();
saveMap.put(tag, s.toString());//在这里根据position去保存文本内容
}
});
helper.getView(R.id.m_assess_edt).setTag(position);//设置editext一个标记
helper.getView(R.id.m_assess_edt).clearFocus();//清除焦点 不清除的话因为item复用的原因 多个Editext同时改变
((EditText) helper.getView(R.id.m_assess_edt)).setText(saveMap.get(position));//将对应保存在集合中的文本内容取出来 并显示上去
helper.getView(R.id.m_ratingBar_shop).setTag(position);//设置editext一个标记
helper.getView(R.id.m_ratingBar_shop).clearFocus();//清除焦点 不清除的话因为item复用的原因 多个Editext同时改变
if(saveMapStart.get(position) == null){
((RatingBar) helper.getView(R.id.m_ratingBar_shop)).setRating(0);//将对应保存在集合中的文本内容取出来 并显示上去
}else {
((RatingBar) helper.getView(R.id.m_ratingBar_shop)).setRating(saveMapStart.get(position));//将对应保存在集合中的文本内容取出来 并显示上去
}
2017,12,22