Luk*_*kas 40 java android textview
我有一个可以包含可点击链接的textview.单击其中一个链接时,我想开始一个活动.这样可以正常工作,但也可以单击整个文本视图并启动另一个活动.
这是我目前的解决方案:
TextView tv = (TextView)findViewById(R.id.textview01);
Spannable span = Spannable.Factory.getInstance().newSpannable("test link span");
span.setSpan(new ClickableSpan() {
@Override
public void onClick(View v) {
Log.d("main", "link clicked");
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(span);
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("main", "textview clicked");
Toast.makeText(Main.this, "textview clicked", Toast.LENGTH_SHORT).show();
}
});
tv.setMovementMethod(LinkMovementMethod.getInstance());
Run Code Online (Sandbox Code Playgroud)
问题是,当我设置一个OnClickListener,每次我点击一个链接第一监听整个的TextView ,然后将一个用于ClickableSpan被调用.
当点击一个链接时,有没有办法防止android为整个textview调用监听器?或者在监听器中决定整个视图,是否单击了链接?
Yoe*_*der 39
找到了一个非常直接的解决方法.在不属于链接的所有文本区域上定义ClickableSpan并处理单击它们,就像单击文本视图一样:
TextView tv = (TextView)findViewById(R.id.textview01);
Spannable span = Spannable.Factory.getInstance().newSpannable("test link span");
span.setSpan(new ClickableSpan() {
@Override
public void onClick(View v) {
Log.d("main", "link clicked");
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// All the rest will have the same spannable.
ClickableSpan cs = new ClickableSpan() {
@Override
public void onClick(View v) {
Log.d("main", "textview clicked");
Toast.makeText(Main.this, "textview clicked", Toast.LENGTH_SHORT).show();
} };
// set the "test " spannable.
span.setSpan(cs, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// set the " span" spannable
span.setSpan(cs, 6, span.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(span);
tv.setMovementMethod(LinkMovementMethod.getInstance());
Run Code Online (Sandbox Code Playgroud)
希望这有所帮助(我知道这个线程已经过时了,但万一现在有人看到它......).
Lah*_*nto 24
这是一个非常简单的解决方案..这对我有用
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ClassroomLog.log(TAG, "Textview Click listener ");
if (textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) {
// do your code here this will only call if its not a hyperlink
}
}
});
Run Code Online (Sandbox Code Playgroud)
Luk*_*kas 10
Matthew建议继承TextView,并用这个提示得出一个相当丑陋的解决方法.但它有效:
我创建了一个"ClickPreventableTextView",当我在TextView中有clickablespans时,我会使用它,它应该是整体可点击的.
在其onTouchEvent方法中,此类在其基础TextView类上调用onTouchEvent之前调用MovementMethod的onTouchEvent方法.因此可以保证,clickablespan的Listener将首先被调用.我可以阻止为整个TextView调用OnClickListener
/**
* TextView that allows to insert clickablespans while whole textview is still clickable<br>
* If a click an a clickablespan occurs, click handler of whole textview will <b>not</b> be invoked
* In your span onclick handler you first have to check whether {@link ignoreSpannableClick} returns true, if so just return from click handler
* otherwise call {@link preventNextClick} and handle the click event
* @author Lukas
*
*/
public class ClickPreventableTextView extends TextView implements OnClickListener {
private boolean preventClick;
private OnClickListener clickListener;
private boolean ignoreSpannableClick;
public ClickPreventableTextView(Context context) {
super(context);
}
public ClickPreventableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ClickPreventableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public boolean onTouchEvent(MotionEvent event) {
if (getMovementMethod() != null)
getMovementMethod().onTouchEvent(this, (Spannable)getText(), event);
this.ignoreSpannableClick = true;
boolean ret = super.onTouchEvent(event);
this.ignoreSpannableClick = false;
return ret;
}
/**
* Returns true if click event for a clickable span should be ignored
* @return true if click event should be ignored
*/
public boolean ignoreSpannableClick() {
return ignoreSpannableClick;
}
/**
* Call after handling click event for clickable span
*/
public void preventNextClick() {
preventClick = true;
}
@Override
public void setOnClickListener(OnClickListener listener) {
this.clickListener = listener;
super.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (preventClick) {
preventClick = false;
} else if (clickListener != null)
clickListener.onClick(v);
}
}
Run Code Online (Sandbox Code Playgroud)
可点击范围的监听器现在看起来像那样
span.setSpan(new ClickableSpan() {
@Override
public void onClick(View v) {
Log.d("main", "link clicked");
if (widget instanceof ClickPreventableTextView) {
if (((ClickPreventableTextView)widget).ignoreSpannableClick())
return;
((ClickPreventableTextView)widget).preventNextClick();
}
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Run Code Online (Sandbox Code Playgroud)
对我来说主要的缺点是,现在getMovementMethod().onTouchEvent将被调用两次(TextView在其onTouchEvent方法中调用该方法).我不知道这是否有任何副作用,因为它按预期工作.
小智 6
代码对我有用,来自LinkMovementMethod的源代码
tv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
TextView tv = (TextView) v;
if (action == MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
Layout layout = tv.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = h.diary.contentSpan.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
} else {
//do other click
}
}
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
49349 次 |
最近记录: |