我有TexView
,需要放在格言为2行,并且其中包含可链接的文字。
如果我将LinkMovementMethod设置为文本视图,我会得到一个可滚动的TextView
,并忽略ellipsize。
Xml代码:
<TextView
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dip"
android:clickable="true"
android:maxLines="2"
android:ellipsize="end"
android:scrollHorizontally="false"
android:scrollbars="horizontal"
android:isScrollContainer="false"/>
这是我的活动:
public class MyActivity extends Activity {
private TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.text_view);
SpannableStringBuilder captionSpan = new SpannableStringBuilder();
captionSpan.append("a very long text here a very long text here a very long text here a very long text here a very long text here a very long text here a very long text here a very long text here");
captionSpan.setSpan(new CustomClickableSpan(), 1, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(captionSpan);
tv.setMovementMethod(LinkMovementMethod.getInstance());
}
}
public class CustomClickableSpan extends android.text.style.ClickableSpan {
@Override
public void updateDrawState(TextPaint tp) {
tp.setColor(tp.linkColor);
tp.setUnderlineText(false);
}
@Override
public void onClick(View widget) {
}
}
如果我没有设置移动方法,一切正常。
答案 0 :(得分:9)
我找到了解决方案!
而是 setMovementMethod()使用 OnTouchListener 。
String text = textView.getText().toString();
SpannableString spanText = new SpannableString(text);
//here set your spans to spanText
textView.setOnTouchListener(new TouchTextView(spanText));
textView.setText(spanText);
我从 LinkMovementMethod 类中获得了 onTouchEvent()。
static class TouchTextView implements View.OnTouchListener {
Spannable spannable;
public TouchTextView (Spannable spannable){
this.spannable = spannable;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if(!(v instanceof TextView)){
return false;
}
TextView textView = (TextView) v;
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
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);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(textView);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(spannable,
spannable.getSpanStart(link[0]),
spannable.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(spannable);
}
}
return false;
}
}
确保 TextView 应该具有以下属性:
android:maxLines="2"
android:ellipsize="end"
答案 1 :(得分:0)
我需要的东西比@Airfreshener的出色解决方案稍微灵活一些。希望它可以帮助其他人。
应该能够将TextView
的实例替换为ClickableSpanTextView
。您可能需要根据需要向ClickableSpanTextView
添加其他构造函数。
public class ClickableSpanTextView extends TextView {
static class SpannableClickListener implements View.OnTouchListener {
private static SpannableClickListener defaultInstance;
public static SpannableClickListener defaultInstance() {
if (defaultInstance == null) {
defaultInstance = new SpannableClickListener();
}
return defaultInstance;
}
private SpannableClickListener() {}
@Override
public boolean onTouch(View view, MotionEvent event) {
if (!(view instanceof TextView)) {
return false;
}
TextView textView = (TextView) view;
CharSequence text = textView.getText();
if (!(text instanceof Spannable)) {
return false;
}
Spannable spannable = (Spannable) text;
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= textView.getTotalPaddingLeft();
y -= textView.getTotalPaddingTop();
x += textView.getScrollX();
y += textView.getScrollY();
android.text.Layout layout = textView.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = spannable.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(textView);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(
spannable, spannable.getSpanStart(link[0]), spannable.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(spannable);
}
}
return false;
}
}
static class CompositeOnTouchListener implements View.OnTouchListener {
OnTouchListener[] listeners;
public CompositeOnTouchListener(OnTouchListener... listeners) {
this.listeners = listeners;
}
@Override
public boolean onTouch(View view, MotionEvent event) {
for (OnTouchListener listener : listeners) {
// Apply each touch listener in order until one returns true
if (listener.onTouch(view, event)) {
return true;
}
}
return false;
}
}
public ClickableSpanTextView(Context context, AttributeSet attrs) {
super(context, attrs);
super.setOnTouchListener(SpannableClickListener.defaultInstance());
}
@Override
public void setOnTouchListener(OnTouchListener listener) {
super.setOnTouchListener(
new CompositeOnTouchListener(SpannableClickListener.defaultInstance(), listener));
}
}