package com.gh.gamecenter; import android.app.Dialog; import android.content.*; import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.*; import android.view.*; import android.view.inputmethod.InputMethodManager; import android.widget.*; import butterknife.*; import com.facebook.drawee.view.SimpleDraweeView; import com.gh.base.AppController; import com.gh.base.BaseActivity; import com.gh.common.constant.Config; import com.gh.common.util.*; import com.gh.gamecenter.adapter.MessageDetailAdapter; import com.gh.gamecenter.db.CommentDao; import com.gh.gamecenter.db.info.CommentInfo; import com.gh.gamecenter.entity.*; import com.gh.gamecenter.manager.CommentManager; import com.gh.gamecenter.retrofit.*; import com.google.gson.Gson; import org.json.*; import retrofit2.HttpException; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; import java.util.List; /** * Created by khy on 2016/11/8. * 消息详情界面 */ public class MessageDetailActivity extends BaseActivity implements MessageDetailAdapter.OnCommentCallBackListener { @BindView(R.id.message_detail_rv) RecyclerView mMessageDetailRv; @BindView(R.id.message_detail_user_rl) RelativeLayout mMessageDetailUserRl; @BindView(R.id.message_detail_comment_rl) RelativeLayout mMessageDetailCommentRl; @BindView(R.id.comment_user_icon) SimpleDraweeView mMessageDetailIconDv; @BindView(R.id.comment_user_name) TextView mMessageDetailUserNameTv; @BindView(R.id.comment_send) TextView mMessageDetailCommentSend; @BindView(R.id.message_detail_comment_et) EditText mMessageDetailEt; @BindView(R.id.message_detail_comment_hint_rl) RelativeLayout mMessageDetailCommentHintRl; @BindView(R.id.message_detail_sv) ScrollView mMessageDetailSv; @BindView(R.id.message_detail_hint_line) View mMessageDetailLine; @BindView(R.id.reuse_no_connection) LinearLayout mNoConnection; @BindView(R.id.message_detail_close_comment) View mColseCommentV; private LinearLayoutManager mLayoutManager; private MessageDetailAdapter adapter; private SharedPreferences sp; private Dialog mSendingDialog; private CommentDao mCommentDao; private ConcernEntity mConcernEntity; private CommentEntity mCommentEntity; // 回复评论的实体 用完马上清空 private String newsId; private int commentNum = -1; //区分来源 -1:资讯关注列表 !=-1 :新闻详情 private TextWatcher watcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.toString().trim().length() > 0) { mMessageDetailCommentSend.setEnabled(true); if (s.length() > 140) { mMessageDetailEt.setText(""); String newText = s.toString().substring(0, 140); mMessageDetailEt.setText(newText); Utils.toast(MessageDetailActivity.this, "评论不能多于140字"); } } else { mMessageDetailCommentSend.setEnabled(false); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }; @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); AppController.put("ConcernEntity", adapter.getConcernEntity()); } @Override protected int getLayoutId() { return R.layout.activity_messagedetail; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mConcernEntity = (ConcernEntity) AppController.get("ConcernEntity", true); mCommentEntity = (CommentEntity) AppController.get("CommentEntity", true); // 来自新闻详情-评论回复 Intent intent = getIntent(); newsId = intent.getExtras().getString("newsId"); commentNum = intent.getExtras().getInt("commentNum"); //复用问题 mConcernEntity对应的文章有可能和跳转之前的文章不一致 if (mConcernEntity != null && newsId != null && !newsId.equals(mConcernEntity.getId())) { mConcernEntity = null; } init(getString(R.string.title_message_detail)); sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); mCommentDao = new CommentDao(this); adapter = new MessageDetailAdapter(this, mCommentDao, mMessageDetailRv, mConcernEntity); mLayoutManager = new LinearLayoutManager(this); mMessageDetailRv.setLayoutManager(mLayoutManager); mMessageDetailRv.setAdapter(adapter); mMessageDetailEt.addTextChangedListener(watcher); mMessageDetailCommentSend.setEnabled(false); mMessageDetailRv.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE && !adapter.isOver() && !adapter.isLoading() && mConcernEntity != null && mLayoutManager.findLastVisibleItemPosition() == adapter.getItemCount() - 1) { int offset = adapter.getItemCount() - adapter.getHotCommentListSize() - 3; if (offset >= 10) { // 防止自动上滑时触发 adapter.addNormalComment(offset); } } } }); //检查sp是否有用户信息 if (TextUtils.isEmpty(sp.getString("user_name", null))) { new Thread(new Runnable() { @Override public void run() { TokenUtils.getToken(MessageDetailActivity.this, true); MessageDetailActivity.this.runOnUiThread(new Runnable() { @Override public void run() { String icon = sp.getString("user_icon", null); if (TextUtils.isEmpty(icon)) { mMessageDetailIconDv.setImageURI( Uri.parse("res:///" + R.drawable.user_default_icon_comment)); } else { ImageUtils.display(mMessageDetailIconDv, icon); } mMessageDetailUserNameTv.setText(sp.getString("user_name", "光环用户")); } }); } }).start(); } else { String icon = sp.getString("user_icon", null); if (TextUtils.isEmpty(icon)) { mMessageDetailIconDv.setImageURI( Uri.parse("res:///" + R.drawable.user_default_icon_comment)); } else { ImageUtils.display(mMessageDetailIconDv, icon); } mMessageDetailUserNameTv.setText(sp.getString("user_name", "光环用户")); } if (Build.VERSION.SDK_INT >= 19) { //解决透明沉浸栏和软键盘冲突(重置ScrollView高度) final View decorView = getWindow().getDecorView(); decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect rect = new Rect(); decorView.getWindowVisibleDisplayFrame(rect); int screenHeight = decorView.getRootView().getHeight(); int heightDifference = screenHeight - rect.bottom;//计算软键盘占有的高度 = 屏幕高度 - 视图可见高度 RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mMessageDetailSv.getLayoutParams(); layoutParams.setMargins(0, 0, 0, heightDifference);//设置ScrollView的marginBottom的值为软键盘占有的高度即可 mMessageDetailSv.requestLayout(); } }); } if (newsId != null && mConcernEntity == null) { getConcernDigest(); } if (intent.getExtras().getBoolean("openSoftInput")) {//新闻详情的发表评论 setSoftInput(true); } } public void getCommentNum() { RetrofitManager.getComment() .getNewsCommentnum(newsId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new com.gh.gamecenter.retrofit.Response>() { @Override public void onResponse(List response) { super.onResponse(response); if (response.size() > 0) { if (!TextUtils.isEmpty(mConcernEntity.getId())) { commentNum = response.get(0).getNum(); mConcernEntity.setCommentnum(commentNum); adapter.notifyItemChanged(0); } } } }); } private void getConcernDigest() { RetrofitManager.getApi().getNewsRichDigest(newsId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Response() { @Override public void onResponse(ConcernEntity response) { mConcernEntity = response; if (commentNum == -1) { getCommentNum(); } else { mConcernEntity.setCommentnum(commentNum); } adapter.addConcernEntity(mConcernEntity); adapter.notifyDataSetChanged(); adapter.addHotComment(0); getNewsViews(); if (commentNum == 0) { setSoftInput(true); } } @Override public void onFailure(HttpException e) { showNoConnection(true); } }); } private void getNewsViews() { RetrofitManager.getData() .getNewsViews(newsId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Response>() { @Override public void onResponse(List viewsEntities) { if (viewsEntities.size() > 0) { mConcernEntity.setViews(viewsEntities.get(0).getViews()); adapter.notifyItemChanged(0); } } }); } @OnClick(R.id.message_detail_comment_hint_rl) public void OnHintClikListener() { setSoftInput(true); } @OnClick(R.id.actionbar_rl_back) public void OnBackClikListener() { if (commentNum != -1 && commentNum != adapter.getConcernEntity().getCommentnum()) { Intent intent = new Intent(); intent.putExtra("commentNum", adapter.getConcernEntity().getCommentnum()); setResult(1001, intent); } finish(); } @OnTouch(R.id.message_detail_close_comment) public boolean OnRecyclerTouchListener() { if (mMessageDetailCommentRl.getVisibility() == View.VISIBLE) { setSoftInput(false); } return true; } @OnClick(R.id.comment_send) public void OnSendCommentListener() { final String content = mMessageDetailEt.getText().toString(); if (content.length() == 0) { Utils.toast(MessageDetailActivity.this, "评论内容不能为空!"); return; } mSendingDialog = DialogUtils.showWaitDialog(this, "正在提交"); JSONObject jsonObject = new JSONObject(); try { jsonObject.put("content", content); } catch (JSONException e) { e.printStackTrace(); } if (newsId == null && mConcernEntity == null || newsId == null && mConcernEntity != null && mConcernEntity.getId() == null) { Utils.toast(this, "评论异常 id null"); mSendingDialog.cancel(); return; } else if (newsId == null) { newsId = mConcernEntity.getId(); } PostCommentUtils.addCommentData(MessageDetailActivity.this, newsId, jsonObject.toString(), true, mCommentEntity, new PostCommentUtils.PostCommentListener() { @Override public void postSuccess(JSONObject response) { mSendingDialog.dismiss(); toast("发表成功"); mMessageDetailEt.setText(""); try { mCommentDao.add(new CommentInfo(response.getString("_id")));//添加评论id到数据库, 后续判断是否是自身评论 JSONObject cacheObject = new JSONObject(); JSONObject cacheUser = new JSONObject(); cacheUser.put("_id", TokenUtils.getDeviceId(MessageDetailActivity.this)); cacheUser.put("icon", sp.getString("user_icon", null)); cacheUser.put("name", sp.getString("user_name", "光环用户")); cacheObject.put("_id", response.getString("_id")); cacheObject.put("content", content); cacheObject.put("time", System.currentTimeMillis() / 1000); cacheObject.put("vote", 0); cacheObject.put("user", cacheUser); if (mCommentEntity != null) { JSONObject cacheParent = new JSONObject(); JSONObject cacheParentUser = new JSONObject(); cacheParentUser.put("_id", mCommentEntity.getId()); cacheParentUser.put("name", mCommentEntity.getUser().getName()); cacheParent.put("user", cacheParentUser); cacheObject.put("parent", cacheParent); } CommentEntity commentEntity = new Gson().fromJson(cacheObject.toString(), CommentEntity.class); if (mConcernEntity != null) { adapter.addNormalComment(commentEntity); } modifyNewsCommentOkhttpCache(0, cacheObject, newsId); } catch (JSONException e) { e.printStackTrace(); } if (mConcernEntity != null) { // 完成评论操作,添加评论数 adapter.addCommentCount(); //修改评论缓存 CommentManager.updateOkhttpCacheForId(newsId); CommentManager.updateOkhttpCache(newsId); adapter.notifyItemInserted(adapter.getHotCommentListSize() + 2); adapter.notifyItemChanged(adapter.getItemCount() - 1); //刷新脚布局高度 } else { showNoConnection(false); } setSoftInput(false); } @Override public void postFailed(Throwable e) { mSendingDialog.dismiss(); if (e instanceof HttpException) { HttpException exception = (HttpException) e; if (exception.code() == 403) { try { JSONObject errorJson = new JSONObject(exception.response().errorBody().string()); String detail = errorJson.getString("detail"); if ("too frequent".equals(detail)) { toast("别话痨哦~休息一会再来评论吧~"); } else if ("user blocked".equals(detail)) { toast("账号状态异常,暂时无法发表评论"); } else if ("article blocked".equals(detail)) { toast("文章异常,无法发表评论"); setSoftInput(false); } else if ("illegal".equals(detail)) { toast("评论内容可能包括敏感信息,请修改后再发表"); } else { toast("评论失败,未知原因"); } } catch (Exception ex) { ex.printStackTrace(); toast("评论异常"); } return; } } toast("提交失败,请检查网络设置"); } }); } private void modifyNewsCommentOkhttpCache(int offset, JSONObject commentData, String id) { String key = TimestampUtils.addTimestamp(Config.COMMENT_HOST + "article/" + id + "/comment?limit=10&offset=" + offset); byte[] data = OkHttpCache.getCache(key); if (data != null) { try { JSONArray jsonArray = new JSONArray(new String(data)); JSONArray newComment = new JSONArray(); newComment.put(commentData); for (int i = 0, size = jsonArray.length() > 9 ? 9 : jsonArray.length(); i < size; i++) { newComment.put(jsonArray.get(i)); } OkHttpCache.updateCache(key, newComment.toString().getBytes()); if (jsonArray.length() == 10) { modifyNewsCommentOkhttpCache(offset + 10, jsonArray.getJSONObject(9), id); } } catch (JSONException e) { e.printStackTrace(); } } } private void showNoConnection(boolean isShow) { if (isShow) { mNoConnection.setVisibility(View.VISIBLE); mMessageDetailRv.setVisibility(View.GONE); } else { mNoConnection.setVisibility(View.GONE); mMessageDetailRv.setVisibility(View.VISIBLE); if (newsId != null) { getConcernDigest(); } if (mMessageDetailCommentRl.getVisibility() == View.VISIBLE) { setSoftInput(false); } } } //软键盘控制 private void setSoftInput(boolean isShow) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (isShow) { imm.showSoftInputFromInputMethod(mMessageDetailEt.getWindowToken(), 0); imm.toggleSoftInputFromWindow(mMessageDetailEt.getWindowToken(), 0, InputMethodManager.HIDE_NOT_ALWAYS); mMessageDetailCommentHintRl.setVisibility(View.GONE); mMessageDetailLine.setVisibility(View.GONE); mMessageDetailCommentRl.setVisibility(View.VISIBLE); mMessageDetailUserRl.setVisibility(View.VISIBLE); mMessageDetailEt.setFocusable(true); mMessageDetailEt.setFocusableInTouchMode(true); mMessageDetailEt.requestFocus(); mColseCommentV.setVisibility(View.VISIBLE); if (mCommentEntity != null && mCommentEntity.getUser() != null) { mMessageDetailEt.setHint("回复" + mCommentEntity.getUser().getName() + ":"); } else { mMessageDetailEt.setHint("优质评论会被优先展示"); } } else { imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0); mMessageDetailCommentHintRl.setVisibility(View.VISIBLE); mMessageDetailLine.setVisibility(View.VISIBLE); mMessageDetailCommentRl.setVisibility(View.GONE); mMessageDetailUserRl.setVisibility(View.GONE); mColseCommentV.setVisibility(View.GONE); if (mCommentEntity != null) { mCommentEntity = null; // 清空当前评论实体 mMessageDetailEt.setHint("优质评论会被优先展示"); mMessageDetailEt.setText(""); } } } @Override public void showSoftInput(CommentEntity entity) { mCommentEntity = entity; setSoftInput(true); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { if (commentNum != -1 && adapter.getConcernEntity() != null && commentNum != adapter.getConcernEntity().getCommentnum()) { Intent intent = new Intent(); intent.putExtra("commentNum", adapter.getConcernEntity().getCommentnum()); setResult(1001, intent); } } return super.onKeyDown(keyCode, event); } }