Skip to content

Commit

Permalink
fix: 修复长按贴中文本无法弹出菜单
Browse files Browse the repository at this point in the history
  • Loading branch information
HuanCheng65 committed Aug 20, 2020
1 parent 9e50d48 commit 3da25a4
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
Expand All @@ -26,6 +25,7 @@
import com.huanchengfly.tieba.post.api.models.CommonResponse;
import com.huanchengfly.tieba.post.api.models.SubFloorListBean;
import com.huanchengfly.tieba.post.api.models.ThreadContentBean;
import com.huanchengfly.tieba.post.components.LinkMovementClickMethod;
import com.huanchengfly.tieba.post.components.spans.MyURLSpan;
import com.huanchengfly.tieba.post.components.spans.MyUserSpan;
import com.huanchengfly.tieba.post.fragments.ConfirmDialogFragment;
Expand Down Expand Up @@ -236,7 +236,7 @@ private boolean appendTextToLastTextView(List<View> views, CharSequence newConte

private TextView createTextView(int type) {
TintTextView textView = new TintTextView(mContext);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setMovementMethod(LinkMovementClickMethod.getInstance());
textView.setClickable(false);
textView.setFocusable(false);
textView.setFocusableInTouchMode(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
Expand All @@ -21,15 +20,15 @@
import androidx.annotation.NonNull;

import com.allen.library.SuperTextView;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import com.huanchengfly.tieba.post.BaseApplication;
import com.huanchengfly.tieba.post.R;
import com.huanchengfly.tieba.post.activities.BaseActivity;
import com.huanchengfly.tieba.post.activities.ReplyActivity;
import com.huanchengfly.tieba.post.api.TiebaApi;
import com.huanchengfly.tieba.post.api.models.CommonResponse;
import com.huanchengfly.tieba.post.api.models.ThreadContentBean;
import com.huanchengfly.tieba.post.components.LinkMovementClickMethod;
import com.huanchengfly.tieba.post.components.LinkTouchMovementMethod;
import com.huanchengfly.tieba.post.components.spans.MyImageSpan;
import com.huanchengfly.tieba.post.components.spans.MyURLSpan;
import com.huanchengfly.tieba.post.components.spans.MyUserSpan;
Expand All @@ -53,6 +52,7 @@
import com.huanchengfly.tieba.post.widgets.MyLinearLayout;
import com.huanchengfly.tieba.post.widgets.VideoPlayerStandard;
import com.huanchengfly.tieba.post.widgets.VoicePlayerView;
import com.huanchengfly.tieba.post.widgets.theme.TintMySpannableTextView;
import com.huanchengfly.tieba.post.widgets.theme.TintTextView;
import com.othershe.baseadapter.ViewHolder;
import com.othershe.baseadapter.base.MultiBaseAdapter;
Expand Down Expand Up @@ -80,10 +80,8 @@ public class RecyclerThreadAdapter extends MultiBaseAdapter<ThreadContentBean.Po
private static final int TEXT_VIEW_TYPE_FLOOR = 1;
private Map<String, ThreadContentBean.UserInfoBean> userInfoBeanMap;
private NavigationHelper navigationHelper;
private RequestOptions avatarRequestOptions;
private LinearLayout.LayoutParams defaultLayoutParams;
private RequestOptions defaultRequestOptions;
private DrawableTransitionOptions transitionOptions;
private LinearLayout.LayoutParams defaultLayoutParamsWithNoMargins;
private ThreadContentBean.ThreadBean threadBean;
private ThreadContentBean dataBean;
private TreeMap<Integer, List<PhotoViewBean>> photoViewBeansMap;
Expand Down Expand Up @@ -112,19 +110,12 @@ public RecyclerThreadAdapter(Context context) {
});
showForum = true;
userInfoBeanMap = new HashMap<>();
avatarRequestOptions = new RequestOptions()
.placeholder(R.drawable.bg_placeholder_circle)
.circleCrop()
.skipMemoryCache(true);
navigationHelper = NavigationHelper.newInstance(mContext);
immersive = false;
this.screenWidthPx = BaseApplication.ScreenInfo.EXACT_SCREEN_WIDTH;
defaultLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
defaultLayoutParams.setMargins(0, 8, 0, 8);
defaultRequestOptions = new RequestOptions()
.placeholder(R.drawable.bg_placeholder)
.skipMemoryCache(true);
transitionOptions = DrawableTransitionOptions.withCrossFade();
defaultLayoutParamsWithNoMargins = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
photoViewBeansMap = new TreeMap<>();
blockCacheMap = new HashMap<>();
}
Expand Down Expand Up @@ -217,7 +208,7 @@ private void addUser(List<ThreadContentBean.UserInfoBean> userInfoBeans) {
}

private void setPic(List<ThreadContentBean.PostListItemBean> postListItemBeans) {
photoViewBeansMap = new TreeMap<Integer, List<PhotoViewBean>>();
photoViewBeansMap = new TreeMap<>();
addPic(postListItemBeans);
}

Expand Down Expand Up @@ -260,24 +251,22 @@ private View getContentView(ThreadContentBean.PostListItemBean subPostListItemBe
builder.append(userInfoBean.getNameShow(), new MyUserSpan(mContext, userInfoBean.getId()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (threadBean.getAuthor() != null && userInfoBean.getId() != null && userInfoBean.getId().equals(threadBean.getAuthor().getId())) {
builder.append(" ");
int start = builder.length();
builder.append("楼主", new RoundBackgroundColorSpan(mContext,
alphaColor(ThemeUtils.getColorByAttr(mContext, R.attr.colorAccent), 30),
ThemeUtils.getColorByAttr(mContext, R.attr.colorAccent),
DisplayUtil.dp2px(mContext, 10)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//builder.setSpan(new TextAppearanceSpan("serif", Typeface.BOLD, DisplayUtil.dp2px(mContext, 10), ColorStateList.valueOf(Color.WHITE), ColorStateList.valueOf(Color.WHITE)), start, start + "楼主".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(" ");
}
builder.append(":");
}
if (subPostListItemBean.getContent().size() >= 1 && "10".equals(subPostListItemBean.getContent().get(0).getType())) {
if (subPostListItemBean.getContent().size() > 0 && "10".equals(subPostListItemBean.getContent().get(0).getType())) {
String voiceUrl = "http://c.tieba.baidu.com/c/p/voice?voice_md5=" + subPostListItemBean.getContent().get(0).getVoiceMD5() + "&play_from=pb_voice_play";
RelativeLayout container = new RelativeLayout(mContext);
container.setLayoutParams(defaultLayoutParams);
container.setLayoutParams(defaultLayoutParamsWithNoMargins);
container.setPadding(DisplayUtil.dp2px(mContext, 8),
1,
8,
DisplayUtil.dp2px(mContext, 8),
1);
8);
container.setBackground(Util.getDrawableByAttr(mContext, R.attr.selectableItemBackground));
container.setOnClickListener(view -> mContext.startActivity(new Intent(mContext, ReplyActivity.class)
.putExtra("data", new ReplyInfoBean(dataBean.getThread().getId(),
Expand All @@ -303,7 +292,7 @@ private View getContentView(ThreadContentBean.PostListItemBean subPostListItemBe
return container;
}
TextView textView = createTextView(TEXT_VIEW_TYPE_FLOOR);
textView.setLayoutParams(defaultLayoutParams);
textView.setLayoutParams(defaultLayoutParamsWithNoMargins);
for (ThreadContentBean.ContentBean contentBean : subPostListItemBean.getContent()) {
switch (contentBean.getType()) {
case "0":
Expand All @@ -329,9 +318,9 @@ private View getContentView(ThreadContentBean.PostListItemBean subPostListItemBe
}
textView.setText(StringUtil.getEmotionContent(EmotionUtil.EMOTION_ALL_TYPE, textView, builder));
textView.setPadding(DisplayUtil.dp2px(mContext, 8),
1,
8,
DisplayUtil.dp2px(mContext, 8),
1);
8);
textView.setBackground(Util.getDrawableByAttr(mContext, R.attr.selectableItemBackground));
textView.setOnClickListener(view -> mContext.startActivity(new Intent(mContext, ReplyActivity.class)
.putExtra("data", new ReplyInfoBean(dataBean.getThread().getId(),
Expand Down Expand Up @@ -393,10 +382,6 @@ private void initFloorView(ViewHolder holder, ThreadContentBean.PostListItemBean
}
}

private boolean canLoadGlide() {
return Util.canLoadGlide(mContext);
}

private int getMaxWidth(String floor) {
int maxWidth = screenWidthPx - DisplayUtil.dp2px(mContext, 28 + 38);
if (isImmersive() || "1".equals(floor)) {
Expand Down Expand Up @@ -575,7 +560,7 @@ protected void convert(ViewHolder holder, ThreadContentBean.PostListItemBean dat
holder.setText(R.id.thread_list_item_user_time, mContext.getString(R.string.tip_thread_item, data.getFloor(), String.valueOf(DateUtils.getRelativeTimeSpanString(Long.valueOf(data.getTime()) * 1000L))));
holder.setText(R.id.thread_list_item_content_title, data.getTitle());
holder.setOnClickListener(R.id.thread_list_item_reply, view -> showMenu(data, position));
if (data.getFloor().equals("1"))
if ("1".equals(data.getFloor()))
holder.setVisibility(R.id.thread_list_item_reply, View.GONE);
else
holder.setVisibility(R.id.thread_list_item_reply, View.VISIBLE);
Expand All @@ -591,11 +576,11 @@ protected void convert(ViewHolder holder, ThreadContentBean.PostListItemBean dat
});
ImageUtil.load(holder.getView(R.id.thread_list_item_user_avatar), ImageUtil.LOAD_TYPE_AVATAR, userInfoBean.getPortrait());
}
if (!data.getFloor().equals("1"))
if (!"1".equals(data.getFloor()))
holder.setVisibility(R.id.thread_list_item_content_title, View.GONE);
else
holder.setVisibility(R.id.thread_list_item_content_title, View.VISIBLE);
initContentView(holder, data);
initContentView(holder, data, position);
initFloorView(holder, data);
if (isImmersive()) {
holder.getView(R.id.thread_list_item_content).setPadding(DisplayUtil.dp2px(mContext, 4), 0, DisplayUtil.dp2px(mContext, 4), 0);
Expand Down Expand Up @@ -694,15 +679,24 @@ private CharSequence getUserContent(CharSequence oldContent, CharSequence newCon
}

private TextView createTextView(int type) {
TintTextView textView = new TintTextView(mContext);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setClickable(false);
TextView textView;
if (type == TEXT_VIEW_TYPE_CONTENT) {
TintMySpannableTextView mySpannableTextView = new TintMySpannableTextView(mContext);
mySpannableTextView.setTintResId(R.color.default_color_text);
mySpannableTextView.setLinkTouchMovementMethod(LinkTouchMovementMethod.getInstance());
textView = mySpannableTextView;
} else {
TintTextView tintTextView = new TintTextView(mContext);
tintTextView.setTintResId(R.color.default_color_text);
tintTextView.setMovementMethod(LinkMovementClickMethod.getInstance());
textView = tintTextView;
}
textView.setFocusable(false);
textView.setFocusableInTouchMode(false);
textView.setClickable(false);
textView.setLongClickable(false);
textView.setTextIsSelectable(false);
textView.setOnClickListener(null);
textView.setOnLongClickListener(null);
textView.setTintResId(R.color.default_color_text);
textView.setLetterSpacing(0.02F);
if (type == TEXT_VIEW_TYPE_CONTENT) {
textView.setTextSize(16);
Expand All @@ -720,7 +714,7 @@ private void setText(TextView textView, CharSequence content) {
}

private LinearLayout.LayoutParams getLayoutParams(ThreadContentBean.ContentBean contentBean, String floor) {
if (!contentBean.getType().equals("3") && !contentBean.getType().equals("20") && !contentBean.getType().equals("5")) {
if (!"3".equals(contentBean.getType()) && !"20".equals(contentBean.getType()) && !"5".equals(contentBean.getType())) {
return defaultLayoutParams;
}
float widthFloat, heightFloat;
Expand Down Expand Up @@ -778,7 +772,7 @@ private boolean needBlock(ThreadContentBean.PostListItemBean postListItemBean) {
return false;
}

private List<View> getContentViews(ThreadContentBean.PostListItemBean postListItemBean) {
private List<View> getContentViews(ThreadContentBean.PostListItemBean postListItemBean, int position) {
List<View> views = new ArrayList<>();
for (ThreadContentBean.ContentBean contentBean : postListItemBean.getContent()) {
switch (contentBean.getType()) {
Expand Down Expand Up @@ -895,10 +889,10 @@ private List<View> getContentViews(ThreadContentBean.PostListItemBean postListIt
return views;
}

private void initContentView(ViewHolder viewHolder, ThreadContentBean.PostListItemBean postListItemBean) {
private void initContentView(ViewHolder viewHolder, ThreadContentBean.PostListItemBean postListItemBean, int position) {
MyLinearLayout myLinearLayout = viewHolder.getView(R.id.thread_list_item_content_content);
myLinearLayout.removeAllViews();
myLinearLayout.addViews(getContentViews(postListItemBean));
myLinearLayout.addViews(getContentViews(postListItemBean, position));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.huanchengfly.tieba.post.components

import android.text.Selection
import android.text.Spannable
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.MotionEvent
import android.widget.TextView


object LinkMovementClickMethod : LinkMovementMethod() {
private const val CLICK_DELAY = 500L

private var lastClickTime: Long = 0

override fun canSelectArbitrarily(): Boolean {
return false
}

override fun onTouchEvent(widget: TextView, buffer: Spannable, event: MotionEvent): Boolean {
val action = event.actionMasked
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
var x = event.x.toInt()
var y = event.y.toInt()
x -= widget.totalPaddingLeft
y -= widget.totalPaddingTop
x += widget.scrollX
y += widget.scrollY
val layout = widget.layout
val line = layout.getLineForVertical(y)
val off = layout.getOffsetForHorizontal(line, x.toFloat())
val link = buffer.getSpans(off, off, ClickableSpan::class.java)
if (link.isNotEmpty()) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget)
} else {
Selection.setSelection(buffer, buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]))
}
return true
} else {
Selection.removeSelection(buffer)
}
}

return false
}

override fun initialize(widget: TextView?, text: Spannable?) {
Selection.removeSelection(text)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.huanchengfly.tieba.post.components;

import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;

public class LinkTouchMovementMethod extends LinkMovementMethod {

private static LinkTouchMovementMethod sInstance;

private ClickableSpan mPressedSpan;

@Override
public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_DOWN) {
mPressedSpan = getPressedSpan(textView, spannable, event);
if (mPressedSpan != null) {
Selection.setSelection(spannable, spannable.getSpanStart(mPressedSpan),
spannable.getSpanEnd(mPressedSpan));
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
ClickableSpan touchedSpan = getPressedSpan(textView, spannable, event);
if (mPressedSpan != null && touchedSpan != mPressedSpan) {
mPressedSpan = null;
Selection.removeSelection(spannable);
}
} else {
if (mPressedSpan != null) {
super.onTouchEvent(textView, spannable, event);
}
mPressedSpan = null;
Selection.removeSelection(spannable);
}
return mPressedSpan != null;
}

/**
* Copy from:
* http://stackoverflow.com/questions/20856105/change-the-text-color-of-a-single-clickablespan-when-pressed-without-affecting-o
* By:
* Steven Meliopoulos
*/
private ClickableSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent event) {

int x = (int) event.getX();
int y = (int) event.getY();

x -= textView.getTotalPaddingLeft();
y -= textView.getTotalPaddingTop();

x += textView.getScrollX();
y += textView.getScrollY();

Layout layout = textView.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);

ClickableSpan[] link = spannable.getSpans(off, off, ClickableSpan.class);
ClickableSpan touchedSpan = null;
if (link.length > 0) {
touchedSpan = link[0];
}
return touchedSpan;
}

public boolean isPressedSpan() {
return mPressedSpan != null;
}

public static LinkTouchMovementMethod getInstance() {
if (sInstance == null) {
sInstance = new LinkTouchMovementMethod();
}
return sInstance;
}
}
Loading

0 comments on commit 3da25a4

Please sign in to comment.