diff --git a/README.md b/README.md
index 9dcb7ed95e..cef58d1229 100644
--- a/README.md
+++ b/README.md
@@ -67,4 +67,5 @@
- 把 ListViewModel 的数据结构类型转换方式换为抽象方法,让继承的类实现,避免出现无响应的问题
-- rxjava2 如果接口返回为空 会发生异常:java.lang.NullPointerException: Null is not a valid element (答案编辑)
\ No newline at end of file
+- rxjava2 如果接口返回为空 会发生异常:java.lang.NullPointerException: Null is not a valid element (答案编辑)
+- constraintLayout 1.1.2 导致布局出现异常(问题编辑标签选择弹窗)
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 47719f2371..44a8572aa4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -299,7 +299,7 @@
android:screenOrientation = "portrait" />
(QuestionsDetailEntity.TAG)
+ if (detailEntity != null) { // 问题编辑
+ mViewModel?.questionEntity = detailEntity
+ mViewModel?.content = detailEntity.description
+ mViewModel?.picList?.postValue(detailEntity.images as MutableList?)
+ if (mViewModel?.title.isNullOrEmpty()) mViewModel?.title = detailEntity.title
+ } else { // 新增问题
+ var searchKey = intent.getStringExtra(EntranceUtils.KEY_QUESTIONS_SEARCH_KEY)
+ if (!searchKey.isNullOrEmpty() && searchKey.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH)
+ searchKey = searchKey.substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH)
+ if (mViewModel?.title.isNullOrEmpty()) mViewModel?.title = searchKey
+ }
+ }
+
+ // Navigation
+ if (mViewModel?.questionEntity != null) {
+ setNavigationTitle("编辑问题")
+ } else {
+ setNavigationTitle(UserManager.getInstance().community.name)
+ }
+
+ mViewModel?.getDefaultTag()
+
+ // TitleTip
+ if (mViewModel?.questionEntity == null) {
+ val titleTipAdapter = QuestionTitleTipAdapter(this, mBinding.questionseditTitle, mViewModel?.communityId)
+ mBinding.questionseditTitle.setAdapter(titleTipAdapter)
+ }
+
+ // TitleEdit
+ mBinding.questionseditTitle.addTextChangedListener(LimitTextWatcher(mBinding.questionseditTitle))
+
+ // ContentEdit
+ mBinding.questionseditContent.addTextChangedListener(LimitTextWatcher(mBinding.questionseditContent))
+
+ // Pic List
+ val picAdapter = QuestionsEditPicAdapter(this, mViewModel!!)
+ mBinding.suggestPicRv.layoutManager = object : GridLayoutManager(this, 5) {
+ override fun canScrollVertically(): Boolean {
+ return false
+ }
+ }
+ mBinding.suggestPicRv.adapter = picAdapter
+
+ // Process dialog
+ mViewModel?.processDialog?.observe(this, Observer { it ->
+ if (it?.isShow!!) {
+ mProcessingDialog = WaitingDialogFragment.newInstance(it.msg, false)
+ mProcessingDialog?.show(supportFragmentManager, null, {
+ if (mViewModel?.uploadImageSubscription != null && !mViewModel?.uploadImageSubscription!!.isDisposed) {
+ mUpdateImageCancelDialog = DialogUtils.showAlertDialog(this, "提示"
+ , "图片正在上传中,确定取消吗?"
+ , "确定", "取消", {
+ mViewModel?.uploadImageSubscription!!.dispose()
+ mUpdateImageCancelDialog?.dismiss()
+ mProcessingDialog?.dismiss()
+ }, null)
+ }
+ })
+ } else {
+ mUpdateImageCancelDialog?.dismiss()
+ mProcessingDialog?.dismiss()
+ }
+ })
+
+ mViewModel?.titleTags?.observe(this, Observer> {
+ if (supportFragmentManager.findFragmentByTag(TagsSelectFragment::javaClass.name) == null) {
+ val dialog = BaseDialogWrapperFragment.getInstance(TagsSelectFragment.getInstance(), false)
+ dialog.show(supportFragmentManager, TagsSelectFragment::javaClass.name)
+ }
+ })
+
+ mViewModel?.picList?.observe(this, Observer { it ->
+ if (it != null) picAdapter.notifyPicList(it)
+ })
+
+ // 增加提问时, 如果searchKey不为空 光标跳到最后
+ mBaseHandler.postDelayed({
+ if (mViewModel?.questionEntity == null) {
+ mBinding.questionseditTitle.setSelection(mBinding.questionseditTitle.text.toString().length)
+ }
+ }, 50)
+ }
+
+ override fun onMenuItemClick(menuItem: MenuItem?): Boolean {
+ mViewModel?.checkTitleAndLoadTitleTag()
+ return false
+ }
+
+
+ // Limits of EditText
+ private inner class LimitTextWatcher(private val mEditText: EditText) : TextWatcher {
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+ if (mEditText === mBinding.questionseditTitle) {
+ val etContent = s.toString()
+
+ // 去空格
+ if (etContent.contains(" ")) {
+ mBinding.questionseditTitle.setText(etContent.replace(" ".toRegex(), ""))
+ mBinding.questionseditTitle.setSelection(start)
+ return
+ }
+
+ // 检查标题最大长度
+ if (s.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) {
+ mBinding.questionseditTitle.setText("")
+ val newText = s.toString().substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH)
+ mBinding.questionseditTitle.setText(newText)
+ mBinding.questionseditTitle.setSelection(mBinding.questionseditTitle.text?.length!!)
+ toast("标题最多${QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH}个字")
+ }
+ } else if (mEditText === mBinding.questionseditContent) {
+
+ // 检查内容最大长度
+ if (s.length > QuestionEditViewModel.QUESTION_CONTENT_MAX_LENGTH) {
+ mBinding.questionseditContent.setText("")
+ val newText = s.toString().substring(0, QuestionEditViewModel.QUESTION_CONTENT_MAX_LENGTH)
+ mBinding.questionseditContent.setText(newText)
+ mBinding.questionseditContent.setSelection(mBinding.questionseditContent.text.length)
+ toast("内容最多${QuestionEditViewModel.QUESTION_CONTENT_MAX_LENGTH}个字")
+ }
+ }
+ }
+
+ override fun afterTextChanged(s: Editable) {}
+ }
+
+ // 退出提示
+ override fun onBackPressed() {
+ // 需要检查的内容,其中任意一个不为空都要打开提示弹窗
+ val imgList = mViewModel?.picList?.value
+ val title = mBinding.questionseditTitle.text.toString().trim()
+ val content = mBinding.questionseditContent.text.toString().trim()
+
+ if (imgList != null && imgList.size > 0 || title.isNotEmpty() || content.isNotEmpty()) {
+ DialogUtils.showCancelAlertDialog(this, "提示"
+ , if (mViewModel?.questionEntity == null) "确定放弃提问吗?" else "确定放弃编辑吗?"
+ , "再想想", " 放弃", null) { finish() }
+ return
+ }
+ super.onBackPressed()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt
new file mode 100644
index 0000000000..f8df75abb5
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt
@@ -0,0 +1,244 @@
+package com.gh.gamecenter.qa.questions.edit
+
+import android.app.Application
+import android.arch.lifecycle.AndroidViewModel
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MediatorLiveData
+import android.content.Intent
+import android.provider.MediaStore
+import android.text.TextUtils
+import com.gh.base.fragment.WaitingDialogFragment
+import com.gh.common.util.GsonUtils
+import com.gh.common.util.UploadUtils
+import com.gh.common.util.UrlFilterUtils
+import com.gh.gamecenter.R
+import com.gh.gamecenter.manager.UserManager
+import com.gh.gamecenter.mvvm.NetworkBoundResource
+import com.gh.gamecenter.mvvm.Resource
+import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
+import com.gh.gamecenter.retrofit.Response
+import com.gh.gamecenter.retrofit.RetrofitManager
+import com.gh.gamecenter.retrofit.service.ApiService
+import com.lightgame.utils.Utils
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import okhttp3.MediaType
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.HttpException
+import java.io.File
+import java.util.*
+
+/**
+ * Created by khy on 28/04/18.
+ */
+class QuestionEditViewModel(application: Application) : AndroidViewModel(application) {
+ companion object {
+ const val QUESTION_TAG_MAX_COUNT = 5
+ const val PIC_MAX_AMOUNT = 3
+ const val QUESTION_TITLE_MIN_LENGTH = 6
+ const val QUESTION_CONTENT_MAX_LENGTH = 300
+ const val QUESTION_TITLE_MAX_LENGTH = 50
+ const val PIC_MAX_FILE_SIZE = 10 * 1024 * 1024
+ }
+
+ private val mApiService: ApiService = RetrofitManager.getInstance(getApplication()).api
+
+ var communityId: String? = null
+
+ val processDialog = MediatorLiveData()
+ val titleTags = MediatorLiveData>()
+
+ var uploadImageSubscription: Disposable? = null
+
+ // post data
+ var title: String? = ""
+ var content: String? = ""
+ val picList = MediatorLiveData>()
+ var defaultTags: MutableList = ArrayList()
+ var questionEntity: QuestionsDetailEntity? = null
+ val selectedTags: MutableList = ArrayList()
+
+ /**
+ * 获取默认标签和确定当前communityId
+ */
+ fun getDefaultTag() {
+ communityId = if (questionEntity != null) questionEntity?.communityId
+ else UserManager.getInstance().community.id
+ mApiService
+ .getCommunitiesTags(communityId)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : Response>() {
+ override fun onResponse(response: List?) {
+ defaultTags = response as MutableList
+ }
+ })
+ }
+
+ /**
+ * 检查标题是否符合规则
+ * 根据问题标题获取相应标签(问题编辑无需获取)
+ */
+ fun checkTitleAndLoadTitleTag() {
+ if (TextUtils.isEmpty(title)) {
+ Utils.toast(getApplication(), "标题不能为空")
+ return
+ }
+
+ // 检查标题长度限制
+ title?.trim()
+ title = title?.replace(" ", "")
+ if (title!!.length < QUESTION_TITLE_MIN_LENGTH) {
+ Utils.toast(getApplication(), "标题至少${QUESTION_TITLE_MIN_LENGTH}个字")
+ return
+ }
+
+ // 检查标题结尾是否存在问号,没则主动加上
+ if (title!!.length <= QUESTION_TITLE_MAX_LENGTH) {
+ val endString = title?.substring(title!!.length - 1, title!!.length)
+ if ("?" != endString && "?" != endString)
+ title += "?"
+ }
+
+ selectedTags.clear() // 清空已选择的标签
+ if (questionEntity == null) {
+ loadTitleTags()
+ } else {
+ titleTags.postValue(null)
+ }
+ }
+
+ /**
+ * 根据问题标题获取相应标签(标签默认选中)
+ */
+ private fun loadTitleTags() {
+ processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
+ mApiService
+ .getQuestionTagsByTitle(communityId, UrlFilterUtils.getFilterQuery("title", title))
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : Response>() {
+ override fun onResponse(response: List?) {
+ titleTags.postValue(response)
+ processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false))
+ }
+
+ override fun onFailure(e: HttpException?) {
+ processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false))
+ Utils.toast(getApplication(), R.string.request_failure_normal_hint)
+ }
+ })
+ }
+
+ /**
+ * 选择动作(选中标签/移除已选中的标签)
+ */
+ fun selectTag(tag: String): Boolean {
+ return when {
+ selectedTags.contains(tag) -> {
+ selectedTags.remove(tag)
+ false
+ }
+ selectedTags.size < QUESTION_TAG_MAX_COUNT -> {
+ selectedTags.add(tag)
+ true
+ }
+ else -> {
+ Utils.toast(getApplication(), R.string.questionsdetail_max_tag_hint)
+ false
+ }
+ }
+ }
+
+ /**
+ * 检查图片是否符合规则并上传图片
+ * @param picPath 图片本地路径
+ */
+ fun uploadPic(data: Intent) {
+ val selectedImage = data.data ?: return
+ val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
+
+ val application: Application = getApplication()
+
+ val cursor = application.contentResolver.query(selectedImage, filePathColumn, null, null, null)
+ ?: return
+ cursor.moveToFirst()
+
+ val columnIndex = cursor.getColumnIndex(filePathColumn[0])
+ val picPath = cursor.getString(columnIndex)
+ cursor.close()
+
+ Utils.log("picturePath = " + picPath)
+ val file = File(picPath)
+ if (file.length() > PIC_MAX_FILE_SIZE) {
+ Utils.toast(getApplication(), R.string.suggestion_pic_hint)
+ return
+ } else {
+ val picList = picList.value
+ if (picList != null && picList.size >= PIC_MAX_AMOUNT) {
+ Utils.toast(getApplication(), R.string.questions_edit_maxpic_hint)
+ return
+ }
+ }
+
+ processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", true))
+ uploadImageSubscription = UploadUtils.compressAndUploadImage(picPath, object : UploadUtils.OnUploadImageListener {
+ override fun onSuccess(imageUrl: String) {
+ processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false))
+ val list = picList.value ?: ArrayList()
+ list.add(imageUrl)
+ picList.postValue(list)
+ }
+
+ override fun onError(e: Throwable?) {
+ processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false))
+ if (e != null && e is HttpException && e.code() == 403) {
+ Utils.toast(getApplication(), "图片违规")
+ } else {
+ Utils.toast(getApplication(), "图片上传失败,请检查网络")
+ }
+ }
+ })
+ }
+
+ /**
+ * 移除以上传的图片
+ * @param picPath 图片成功上传后的URL
+ */
+ fun removePic(picPath: String) {
+ val list = picList.value
+ if (list != null && list.remove(picPath)) {
+ picList.postValue(list)
+ }
+ }
+
+ /**
+ * 提交问题
+ */
+ fun postQuestion(): LiveData> {
+ val entity = QuestionsDetailEntity()
+ entity.title = title
+ entity.description = content
+ entity.tags = selectedTags
+ entity.images = if (picList.value != null) {
+ picList.value!!
+ } else {
+ ArrayList()
+ }
+
+ val body = RequestBody.create(MediaType.parse("application/json"), GsonUtils.getInstance().toJson(entity))
+ val observable = if (questionEntity != null) {
+ questionEntity?.tags = entity.tags
+ questionEntity?.images = entity.images
+ questionEntity?.title = entity.title
+ questionEntity?.description = entity.description
+ mApiService.patchQuestions(body, questionEntity?.id) // patch
+ } else {
+ mApiService.postQuestions(body, communityId) // add
+ }
+
+ return NetworkBoundResource(observable).asLiveData()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt
new file mode 100644
index 0000000000..3d4fb00eb3
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt
@@ -0,0 +1,214 @@
+package com.gh.gamecenter.qa.questions.edit
+
+import android.app.Activity
+import android.app.Dialog
+import android.arch.lifecycle.Observer
+import android.arch.lifecycle.ViewModelProviders
+import android.content.Intent
+import android.os.Bundle
+import android.support.v4.content.ContextCompat
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.Window
+import android.widget.EditText
+import android.widget.TextView
+import com.gh.base.fragment.BaseDialogWrapperFragment
+import com.gh.base.fragment.BaseFragment
+import com.gh.base.fragment.WaitingDialogFragment
+import com.gh.common.util.AskErrorResponseUtils
+import com.gh.common.util.DisplayUtils
+import com.gh.common.util.LoginUtils
+import com.gh.gamecenter.R
+import com.gh.gamecenter.mvvm.Status
+import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
+import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
+import com.google.android.flexbox.FlexboxLayout
+import com.lightgame.utils.Util_System_Keyboard
+import kotterknife.bindView
+import org.json.JSONObject
+import java.util.*
+
+/**
+ * Created by khy on 28/04/18.
+ */
+class TagsSelectFragment : BaseFragment() {
+
+ companion object {
+ fun getInstance(): TagsSelectFragment {
+ val fragment = TagsSelectFragment()
+ return fragment
+ }
+ }
+
+ private val mTagFl by bindView(R.id.questions_edit_tag)
+ private val mAddTagBtn by bindView(R.id.questions_edit_tag_add)
+ private val mPostBtn by bindView(R.id.questions_edit_tag_positive)
+ private val mCancelBtn by bindView(R.id.questions_edit_tag_cancel)
+
+ private var mViewModel: QuestionEditViewModel? = null
+
+ private val mAllTags: MutableList = ArrayList() // 所有标签集合
+
+ override fun getLayoutId(): Int {
+ return R.layout.questions_edit_tag
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ if (activity != null) mViewModel = ViewModelProviders.of(activity!!).get(QuestionEditViewModel::class.java)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ initTags()
+
+ mAddTagBtn.setOnClickListener {
+ if (mViewModel?.selectedTags?.size!! < QuestionEditViewModel.QUESTION_TAG_MAX_COUNT) {
+ showAddTagDialog()
+ } else {
+ toast(R.string.questionsdetail_max_tag_hint)
+ }
+ }
+
+ mCancelBtn.setOnClickListener {
+ val fragment = parentFragment
+ (fragment as? BaseDialogWrapperFragment)?.dismiss()
+ }
+
+ mPostBtn.setOnClickListener {
+ mViewModel?.postQuestion()?.observe(this, Observer { it ->
+ when (it?.status) {
+ Status.SUCCESS -> {
+ mViewModel?.processDialog?.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false))
+ toast("提交成功")
+ if (mViewModel?.questionEntity != null) { // 修改问题
+ val data = Intent()
+ data.putExtra(QuestionsDetailEntity.TAG, mViewModel?.questionEntity)
+ activity?.setResult(Activity.RESULT_OK, data)
+ } else {
+ val data = JSONObject(it.data?.string())
+ startActivity(QuestionsDetailActivity.getIntent(context, data.getString("_id"), "(回答编辑)"))
+ }
+ activity?.finish()
+ }
+ Status.ERROR -> {
+ mViewModel?.processDialog?.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false))
+ if (!LoginUtils.userPostErrorToast(it.exception, context, false)) {
+ toast("提交失败")
+ AskErrorResponseUtils.errorResponseControl(context, it.exception)
+ }
+ }
+ Status.LOADING -> {
+ mViewModel?.processDialog?.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
+ }
+ }
+ })
+ }
+
+ }
+
+ private fun initTags() {
+ // 添加标签
+ val mDefaultTag = mViewModel?.defaultTags ?: ArrayList()
+
+ if (mViewModel?.questionEntity == null) {
+ val mTitleTag = (mViewModel?.titleTags?.value ?: ArrayList()) as MutableList
+ // 添加默认标签(如果标题标签与默认标签重复则选中)
+ for (s in mDefaultTag.reversed()) {
+ val contains = mTitleTag.contains(tag)
+ addTag(s, contains)
+ if (contains) mTitleTag.remove(tag)
+ }
+ // 未匹配到默认标签的默认选中在前排
+ for (s in mTitleTag) {
+ addTag(s, true)
+ }
+ } else {
+ val tags = mViewModel?.questionEntity?.tags ?: ArrayList()
+ for (s in mDefaultTag) {
+ if (!tags.contains(s))
+ addTag(s, false)
+ }
+ for (s in tags.reversed()) {
+ addTag(s, true)
+ }
+ }
+ }
+
+ private fun showAddTagDialog() {
+ view?.visibility = View.GONE
+ val dialog = Dialog(context!!)
+ val view = View.inflate(context, R.layout.dialog_modify_nickname, null)
+ val title = view.findViewById(R.id.dialog_nickname_title)
+ val input = view.findViewById(R.id.dialog_nickname_input)
+ title.text = "新建标签"
+ input.hint = ""
+ input.setSelection(input.text.length)
+ // 取消按钮
+ view.findViewById(R.id.dialog_nickname_cancel).setOnClickListener { dialog.dismiss() }
+ // 确定按钮
+ view.findViewById(R.id.dialog_nickname_confirm).setOnClickListener {
+ if (!TextUtils.isEmpty(input.text.toString().trim())) {
+ addTag(input.text.toString().trim(), true)
+ dialog.dismiss()
+ } else {
+ toast(R.string.vote_empty_hint)
+ }
+ }
+ dialog.setOnDismissListener {
+ Util_System_Keyboard.hideSoftKeyboard(activity)
+ this.view?.visibility = View.VISIBLE
+ }
+ dialog.setCancelable(false)
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
+ dialog.setContentView(view)
+ dialog.show()
+ mBaseHandler.postDelayed({ Util_System_Keyboard.showSoftKeyboard(context, input) }, 300)
+ }
+
+ private fun addTag(tag: String, isSelect: Boolean) {
+ if (isSelect && mAllTags.contains(tag)) { // 标签已存在
+ if (!mViewModel?.selectedTags?.contains(tag)!!) { // 标签已存在且未选择
+ for (i in 0 until mTagFl.childCount) {
+ val tagView = mTagFl.getChildAt(i) as TextView
+ val text = tagView.text
+ if (text != null && text.toString() == tag) {
+ mViewModel?.selectedTags?.add(tag)
+ tagView.setBackgroundResource(R.drawable.comment_border_bg)
+ tagView.setTextColor(ContextCompat.getColor(context!!, R.color.theme))
+ }
+ }
+ }
+ toast("标签已存在")
+ return
+ }
+
+ val view = LayoutInflater.from(context).inflate(R.layout.questionsdedit_tag_item, null)
+ val tagTv = view as TextView
+ tagTv.text = tag
+ val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ params.setMargins(0, DisplayUtils.dip2px(context, 5f), DisplayUtils.dip2px(context, 15f), DisplayUtils.dip2px(context, 5f))
+ tagTv.layoutParams = params
+ mTagFl.addView(view, 0)
+
+ tagTv.setOnClickListener({
+ if (mViewModel?.selectTag(tagTv.text.toString())!!) {
+ tagTv.setBackgroundResource(R.drawable.comment_border_bg)
+ tagTv.setTextColor(ContextCompat.getColor(context!!, R.color.theme))
+ } else {
+ tagTv.setBackgroundResource(R.drawable.border_suggest_bg)
+ tagTv.setTextColor(ContextCompat.getColor(context!!, R.color.content))
+ }
+ })
+
+ if (isSelect) {
+ mViewModel?.selectedTags?.add(tag)
+ tagTv.setBackgroundResource(R.drawable.comment_border_bg)
+ tagTv.setTextColor(ContextCompat.getColor(context!!, R.color.theme))
+ }
+ mAllTags.add(tag)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/pic/QuestionsEditPicAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/pic/QuestionsEditPicAdapter.kt
new file mode 100644
index 0000000000..cb894e5eed
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/pic/QuestionsEditPicAdapter.kt
@@ -0,0 +1,87 @@
+package com.gh.gamecenter.qa.questions.edit.pic
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.provider.MediaStore
+import android.support.v7.widget.RecyclerView
+import android.view.View
+import android.view.ViewGroup
+import com.gh.common.util.ClickUtils
+import com.gh.common.util.DialogUtils
+import com.gh.common.util.ImageUtils
+import com.gh.common.util.NetworkUtils
+import com.gh.gamecenter.R
+import com.gh.gamecenter.SuggestionActivity.MEDIA_STORE_REQUEST
+import com.gh.gamecenter.qa.questions.edit.QuestionEditViewModel
+import com.gh.gamecenter.suggest.SuggestPicViewHolder
+import com.lightgame.adapter.BaseRecyclerAdapter
+import com.lightgame.utils.Utils
+import java.util.*
+
+/**
+ * Created by khy on 5/05/18.
+ */
+class QuestionsEditPicAdapter(context: Context, viewModel: QuestionEditViewModel) : BaseRecyclerAdapter(context) {
+
+ private val mViewModel: QuestionEditViewModel = viewModel
+ private var picList: MutableList = ArrayList()
+ private var mAgreePostPic: Boolean = false
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val view = mLayoutInflater.inflate(R.layout.suggest_pic_item, parent, false)
+ return SuggestPicViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ if (holder is SuggestPicViewHolder) {
+ if (position == itemCount - 1 && picList.size < QuestionEditViewModel.PIC_MAX_AMOUNT) {
+ holder.delate.visibility = View.GONE
+ ImageUtils.display(holder.icon, R.drawable.suggest_add_pic_icon)
+ } else {
+ holder.icon.setImageURI(picList[position])
+ holder.delate.visibility = View.VISIBLE
+ }
+
+ holder.itemView.setOnClickListener {
+ if (!ClickUtils.isFastDoubleClick(R.id.menu_question_post) && position == itemCount - 1
+ && picList.size < QuestionEditViewModel.PIC_MAX_AMOUNT
+ && mContext is Activity) {
+ if (NetworkUtils.isWifiConnected(mContext) || mAgreePostPic) {
+ addPic(mContext as Activity)
+ } else {
+ mAgreePostPic = true
+ DialogUtils.showAlertDialog(mContext,
+ "警告",
+ "当前使用移动网络,上传图片会消耗流量,确定上传吗?",
+ "继续上传", "取消",
+ { addPic(mContext as Activity) }, null)
+ }
+ }
+ }
+
+ holder.delate.setOnClickListener {
+ mViewModel.removePic(picList[position])
+ }
+ }
+ }
+
+ private fun addPic(activity: Activity) {
+ try {
+ val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+ activity.startActivityForResult(intent, MEDIA_STORE_REQUEST)
+ } catch (e: Exception) {
+ Utils.toast(mContext, R.string.media_image_hint)
+ e.printStackTrace()
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return if (picList.size >= QuestionEditViewModel.PIC_MAX_AMOUNT) picList.size else picList.size + 1
+ }
+
+ fun notifyPicList(picPath: MutableList) {
+ picList = ArrayList(picPath)
+ notifyDataSetChanged()
+ }
+}
diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/tip/QuestionTitleTipAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/tip/QuestionTitleTipAdapter.kt
new file mode 100644
index 0000000000..d88dae6359
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/tip/QuestionTitleTipAdapter.kt
@@ -0,0 +1,129 @@
+package com.gh.gamecenter.qa.questions.edit.tip
+
+import android.content.Context
+import android.databinding.DataBindingUtil
+import android.text.Html
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AutoCompleteTextView
+import android.widget.BaseAdapter
+import android.widget.Filter
+import android.widget.Filterable
+import com.gh.common.util.DisplayUtils
+import com.gh.common.util.UrlFilterUtils
+import com.gh.gamecenter.R
+import com.gh.gamecenter.databinding.QuestionEditTitleSearchItemBinding
+import com.gh.gamecenter.qa.entity.QuestionsIndexEntity
+import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
+import com.gh.gamecenter.retrofit.Response
+import com.gh.gamecenter.retrofit.RetrofitManager
+import java.util.*
+
+
+/**
+ * Created by khy on 3/05/18.
+ */
+class QuestionTitleTipAdapter(private val context: Context, title: AutoCompleteTextView, communityId: String?) : BaseAdapter(), Filterable {
+
+ var questionList: MutableList = ArrayList()
+ var mTitleView = title
+ var mCommunityId = communityId
+ var mSearchKey: String? = null
+
+ override fun getView(pos: Int, convertView: View?, parent: ViewGroup?): View {
+ val view: View
+ val binding: QuestionEditTitleSearchItemBinding
+ if (convertView == null) {
+ binding = DataBindingUtil.bind(LayoutInflater.from(context).inflate(R.layout.question_edit_title_search_item, convertView, false))!!
+ view = binding.root
+ view.tag = binding
+ } else {
+ view = convertView
+ binding = view.tag as QuestionEditTitleSearchItemBinding
+ }
+ val entity = questionList[pos]
+ binding.entity = entity
+ binding.questionsEditIndexTitle.text = Html.fromHtml(replayKeyword(entity.title))
+ view.setOnClickListener({
+ val tracers = "(问题编辑)+(标题自动搜索)"
+ context.startActivity(QuestionsDetailActivity.getIntent(context, entity.id, tracers))
+ })
+ return view
+
+ }
+
+ private fun replayKeyword(title: String): String {
+ var translationKey = escapeExprSpecialWord(mSearchKey)
+ return if (TextUtils.isEmpty(translationKey)) title else title.replace(translationKey?.toRegex()!!, getHtmlKeyword())
+ }
+
+ // 特殊符合转译
+ private fun escapeExprSpecialWord(s: String?): String? {
+ var keyword = s
+ if (!keyword.isNullOrEmpty()) {
+ val fbsArr = arrayOf("\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|")
+ for (key in fbsArr) {
+ if (keyword!!.contains(key)) {
+ keyword = keyword.replace(key, "\\" + key)
+ }
+ }
+ }
+ return keyword
+ }
+
+ private fun getHtmlKeyword(): String {
+ return "$mSearchKey"
+ }
+
+ override fun getItem(pos: Int): Any {
+ return questionList[pos]
+ }
+
+ override fun getItemId(pos: Int): Long {
+ return pos.toLong()
+ }
+
+ override fun getCount(): Int {
+ return questionList.size
+ }
+
+ override fun getFilter(): Filter {
+ return QuestionTitleFilter()
+ }
+
+ inner class QuestionTitleFilter : Filter() {
+
+ override fun performFiltering(prefix: CharSequence?): FilterResults {
+ val results = FilterResults()
+ if (prefix.isNullOrBlank()) return results
+ RetrofitManager
+ .getInstance(context).api
+ .getAskSearchByTitle(mCommunityId, UrlFilterUtils.getFilterQuery("keyword", prefix.toString()), 1)
+ .subscribe(object : Response>() {
+ override fun onResponse(response: List?) {
+ results.values = response
+ results.count = response!!.size
+ mSearchKey = prefix.toString()
+ }
+ })
+ return results
+ }
+
+ override fun publishResults(constant: CharSequence?, results: FilterResults?) {
+ if (results != null && results.count > 0) {
+ questionList = results.values as ArrayList
+ } else {
+ questionList.clear()
+ }
+ if (questionList.size > 2) {
+ mTitleView.dropDownHeight = DisplayUtils.dip2px(context, 200F)
+ } else {
+ mTitleView.dropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT
+ }
+ notifyDataSetChanged()
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/gh/gamecenter/qa/recommends/AskQuestionsRecommendsFragment.java b/app/src/main/java/com/gh/gamecenter/qa/recommends/AskQuestionsRecommendsFragment.java
index 63a84bd1ac..cb7a59b9d7 100644
--- a/app/src/main/java/com/gh/gamecenter/qa/recommends/AskQuestionsRecommendsFragment.java
+++ b/app/src/main/java/com/gh/gamecenter/qa/recommends/AskQuestionsRecommendsFragment.java
@@ -22,7 +22,7 @@ import com.gh.gamecenter.baselist.LoadType;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.fragment.MainWrapperFragment;
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity;
-import com.gh.gamecenter.qa.ask.QuestionEditActivity;
+import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity;
import com.gh.gamecenter.qa.entity.AnswerEntity;
import com.gh.gamecenter.qa.entity.Questions;
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity;
diff --git a/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchActivity.java b/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchActivity.java
index 546bff8140..71cb249c03 100644
--- a/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchActivity.java
@@ -16,7 +16,7 @@ import android.widget.TextView;
import com.gh.base.BaseActivity;
import com.gh.common.util.CheckLoginUtils;
import com.gh.gamecenter.R;
-import com.gh.gamecenter.qa.ask.QuestionEditActivity;
+import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity;
import com.lightgame.utils.Util_System_Keyboard;
import butterknife.BindView;
diff --git a/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchFragment.java b/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchFragment.java
index 09e007767f..856408e755 100644
--- a/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchFragment.java
+++ b/app/src/main/java/com/gh/gamecenter/qa/search/AskSearchFragment.java
@@ -19,7 +19,7 @@ import com.gh.gamecenter.baselist.LoadType;
import com.gh.gamecenter.baselist.NormalListViewModel;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity;
-import com.gh.gamecenter.qa.ask.QuestionEditActivity;
+import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity;
import com.gh.gamecenter.qa.entity.AskSearchEntity;
import com.gh.gamecenter.qa.entity.Questions;
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity;
diff --git a/app/src/main/res/layout/activity_questions_edit.xml b/app/src/main/res/layout/activity_questions_edit.xml
index 6fac143c31..0833114285 100644
--- a/app/src/main/res/layout/activity_questions_edit.xml
+++ b/app/src/main/res/layout/activity_questions_edit.xml
@@ -5,7 +5,7 @@
+ type = "com.gh.gamecenter.qa.questions.edit.QuestionEditViewModel" />