Compare commits
2 Commits
v5.32.8-99
...
feature-js
| Author | SHA1 | Date | |
|---|---|---|---|
| 49a610deee | |||
| 61f43d53b2 |
@ -352,9 +352,9 @@ RE.ImageClickListener = function() {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link"|| img.className == "poster") continue;
|
||||
window.imagelistener.imageArr(img.src);
|
||||
window.NativeCallBack.invokeMethod("imageArr", img.src);
|
||||
img.onclick = function() {
|
||||
window.imagelistener.imageClick(this.src);
|
||||
window.NativeCallBack.invokeMethod("imageClick", this.src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,8 +43,10 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (C) 2017 Wasabeef
|
||||
@ -77,6 +79,8 @@ public class RichEditor extends WebView {
|
||||
|
||||
private EmptyCallback mInitialLayoutCallback;
|
||||
|
||||
private Map<String, DynamicJsInterface> mDynamicJsInterfaces = new HashMap<>();
|
||||
|
||||
private String mCurrentContent = "";
|
||||
|
||||
public enum Type {
|
||||
@ -605,6 +609,14 @@ public class RichEditor extends WebView {
|
||||
exec("javascript:RE.formatBlock();");
|
||||
}
|
||||
|
||||
public void registerDynamicJsInterface(String method, DynamicJsInterface jsInterface) {
|
||||
mDynamicJsInterfaces.put(method, jsInterface);
|
||||
}
|
||||
|
||||
public void unregisterDynamicJsInterface(String method) {
|
||||
mDynamicJsInterfaces.remove(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 JS 方法,告诉网页端该 url 对应视频播放的进度
|
||||
*/
|
||||
@ -862,6 +874,14 @@ public class RichEditor extends WebView {
|
||||
public void logMtaEvent(String event) {
|
||||
// do nothing, mta is deprecated
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void invokeMethod(String method, String data) {
|
||||
DynamicJsInterface jsInterface = mDynamicJsInterfaces.get(method);
|
||||
if (jsInterface != null) {
|
||||
jsInterface.invoke(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -874,4 +894,8 @@ public class RichEditor extends WebView {
|
||||
mInitialLayoutCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface DynamicJsInterface {
|
||||
void invoke(String data);
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
|
||||
ArticleWebCacheManager.init(requireContext())
|
||||
ArticleWebCacheManager.init(requireContext().applicationContext)
|
||||
|
||||
mViewModel = viewModelProvider()
|
||||
|
||||
|
||||
@ -8,14 +8,12 @@ import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager.LayoutParams
|
||||
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.UnAvaliableWebviewViewHolder
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.databinding.TabItemBinding
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.visibleIf
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
@ -53,6 +51,7 @@ class ArticleDetailAdapter(
|
||||
ITEM_ARTICLE_DETAIL -> {
|
||||
val isWebViewInstalled = PackageUtils.checkWebViewIsAvailable(mContext)
|
||||
if (isWebViewInstalled) {
|
||||
ArticleDetailContentViewHolder.wvLoadTimeInMills = System.currentTimeMillis()
|
||||
val binding: ItemArticleDetailContentBinding =
|
||||
ItemArticleDetailContentBinding.inflate(mLayoutInflater, parent, false)
|
||||
ArticleDetailContentViewHolder(binding, mViewModel).apply { articleDetailVH = this }
|
||||
|
||||
@ -5,10 +5,10 @@ import android.app.Activity
|
||||
import android.graphics.Bitmap
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
@ -42,6 +42,33 @@ class ArticleDetailContentViewHolder(
|
||||
var viewModel: ArticleDetailViewModel
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
companion object {
|
||||
var wvLoadTimeInMills = 0L
|
||||
}
|
||||
|
||||
val richEditor = ArticleWebCacheManager
|
||||
.attachToRichEditor(binding.richEditorContainer)
|
||||
.apply {
|
||||
setInputEnabled(false)
|
||||
setPadding(16, 4, 16, 4)
|
||||
enableForceDark(DarkModeUtils.isDarkModeOn(binding.root.context))
|
||||
setTransparentBackground()
|
||||
setLayoutCallback { viewModel.articleRenderedLiveData.postValue(true) }
|
||||
setPageFinishedListener {
|
||||
Log.d("ArticleDetail", "pageFinished->${System.currentTimeMillis() - wvLoadTimeInMills}")
|
||||
viewModel.articlePageFinishedLiveData.postValue(true)
|
||||
}
|
||||
setChromeClientListener(object : RichEditor.WebChromeClientListener {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
Log.d("ArticleDetail", "onPageFinished: $url->${System.currentTimeMillis() - wvLoadTimeInMills}")
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
||||
return DefaultUrlHandler.interceptUrl(binding.root.context, url ?: "", "帖子详情")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private var mEntrance = ""
|
||||
val articleImgUrlList = ArrayList<String>()
|
||||
|
||||
@ -59,11 +86,41 @@ class ArticleDetailContentViewHolder(
|
||||
titleTv.setTextColor(R.color.text_title.toColor(binding.root.context))
|
||||
gameName.setTextColor(R.color.text_subtitleDesc.toColor(binding.root.context))
|
||||
|
||||
richEditor.enableForceDark(DarkModeUtils.isDarkModeOn(binding.root.context))
|
||||
richEditor.setTransparentBackground()
|
||||
richEditor.setInputEnabled(false)
|
||||
richEditor.setPadding(16, 4, 16, 4)
|
||||
richEditor.addJavascriptInterface(JsInterface(article.status ?: ""), "imagelistener")
|
||||
richEditor.registerDynamicJsInterface("imageArr") { url ->
|
||||
val defUrl = url.split("\\?".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]
|
||||
if (!articleImgUrlList.contains(defUrl) && !url.contains("web_load_dfimg_icon.png")) {
|
||||
articleImgUrlList.add(defUrl)
|
||||
}
|
||||
}
|
||||
richEditor.registerDynamicJsInterface("imageClick") { url ->
|
||||
when {
|
||||
url.contains("web_load_dfimg_icon.png") -> {
|
||||
runOnUiThread { richEditor.replaceAllDfImageExcludeGif() }
|
||||
}
|
||||
else -> {
|
||||
val status = article.status ?: ""
|
||||
clickToastByStatus(status) {
|
||||
var current = 0
|
||||
var i = 0
|
||||
val size = articleImgUrlList.size
|
||||
while (i < size) {
|
||||
if (url.contains(articleImgUrlList.get(i))) {
|
||||
current = i
|
||||
}
|
||||
i++
|
||||
}
|
||||
val intent = ImageViewerActivity.getIntent(
|
||||
binding.root.context, articleImgUrlList, current,
|
||||
mEntrance + "+(帖子详情[" + binding.titleTv.text.toString() + "])"
|
||||
)
|
||||
(binding.root.context as Activity).startActivityForResult(
|
||||
intent,
|
||||
ImageViewerActivity.REQUEST_FOR_VIEWED_IMAGE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
richEditor.addJavascriptInterface(
|
||||
OnLinkClickListener(
|
||||
root.context,
|
||||
@ -73,26 +130,6 @@ class ArticleDetailContentViewHolder(
|
||||
"帖子详情"
|
||||
), "OnLinkClickListener"
|
||||
)
|
||||
richEditor.setLayoutCallback(object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
viewModel.articleRenderedLiveData.postValue(true)
|
||||
}
|
||||
})
|
||||
richEditor.setPageFinishedListener {
|
||||
viewModel.articlePageFinishedLiveData.postValue(true)
|
||||
}
|
||||
richEditor.setChromeClientListener(object : RichEditor.WebChromeClientListener {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
||||
return DefaultUrlHandler.interceptUrl(binding.root.context, url ?: "", "帖子详情")
|
||||
}
|
||||
})
|
||||
richEditor.setWebResourceRequestInterceptor { view, url ->
|
||||
ArticleWebCacheManager.shouldInterceptRequest(view, url)
|
||||
}
|
||||
|
||||
approvalStatusTv.goneIf(article.status == "pass")
|
||||
statusContainer.goneIf(article.status == "pass")
|
||||
@ -325,7 +362,7 @@ class ArticleDetailContentViewHolder(
|
||||
* 回调列表视频播放结束时的时间
|
||||
*/
|
||||
fun onVideoPlayedCallback(url: String, position: Int) {
|
||||
binding.richEditor.onVideoPlayedCallback(url, position)
|
||||
richEditor.onVideoPlayedCallback(url, position)
|
||||
}
|
||||
|
||||
fun updateFollowBtn(isFollowed: Boolean) {
|
||||
@ -349,7 +386,7 @@ class ArticleDetailContentViewHolder(
|
||||
fun imageClick(url: String) {
|
||||
when {
|
||||
url.contains("web_load_dfimg_icon.png") -> {
|
||||
runOnUiThread { binding.richEditor.replaceAllDfImageExcludeGif() }
|
||||
runOnUiThread { richEditor.replaceAllDfImageExcludeGif() }
|
||||
}
|
||||
// url.contains(RichEditor.IMAGE_FLAG_THUMBNAIL) -> {
|
||||
// runOnUiThread { binding.richEditor.replaceDfImageByUrl(url) }
|
||||
@ -386,4 +423,14 @@ class ArticleDetailContentViewHolder(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
richEditor.setLayoutCallback(null)
|
||||
richEditor.removeJavascriptInterface("imagelistener")
|
||||
richEditor.removeJavascriptInterface("OnLinkClickListener")
|
||||
richEditor.setChromeClientListener(null)
|
||||
richEditor.setContentOwner(false)
|
||||
richEditor.setPageFinishedListener(null)
|
||||
ArticleWebCacheManager.detachFromRichEditor(binding.richEditorContainer)
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,6 @@ import com.gh.gamecenter.common.baselist.LoadType
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.AdditionalParamsEntity
|
||||
import com.gh.gamecenter.feature.entity.CommentEntity
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.entity.NormalShareEntity
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
@ -41,6 +40,7 @@ import com.gh.gamecenter.eventbus.EBDeleteCommentDetail
|
||||
import com.gh.gamecenter.eventbus.EBDeleteDetail
|
||||
import com.gh.gamecenter.eventbus.EBTopCommunityChanged
|
||||
import com.gh.gamecenter.feature.entity.ArticleDraftEntity
|
||||
import com.gh.gamecenter.feature.entity.CommentEntity
|
||||
import com.gh.gamecenter.feature.entity.Permissions
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
|
||||
@ -119,11 +119,11 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
mAdapter?.articleDetailVH?.run {
|
||||
if (articleImgUrlList.size > 0) {
|
||||
if (imageSet.size == articleImgUrlList.size) {
|
||||
binding.richEditor.replaceAllDfImage()
|
||||
richEditor.replaceAllDfImage()
|
||||
} else {
|
||||
for (i in imageSet) {
|
||||
val url = articleImgUrlList[i.toInt()]
|
||||
binding.richEditor.replaceDfImageByUrl(url)
|
||||
richEditor.replaceDfImageByUrl(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,6 +165,9 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
||||
mAdapter?.articleDetailVH?.destroy()
|
||||
|
||||
if (mViewModel.detailEntity != null) {
|
||||
HistoryHelper.insertArticleEntity(mViewModel.detailEntity!!)
|
||||
|
||||
|
||||
@ -2,8 +2,11 @@ package com.gh.gamecenter.qa.article.detail
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.MutableContextWrapper
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.common.utils.EnvHelper
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import io.reactivex.Single
|
||||
@ -18,6 +21,7 @@ import retrofit2.http.GET
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -25,23 +29,26 @@ import java.util.concurrent.TimeUnit
|
||||
/**
|
||||
* 社区文章详情-Web资源缓存管理类
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object ArticleWebCacheManager {
|
||||
|
||||
private lateinit var cacheDir: File
|
||||
|
||||
private lateinit var cacheRichEditor: RichEditor
|
||||
|
||||
private var isInit = false
|
||||
|
||||
fun init(context: Context) {
|
||||
init(File(context.cacheDir, "article/web"))
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun init(cacheDir: File) {
|
||||
fun init(applicationContext: Context) {
|
||||
if (isInit) return
|
||||
|
||||
isInit = true
|
||||
|
||||
this.cacheDir = cacheDir.apply {
|
||||
this.cacheRichEditor = RichEditor(
|
||||
MutableContextWrapper(applicationContext)
|
||||
)
|
||||
|
||||
this.cacheDir = File(applicationContext.cacheDir, "article/web").apply {
|
||||
if (!exists()) mkdirs()
|
||||
}
|
||||
|
||||
@ -92,6 +99,25 @@ object ArticleWebCacheManager {
|
||||
.subscribe({}, {})
|
||||
}
|
||||
|
||||
fun attachToRichEditor(parent: ViewGroup): RichEditor {
|
||||
val richEditor = this.cacheRichEditor.apply {
|
||||
(this.context as MutableContextWrapper).baseContext = parent.context
|
||||
setWebResourceRequestInterceptor { view, url -> shouldInterceptRequest(view, url) }
|
||||
}
|
||||
parent.addView(
|
||||
richEditor,
|
||||
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
)
|
||||
return cacheRichEditor
|
||||
}
|
||||
|
||||
fun detachFromRichEditor(parent: ViewGroup) {
|
||||
this.cacheRichEditor.setHtml("", false)
|
||||
this.cacheRichEditor.setWebResourceRequestInterceptor(null)
|
||||
(this.cacheRichEditor.context as MutableContextWrapper).baseContext = parent.context.applicationContext
|
||||
parent.removeView(this.cacheRichEditor)
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截WebView的资源请求,并返回URL对应的缓存数据
|
||||
*/
|
||||
|
||||
@ -108,11 +108,11 @@ class NewQuestionDetailFragment :
|
||||
mAdapter?.questionDetailVH?.run {
|
||||
if (questionImgUrlList.size > 0) {
|
||||
if (imageSet.size == questionImgUrlList.size) {
|
||||
binding.richEditor.replaceAllDfImage()
|
||||
richEditor.replaceAllDfImage()
|
||||
} else {
|
||||
for (i in imageSet) {
|
||||
val url = questionImgUrlList[i.toInt()]
|
||||
binding.richEditor.replaceDfImageByUrl(url)
|
||||
richEditor.replaceDfImageByUrl(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -742,6 +742,11 @@ class NewQuestionDetailFragment :
|
||||
mBinding.root.setBackgroundColor(Color.TRANSPARENT)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
mAdapter?.questionDetailVH?.destroy()
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mAdapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
|
||||
|
||||
@ -6,7 +6,6 @@ import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@ -38,43 +37,39 @@ class QuestionDetailContentViewHolder(
|
||||
var viewModel: NewQuestionDetailViewModel
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
val richEditor = ArticleWebCacheManager
|
||||
.attachToRichEditor(binding.richEditorContainer)
|
||||
.apply {
|
||||
setInputEnabled(false)
|
||||
setPadding(16, 4, 16, 4)
|
||||
enableForceDark(DarkModeUtils.isDarkModeOn(binding.root.context))
|
||||
setTransparentBackground()
|
||||
setLayoutCallback { viewModel.questionRenderedLiveData.postValue(true) }
|
||||
setPageFinishedListener { viewModel.questionPageFinishedLiveData.postValue(true) }
|
||||
setChromeClientListener(object : RichEditor.WebChromeClientListener {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {}
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
||||
return DefaultUrlHandler.interceptUrl(binding.root.context, url ?: "", "问题详情")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private var mEntrance = ""
|
||||
val questionImgUrlList = ArrayList<String>()
|
||||
|
||||
@SuppressLint("AddJavascriptInterface")
|
||||
fun bindView(question: QuestionsDetailEntity) {
|
||||
binding.run {
|
||||
richEditor.setInputEnabled(false)
|
||||
richEditor.enableForceDark(DarkModeUtils.isDarkModeOn(binding.root.context))
|
||||
richEditor.setTransparentBackground()
|
||||
richEditor.setPadding(16, 4, 16, 4)
|
||||
richEditor.removeJavascriptInterface("imagelistener")
|
||||
richEditor.addJavascriptInterface(JsInterface(question.status), "imagelistener")
|
||||
richEditor.removeJavascriptInterface("OnLinkClickListener")
|
||||
richEditor.addJavascriptInterface(
|
||||
OnLinkClickListener(
|
||||
root.context, question.title
|
||||
?: "", question.status, mEntrance, "问题详情"
|
||||
), "OnLinkClickListener"
|
||||
)
|
||||
richEditor.setLayoutCallback(object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
viewModel.questionRenderedLiveData.postValue(true)
|
||||
}
|
||||
})
|
||||
richEditor.setPageFinishedListener {
|
||||
viewModel.questionPageFinishedLiveData.postValue(true)
|
||||
}
|
||||
richEditor.setChromeClientListener(object : RichEditor.WebChromeClientListener {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
||||
return DefaultUrlHandler.interceptUrl(binding.root.context, url ?: "", "问题详情")
|
||||
}
|
||||
})
|
||||
richEditor.setWebResourceRequestInterceptor { view, url ->
|
||||
ArticleWebCacheManager.shouldInterceptRequest(view, url)
|
||||
}
|
||||
approvalStatusTv.goneIf(question.status == "pass")
|
||||
statusContainer.goneIf(question.status == "pass")
|
||||
when (question.status) {
|
||||
@ -280,7 +275,7 @@ class QuestionDetailContentViewHolder(
|
||||
* 回调列表视频播放结束时的时间
|
||||
*/
|
||||
fun onVideoPlayedCallback(url: String, position: Int) {
|
||||
binding.richEditor.onVideoPlayedCallback(url, position)
|
||||
richEditor.onVideoPlayedCallback(url, position)
|
||||
}
|
||||
|
||||
inner class JsInterface(val status: String) {
|
||||
@ -288,7 +283,7 @@ class QuestionDetailContentViewHolder(
|
||||
fun imageClick(url: String) {
|
||||
when {
|
||||
url.contains("web_load_dfimg_icon.png") -> {
|
||||
runOnUiThread { binding.richEditor.replaceAllDfImageExcludeGif() }
|
||||
runOnUiThread { richEditor.replaceAllDfImageExcludeGif() }
|
||||
}
|
||||
// url.contains(RichEditor.IMAGE_FLAG_THUMBNAIL) -> {
|
||||
// runOnUiThread { binding.richEditor.replaceDfImageByUrl(url) }
|
||||
@ -325,4 +320,14 @@ class QuestionDetailContentViewHolder(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
richEditor.setLayoutCallback(null)
|
||||
richEditor.removeJavascriptInterface("imagelistener")
|
||||
richEditor.removeJavascriptInterface("OnLinkClickListener")
|
||||
richEditor.setChromeClientListener(null)
|
||||
richEditor.setContentOwner(false)
|
||||
richEditor.setPageFinishedListener(null)
|
||||
ArticleWebCacheManager.detachFromRichEditor(binding.richEditorContainer)
|
||||
}
|
||||
}
|
||||
@ -217,8 +217,8 @@
|
||||
android:textStyle="bold"
|
||||
tools:text="这是一个很长很长很长很长很长很长很长很长很长很长的标题" />
|
||||
|
||||
<com.gh.common.view.RichEditor
|
||||
android:id="@+id/richEditor"
|
||||
<FrameLayout
|
||||
android:id="@+id/richEditorContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="13dp" />
|
||||
|
||||
Reference in New Issue
Block a user