一、首先说互评:今天朋友圈里要实现用户相互评论回复的功能,不同的用户对其他用户上传的图片进行评论,同时也要对用户评论的内容及进行回复。。
这里面要理清的几个逻辑:
A上传了图片:
1、B可以直接点击界面上的评论按钮,对A的图片进行评论
2、C可以点击B的评论,然后进行评论回复
3、A对B(或者C)进行回复
这里面的要解决的问题:
1、评论编辑框的弹出有两个入口:
1.1 点击评论图标 ,编辑框的hint是”回复 :上传图片的用户“
1.2 点击评论内容 ,编辑框的hint是”回复:此条评论的发起人“
并且二者都是绑定了相同的监听器,监听内容就是监听到用户点击评论图标、或者评论的内容,都会展开这个comment_layout,然后编辑框里面的hint显示出来。由于不同的入口,编辑框里面的hint内容不一样,因此这个监听器就要判断用户是点击了哪个控件,根据传入的控件的id进行判断,然后在执行相应的操作。
下面看一下监听器的参数:
private Button.OnClickListener btnCommentListener = new Button.OnClickListener() { @Override public void onClick(View arg0) { if(arg0.getId()== R.id.imgbtn_comment){//如果是点击评论图标 comment_layout.setVisibility(View.VISIBLE); comment_ediText.setHint(" 回复 " + users_name+ " : "); flag_comment = 0; //这里的标志位是为了区分两种方式,从而在后面执行提交评论异步任务传参的时候进行区分 } else{//如果是点击评论内容 TextView txtCommentNew = (TextView)arg0; //获取传进来的textview,就是单条评论内容 String txtComment1 = txtCommentNew.getText().toString(); String txtCommentsplit[] = txtComment1.split(" "); /取出评论内容里面的评论的发起人 replyed_user = txtCommentsplit[0]; if(!replyed_user.equals(ARUtils.username)){ comment_layout.setVisibility(View.VISIBLE); comment_ediText.setHint(" 回复 " + replyed_user + " : "); flag_comment = 1; }else Toast.makeText(mContext, "您不能对自己评论。", Toast.LENGTH_SHORT).show();//如果评论的发起人就是用户自己,判断一下 } } };
上面完成了对用户进入评论的入口进行判断,又有一个问题,就是提交评论异步任务的时候,我给服务器传的参数不同,因为被评论人是不一样的,这样我在程序里面设置了一个全局变量,标志位flag_comment,用于区分用户是点击评论图标对图片上传的用户进行直接评论,还是点击评论内容对评论的发起人进行回复:
//发送评论异步任务 class webTaskForComment extends AsyncTask<String, String, String> { @Override protected String doInBackground(String... params) { ArrayList<NameValuePair> paramsToPass = new ArrayList<NameValuePair>(); paramsToPass.add(new BasicNameValuePair("comment_users", params[0])); paramsToPass.add(new BasicNameValuePair("commented_users", params[1])); paramsToPass.add(new BasicNameValuePair("comment_contents", params[2])); paramsToPass.add(new BasicNameValuePair("passWord", params[3])); paramsToPass.add(new BasicNameValuePair("picture_id", params[4])); String serverResp = "未获得数据,请稍候重试…"; try { HttpPost postReq = new HttpPost(commentApiUrl); postReq.setEntity(new UrlEncodedFormEntity(paramsToPass, HTTP.UTF_8)); HttpResponse response = ARUtils.GetHttpClient().execute(postReq); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { serverResp = EntityUtils.toString(response.getEntity()); try { JSONObject jObject = new JSONObject(serverResp); serverResp = jObject.getString("status"); } catch (JSONException e) { serverResp = "服务器端错误"; } } else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_FORBIDDEN) { serverResp = EntityUtils.toString(response.getEntity()); try { JSONObject jObject = new JSONObject(serverResp); serverResp = jObject.getString("status"); } catch (JSONException e) { e.printStackTrace(); serverResp = "服务器端错误"; } } else { serverResp = "网络连接错误"; } } catch (ClientProtocolException e) { Log.d("protocolException", e.getMessage()); } catch (IOException e) { Log.d("IOException", e.getMessage()); } return serverResp; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if (result.equalsIgnoreCase("success")){ if(flag_comment == 0){//如果直接回复,更新ui comment_content_item = comment_ediText.getText().toString(); SpannableStringBuilder comment_item = setUserStyle(ARUtils.username); comment_item.append(" : "); SpannableStringBuilder comment_item1 = setContentStyle(comment_ediText.getText().toString()); comment_item.append(comment_item1); TextView txtComment = new TextView(mContext); txtComment.setText(comment_item); comment_layout.setVisibility(View.GONE); linearComment.addView(txtComment); } if(flag_comment == 1){//如果在评论里进行回复,更新ui comment_content_item = comment_ediText.getText().toString(); SpannableStringBuilder comment_item = setUserStyle(ARUtils.username); SpannableStringBuilder comment_item1 = setContentStyle(" 回复 "); SpannableStringBuilder comment_item2 = setUserStyle(replyed_user); SpannableStringBuilder comment_item3 = setContentStyle(comment_ediText.getText().toString()); comment_item.append(comment_item1); comment_item.append(comment_item2); comment_item.append(" : "); comment_item.append(comment_item3); TextView txtComment = new TextView(mContext); txtComment.setText(comment_item); comment_layout.setVisibility(View.GONE); linearComment.addView(txtComment); } Toast.makeText(mContext, "评论成功!", Toast.LENGTH_SHORT).show(); comment_ediText.setText(""); }else Toast.makeText(mContext, "评论失败,请稍后重试。。。", Toast.LENGTH_SHORT).show(); } }
更新ui的操作最好放在post函数里面,而不是执行异步任务之前,用户万一没提交成功,是i不能更新ui的。。
二、点赞的实现:
点赞就相比容易多了,但是在过程中也出现了一个逗比的小问题:布局文件里的”ok“。。。
就是在没有人点赞的时候,但是朋友圈的点赞列表就逗比的出现了一个“ok”,后来调试也没检查出问题,这时看了下点赞列表的布局文件,原来我在那里的textview里赋了个初值“ok”,是为了调布局的时候看其位置。。。
并且也有一个问题需要用到全局标志位flag_like,就是点赞列表的ui更新问题。
一个图片在没有点赞之前,第一个点赞用户的应该是直接显示在点赞列表的textview里的,如过已经有点赞人了,那么后续的点赞用户更新ui的时候,需要先在原来点赞用户列表的后面append “,”,然后在append点赞用户。
我的点赞列表是个textview,点赞用户都用的richTex,然后setText方法加载到控件上,这个richText声明为全局变量,便于在后面更新ui的时候引用:
//设置点赞列表,infoPack[4]里面是点赞的用户,用|分隔 if(!infoPack[4].equals("")) //如果有点赞人 { String like_users = infoPack[4].replace("|", " , "); strNameSpan = setUserStyle(like_users); linear_likes.setText(strNameSpan); flag_like = 1; //点赞标志位设为1 }else flag_like = 0;
//点赞按钮响应 private Button.OnClickListener btnLikeListener = new Button.OnClickListener() { @Override public void onClick(View arg0) { //建立网络连接,执行点赞异步任务,将点赞内容发送给服务器 ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.isConnected()){ String likeData[] = { "", "" , "", ""}; likeData[0] = ARUtils.username; //点赞人,就是登陆的用户名 likeData[1] = users_name; //被点赞人 likeData[2] = ARUtils.password; likeData[3] = pic_id; //likeData[3] = "2"; webTaskForLike asyncWebForLike = new webTaskForLike(); if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { asyncWebForLike.executeOnExecutor( webTaskForLike.THREAD_POOL_EXECUTOR, likeData); } else { asyncWebForLike.execute(likeData); } } } };
class webTaskForLike extends AsyncTask<String, String, String> //点赞异步任务 { @Override protected String doInBackground(String... params) { ArrayList<NameValuePair> paramsToPass = new ArrayList<NameValuePair>(); paramsToPass.add(new BasicNameValuePair("userName", params[0])); paramsToPass.add(new BasicNameValuePair("picture_id", params[3])); paramsToPass.add(new BasicNameValuePair("passWord", params[2])); String serverResp = "未获得数据,请稍候重试…"; try { HttpPost postReq = new HttpPost(likeApiUrl); postReq.setEntity(new UrlEncodedFormEntity(paramsToPass, HTTP.UTF_8)); HttpResponse response = ARUtils.GetHttpClient().execute(postReq); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { serverResp = EntityUtils.toString(response.getEntity()); try { JSONObject jObject = new JSONObject(serverResp); serverResp = jObject.getString("status"); } catch (JSONException e) { serverResp = "服务器端错误"; } } else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_FORBIDDEN) { serverResp = EntityUtils.toString(response.getEntity()); try { JSONObject jObject = new JSONObject(serverResp); serverResp = jObject.getString("status"); } catch (JSONException e) { e.printStackTrace(); serverResp = "服务器端错误"; } } else { serverResp = "网络连接错误"; } } catch (ClientProtocolException e) { Log.d("protocolException", e.getMessage()); } catch (IOException e) { Log.d("IOException", e.getMessage()); } return serverResp; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if (result.equalsIgnoreCase("success")){ if(flag_like == 1 ){//如果已经存在点赞人 SpannableStringBuilder like_item = setUserStyle(ARUtils.username); strNameSpan.append(", "); strNameSpan.append(like_item); linear_likes.setText(strNameSpan); }else {//否则设置第一个点赞人 SpannableStringBuilder like_item = setUserStyle(ARUtils.username); linear_likes.setText(like_item); } Toast.makeText(mContext, "点赞成功!", Toast.LENGTH_SHORT).show(); }//else Toast.makeText(mContext, "点赞失败,请稍后重试。。。", Toast.LENGTH_SHORT).show(); if (result.equalsIgnoreCase("like_exist")){ Toast.makeText(mContext, "您已点过赞", Toast.LENGTH_SHORT).show(); } if (result.equalsIgnoreCase("like_fail")){ Toast.makeText(mContext, "点赞失败,请稍后重试。。。", Toast.LENGTH_SHORT).show(); } } }
error:
总结一下期间出现过的问题: 1、 首先说监听器的绑定,点击评论内容事件、点击评论按钮绑定了不同的评论布局弹出监听器,虽然他们是操作不太一样,但是可以通过根据点击 的控件id来区分,这样他们可以共用布局里面的发送按钮监听器了(还是师兄逻辑清楚。。。程序要尽可能地逻辑简单)
2、 监听器里的内容取replyedUser时候,出现了混乱,因为局部变量的使用很容易混淆
3、 不能重复点赞、不能对自己的评论进行回复。。。这些师兄提醒的细节,注意点啦。。