gpt4 book ai didi

android - ListView : TextView with LinkMovementMethod makes list item unclickable?

转载 作者:IT老高 更新时间:2023-10-28 21:35:55 29 4
gpt4 key购买 nike

我想要做的:一个包含这样消息的列表:

<UserName> and here is the mnessage the user writes, that will wrap nicely to the next line. exactly like this.

我有什么:

ListView R.layout.list_item:

<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text_message"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="(Message Text)" />

扩展上述布局并执行以下操作的适配器:

SpannableStringBuilder f = new SpannableStringBuilder(check.getContent());
f.append(username);
f.setSpan(new InternalURLSpan(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "Clicked User", Toast.LENGTH_SHORT).show();
}
}), f.length() - username.length(), f.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

f.append(" " + message);

messageTextView.setText(f);
messageTextView.setMovementMethod(LinkMovementMethod.getInstance());
meesageTextView.setFocusable(false);

InternalURLSpan 类

public class InternalURLSpan extends ClickableSpan {
OnClickListener mListener;

public InternalURLSpan(OnClickListener listener) {
mListener = listener;
}

@Override
public void onClick(View widget) {
mListener.onClick(widget);
}

@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}

onCreate(...) 中的 Activity 中:

listView.setOnItemClickListener(ProgramChecksActivity.this);

以及上面的实现

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Toast.makeText(context, "Clicked Item", Toast.LENGTH_SHORT).show();
}

问题:

点击项目,不显示 toast 。只有点击用户名才会显示 toast。

我猜,setMovementMethod(LinkMovementMethod.getInstance()); 使 TextView 可点击。所以项目本身不再被点击。

如何使这些项目再次可点击?拥有我想要的相同功能。

最佳答案

在这种情况下,有 3 个阻碍因素。根本原因是当你调用 setMovementMethodsetKeyListener 时,TextView “修复”了它的设置:

setFocusable(true);
setClickable(true);
setLongClickable(true);

第一个问题是当 View 可点击时 - 它总是消耗 ACTION_UP 事件(它在 onTouchEvent(MotionEvent event) 中返回 true)。
要解决这个问题,您应该仅在用户实际单击 URL 时在该方法中返回 true。

但是 LinkMovementMethod 并没有告诉我们用户是否真的点击了一个链接。如果用户单击链接,它会在其 onTouch 中返回“true”,但在许多其他情况下也是如此。

所以,实际上我在这里做了一个技巧:

public class TextViewFixTouchConsume extends TextView {

boolean dontConsumeNonUrlClicks = true;
boolean linkHit;

public TextViewFixTouchConsume(Context context) {
super(context);
}

public TextViewFixTouchConsume(Context context, AttributeSet attrs) {
super(context, attrs);
}

public TextViewFixTouchConsume(
Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
linkHit = false;
boolean res = super.onTouchEvent(event);

if (dontConsumeNonUrlClicks)
return linkHit;
return res;

}

public void setTextViewHTML(String html)
{
CharSequence sequence = Html.fromHtml(html);
SpannableStringBuilder strBuilder =
new SpannableStringBuilder(sequence);
setText(strBuilder);
}

public static class LocalLinkMovementMethod extends LinkMovementMethod{
static LocalLinkMovementMethod sInstance;


public static LocalLinkMovementMethod getInstance() {
if (sInstance == null)
sInstance = new LocalLinkMovementMethod();

return sInstance;
}

@Override
public boolean onTouchEvent(TextView widget,
Spannable buffer, MotionEvent event) {
int action = event.getAction();

if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();

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

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

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

ClickableSpan[] link = buffer.getSpans(
off, off, ClickableSpan.class);

if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}

if (widget instanceof TextViewFixTouchConsume){
((TextViewFixTouchConsume) widget).linkHit = true;
}
return true;
} else {
Selection.removeSelection(buffer);
Touch.onTouchEvent(widget, buffer, event);
return false;
}
}
return Touch.onTouchEvent(widget, buffer, event);
}
}
}

你应该调用某个地方

textView.setMovementMethod(
TextViewFixTouchConsume.LocalLinkMovementMethod.getInstance()
);

为 textView 设置此 MovementMethod。

如果用户实际点击链接,则此 MovementMethod 会在 TextViewFixTouchConsume 中引发一个标志。(仅在 ACTION_UPACTION_DOWN 事件中)和 TextViewFixTouchConsume.onTouchEvent 仅在用户实际点击链接时返回 true。

但这还不是全部!!!!第三个问题是 ListView (AbsListView) 调用它的 performClick 方法(调用 onItemClick 事件处理程序)仅当ListView 的项目 View 没有焦点。所以,你需要覆盖

@Override
public boolean hasFocusable() {
return false;
}

在您添加到 ListView 的 View 中。(在我的例子中,这是一个包含 textView 的布局)

或者您可以为该 View 使用 setOnClickLIsener。这个技巧不是很好,但很有效。

关于android - ListView : TextView with LinkMovementMethod makes list item unclickable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8558732/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com