安卓:ClickableSpan在点击的TextView [英] Android: ClickableSpan in clickable TextView

查看:620
本文介绍了安卓:ClickableSpan在点击的TextView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可以包含可点击的链接一个TextView。当点击这个链接之一,我要开始一个活动。这工作得很好,但它也应该可以点击整个TextView的,并开始另一项活动。

I have a textview that can contain clickable links. When one of this links is clicked, I want to start an activity. This works fine, but it should also be possible to click the whole textview and start another activity.

这就是我目前的解决方案:

So that's my current solution:

    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());

现在的问题是,当我设置一个OnClickListener,每次我点击一个链接的首先监听整个TextView的,然后一个为ClickableSpan被称为

The problem is, that when I set an OnClickListener, everytime I click on a link first the listener for the whole textview and then the one for the ClickableSpan is called.

有没有一种方法,以prevent机器人从呼吁听众为全TextView中,点击一个链接的时候?还是决定在听者整个看来,如果一个链接被点击或不?

Is there a way to prevent android from calling the listener for the whole textview, when a link is clicked? Or to decide in the listener for the whole view, if a link was clicked or not?

推荐答案

马修建议TextView的继承和那一抹一个想出了一个比较难看的解决方法。但是,它的工作原理:

Matthew suggested subclassing TextView and with that hint a came up with a rather ugly workaround. But it works:

我创建了一个点击preventableTextView我用的时候我有clickablespans在一个TextView,应该是可以点击的整体。

I've created a "ClickPreventableTextView" which I use when I have clickablespans in a TextView that should be clickable as a whole.

在它的onTouchEvent方法,这个类在其基的TextView类调用的onTouchEvent之前调用MovementMethod的的onTouchEvent方法。因此它guaranted,该clickablespan的监听器将被首先调用。我可以prevent调用OnClickListener整个的TextView

In its onTouchEvent method this class calls the onTouchEvent method of MovementMethod before calling onTouchEvent on its base TextView class. So it is guaranted, that the Listener of the clickablespan will be invoked first. And I can prevent invoking the OnClickListener for the whole TextView

/**
 * 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);
}
}

监听器的点击范围现在看起来像

The listener for the clickable span now looks like that

    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);

有关我的主要缺点是,现在getMovementMethod()的onTouchEvent将被调用两次(TextView的要求,在它的方法是的onTouchEvent方法)。我不知道这是否有任何副作用,ATM它将按预期工作。

For me the main disadvantage is, that now getMovementMethod().onTouchEvent will be called twice (TextView calls that method in it's onTouchEvent method). I don't know if this has any side effects, atm it works as expected.

这篇关于安卓:ClickableSpan在点击的TextView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆