This commit is contained in:
chenjuntao
2019-09-18 11:12:34 +08:00
parent 3ec6526aa4
commit 21dc20dff1
15 changed files with 1225 additions and 982 deletions

View File

@ -15,6 +15,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.*
import androidx.viewpager.widget.ViewPager
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.constant.Config
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
@ -308,6 +309,13 @@ fun Int.toSimpleCount(): String {
return NumberUtils.transSimpleCount(this)
}
/**
* Image related
*/
fun SimpleDraweeView.display(url: String) {
ImageUtils.display(this, url)
}
/**
* 测试用包裹
*/

View File

@ -98,6 +98,9 @@ class MeEntity(@SerializedName("is_community_voted")
@SerializedName("is_appointment")
var isGameReserved: Boolean = false, // 是否已预约了游戏
@SerializedName("is_smart_invite")
var isSmartInvited: Boolean = false, // 是否在具体问题详情页面点了智能邀请按钮
@SerializedName("permissions")
val moderatorPermissions: Permissions = Permissions()) : Parcelable

View File

@ -339,8 +339,13 @@ public class PersonalFragment extends BaseFragment implements Observer<ApiRespon
}
break;
case R.id.personal_game:
MtaHelper.onEvent("我的光环", "我的游戏");
startActivity(new Intent(getContext(), MyGameActivity.class));
if (mUserInfoEntity != null) {
MtaHelper.onEvent("我的光环", "我的游戏");
startActivity(new Intent(getContext(), MyGameActivity.class));
} else {
MtaHelper.onEvent("我的光环", "手机登录");
CheckLoginUtils.checkLogin(getContext(), "我的光环-我的游戏", null);
}
break;
case R.id.personal_share:
MtaHelper.onEvent("我的光环", "分享");

View File

@ -25,8 +25,6 @@ data class QuestionsDetailEntity(var id: String? = null,
var community: CommunityEntity = CommunityEntity(),
var isExistDrafts: Boolean = false,
var me: MeEntity = MeEntity(),
@SerializedName("is_smart_invite")
var isSmartInvited: Boolean = false,
@SerializedName("follow_count")
private var followCount: Int = 0) : Parcelable {

View File

@ -0,0 +1,9 @@
package com.gh.gamecenter.qa.questions.detail
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.InviteEntity
data class QuestionDetailItemData(var answer: AnswerEntity? = null,
var showSimilarAnswerHint: Boolean? = null,
var similarAnswer: AnswerEntity? = null,
var recommendedUserToInvite: List<InviteEntity>? = null)

View File

@ -1,356 +0,0 @@
package com.gh.gamecenter.qa.questions.detail;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.gh.base.OnListClickListener;
import com.gh.common.constant.ItemViewType;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.NumberUtils;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder;
import com.gh.gamecenter.adapter.viewholder.ReuseViewHolder;
import com.gh.gamecenter.baselist.ListAdapter;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity;
import com.gh.gamecenter.qa.entity.AnswerEntity;
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity;
import com.google.android.flexbox.FlexboxLayout;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
/**
* Created by khy on 7/12/17.
*/
public class QuestionsDetailAdapter extends ListAdapter<AnswerEntity> {
private final static int ITEM_EMPTY_COUNT = 1;
private boolean mIsNoneData;
private OnListClickListener mListClickListener;
private QuestionsDetailEntity mQuestionsDetailEntity;
private String mEntrance;
QuestionsDetailAdapter(Context context, OnListClickListener listClickListener, String entrance) {
super(context);
mListClickListener = listClickListener;
mEntrance = entrance;
}
public void setQuestionsEntity(QuestionsDetailEntity questionsDetailEntity) {
mQuestionsDetailEntity = questionsDetailEntity;
notifyDataSetChanged();
}
public String getQuestionsTitle() {
return mQuestionsDetailEntity != null ? mQuestionsDetailEntity.getTitle() : "";
}
@Override
protected void setListData(List<AnswerEntity> updateData) {
if (updateData != null && updateData.size() == 0) {
mIsNoneData = true;
} else {
mIsNoneData = false;
}
mEntityList = new ArrayList<>(updateData);
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (position == 0 && mQuestionsDetailEntity != null) {
return ItemViewType.ITEM_HEADER;
} else if (position == getItemCount() - 1) {
return ItemViewType.ITEM_FOOTER;
} else if (mEntityList == null || mEntityList.isEmpty()) {
return ItemViewType.ITEM_EMPTY;
} else {
return ItemViewType.ITEM_BODY;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case ItemViewType.ITEM_HEADER:
view = mLayoutInflater.inflate(R.layout.questionsdetail_item, parent, false);
return new QuestionsDetailItemViewHolder(view, mListClickListener);
case ItemViewType.ITEM_FOOTER:
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false);
return new FooterViewHolder(view, mListClickListener);
case ItemViewType.ITEM_BODY:
view = mLayoutInflater.inflate(R.layout.ask_answer_item, parent, false);
return new AnswerViewHolder(view, mListClickListener);
case ItemViewType.ITEM_EMPTY:
view = mLayoutInflater.inflate(R.layout.reuse_nodata_skip, parent, false);
return new EmptyViewHolder(view);
default:
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case ItemViewType.ITEM_HEADER:
initQuestionsDetailItemViewHolder((QuestionsDetailItemViewHolder) holder);
break;
case ItemViewType.ITEM_EMPTY:
EmptyViewHolder emptyViewHolder = (EmptyViewHolder) holder;
if (mQuestionsDetailEntity != null && mQuestionsDetailEntity.isAnswerFold()) {
emptyViewHolder.tvHint.setText("");
} else {
emptyViewHolder.tvHint.setText("暂无回答");
}
if (mQuestionsDetailEntity != null && !TextUtils.isEmpty(mQuestionsDetailEntity.getMe().getMyAnswerId())) {
emptyViewHolder.tvBtn.setVisibility(View.GONE);
} else {
emptyViewHolder.tvBtn.setVisibility(View.VISIBLE);
}
emptyViewHolder.tvBtn.setText("我来回答");
emptyViewHolder.itemView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(200)));
emptyViewHolder.itemView.setOnClickListener(v -> mListClickListener.onListClick(holder.itemView, 1, null));
break;
case ItemViewType.ITEM_FOOTER:
FooterViewHolder footerViewHolder = (FooterViewHolder) holder;
footerViewHolder.initItemPadding();
LinearLayout item = (LinearLayout) footerViewHolder.itemView;
footerViewHolder.lineLeft.setVisibility(View.GONE);
footerViewHolder.lineRight.setVisibility(View.GONE);
if (mIsNetworkError) {
footerViewHolder.loading.setVisibility(View.GONE);
footerViewHolder.hint.setText(R.string.loading_failed_retry);
footerViewHolder.hint.setCompoundDrawables(null, null, null, null);
footerViewHolder.hint.setPadding(0, 0, 0, 0);
item.setGravity(Gravity.CENTER);
} else if (mIsOver) {
footerViewHolder.loading.setVisibility(View.GONE);
footerViewHolder.hint.setText(R.string.questionsdetail_fold_hint);
footerViewHolder.hint.setPadding(DisplayUtils.dip2px(mContext, 20), 0, 0, 0);
Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_footer_icon);
item.setGravity(Gravity.CENTER_VERTICAL);
if (drawable != null) {
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
footerViewHolder.hint.setCompoundDrawables(null, null, drawable, null);
footerViewHolder.hint.setCompoundDrawablePadding(20);
}
} else {
footerViewHolder.loading.setVisibility(View.VISIBLE);
footerViewHolder.hint.setText(R.string.loading);
footerViewHolder.hint.setCompoundDrawables(null, null, null, null);
footerViewHolder.hint.setPadding(0, 0, 0, 0);
item.setGravity(Gravity.CENTER);
}
if (!mIsOver || (mQuestionsDetailEntity != null && mQuestionsDetailEntity.isAnswerFold())) {
footerViewHolder.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
} else {
footerViewHolder.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0));
}
break;
case ItemViewType.ITEM_BODY:
int index = position - ListAdapter.TOP_ITEM_COUNT;
if (index != -1)
((AnswerViewHolder) holder).initAnswerViewHolder(mContext, mEntityList.get(index), mEntrance, "问题详情");
break;
}
}
private void initQuestionsDetailItemViewHolder(QuestionsDetailItemViewHolder holder) {
List<String> images = mQuestionsDetailEntity.getImages();
if (mQuestionsDetailEntity.getImages().size() == 0) {
holder.mPic2.setVisibility(View.INVISIBLE);
} else if (mQuestionsDetailEntity.getImages().size() == 1) {
holder.mPic2.setVisibility(View.INVISIBLE);
holder.mPic3.setVisibility(View.INVISIBLE);
holder.mPic3Desc.setVisibility(View.GONE);
holder.mPic3Mask.setVisibility(View.GONE);
} else if(mQuestionsDetailEntity.getImages().size() == 2) {
holder.mPic3.setVisibility(View.INVISIBLE);
holder.mPic3Desc.setVisibility(View.GONE);
holder.mPic3Mask.setVisibility(View.GONE);
} else if(mQuestionsDetailEntity.getImages().size() == 3) {
holder.mPic3Desc.setVisibility(View.GONE);
holder.mPic3Mask.setVisibility(View.GONE);
}
for (int i = 0; i < images.size(); i++) {
switch (i) {
case 0:
holder.mPic1.setVisibility(View.VISIBLE);
ImageUtils.display(holder.mPic1, images.get(i));
break;
case 1:
holder.mPic2.setVisibility(View.VISIBLE);
ImageUtils.display(holder.mPic2, images.get(i));
break;
case 2:
holder.mPic3.setVisibility(View.VISIBLE);
ImageUtils.display(holder.mPic3, images.get(i));
if (images.size() > 3) {
holder.mPic3Mask.setVisibility(View.VISIBLE);
holder.mPic3Desc.setVisibility(View.VISIBLE);
holder.mPic3Desc.setText("+" + (images.size() - 3));
}
break;
}
}
if (images.size() > 0) {
holder.mImgLl.setVisibility(View.VISIBLE);
} else {
holder.mImgLl.setVisibility(View.GONE);
}
List<String> tags = mQuestionsDetailEntity.getTags();
holder.mTagRl.removeAllViews();
for (int i = 0; i < tags.size(); i++) {
if (!TextUtils.isEmpty(tags.get(i))) addTag(holder.mTagRl, tags.get(i), false);
}
// addTag(holder.mTagRl, mQuestionsDetailEntity.getCommunityName(), true);
String description = mQuestionsDetailEntity.getDescription();
if (TextUtils.isEmpty(description)) {
holder.mDes.setVisibility(View.GONE);
} else {
holder.mDes.setVisibility(View.VISIBLE);
holder.mDes.setText(description);
}
if (!TextUtils.isEmpty(mQuestionsDetailEntity.getMe().getMyAnswerId())) {
setAnswerTv(holder.answerTv, R.string.question_detail_myanswer);
} else if (mQuestionsDetailEntity.isExistDrafts()) {
setAnswerTv(holder.answerTv, R.string.question_detail_resume_answer);
} else {
setAnswerTv(holder.answerTv, R.string.question_detail_answer);
}
if (mQuestionsDetailEntity.getMe().isQuestionOwn()) {
holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg);
holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint));
holder.concern.setText("编辑问题");
} else if (mQuestionsDetailEntity.getMe().isQuestionFollowed()) {
holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg);
holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint));
holder.concern.setText("已关注");
} else {
holder.concern.setBackgroundResource(R.drawable.button_normal_style);
holder.concern.setTextColor(Color.WHITE);
holder.concern.setText("关注问题");
}
if (mQuestionsDetailEntity.getRelatedQuestion() != null) {
holder.mRelatedQuestionContainer.setVisibility(View.VISIBLE);
holder.mRelatedQuestionContainer.setOnClickListener(v -> {
mContext.startActivity(QuestionsDetailActivity.getIntent(
mContext,
mQuestionsDetailEntity.getRelatedQuestion().getId(),
mEntrance,
"关联问题"));
});
holder.mRelatedQuestionTitle.setText(mQuestionsDetailEntity.getRelatedQuestion().getTitle());
holder.mRelatedQuestionAnswerCount.setText(
(NumberUtils.transSimpleCount(mQuestionsDetailEntity.getRelatedQuestion().getAnswerCount()) + "回答"));
} else {
holder.mRelatedQuestionContainer.setVisibility(View.GONE);
}
holder.mTitle.setText(mQuestionsDetailEntity.getTitle());
holder.concernCount.setText((NumberUtils.transSimpleCount(mQuestionsDetailEntity.getFollowCount()) + "人关注"));
if (mQuestionsDetailEntity.getAnswersCount() == 0) {
holder.mAnswercount.setVisibility(View.GONE);
} else {
holder.mAnswercount.setVisibility(View.VISIBLE);
holder.mAnswercount.setText(mContext.getString(R.string.ask_answer_count, NumberUtils.transSimpleCount(mQuestionsDetailEntity.getAnswersCount())));
}
}
private void addTag(FlexboxLayout mTagRl, String tag, boolean isLastTag) {
View view = LayoutInflater.from(mContext).inflate(R.layout.questionsdedit_tag_item, null);
TextView tagTv = (TextView) view;
tagTv.setText(tag);
tagTv.setBackgroundResource(R.drawable.button_normal_style);
tagTv.setTextColor(Color.WHITE);
FlexboxLayout.LayoutParams params = new FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(0, DisplayUtils.dip2px(mContext, 5), !isLastTag ? DisplayUtils.dip2px(mContext, 8) : 0,
DisplayUtils.dip2px(mContext, 5));
tagTv.setLayoutParams(params);
mTagRl.addView(view);
view.setOnClickListener(v -> {
DataUtils.onMtaEvent(mContext, "问题标签", mQuestionsDetailEntity.getCommunity().getName(), mQuestionsDetailEntity.getTitle() + "-" + tag);
mContext.startActivity(AskColumnDetailActivity.Companion.getIntentByTag(mContext, tag,
new CommunityEntity(mQuestionsDetailEntity.getCommunity().getId(),
mQuestionsDetailEntity.getCommunity().getName()), mEntrance, "问题详情"));
});
}
private void setAnswerTv(TextView answerTv, @StringRes int answerTvId) {
String answerText = mContext.getString(answerTvId);
answerTv.setText(answerText);
Drawable drawable;
if (mContext.getString(R.string.question_detail_myanswer).equals(answerText)) {
drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_myanswer_icon);
} else {
drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_answer_icon);
}
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
answerTv.setCompoundDrawables(drawable, null, null, null);
}
@Override
public int getItemCount() {
if (mQuestionsDetailEntity == null) {
return 0;
}
if (mIsNoneData && (mEntityList == null || mEntityList.isEmpty())) {
if (mQuestionsDetailEntity.isAnswerFold()) {
return FOOTER_ITEM_COUNT + TOP_ITEM_COUNT;
} else {
return FOOTER_ITEM_COUNT + TOP_ITEM_COUNT + ITEM_EMPTY_COUNT;
}
}
return mEntityList == null ? FOOTER_ITEM_COUNT + TOP_ITEM_COUNT : mEntityList.size() + FOOTER_ITEM_COUNT + TOP_ITEM_COUNT;
}
boolean isOver() {
return mIsOver;
}
class EmptyViewHolder extends ReuseViewHolder {
@BindView(R.id.reuse_nodata_skip_tv_hint)
TextView tvHint;
@BindView(R.id.reuse_nodata_skip_tv_btn)
TextView tvBtn;
public EmptyViewHolder(View itemView) {
super(itemView);
}
}
}

View File

@ -0,0 +1,407 @@
package com.gh.gamecenter.qa.questions.detail
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.text.TextUtils
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import com.gh.base.BaseRecyclerViewHolder
import com.gh.base.OnListClickListener
import com.gh.common.constant.ItemViewType
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
import com.gh.gamecenter.adapter.viewholder.ReuseViewHolder
import com.gh.gamecenter.baselist.ListAdapter
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity
import com.gh.gamecenter.qa.entity.InviteEntity
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
import com.gh.gamecenter.qa.questions.invite.QuestionsInviteAdapter
import com.google.android.flexbox.FlexboxLayout
class QuestionsDetailAdapter(
context: Context,
private var mListClickListener: OnListClickListener,
private var mQuestionEntity: QuestionsDetailEntity? = null,
private val mViewModel: QuestionsDetailViewModel,
private val mEntrance: String) : ListAdapter<QuestionDetailItemData>(context) {
private var mIsNoneData: Boolean = false
fun setQuestionsEntity(questionsDetailEntity: QuestionsDetailEntity) {
mQuestionEntity = questionsDetailEntity
notifyDataSetChanged()
}
fun getQuestionsTitle(): String {
return mQuestionEntity?.title ?: ""
}
override fun setListData(updateData: List<QuestionDetailItemData>?) {
mIsNoneData = updateData != null && updateData.isEmpty()
mEntityList = ArrayList(updateData!!)
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
return when {
position == 0 && mQuestionEntity != null -> ItemViewType.ITEM_HEADER
position == itemCount - 1 -> ItemViewType.ITEM_FOOTER
mEntityList == null || mEntityList.isEmpty() -> ItemViewType.ITEM_EMPTY
mEntityList[position - TOP_ITEM_COUNT].answer != null -> ItemViewType.ITEM_BODY
mEntityList[position - TOP_ITEM_COUNT].similarAnswer != null -> TYPE_SIMILAR_ANSWER
mEntityList[position - TOP_ITEM_COUNT].showSimilarAnswerHint != null -> TYPE_SIMILAR_ANSWER_HINT
mEntityList[position - TOP_ITEM_COUNT].recommendedUserToInvite != null -> TYPE_RECOMMEND_USER_TO_INVITE
else -> ItemViewType.ITEM_FOOTER
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View
when (viewType) {
ItemViewType.ITEM_HEADER -> {
view = mLayoutInflater.inflate(R.layout.questionsdetail_item, parent, false)
return QuestionsDetailItemViewHolder(view, mListClickListener)
}
ItemViewType.ITEM_FOOTER -> {
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
return FooterViewHolder(view, mListClickListener)
}
ItemViewType.ITEM_BODY, TYPE_SIMILAR_ANSWER -> {
view = mLayoutInflater.inflate(R.layout.ask_answer_item, parent, false)
return AnswerViewHolder(view, mListClickListener)
}
ItemViewType.ITEM_EMPTY -> {
view = mLayoutInflater.inflate(R.layout.reuse_nodata_skip, parent, false)
return EmptyViewHolder(view)
}
TYPE_SIMILAR_ANSWER_HINT -> {
view = mLayoutInflater.inflate(R.layout.item_question_detail_similar_answer_hint, parent, false)
return SimilarAnswerHint(view)
}
TYPE_RECOMMEND_USER_TO_INVITE -> {
view = mLayoutInflater.inflate(R.layout.item_question_detail_recommended_user, parent, false)
return RecommendedUserToInviteViewHolder(view)
}
else -> {
view = mLayoutInflater.inflate(R.layout.reuse_nodata_skip, parent, false)
return EmptyViewHolder(view)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getItemViewType(position)) {
ItemViewType.ITEM_HEADER -> initQuestionsDetailItemViewHolder(holder as QuestionsDetailItemViewHolder)
ItemViewType.ITEM_EMPTY -> {
val emptyViewHolder = holder as EmptyViewHolder
if (mQuestionEntity != null && mQuestionEntity!!.isAnswerFold) {
emptyViewHolder.tvHint.text = ""
} else {
emptyViewHolder.tvHint.text = "暂无回答"
}
if (mQuestionEntity != null && !TextUtils.isEmpty(mQuestionEntity!!.me.myAnswerId)) {
emptyViewHolder.tvBtn.visibility = View.GONE
} else {
emptyViewHolder.tvBtn.visibility = View.VISIBLE
}
emptyViewHolder.tvBtn.text = "我来回答"
emptyViewHolder.itemView.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(200f))
emptyViewHolder.itemView.setOnClickListener { mListClickListener.onListClick<Any>(holder.itemView, 1, null) }
}
ItemViewType.ITEM_FOOTER -> {
val footerViewHolder = holder as FooterViewHolder
footerViewHolder.initItemPadding()
val item = footerViewHolder.itemView as LinearLayout
footerViewHolder.lineLeft.visibility = View.GONE
footerViewHolder.lineRight.visibility = View.GONE
if (mIsNetworkError) {
footerViewHolder.loading.visibility = View.GONE
footerViewHolder.hint.setText(R.string.loading_failed_retry)
footerViewHolder.hint.setCompoundDrawables(null, null, null, null)
footerViewHolder.hint.setPadding(0, 0, 0, 0)
item.gravity = Gravity.CENTER
} else if (mIsOver) {
footerViewHolder.loading.visibility = View.GONE
footerViewHolder.hint.setText(R.string.questionsdetail_fold_hint)
footerViewHolder.hint.setPadding(DisplayUtils.dip2px(mContext, 20f), 0, 0, 0)
val drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_footer_icon)
item.gravity = Gravity.CENTER_VERTICAL
if (drawable != null) {
drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
footerViewHolder.hint.setCompoundDrawables(null, null, drawable, null)
footerViewHolder.hint.compoundDrawablePadding = 20
}
} else {
footerViewHolder.loading.visibility = View.VISIBLE
footerViewHolder.hint.setText(R.string.loading)
footerViewHolder.hint.setCompoundDrawables(null, null, null, null)
footerViewHolder.hint.setPadding(0, 0, 0, 0)
item.gravity = Gravity.CENTER
}
if (!mIsOver || mQuestionEntity != null && mQuestionEntity!!.isAnswerFold) {
footerViewHolder.itemView.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
} else {
footerViewHolder.itemView.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0))
}
}
ItemViewType.ITEM_BODY -> {
val index = position - TOP_ITEM_COUNT
if (index != -1) {
(holder as AnswerViewHolder).initAnswerViewHolder(mContext, mEntityList[index].answer, mEntrance, "问题详情")
}
}
TYPE_RECOMMEND_USER_TO_INVITE -> {
(holder as RecommendedUserToInviteViewHolder).bindView(mViewModel, mQuestionEntity!!, mEntityList[position - TOP_ITEM_COUNT].recommendedUserToInvite!!)
}
TYPE_SIMILAR_ANSWER -> {
val index = position - TOP_ITEM_COUNT
if (index != -1) {
(holder as AnswerViewHolder).initAnswerViewHolder(mContext, mEntityList[index].similarAnswer, mEntrance, "问题详情")
}
}
}
}
@SuppressLint("SetTextI18n")
private fun initQuestionsDetailItemViewHolder(holder: QuestionsDetailItemViewHolder) {
val tags = mQuestionEntity?.tags ?: arrayListOf()
val images = mQuestionEntity?.images ?: arrayListOf()
val description = mQuestionEntity?.description ?: ""
val relatedQuestion = mQuestionEntity?.relatedQuestion
// 标签
holder.mTagRl.removeAllViews()
for (tag in tags) {
if (!TextUtils.isEmpty(tag)) {
addTag(holder.mTagRl, tag, false)
}
}
// 缩略图
holder.mImgLl.goneIf(images.isEmpty())
holder.mPic1.visibleIf(images.isNotEmpty())
holder.mPic2.visibleIf(images.size > 1)
holder.mPic3.visibleIf(images.size > 2)
holder.mPic3Desc.goneIf(images.size <= 3)
holder.mPic3Mask.goneIf(images.size <= 3)
for (i in images.indices) {
when (i) {
0 -> holder.mPic1.display(images[i])
1 -> holder.mPic2.display(images[i])
2 -> {
holder.mPic3.display(images[i])
holder.mPic3Desc.text = "+" + (images.size - 3)
}
}
}
// 问题描述
holder.mDes.text = description
holder.mDes.goneIf(TextUtils.isEmpty(description))
// "我来回答"
if (!TextUtils.isEmpty(mQuestionEntity!!.me.myAnswerId)) {
updateAnswerTv(holder.answerTv, R.string.question_detail_myanswer)
} else if (mQuestionEntity!!.isExistDrafts) {
updateAnswerTv(holder.answerTv, R.string.question_detail_resume_answer)
} else {
updateAnswerTv(holder.answerTv, R.string.question_detail_answer)
}
// "关注问题"
when {
mQuestionEntity!!.me.isQuestionOwn -> {
holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg)
holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint))
holder.concern.text = "编辑问题"
}
mQuestionEntity!!.me.isQuestionFollowed -> {
holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg)
holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint))
holder.concern.text = "已关注"
}
else -> {
holder.concern.setBackgroundResource(R.drawable.button_normal_style)
holder.concern.setTextColor(Color.WHITE)
holder.concern.text = "关注问题"
}
}
// "关联问题"区域
holder.mRelatedQuestionContainer.goneIf(relatedQuestion == null)
relatedQuestion?.let {
holder.mRelatedQuestionContainer.setOnClickListener {
mContext.startActivity(QuestionsDetailActivity.getIntent(
mContext,
relatedQuestion.id,
mEntrance,
"关联问题"))
}
holder.mRelatedQuestionTitle.text = relatedQuestion.title
holder.mRelatedQuestionAnswerCount.text = NumberUtils.transSimpleCount(relatedQuestion.answerCount!!) + "回答"
}
holder.mTitle.text = mQuestionEntity?.title
holder.concernCount.text = NumberUtils.transSimpleCount(mQuestionEntity?.getFollowCount()
?: 0) + "人关注"
holder.mAnswercount.goneIf(mQuestionEntity?.answersCount == 0)
holder.mAnswercount.text = mContext.getString(R.string.ask_answer_count, NumberUtils.transSimpleCount(mQuestionEntity?.answersCount
?: 0))
}
private fun addTag(mTagRl: FlexboxLayout, tag: String, isLastTag: Boolean) {
val view = LayoutInflater.from(mContext).inflate(R.layout.questionsdedit_tag_item, null)
val tagTv = view as TextView
tagTv.text = tag
tagTv.setBackgroundResource(R.drawable.button_normal_style)
tagTv.setTextColor(Color.WHITE)
val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
params.setMargins(0, DisplayUtils.dip2px(mContext, 5f), if (!isLastTag) DisplayUtils.dip2px(mContext, 8f) else 0,
DisplayUtils.dip2px(mContext, 5f))
tagTv.layoutParams = params
mTagRl.addView(view)
view.setOnClickListener {
DataUtils.onMtaEvent(mContext, "问题标签", mQuestionEntity!!.community.name, mQuestionEntity!!.title + "-" + tag)
mContext.startActivity(AskColumnDetailActivity.getIntentByTag(mContext, tag,
CommunityEntity(mQuestionEntity!!.community.id,
mQuestionEntity!!.community.name), mEntrance, "问题详情"))
}
}
private fun updateAnswerTv(answerTv: TextView, @StringRes stringId: Int) {
answerTv.text = mContext.getString(stringId)
val drawable = if (R.string.question_detail_myanswer == stringId) {
ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_myanswer_icon)
} else {
ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_answer_icon)
}
drawable?.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
answerTv.setCompoundDrawables(drawable, null, null, null)
}
override fun getItemCount(): Int {
if (mQuestionEntity == null) {
return 0
}
if (mIsNoneData && (mEntityList == null || mEntityList.isEmpty())) {
return if (mQuestionEntity!!.isAnswerFold) {
FOOTER_ITEM_COUNT + TOP_ITEM_COUNT
} else {
FOOTER_ITEM_COUNT + TOP_ITEM_COUNT + ITEM_EMPTY_COUNT
}
}
return if (mEntityList == null) FOOTER_ITEM_COUNT + TOP_ITEM_COUNT else mEntityList.size + FOOTER_ITEM_COUNT + TOP_ITEM_COUNT
}
fun isOver(): Boolean {
return mIsOver
}
class EmptyViewHolder(itemView: View) : ReuseViewHolder(itemView) {
@BindView(R.id.reuse_nodata_skip_tv_hint)
lateinit var tvHint: TextView
@BindView(R.id.reuse_nodata_skip_tv_btn)
lateinit var tvBtn: TextView
}
class RecommendedUserToInviteViewHolder(itemView: View) : BaseRecyclerViewHolder<Any>(itemView) {
@BindView(R.id.inviteBtn)
lateinit var inviteBtn: View
@BindView(R.id.recyclerview)
lateinit var recyclerView: RecyclerView
var adapter: SimpleInviteAdapter? = null
fun bindView(viewModel: QuestionsDetailViewModel, question: QuestionsDetailEntity, userList: List<InviteEntity>) {
inviteBtn.visibleIf(question.me.isQuestionOwn && !question.me.isSmartInvited)
inviteBtn.setOnClickListener {
DialogUtils.showAlertDialog(
inviteBtn.context,
"智能邀请",
"将为你智能邀请用户来回答!你还可以手动邀请喔~",
"确定",
"取消",
{ viewModel.doSmartInvitation() },
null
)
}
if (adapter == null) {
adapter = SimpleInviteAdapter(recyclerView.context, object : OnListClickListener {
override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
when (view?.id) {
R.id.questionsinvite_item_invite -> {
val inviteEntity = data as InviteEntity
val me = inviteEntity.me
if (me == null || !me.isUserInvite) {
recyclerView.context.ifLogin("问题详情-邀请回答-[邀请]") { viewModel.invite(inviteEntity.id!!) }
}
}
}
}
}, "问题详情")
}
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(recyclerView.context)
adapter?.setData(userList)
}
}
class SimpleInviteAdapter(context: Context, onListClickListener: OnListClickListener, entrance: String)
: QuestionsInviteAdapter(context, onListClickListener, entrance) {
override fun getItemViewType(position: Int): Int {
return ItemViewType.ITEM_BODY
}
override fun getItemCount(): Int {
return if (mEntityList != null && mEntityList.size != 0) mEntityList.size else 0
}
fun setData(dataList: List<InviteEntity>) {
setListData(dataList)
}
}
class SimilarAnswerHint(itemView: View) : BaseRecyclerViewHolder<Any>(itemView)
companion object {
private const val ITEM_EMPTY_COUNT = 1
private const val TYPE_RECOMMEND_USER_TO_INVITE = 987
private const val TYPE_SIMILAR_ANSWER = 988
private const val TYPE_SIMILAR_ANSWER_HINT = 989
}
}

View File

@ -1,616 +0,0 @@
package com.gh.gamecenter.qa.questions.detail;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import com.ethanhua.skeleton.Skeleton;
import com.gh.base.fragment.BaseDialogWrapperFragment;
import com.gh.common.TimeElapsedHelper;
import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.ConcernUtils;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.GdtHelper;
import com.gh.common.util.LogUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.PermissionHelper;
import com.gh.common.util.ShareUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.util.UrlFilterUtils;
import com.gh.common.view.VerticalItemDecoration;
import com.gh.gamecenter.R;
import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.ViewImageActivity;
import com.gh.gamecenter.baselist.ListAdapter;
import com.gh.gamecenter.baselist.ListFragment;
import com.gh.gamecenter.baselist.LoadType;
import com.gh.gamecenter.entity.Permissions;
import com.gh.gamecenter.entity.SpecialColumn;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.mvvm.Status;
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity;
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity;
import com.gh.gamecenter.qa.answer.fold.AnswerFoldActivity;
import com.gh.gamecenter.qa.entity.AnswerDraftEntity;
import com.gh.gamecenter.qa.entity.AnswerEntity;
import com.gh.gamecenter.qa.entity.Questions;
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity;
import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity;
import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment;
import com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity;
import com.gh.gamecenter.qa.questions.invite.QuestionsInviteActivity;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.suggest.SuggestType;
import com.lightgame.utils.Utils;
import com.qq.gdt.action.ActionType;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import butterknife.BindView;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
/**
* Created by khy on 7/12/17.
*/
public class QuestionsDetailFragment
extends ListFragment<AnswerEntity, QuestionsDetailViewModel>
implements TagsSelectFragment.OnModeratorPatchTagsCallback {
public static final int QUESTIONS_DETAIL_ANSWER_REQUEST = 110;
public static final int QUESTIONS_EDIT_REQUEST = 111;
public static final int QUESTIONS_MODERATOR_HISTORY_REQUEST = 112;
private SpecialColumn mSpecialColumn = null;
@BindView(R.id.reuse_tv_none_data)
TextView mNoDataTv;
@BindView(R.id.list_skeleton)
View mSkeletonMaskView;
private QuestionsDetailAdapter mAdapter;
private QuestionsDetailEntity mQuestionsDetailEntity;
private String mQuestionsId;
private boolean mIsCheckConcern;
private String mPath;
private TimeElapsedHelper mElapsedHelper;
public static QuestionsDetailFragment getInstance(String questionsId) {
QuestionsDetailFragment fragment = new QuestionsDetailFragment();
Bundle args = new Bundle();
args.putString(EntranceUtils.KEY_QUESTIONS_ID, questionsId);
fragment.setArguments(args);
return fragment;
}
protected RecyclerView.ItemDecoration getItemDecoration() {
return new VerticalItemDecoration(getContext(), 8, false);
}
@Override
protected int getLayoutId() {
return R.layout.fragment_list_base_skeleton_no_loading;
}
@Override
protected ListAdapter provideListAdapter() {
return mAdapter == null ? mAdapter = new QuestionsDetailAdapter(getContext(), this, mEntrance) : mAdapter;
}
@Override
protected QuestionsDetailViewModel provideListViewModel() {
QuestionsDetailViewModel.Factory factory = new QuestionsDetailViewModel.Factory(mQuestionsId);
return ViewModelProviders.of(this, factory).get(QuestionsDetailViewModel.class);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == QUESTIONS_DETAIL_ANSWER_REQUEST) {
if (resultCode == AnswerEditActivity.SAVE_DRAFTS) {
postDraftsSuccess();
} else if (resultCode == RESULT_REFRESH) {
onLoadRefresh();
} else if (resultCode == Activity.RESULT_OK) {
if (data != null) {
postAnswerSuccess(data.getStringExtra(EntranceUtils.KEY_ANSWER_ID));
}
}
} else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_OK) {
if (data != null && data.getParcelableExtra(QuestionsDetailEntity.class.getSimpleName()) != null) {
mQuestionsDetailEntity = data.getParcelableExtra(QuestionsDetailEntity.class.getSimpleName());
mAdapter.setQuestionsEntity(mQuestionsDetailEntity);
}
} else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_CANCELED) {
onPermissionError();
} else if (requestCode == QUESTIONS_MODERATOR_HISTORY_REQUEST && resultCode == Activity.RESULT_OK) {
onLoadRefresh();
}
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initMenu(R.menu.menu_questions_detail);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments != null) {
mIsCheckConcern = arguments.getBoolean(EntranceUtils.KEY_CHECK_QUESTION_CONCERN, false);
mQuestionsId = arguments.getString(EntranceUtils.KEY_QUESTIONS_ID);
mPath = arguments.getString(EntranceUtils.KEY_PATH);
mSpecialColumn = arguments.getParcelable(EntranceUtils.KEY_DATA);
}
super.onCreate(savedInstanceState);
mNoDataTv.setText(R.string.content_delete_hint);
mElapsedHelper = new TimeElapsedHelper(this);
mSkeletonScreen = Skeleton.bind(mSkeletonMaskView).load(R.layout.fragment_question_detail_skeleton).shimmer(false).show();
mListViewModel.getHeadLiveData().observe(this, detailResource -> {
Objects.requireNonNull(detailResource);
if (detailResource.status == Status.SUCCESS) {
QuestionsDetailEntity data = detailResource.data;
Objects.requireNonNull(data);
if (TextUtils.isEmpty(data.getMe().getMyAnswerId())) {
getUserAnswerDrafts();
}
data.setId(mQuestionsId);
mQuestionsDetailEntity = data;
mAdapter.setQuestionsEntity(data);
GdtHelper.INSTANCE.logAction(ActionType.PAGE_VIEW,
GdtHelper.CONTENT_TYPE, "QUESTION",
GdtHelper.CONTENT_ID, mQuestionsId);
setNavigationTitle(mQuestionsDetailEntity.getCommunity().getName() + " - 问题详情");
DataUtils.onMtaEvent(getContext(), "详情页面", "问题详情", data.getTitle());
} else if (detailResource.status == Status.ERROR) {
try {
HttpException e = detailResource.exception;
if (e != null && e.code() == 404 && e.response().errorBody().string().length() > 0) {
Utils.toast(getContext(), R.string.content_delete_toast);
if (mIsCheckConcern) {
showCancelConcernDialog();
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((DefaultItemAnimator) mListRv.getItemAnimator()).setSupportsChangeAnimations(false);
mReuseNoConn.setOnClickListener(view1 -> { // 重新设置重连点击
onRefresh();
});
mCachedView.getViewTreeObserver().addOnScrollChangedListener(() -> {
View topView = mLayoutManager.findViewByPosition(0);
if (mQuestionsDetailEntity != null) {
if (topView == null || -topView.getTop() > 240) {
setNavigationTitle(mQuestionsDetailEntity.getTitle());
} else {
setNavigationTitle(mQuestionsDetailEntity.getCommunity().getName() + " - 问题详情");
}
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mQuestionsDetailEntity != null) {
MtaHelper.onEventWithTime(
"问题阅读量_按社区",
mElapsedHelper.getElapsedTime(),
mQuestionsDetailEntity.getCommunity().getName(),
StringUtils.combineTwoString(mQuestionsDetailEntity.getTitle(), mQuestionsDetailEntity.getId()));
MtaHelper.onEventWithTime(
"问题阅读量_按位置",
mElapsedHelper.getElapsedTime(),
mPath,
StringUtils.combineTwoString(mQuestionsDetailEntity.getTitle(), mQuestionsDetailEntity.getId()));
MtaHelper.onEventWithTime(
"问题阅读量_社区加位置",
mElapsedHelper.getElapsedTime(),
mQuestionsDetailEntity.getCommunity().getName(),
mPath);
Questions questions = new Questions();
questions.setId(mQuestionsId);
questions.setTitle(mQuestionsDetailEntity.getTitle());
LogUtils.uploadQuestionReadTime(mEntrance,
mElapsedHelper.getElapsedTime(),
questions,
mQuestionsDetailEntity.getCommunity().getId(),
mQuestionsDetailEntity.getCommunity().getName(),
mSpecialColumn);
}
}
@Override
public Observable<List<AnswerEntity>> provideDataObservable(int page) {
return RetrofitManager.getInstance(getContext()).getApi()
.getQuestionsAnswer(mQuestionsId, UrlFilterUtils.getFilterQuery("fold", "false"), page);
}
@Override
public void onListClick(View view, int position, Object data) {
super.onListClick(view, position, data);
int imgPosition = -1;
switch (view.getId()) {
case R.id.footerview_item:
if (mAdapter.isNetworkError()) {
mListViewModel.load(LoadType.RETRY);
} else if (mAdapter.isOver()) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
startActivity(AnswerFoldActivity.getIntent(getContext(), mQuestionsDetailEntity.getId(), mEntrance + "+(问题详情)"));
}
}
break;
case R.id.ask_answer_item_constraintlayout:
case R.id.ask_answer_item_img:
case R.id.ask_answer_item_content:
case R.id.ask_answer_item_title:
AnswerEntity entity = (AnswerEntity) data;
startActivityForResult(AnswerDetailActivity.getIntent(getContext(), entity.getId(), mEntrance, "问题详情-答案列表")
, QUESTIONS_DETAIL_ANSWER_REQUEST);
break;
case R.id.questionsdetail_item_pic1:
imgPosition = 0;
case R.id.questionsdetail_item_pic2:
if (imgPosition == -1) imgPosition = 1;
case R.id.questionsdetail_item_pic3:
if (imgPosition == -1) imgPosition = 2;
if (mQuestionsDetailEntity.getImages().size() > imgPosition) {
Intent intent = ViewImageActivity.getViewImageIntent(getContext(), new ArrayList<>(mQuestionsDetailEntity.getImages())
, imgPosition, mEntrance + "+(问题详情-答案列表)");
startActivity(intent);
}
break;
case R.id.questionsdetail_answer:
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
CheckLoginUtils.checkLogin(getContext(), "问题详情-[我来回答]", () -> {
if (mQuestionsDetailEntity != null && !TextUtils.isEmpty(mQuestionsDetailEntity.getMe().getMyAnswerId())) {
Intent intent = AnswerDetailActivity.getIntent(getContext(), mQuestionsDetailEntity.getMe().getMyAnswerId(),
mEntrance, "问题详情-答案列表");
startActivityForResult(intent, QUESTIONS_DETAIL_ANSWER_REQUEST);
} else {
startActivityForResult(AnswerEditActivity.Companion.getIntent(getContext(), mQuestionsId
, getQuestionsTitle(), mQuestionsDetailEntity.getCommunity().getName()), QUESTIONS_DETAIL_ANSWER_REQUEST);
}
});
break;
case R.id.questionsdetail_invite:
startActivity(QuestionsInviteActivity.getIntent(getContext(), mQuestionsDetailEntity, mEntrance + "+(问题详情)"));
break;
case R.id.questionsdetail_concern:
CheckLoginUtils.checkLogin(getContext(), "问题详情-[关注问题]", () -> {
if (mQuestionsDetailEntity.getMe().isQuestionOwn()) {
startActivityForResult(QuestionEditActivity.Companion.getIntent(getContext(), mQuestionsDetailEntity), QUESTIONS_EDIT_REQUEST);
} else if (!mQuestionsDetailEntity.getMe().isQuestionFollowed()) {
ConcernUtils.INSTANCE.postConcernQuestions(getContext(), mQuestionsId
, new ConcernUtils.onConcernListener() {
@Override
public void onSuccess() {
mQuestionsDetailEntity.getMe().setQuestionFollowed(true);
mQuestionsDetailEntity.setFollowCount(mQuestionsDetailEntity.getFollowCount() + 1);
mAdapter.notifyItemChanged(0);
GdtHelper.INSTANCE.logAction(ActionType.ADD_TO_WISHLIST,
GdtHelper.CONTENT_TYPE, "QUESTION",
GdtHelper.CONTENT_ID, mQuestionsId);
toast("已关注 ");
}
@Override
public void onError() {
}
});
} else {
cancelConcern();
}
});
break;
case R.id.reuse_nodata_skip:
CheckLoginUtils.checkLogin(getContext(), "问题详情-[我来回答]", () -> {
PermissionHelper.checkReadPhoneStateAndStoragePermissionBeforeAction(requireContext(), () -> {
startActivityForResult(AnswerEditActivity.Companion.getIntent(requireContext(), mQuestionsId
, getQuestionsTitle(), mQuestionsDetailEntity.getCommunity().getName()), QUESTIONS_DETAIL_ANSWER_REQUEST);
});
});
break;
}
}
@Override
public void onMenuItemClick(MenuItem menuItem) {
if (mQuestionsDetailEntity == null) return;
switch (menuItem.getItemId()) {
case R.id.menu_more:
showMoreItemDialog();
break;
}
}
private void showMoreItemDialog() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED) || mQuestionsDetailEntity != null) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.menu_question_detail_more_item, null);
Dialog dialog = new Dialog(getActivity());
dialog.setContentView(view);
Window window = dialog.getWindow();
if (window != null) {
window.setGravity(Gravity.RIGHT | Gravity.TOP);
window.setBackgroundDrawable(new ColorDrawable(0));
window.setDimAmount(0.2f);
WindowManager.LayoutParams lp = window.getAttributes();
lp.x = DisplayUtils.dip2px(getContext(), 17);
lp.y = DisplayUtils.dip2px(getContext(), 45); // 减去卡片高度
window.setAttributes(lp);
}
dialog.show();
View item1 = view.findViewById(R.id.more_item1);
View item2 = view.findViewById(R.id.more_item2);
View managerItem = view.findViewById(R.id.more_manager);
managerItem.setVisibility(mQuestionsDetailEntity.getMe().isModerator() ? View.VISIBLE : View.GONE);
item1.setOnClickListener(v -> {
dialog.dismiss();
// 跳转意见反馈
SuggestionActivity.startSuggestionActivity(getContext(), SuggestType.normal, "report",
"问题投诉(" + mQuestionsDetailEntity.getId() + "");
});
item2.setOnClickListener(v -> {
GdtHelper.INSTANCE.logAction(ActionType.SHARE,
GdtHelper.CONTENT_TYPE, "QUESTION",
GdtHelper.CONTENT_ID, mQuestionsId);
dialog.dismiss();
String shareIcon;
if (mQuestionsDetailEntity.getImages().size() > 0) {
shareIcon = mQuestionsDetailEntity.getImages().get(0);
} else {
shareIcon = getString(R.string.share_ghzs_logo);
}
String description = mQuestionsDetailEntity.getDescription();
if (TextUtils.isEmpty(description)) {
description = getString(R.string.ask_share_default_summary);
}
ShareUtils.getInstance(getActivity()).showShareWindows(getActivity(), view
, getString(R.string.share_questions_url, mQuestionsDetailEntity.getId())
, shareIcon
, getString(R.string.ask_share_questions_title, mQuestionsDetailEntity.getTitle(), mQuestionsDetailEntity.getAnswersCount())
, description, ShareUtils.ShareType.askNormal);
});
managerItem.setOnClickListener(v -> {
dialog.dismiss();
showManagerPatchDialog();
});
}
}
private void showManagerPatchDialog() {
if (getContext() == null) return;
final String patchTag = "修改标签";
final String patchQuestion = "修改问题";
final String hideQuestion = "隐藏问题";
final String historyVersion = "历史版本";
final List<String> arrReportType = new ArrayList<>();
Permissions permissions = mQuestionsDetailEntity.getMe().getModeratorPermissions();
if (permissions.getUpdateQuestionTag() > Permissions.GUEST) {
arrReportType.add(patchTag);
}
if (permissions.getUpdateQuestion() > Permissions.GUEST) {
arrReportType.add(patchQuestion);
}
if (permissions.getHideQuestion() > Permissions.GUEST) {
arrReportType.add(hideQuestion);
}
if (permissions.getGetModifiedVersions() > Permissions.GUEST) {
arrReportType.add(historyVersion);
}
int widthPixels = getResources().getDisplayMetrics().widthPixels;
final Dialog dialog = new Dialog(getContext());
LinearLayout container = new LinearLayout(getContext());
container.setOrientation(LinearLayout.VERTICAL);
int pad = DisplayUtils.dip2px(getContext(), 12);
container.setPadding(0, pad, 0, pad);
container.setBackgroundColor(Color.WHITE);
for (final String s : arrReportType) {
TextView itemTv = new TextView(getContext());
itemTv.setText(s);
itemTv.setTextSize(17);
itemTv.setTextColor(ContextCompat.getColor(getContext(), R.color.title));
itemTv.setBackgroundResource(R.drawable.textview_white_style);
itemTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
LinearLayout.LayoutParams.WRAP_CONTENT));
itemTv.setPadding(DisplayUtils.dip2px(getContext(), 20), pad, 0, pad);
container.addView(itemTv);
itemTv.setOnClickListener(v -> {
switch (s) {
case patchTag:
TagsSelectFragment tagsFragment = TagsSelectFragment.getInstance(mQuestionsDetailEntity);
BaseDialogWrapperFragment tagDialog = BaseDialogWrapperFragment.getInstance(tagsFragment, false);
tagsFragment.setPatchTagsCallBack(this);
tagDialog.show(getChildFragmentManager(), TagsSelectFragment.class.getSimpleName());
break;
case patchQuestion:
Intent intent = QuestionEditActivity.getManagerIntent(getContext(), mQuestionsDetailEntity);
startActivityForResult(intent, QUESTIONS_EDIT_REQUEST);
break;
case hideQuestion:
DialogUtils.showAlertDialog(getContext(), "隐藏问题",
mQuestionsDetailEntity.getMe().getModeratorPermissions().getHideQuestion() == Permissions.REPORTER ?
"你的操作将提交给小编审核,确定提交吗?"
: "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)",
"确定", "取消",
() -> mListViewModel.moderatorsHideQuestion(), null);
break;
case historyVersion:
startActivityForResult(HistoryActivity.getIntent(getContext(),
mQuestionsDetailEntity.getId()), QUESTIONS_MODERATOR_HISTORY_REQUEST);
break;
}
dialog.cancel();
});
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(container);
dialog.show();
}
public String getQuestionsTitle() {
return mAdapter.getQuestionsTitle();
}
public void postAnswerSuccess(String answerId) {
if (mQuestionsDetailEntity != null) {
mQuestionsDetailEntity.getMe().setMyAnswerId(answerId);
mListViewModel.load(LoadType.REFRESH);
}
}
public void postDraftsSuccess() {
mQuestionsDetailEntity.setExistDrafts(true);
mAdapter.notifyItemChanged(0);
}
private void getUserAnswerDrafts() {
RetrofitManager.getInstance(getContext()).getApi()
.getUserAnswerDrafts(mQuestionsId, Utils.getTime(getContext()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<AnswerDraftEntity>() {
@Override
public void onResponse(AnswerDraftEntity draft) {
super.onResponse(draft);
if (draft != null) {
mQuestionsDetailEntity.setExistDrafts(true);
mAdapter.notifyItemChanged(0);
}
}
@Override
public void onFailure(HttpException e) {
super.onFailure(e);
}
});
}
private void cancelConcern() {
ConcernUtils.INSTANCE.deleteConcernQuestions(getContext(), mQuestionsId
, new ConcernUtils.onConcernListener() {
@Override
public void onSuccess() {
toast("取消关注");
if (mQuestionsDetailEntity == null) {
FragmentActivity activity = getActivity();
if (activity != null) {
activity.setResult(Activity.RESULT_OK);
activity.finish();
}
} else {
if (mQuestionsDetailEntity.getFollowCount() > 0) {
mQuestionsDetailEntity.setFollowCount(mQuestionsDetailEntity.getFollowCount() - 1);
}
mQuestionsDetailEntity.getMe().setQuestionFollowed(false);
mAdapter.notifyItemChanged(0);
}
}
@Override
public void onError() {
}
});
}
private void showCancelConcernDialog() {
DialogUtils.showAlertDialog(getContext()
, "取消关注问题", "问题已被删除,是否取消关注?"
, " 取消关注", "暂不 "
, () -> {
cancelConcern();
}
, () -> {
if (getActivity() != null) getActivity().finish();
});
}
// 登录事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (reuse.getType().equals(LOGIN_TAG)) { // 登入
onRefresh();
}
}
@Override
public void onPatchTagsSuccess() {
mAdapter.notifyDataSetChanged();
}
@Override
public void onPermissionError() {
mListViewModel.load(LoadType.REFRESH);
}
}

View File

@ -0,0 +1,571 @@
package com.gh.gamecenter.qa.questions.detail
import android.app.Activity
import android.app.Dialog
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.os.Parcelable
import android.text.TextUtils
import android.view.*
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import com.ethanhua.skeleton.Skeleton
import com.gh.base.fragment.BaseDialogWrapperFragment
import com.gh.base.fragment.BaseFragment
import com.gh.common.TimeElapsedHelper
import com.gh.common.util.*
import com.gh.common.view.VerticalItemDecoration
import com.gh.gamecenter.R
import com.gh.gamecenter.SuggestionActivity
import com.gh.gamecenter.ViewImageActivity
import com.gh.gamecenter.baselist.ListAdapter
import com.gh.gamecenter.baselist.ListFragment
import com.gh.gamecenter.baselist.LoadType
import com.gh.gamecenter.entity.Permissions
import com.gh.gamecenter.entity.SpecialColumn
import com.gh.gamecenter.eventbus.EBReuse
import com.gh.gamecenter.mvvm.Status
import com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
import com.gh.gamecenter.qa.answer.fold.AnswerFoldActivity
import com.gh.gamecenter.qa.entity.AnswerDraftEntity
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.Questions
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity
import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment
import com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity
import com.gh.gamecenter.qa.questions.invite.QuestionsInviteActivity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.suggest.SuggestType
import com.lightgame.utils.Utils
import com.qq.gdt.action.ActionType
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.IOException
class QuestionsDetailFragment :
ListFragment<QuestionDetailItemData, QuestionsDetailViewModel>(),
TagsSelectFragment.OnModeratorPatchTagsCallback {
@BindView(R.id.reuse_tv_none_data)
lateinit var mNoDataTv: TextView
@BindView(R.id.list_skeleton)
lateinit var mSkeletonMaskView: View
private var mAdapter: QuestionsDetailAdapter? = null
private var mPath: String? = null
private var mQuestionsId: String? = null
private var mIsCheckConcern: Boolean = false
private var mSpecialColumn: SpecialColumn? = null
private var mElapsedHelper: TimeElapsedHelper? = null
private var mQuestionsDetailEntity: QuestionsDetailEntity? = null
val questionsTitle: String
get() = mAdapter?.getQuestionsTitle() ?: ""
override fun getItemDecoration(): RecyclerView.ItemDecoration {
return VerticalItemDecoration(context, 8f, false)
}
override fun getLayoutId(): Int {
return R.layout.fragment_list_base_skeleton_no_loading
}
override fun provideListAdapter(): ListAdapter<*> {
return if (mAdapter != null) {
mAdapter!!
} else {
QuestionsDetailAdapter(requireContext(), this, mQuestionsDetailEntity, mListViewModel, mEntrance).apply { mAdapter = this }
}
}
override fun provideListViewModel(): QuestionsDetailViewModel {
return viewModelProvider(QuestionsDetailViewModel.Factory(mQuestionsId!!))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == QUESTIONS_DETAIL_ANSWER_REQUEST) {
if (resultCode == AnswerEditActivity.SAVE_DRAFTS) {
postDraftsSuccess()
} else if (resultCode == BaseFragment.RESULT_REFRESH) {
onLoadRefresh()
} else if (resultCode == Activity.RESULT_OK) {
if (data != null) {
postAnswerSuccess(data.getStringExtra(EntranceUtils.KEY_ANSWER_ID))
}
}
} else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_OK) {
if (data?.getParcelableExtra<Parcelable>(QuestionsDetailEntity::class.java.simpleName) != null) {
mQuestionsDetailEntity = data.getParcelableExtra(QuestionsDetailEntity::class.java.simpleName)
mAdapter?.setQuestionsEntity(mQuestionsDetailEntity!!)
}
} else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_CANCELED) {
onPermissionError()
} else if (requestCode == QUESTIONS_MODERATOR_HISTORY_REQUEST && resultCode == Activity.RESULT_OK) {
onLoadRefresh()
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initMenu(R.menu.menu_questions_detail)
}
override fun onCreate(savedInstanceState: Bundle?) {
arguments?.let {
mIsCheckConcern = it.getBoolean(EntranceUtils.KEY_CHECK_QUESTION_CONCERN, false)
mQuestionsId = it.getString(EntranceUtils.KEY_QUESTIONS_ID)
mPath = it.getString(EntranceUtils.KEY_PATH)
mSpecialColumn = it.getParcelable(EntranceUtils.KEY_DATA)
}
super.onCreate(savedInstanceState)
mNoDataTv.setText(R.string.content_delete_hint)
mElapsedHelper = TimeElapsedHelper(this)
mSkeletonScreen = Skeleton.bind(mSkeletonMaskView).load(R.layout.fragment_question_detail_skeleton).shimmer(false).show()
mListViewModel.headLiveData.observeNonNull(this) { detailResource ->
if (detailResource.status == Status.SUCCESS) {
detailResource.data?.let {
if (TextUtils.isEmpty(it.me.myAnswerId)) {
getUserAnswerDrafts()
}
it.id = mQuestionsId
mQuestionsDetailEntity = it
mAdapter?.setQuestionsEntity(it)
GdtHelper.logAction(ActionType.PAGE_VIEW, GdtHelper.CONTENT_TYPE, "QUESTION", GdtHelper.CONTENT_ID, mQuestionsId)
setNavigationTitle(mQuestionsDetailEntity!!.community.name + " - 问题详情")
DataUtils.onMtaEvent(context, "详情页面", "问题详情", it.title)
}
} else if (detailResource.status == Status.ERROR) {
try {
val e = detailResource.exception
if (e != null && e.code() == 404 && e.response().errorBody()?.string()!!.isNotEmpty()) {
Utils.toast(context, R.string.content_delete_toast)
if (mIsCheckConcern) {
showCancelConcernDialog()
}
}
} catch (e1: IOException) {
e1.printStackTrace()
}
}
}
mListViewModel.doRefreshList.observeNonNull(this) {
if (it) {
mAdapter?.notifyDataSetChanged()
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(mListRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
mReuseNoConn.setOnClickListener {
// 重新设置重连点击
onRefresh()
}
mCachedView.viewTreeObserver.addOnScrollChangedListener {
val topView = mLayoutManager.findViewByPosition(0)
if (mQuestionsDetailEntity != null) {
if (topView == null || -topView.top > 240) {
setNavigationTitle(mQuestionsDetailEntity!!.title)
} else {
setNavigationTitle(mQuestionsDetailEntity!!.community.name + " - 问题详情")
}
}
}
}
override fun onDestroyView() {
super.onDestroyView()
mQuestionsDetailEntity?.let {
MtaHelper.onEventWithTime(
"问题阅读量_按社区",
mElapsedHelper!!.elapsedTime,
it.community.name,
StringUtils.combineTwoString(it.title, it.id))
MtaHelper.onEventWithTime(
"问题阅读量_按位置",
mElapsedHelper!!.elapsedTime,
mPath,
StringUtils.combineTwoString(it.title, it.id))
MtaHelper.onEventWithTime(
"问题阅读量_社区加位置",
mElapsedHelper!!.elapsedTime,
it.community.name,
mPath)
val questions = Questions()
questions.id = mQuestionsId ?: ""
questions.title = it.title
LogUtils.uploadQuestionReadTime(mEntrance,
mElapsedHelper!!.elapsedTime,
questions,
it.community.id,
it.community.name,
mSpecialColumn)
}
}
override fun <LIST : Any?> onListClick(view: View?, position: Int, data: Any?) {
var imgPosition = -1
when (view?.id) {
R.id.footerview_item -> if (mAdapter!!.isNetworkError) {
mListViewModel.load(LoadType.RETRY)
} else if (mAdapter!!.isOver()) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
startActivity(AnswerFoldActivity.getIntent(context, mQuestionsDetailEntity!!.id, "$mEntrance+(问题详情)"))
}
}
R.id.ask_answer_item_constraintlayout, R.id.ask_answer_item_img, R.id.ask_answer_item_content, R.id.ask_answer_item_title -> {
val entity = data as AnswerEntity
startActivityForResult(AnswerDetailActivity.getIntent(context, entity.id, mEntrance, "问题详情-答案列表"), QUESTIONS_DETAIL_ANSWER_REQUEST)
}
R.id.questionsdetail_item_pic1 -> {
imgPosition = 0
if (imgPosition == -1) imgPosition = 1
if (imgPosition == -1) imgPosition = 2
if (mQuestionsDetailEntity!!.images.size > imgPosition) {
val intent = ViewImageActivity.getViewImageIntent(context, ArrayList(mQuestionsDetailEntity!!.images), imgPosition, "$mEntrance+(问题详情-答案列表)")
startActivity(intent)
}
}
R.id.questionsdetail_item_pic2 -> {
if (imgPosition == -1) imgPosition = 1
if (imgPosition == -1) imgPosition = 2
if (mQuestionsDetailEntity!!.images.size > imgPosition) {
val intent = ViewImageActivity.getViewImageIntent(context, ArrayList(mQuestionsDetailEntity!!.images), imgPosition, "$mEntrance+(问题详情-答案列表)")
startActivity(intent)
}
}
R.id.questionsdetail_item_pic3 -> {
if (imgPosition == -1) imgPosition = 2
if (mQuestionsDetailEntity!!.images.size > imgPosition) {
val intent = ViewImageActivity.getViewImageIntent(context, ArrayList(mQuestionsDetailEntity!!.images), imgPosition, "$mEntrance+(问题详情-答案列表)")
startActivity(intent)
}
}
R.id.questionsdetail_answer -> if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED))
CheckLoginUtils.checkLogin(context, "问题详情-[我来回答]") {
if (mQuestionsDetailEntity != null && !TextUtils.isEmpty(mQuestionsDetailEntity!!.me.myAnswerId)) {
val intent = AnswerDetailActivity.getIntent(context, mQuestionsDetailEntity!!.me.myAnswerId,
mEntrance, "问题详情-答案列表")
startActivityForResult(intent, QUESTIONS_DETAIL_ANSWER_REQUEST)
} else {
startActivityForResult(AnswerEditActivity.getIntent(context!!, mQuestionsId, questionsTitle, mQuestionsDetailEntity!!.community.name), QUESTIONS_DETAIL_ANSWER_REQUEST)
}
}
R.id.questionsdetail_invite -> startActivity(QuestionsInviteActivity.getIntent(context, mQuestionsDetailEntity, "$mEntrance+(问题详情)"))
R.id.questionsdetail_concern -> CheckLoginUtils.checkLogin(context, "问题详情-[关注问题]") {
if (mQuestionsDetailEntity!!.me.isQuestionOwn) {
startActivityForResult(QuestionEditActivity.getIntent(context!!, mQuestionsDetailEntity!!), QUESTIONS_EDIT_REQUEST)
} else if (!mQuestionsDetailEntity!!.me.isQuestionFollowed) {
ConcernUtils.postConcernQuestions(context!!, mQuestionsId!!, object : ConcernUtils.onConcernListener {
override fun onSuccess() {
mQuestionsDetailEntity!!.me.isQuestionFollowed = true
mQuestionsDetailEntity!!.setFollowCount(mQuestionsDetailEntity!!.getFollowCount() + 1)
mAdapter!!.notifyItemChanged(0)
GdtHelper.logAction(ActionType.ADD_TO_WISHLIST,
GdtHelper.CONTENT_TYPE, "QUESTION",
GdtHelper.CONTENT_ID, mQuestionsId)
toast("已关注 ")
}
override fun onError() {
}
})
} else {
cancelConcern()
}
}
R.id.reuse_nodata_skip -> ifLogin("问题详情-[我来回答]") {
checkReadPhoneStateAndStoragePermissionBeforeAction {
startActivityForResult(
AnswerEditActivity.getIntent(
requireContext(),
mQuestionsId,
questionsTitle,
mQuestionsDetailEntity!!.community.name),
QUESTIONS_DETAIL_ANSWER_REQUEST)
}
}
}
}
override fun onMenuItemClick(menuItem: MenuItem) {
if (mQuestionsDetailEntity == null) return
when (menuItem.itemId) {
R.id.menu_more -> showMoreItemDialog()
}
}
private fun showMoreItemDialog() {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) || mQuestionsDetailEntity != null) {
val view = LayoutInflater.from(context).inflate(R.layout.menu_question_detail_more_item, null)
val dialog = Dialog(activity!!)
dialog.setContentView(view)
val window = dialog.window
if (window != null) {
window.setGravity(Gravity.RIGHT or Gravity.TOP)
window.setBackgroundDrawable(ColorDrawable(0))
window.setDimAmount(0.2f)
val lp = window.attributes
lp.x = DisplayUtils.dip2px(context!!, 17f)
lp.y = DisplayUtils.dip2px(context!!, 45f) // 减去卡片高度
window.attributes = lp
}
dialog.show()
val item1 = view.findViewById<View>(R.id.more_item1)
val item2 = view.findViewById<View>(R.id.more_item2)
val managerItem = view.findViewById<View>(R.id.more_manager)
managerItem.visibility = if (mQuestionsDetailEntity!!.me.isModerator) View.VISIBLE else View.GONE
item1.setOnClickListener {
dialog.dismiss()
// 跳转意见反馈
SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report",
"问题投诉(" + mQuestionsDetailEntity!!.id + "")
}
item2.setOnClickListener {
GdtHelper.logAction(ActionType.SHARE,
GdtHelper.CONTENT_TYPE, "QUESTION",
GdtHelper.CONTENT_ID, mQuestionsId)
dialog.dismiss()
val shareIcon: String
if (mQuestionsDetailEntity!!.images.isNotEmpty()) {
shareIcon = mQuestionsDetailEntity!!.images[0]
} else {
shareIcon = getString(R.string.share_ghzs_logo)
}
var description = mQuestionsDetailEntity!!.description
if (TextUtils.isEmpty(description)) {
description = getString(R.string.ask_share_default_summary)
}
ShareUtils.getInstance(activity).showShareWindows(
activity,
view,
getString(R.string.share_questions_url, mQuestionsDetailEntity!!.id),
shareIcon,
getString(R.string.ask_share_questions_title, mQuestionsDetailEntity!!.title, mQuestionsDetailEntity!!.answersCount),
description,
ShareUtils.ShareType.askNormal)
}
managerItem.setOnClickListener {
dialog.dismiss()
showManagerPatchDialog()
}
}
}
private fun showManagerPatchDialog() {
if (context == null) return
val patchTag = "修改标签"
val patchQuestion = "修改问题"
val hideQuestion = "隐藏问题"
val historyVersion = "历史版本"
val arrReportType = ArrayList<String>()
val (_, _, _, _, _,
updateTagPermission,
updateQuestionPermission,
hideQuestionPermission,
getModifiedVersionsPermission) = mQuestionsDetailEntity?.me?.moderatorPermissions!!
if (updateTagPermission > Permissions.GUEST) {
arrReportType.add(patchTag)
}
if (updateQuestionPermission > Permissions.GUEST) {
arrReportType.add(patchQuestion)
}
if (hideQuestionPermission > Permissions.GUEST) {
arrReportType.add(hideQuestion)
}
if (getModifiedVersionsPermission > Permissions.GUEST) {
arrReportType.add(historyVersion)
}
val widthPixels = resources.displayMetrics.widthPixels
val dialog = Dialog(requireContext())
val container = LinearLayout(context)
container.orientation = LinearLayout.VERTICAL
val pad = DisplayUtils.dip2px(requireContext(), 12f)
container.setPadding(0, pad, 0, pad)
container.setBackgroundColor(Color.WHITE)
for (s in arrReportType) {
val itemTv = TextView(context)
itemTv.text = s
itemTv.textSize = 17f
itemTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.title))
itemTv.setBackgroundResource(R.drawable.textview_white_style)
itemTv.layoutParams = LinearLayout.LayoutParams(widthPixels * 9 / 10,
LinearLayout.LayoutParams.WRAP_CONTENT)
itemTv.setPadding(DisplayUtils.dip2px(context!!, 20f), pad, 0, pad)
container.addView(itemTv)
itemTv.setOnClickListener {
when (s) {
patchTag -> {
val tagsFragment = TagsSelectFragment.getInstance(mQuestionsDetailEntity!!)
val tagDialog = BaseDialogWrapperFragment.getInstance(tagsFragment, false)
tagsFragment.setPatchTagsCallBack(this)
tagDialog.show(childFragmentManager, TagsSelectFragment::class.java.simpleName)
}
patchQuestion -> {
val intent = QuestionEditActivity.getManagerIntent(requireContext(), mQuestionsDetailEntity!!)
startActivityForResult(intent, QUESTIONS_EDIT_REQUEST)
}
hideQuestion -> DialogUtils.showAlertDialog(context,
"隐藏问题",
if (mQuestionsDetailEntity!!.me.moderatorPermissions.hideQuestion == Permissions.REPORTER)
"你的操作将提交给小编审核,确定提交吗?"
else
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)",
"确定", "取消",
{ mListViewModel.moderatorsHideQuestion() }, null)
historyVersion -> {
startActivityForResult(
HistoryActivity.getIntent(requireContext(), mQuestionsDetailEntity?.id!!),
QUESTIONS_MODERATOR_HISTORY_REQUEST)
}
}
dialog.cancel()
}
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog.setContentView(container)
dialog.show()
}
fun postAnswerSuccess(answerId: String) {
if (mQuestionsDetailEntity != null) {
mQuestionsDetailEntity?.me?.myAnswerId = answerId
mListViewModel.load(LoadType.REFRESH)
}
}
fun postDraftsSuccess() {
mQuestionsDetailEntity?.isExistDrafts = true
mAdapter?.notifyItemChanged(0)
}
private fun getUserAnswerDrafts() {
RetrofitManager.getInstance(context).api
.getUserAnswerDrafts(mQuestionsId, Utils.getTime(context))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<AnswerDraftEntity>() {
override fun onResponse(draft: AnswerDraftEntity?) {
super.onResponse(draft)
if (draft != null) {
mQuestionsDetailEntity?.isExistDrafts = true
mAdapter!!.notifyItemChanged(0)
}
}
})
}
private fun cancelConcern() {
ConcernUtils.deleteConcernQuestions(requireContext(), mQuestionsId!!, object : ConcernUtils.onConcernListener {
override fun onSuccess() {
toast("取消关注")
if (mQuestionsDetailEntity == null) {
val activity = activity
if (activity != null) {
activity.setResult(Activity.RESULT_OK)
activity.finish()
}
} else {
mQuestionsDetailEntity?.let {
if (it.getFollowCount() > 0) {
it.setFollowCount(it.getFollowCount() - 1)
}
it.me.isQuestionFollowed = false
}
mAdapter?.notifyItemChanged(0)
}
}
override fun onError() {
}
})
}
private fun showCancelConcernDialog() {
DialogUtils.showAlertDialog(
context,
"取消关注问题",
"问题已被删除,是否取消关注?",
" 取消关注",
"暂不 ",
{ cancelConcern() },
{
if (activity != null && activity?.isFinishing == false) {
activity?.finish()
}
})
}
// 登录事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(reuse: EBReuse) {
if (reuse.type == LOGIN_TAG) { // 登入
onRefresh()
}
}
override fun onPatchTagsSuccess() {
mAdapter?.notifyDataSetChanged()
}
override fun onPermissionError() {
mListViewModel.load(LoadType.REFRESH)
}
companion object {
const val QUESTIONS_DETAIL_ANSWER_REQUEST = 110
const val QUESTIONS_EDIT_REQUEST = 111
const val QUESTIONS_MODERATOR_HISTORY_REQUEST = 112
fun getInstance(questionsId: String): QuestionsDetailFragment {
val fragment = QuestionsDetailFragment()
val args = Bundle()
args.putString(EntranceUtils.KEY_QUESTIONS_ID, questionsId)
fragment.arguments = args
return fragment
}
}
}

View File

@ -1,30 +1,41 @@
package com.gh.gamecenter.qa.questions.detail
import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.util.ErrorHelper
import com.gh.common.util.UrlFilterUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.baselist.ListHeadViewModel
import com.gh.gamecenter.baselist.LoadStatus
import com.gh.gamecenter.baselist.LoadType
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.Permissions
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.mvvm.Resource
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.HttpException
class QuestionsDetailViewModel(application: Application, val questionId: String)
: ListHeadViewModel<AnswerEntity, AnswerEntity, QuestionsDetailEntity>(application) {
: ListHeadViewModel<AnswerEntity, QuestionDetailItemData, QuestionsDetailEntity>(application) {
val doRefreshList = MutableLiveData<Boolean>()
override fun provideHeadDataObservable(): Observable<QuestionsDetailEntity> {
return mApi.getQuestionsById(questionId)
@ -35,7 +46,108 @@ class QuestionsDetailViewModel(application: Application, val questionId: String)
}
override fun mergeResultLiveData() {
mResultLiveData.addSource(mListLiveData) { mResultLiveData.postValue(it) }
mResultLiveData.addSource(mListLiveData) {
val itemDataList = arrayListOf<QuestionDetailItemData>()
for (answer in it) {
itemDataList.add(QuestionDetailItemData(answer = answer))
}
// 当回答列表为空时尝试请求
if (itemDataList.size == 0) {
loadRecommendedUsersAndSimilarAnswers()
} else {
mResultLiveData.postValue(itemDataList)
}
}
}
@SuppressLint("CheckResult")
fun loadRecommendedUsersAndSimilarAnswers() {
val itemDataList = arrayListOf<QuestionDetailItemData>()
mApi.getQuestionInvitations(questionId)
.subscribeOn(Schedulers.io())
.flatMap { response ->
mHeadLiveData.value?.data?.let { question ->
itemDataList.add(QuestionDetailItemData(recommendedUserToInvite = response))
}
return@flatMap mApi.getSimilarAnswers(questionId)
}
.subscribe(object : BiResponse<List<AnswerEntity>>() {
override fun onSuccess(data: List<AnswerEntity>) {
if (data.isNotEmpty()) {
itemDataList.add(QuestionDetailItemData(showSimilarAnswerHint = true))
for (answer in data) {
itemDataList.add(QuestionDetailItemData(similarAnswer = answer))
}
}
mResultLiveData.postValue(itemDataList)
}
override fun onFailure(exception: Exception) {
// 请求失败时回落到原始的没有加载推荐的我来回答界面
mResultLiveData.postValue(arrayListOf())
}
})
}
@SuppressLint("CheckResult")
fun doSmartInvitation() {
mApi.postSmartInvitations(questionId)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
mHeadLiveData.value?.data?.let { question ->
question.me.isSmartInvited = true
mHeadLiveData.postValue(Resource.success(question))
}
doRefreshList.postValue(true)
}
})
}
fun invite(userId: String) {
val jsonObject = JSONObject()
try {
jsonObject.put("user_id", userId)
} catch (e: JSONException) {
e.printStackTrace()
}
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
RetrofitManager.getInstance(getApplication()).api
.postInvite(body, questionId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
Utils.toast(getApplication(), "邀请成功")
mResultLiveData.value?.let {
for (item in it) {
item.recommendedUserToInvite?.let { userList ->
for (user in userList) {
if (userId == user.id) {
if (user.me == null) {
user.me = MeEntity()
}
user.me?.isUserInvite = true
}
}
}
}
mResultLiveData.postValue(it)
}
doRefreshList.postValue(true)
}
override fun onFailure(e: HttpException?) {
try {
val string = e?.response()?.errorBody()?.string()
ErrorHelper.handleError(getApplication(), string, false)
} catch (e1: Exception) {
e1.printStackTrace()
}
}
})
}
fun moderatorsHideQuestion() {

View File

@ -1,9 +1,9 @@
package com.gh.gamecenter.qa.questions.invite
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.base.OnListClickListener
import com.gh.common.constant.ItemViewType
import com.gh.gamecenter.PersonalHomeActivity
@ -15,9 +15,9 @@ import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.qa.entity.InviteEntity
import java.util.*
class QuestionsInviteAdapter(context: Context,
private val mListClickListener: OnListClickListener,
private val mEntrance: String) : ListAdapter<InviteEntity>(context) {
open class QuestionsInviteAdapter(context: Context,
private val mListClickListener: OnListClickListener,
private val mEntrance: String) : ListAdapter<InviteEntity>(context) {
override fun setListData(listData: List<InviteEntity>?) {
if (listData != null && listData.isNotEmpty()) {

View File

@ -40,6 +40,7 @@ import com.gh.gamecenter.entity.SubjectSettingEntity;
import com.gh.gamecenter.entity.TagEntity;
import com.gh.gamecenter.entity.TimeEntity;
import com.gh.gamecenter.entity.ToolBoxEntity;
import com.gh.gamecenter.entity.UserEntity;
import com.gh.gamecenter.entity.UserInfoEntity;
import com.gh.gamecenter.entity.VersionVoteEntity;
import com.gh.gamecenter.entity.VideoDraftEntity;
@ -1927,6 +1928,24 @@ public interface ApiService {
@POST("videos")
Observable<ResponseBody> postVideo(@Body RequestBody body);
/**
* 获取相应问题的邀请列表
*/
@GET("questions/{question_id}/invitations")
Single<List<InviteEntity>> getQuestionInvitations(@Path("question_id") String questionId);
/**
* 对相应问题进行只能邀请
*/
@POST("questions/{question_id}:smart_invite")
Single<ResponseBody> postSmartInvitations(@Path("question_id") String questionId);
/**
* 获取对应问题的相似回答
*/
@GET("questions/{question_id}/similar_answers")
Single<List<AnswerEntity>> getSimilarAnswers(@Path("question_id") String questionId);
/**
* 提交视频草稿
*/