我想做什么:包含这样的消息的列表:
<UserName>,这是用户编写的mnessage,它将很好地包装到下一行.完全是这样的.
是)我有的:
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)" />
Run Code Online (Sandbox Code Playgroud)
膨胀以上布局的适配器并执行:
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);
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的活动中onCreate(...):
listView.setOnItemClickListener(ProgramChecksActivity.this);
Run Code Online (Sandbox Code Playgroud)
并执行上述内容
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Toast.makeText(context, "Clicked Item", Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)
问题:
点击该项目,不显示祝酒词.只需点击用户名即可显示祝酒词.
我猜,这setMovementMethod(LinkMovementMethod.getInstance());使得TextView可以点击.所以物品本身永远不会被点击了.
如何再次点击项目?拥有我想要的相同功能.
bab*_*bay 58
在这种情况下有三个显示停止者.的根本原因是,当你打电话setMovementMethod或者setKeyListener,TextView"修复",它的设置:
setFocusable(true);
setClickable(true);
setLongClickable(true);
Run Code Online (Sandbox Code Playgroud)
第一个问题是当View可以点击时 - 它总是消耗ACTION_UP事件(它返回true onTouchEvent(MotionEvent event)).
要解决此问题,只有在用户实际单击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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
你应该打电话到某个地方
textView.setMovementMethod(
TextViewFixTouchConsume.LocalLinkMovementMethod.getInstance()
);
Run Code Online (Sandbox Code Playgroud)
为textView设置此MovementMethod.
TextViewFixTouchConsume如果用户实际点击链接,则此MovementMethod会引发一个标记.(仅在ACTION_UP和ACTION_DOWN事件中)并且TextViewFixTouchConsume.onTouchEvent仅当用户实际点击链接时才返回true.
但那还不是全部!!!! 第三个问题是ListView(AbsListView)只有当项目视图没有焦点时才调用它的performClick方法(调用onItemClick事件处理程序)ListView.所以,你需要覆盖
@Override
public boolean hasFocusable() {
return false;
}
Run Code Online (Sandbox Code Playgroud)
在您添加到的视图中ListView.(在我的情况下,这是一个包含textView的布局)
或者您可以setOnClickLIstener用于该视图.技巧不是很好,但它确实有效.
Den*_*s K 44
babay的回答非常好.但是如果你不想继承TextView并且不关心LinkMovementMethod功能而不是点击链接你可以使用这种方法(这基本上是将LinkMovementMethod的onTouch功能复制到TextView的OnTouchListener中):
myTextView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
boolean ret = false;
CharSequence text = ((TextView) v).getText();
Spannable stext = Spannable.Factory.getInstance().newSpannable(text);
TextView widget = (TextView) v;
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 = stext.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
}
ret = true;
}
}
return ret;
}
});
Run Code Online (Sandbox Code Playgroud)
只需将此侦听器分配给列表适配器getView()方法中的TextView即可.
这是快速修复,使ListView项目和TextView UrlSpans可点击:
private class YourListadapter extends BaseAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
((ViewGroup)convertView).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
return convertView
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19482 次 |
| 最近记录: |