前幾日一商城類項(xiàng)目,有一需求,需要對一份訂單的里面幾個(gè)商品進(jìn)行分別評價(jià)(圖片,文字內(nèi)容,星級);以前都是對一份訂單所有商品一起評價(jià),那種簡單的多;
后來,承蒙老大細(xì)心指導(dǎo),終于弄出來個(gè)看起來還算湊活的,還是先貼一下效果圖吧。。。
抖動(dòng)的有點(diǎn)卡,gif圖的問題


*上面這張圖是訂單列表,可以看到有幾個(gè)商品,要對這幾個(gè)商品進(jìn)行分條評價(jià);
*這個(gè)gif圖是具體的對每一個(gè)商品進(jìn)行上傳圖片,內(nèi)容,星級評價(jià)操作
好了,下面就來分析一下怎么寫出這玩意,先從布局開始:
布局很好寫,一看就可看出是一個(gè)listview,外加一個(gè)提交評論的按鈕,給listview設(shè)置layout_weight屬性,固定一下提交按鈕的位置。
android:layout_weight="1"
然后就是listview的item,主要說下上傳圖片那一塊,我添了三個(gè)imgview,比較low,做了一些判斷,選擇圖片的控件是單選的,只好一個(gè)一個(gè)選,這樣也好,比較簡單清楚。
畫了張草圖,大家可以看一下,方便理解;

著重說一下代碼實(shí)現(xiàn):
1,首先,從上個(gè)訂單頁面?zhèn)鬟^來每個(gè)商品的id,圖片,圖片用于顯示,商品id用來判定評價(jià)的是哪個(gè)商品,id 和圖片用兩個(gè)數(shù)組存起來;
//demo中在Mainactivity.java
private List<String> img = new ArrayList<>();
private List<String> ids = new ArrayList<>();
2,要給listview 填充數(shù)據(jù),和獲得item里面的每條數(shù)據(jù),我們就先建一個(gè)實(shí)體類GoodsAssessBean.java,數(shù)據(jù)是下面幾個(gè),里面有幾個(gè)方法,列出來(因?yàn)檫@是每條item的數(shù)據(jù),所以,拿到相應(yīng)的東西和方法相對好實(shí)現(xiàn));
private String id;//商品id
private String icon;//商品圖片
private String content ="";//商品評價(jià)內(nèi)容
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 每個(gè)item里面的URL
*/
public void save(String url){
imgList.add(url);
}
/**
* 這個(gè)方法是把七牛返回的圖片地址進(jìn)行拼接,用“;”隔開
* @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);
}
}
/**
* 把每個(gè) item(每個(gè)商品)的評價(jià)內(nèi)容,星級,圖片等轉(zhuǎn)成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,在自己寫一個(gè)圖片幫助類AssessImgHelp。在這個(gè)類里,我們把寫一個(gè)方法,把拿到的商品id,和商品圖片存到實(shí)體類里,在這里面也有些方法,列出來。
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的位置 相當(dāng)于position
* @param bitmap bitmap用于本地顯士
* @param url 七牛返回地址
* @param inIndex 圖片位置
*/
public void doQiNiuDone(int outIndex, Bitmap bitmap, String url,int inIndex){
//哪個(gè)item調(diào)用GoodsAssessBean.java里的方法,也就是添加更換圖片
mBeanList.get(outIndex).addOrSetImage(BitmapUtils.compressImage(bitmap), inIndex, url);
}
//長按刪除圖片
public void longDelete(int outIndex,int inIndex){
//調(diào)用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,最后一個(gè)幫助類AssessBeanUtils.java;存入list的position和每個(gè)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,好的,現(xiàn)在到目前為止,我們所有的數(shù)據(jù)都能拿的到,還有一些圖片的刪除,更換,添加等等方法全部準(zhǔn)備完畢,剩下的只是在MainActivity中調(diào)用即可(demo中的MainActivity),著重看幾個(gè)地方;
//list之外的星級判定,物流,描述等獲取可以用setOnRatingBarChangeListener()方法;
mRatingBarMiaoshu.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
miaoshu = rating + "";
}
});
/*
* 填充數(shù)據(jù)
* */
private void showData() {
//長按圖片抖動(dòng)效果
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());
//獲取商品星級評價(jià)
((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 + "");
}
});
//獲取評價(jià)內(nèi)容
((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 + "");
}
});
//三個(gè)imageView和三個(gè)刪除按鈕
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
//獲取本地圖片數(shù)量。分別對應(yīng)相應(yīng)的顯示
int size = item.getBitMapListSize();
if (size == 0) {
setImageViewVisibility(img1, true, img2, false, img3, false);
img1.setImageResource(R.mipmap.pj_tj);//默認(rèn)圖片
} 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));
}
//點(diǎn)擊事件
img1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("123", "img: " + img1.getId());
mAssessBean.setBean(position, 0);//存儲(chǔ)一級二級位置
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) {
//一些小細(xì)節(jié)判斷,如果第一張沒有圖片,長按提示請選擇圖片
if (assessImgHelp.getBeanList().get(position).getImgListSize() > 0) {
img1.startAnimation(anim);//抖動(dòng)效果
imgclose1.setVisibility(View.VISIBLE);//顯示刪除按鈕
} else {
toast("請?zhí)砑訄D片");
}
return true;
}
});
//刪除按鈕點(diǎn)擊事件
imgclose1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
assessImgHelp.longDelete(position, 0);//調(diào)用刪除方法
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("請?zhí)砑訄D片");
}
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("請?zhí)砑訄D片");
}
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);
}
后面的就是一些調(diào)用相冊,相機(jī),選取圖片,上傳七牛,還有就是6.0權(quán)限問題也有判斷。
七牛上傳成功之后,調(diào)這個(gè)方法:
//第一個(gè)是position,第三個(gè)是七牛返回的圖片地址,第四個(gè)是圖片位置;
assessImgHelp.doQiNiuDone(mAssessBean.getOutIndex(), bitmap, key, mAssessBean.getInIndex());
具體看Demo吧,足夠詳細(xì),絕對能看懂,以上;
https://github.com/WKaKa/Assess
PS:圖片提示失敗是應(yīng)為七牛Token接口失效了,需要換成自己項(xiàng)目里的。

拍完照或者選擇完圖片后,之前填寫的星級和內(nèi)容會(huì)刷新掉。解決方法就是弄兩個(gè)hashMap暫時(shí)存一下,只是用來顯示。。。。。。
HashMap<Integer, String> saveMap = new HashMap<Integer, String>();;//這個(gè)集合用來存儲(chǔ)對應(yīng)位置上Editext中的文本內(nèi)容
HashMap<Integer, Float> saveMapStart = new HashMap<Integer, Float>();;//這個(gè)集合用來存儲(chǔ)對應(yīng)位置上評價(jià)星級
((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);//在這里根據(jù)position去保存文本內(nèi)容
}
});
((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());//在這里根據(jù)position去保存文本內(nèi)容
}
});
helper.getView(R.id.m_assess_edt).setTag(position);//設(shè)置editext一個(gè)標(biāo)記
helper.getView(R.id.m_assess_edt).clearFocus();//清除焦點(diǎn) 不清除的話因?yàn)閕tem復(fù)用的原因 多個(gè)Editext同時(shí)改變
((EditText) helper.getView(R.id.m_assess_edt)).setText(saveMap.get(position));//將對應(yīng)保存在集合中的文本內(nèi)容取出來 并顯示上去
helper.getView(R.id.m_ratingBar_shop).setTag(position);//設(shè)置editext一個(gè)標(biāo)記
helper.getView(R.id.m_ratingBar_shop).clearFocus();//清除焦點(diǎn) 不清除的話因?yàn)閕tem復(fù)用的原因 多個(gè)Editext同時(shí)改變
if(saveMapStart.get(position) == null){
((RatingBar) helper.getView(R.id.m_ratingBar_shop)).setRating(0);//將對應(yīng)保存在集合中的文本內(nèi)容取出來 并顯示上去
}else {
((RatingBar) helper.getView(R.id.m_ratingBar_shop)).setRating(saveMapStart.get(position));//將對應(yīng)保存在集合中的文本內(nèi)容取出來 并顯示上去
}
2017,12,22