如何在editText中处理imageSpan的onClick事件?

12

我正在开发一个应用程序,用户可以从图库中选择一张图片并将其添加到编辑框中。现在,如果用户在编辑框中点击图片,它应该在全屏模式下打开。我使用了以下代码:

public void addToEdt(Bitmap bitmap){
    SpannableString ss = new SpannableString("abc");
    Drawable d = new BitmapDrawable(getResources(), bitmap);
    d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
    ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
    ss.setSpan(span, 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
    edt_note.setTransformationMethod(null);
    edt_note.getText().insert(edt_note.getSelectionStart(), ss);

    final int start = ss.getSpanStart(span);
    final int end = ss.getSpanEnd(span);

    ClickableSpan click_span = new ClickableSpan() {
        @Override
        public void onClick(View widget) {
                   Toast.makeText(getApplicationContext(),"Clicked",Toast.LENGTH_LONG).show();
        }
    };

    ClickableSpan[] click_spans = ss.getSpans(start, end,  ClickableSpan.class);

    if(click_spans.length != 0) {
        // remove all click spans
        for (ClickableSpan c_span : click_spans) {
            ss.removeSpan(c_span);
        }
    }

    ss.setSpan(click_span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

我尝试了上面的代码,但它没有响应onClick事件,现在我该如何监听这张图片的点击事件并执行进一步的任务?

4个回答

16

在editText相同的起始和结束位置可点击的Span。

sb.setSpan(cs, imageStartSpan,imageEndSpan , Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

此外

editText.setMovementMethod(LinkMovementMethod.getInstance());

我无法为你编写整个代码。尝试使用以下示例:

public void addToEdt(Bitmap bitmap){
    SpannableString ss = new SpannableString();
    Drawable d = new BitmapDrawable(getResources(), bitmap);
    d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
    ss.append("abc"); // Append the text here
    ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
    ss.setSpan(span, 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // start(0) and end (2) will create an image span over abc text
    ss.setSpan(new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    ss.delete(0, 2);
                    editText.setText(ss);
                }
            },0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // this will add a clickable span and on click will delete the span and text
    editText.setText(ss); // this will show your image/clickable span in edittext
}


editText.setMovementMethod(LinkMovementMethod.getInstance());

1
我尝试使用setMovementMethod,但它没有起作用,您能否详细解释一下,在我的上面的代码(addToEdt(Bitmap bitmap)方法)中应该在哪里更改? - user5211136
1
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); ss.setSpan(span, 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);同样的方式,将ClickableSpan添加到相同位置的开始和结束-- > 0,3。 - Rahul
1
抱歉,我不明白,请您编辑我的代码并将其作为您的答案发布,如果它能够正常工作,我会接受您的答案 :) - user5211136
1
非常感谢你,你让我的一天变得美好了:),只有一个问题,调用setMovementMethod后,editText的光标消失了:o,现在看起来很奇怪,有什么技巧可以解决吗??? - user5211136
1
嘿,Rahul,你为什么要使用ss.delete(0, 2)删除span和text?这是有特定目的还是只是为了演示? - user5211136
显示剩余2条评论

5
我发现使用ClickableSpansetMovementMethod会导致问题,因此我认为它们并不适用于EditText控件。此外,我需要知道用户在中的点击位置。我的图片在右侧有一个关闭按钮,我想知道用户是否点击了X,而不仅仅是单击标签。

因此,我找到了另一种方法:

  • 子类化ImageSpan并重写draw方法,只调用super,并将x/y/left/top存储在成员变量中,这样,您就可以知道EditText中的位置。
  • 子类化EditText并处理onTouchEvent,只调用super,但也要获取您的并分别进行命中测试,以查明用户是否点击了该(或的某个部分)。

就是这样,这种方法没有副作用。


如何获取X关闭按钮的Y值?当EditText滚动时,它应该改变,但我有一个常数。 - Andrey Degtiarev

1

尝试

final int start = ss.getSpanStart(span);
final int end = ss.getSpanEnd(span);

ClickableSpan click_span = new ClickableSpan() {
    @Override
    public void onClick(View widget) {

    }
};

ClickableSpan[] click_spans = ss.getSpans(start, end, ClickableSpan.class);

if(click_spans.length != 0) {
    // remove all click spans
    for (ClickableSpan c_span : click_spans) {
        ss.removeSpan(c_span);
    }
}

ss.setSpan(click_span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

同时添加这个:

yourEditText.setMovementMethod(LinkMovementMethod.getInstance());

1
谢谢,我会试用你的代码并给你反馈 :) - user5211136
1
我在EditText中添加了setMovementMethod(LinkMovementMethod.getInstance()),然后当调用addToEdt(Bitmap bitmap)时出现错误。这意味着在添加setMovementMethod之后,我甚至无法添加图片:( - user5211136
1
嗯,看一下这些帖子:http://stackoverflow.com/a/16182500/2528167 https://dev59.com/WW035IYBdhLWcg3wMM4G#6357661 - user2528167
1
曾经看过但没找到解决方案 :( stackoverflow 是我唯一的希望 ;( - user5211136
2
是的,希望如此...否则我就得使用imageView来解决这个问题了...虽然你的答案没有解决问题,但你还是尝试帮助我了,所以我接受你的答案 :) - user5211136
显示剩余3条评论

0

我找到了另一种比使用LinkMovementMethod更少侵入性的解决方案。相反,我只是扩展了ArrowKeyMovementMethodEditText的默认移动方法),并添加了一些来自LinkMovementMethod的代码,用于确定所单击的跨度。在我的情况下,我查找了一个ImageSpan,然后删除了该跨度覆盖的文本(因此单击会删除图像):

private class SpanDeletingMovementMethod : ArrowKeyMovementMethod() {
    override fun onTouchEvent(
        widget: TextView,
        buffer: Spannable,
        event: MotionEvent
    ): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            var x = event.x.toInt()
            var y = event.y.toInt()
            x -= widget.totalPaddingLeft
            y -= widget.totalPaddingTop
            x += widget.scrollX
            y += widget.scrollY
            val layout = widget.layout
            val line = layout.getLineForVertical(y)
            val off = layout.getOffsetForHorizontal(line, x.toFloat())

            val committedTags = buffer.getSpans<ImageSpan>(off, off)
            if (committedTags.isNotEmpty()) {
                val tag = committedTags[0]
                (buffer as Editable).replace(buffer.getSpanStart(tag), buffer.getSpanEnd(tag), "")
                return true
            }
        }

        return super.onTouchEvent(widget, buffer, event)
    }
}

只需在EditText上设置此移动方法(或覆盖getDefaultMovementMethod),即可处理跨度点击。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接