繁体   English   中英

我怎样才能让 EditText 带有可点击的 Spannables 并且仍然可以通过 longClick 选择?

[英]How can i have EditText with Clickable Spannables and still selectable by longClick?

我有 TextView,其跨度类型为 ClickableStringSpan,定义如下:

public class ClickableStringSpan extends ClickableSpan {
    private View.OnClickListener mListener;
    int color;
    public ClickableStringSpan(View.OnClickListener listener,int color) {
        mListener = listener;
        this.color = color;

    }

    @Override
    public void onClick(View v) {
        mListener.onClick(v);
    }

       @Override public void updateDrawState(TextPaint ds) {
           super.updateDrawState(ds);
           ds.setUnderlineText(false);
           ds.setColor(color);
       }
}

我在我的文本上设置了可点击的跨度,如下所示:

spanStr.setSpan(new ClickableString(new linkedTextClickListener(), linkColor),
                        startIndex, endIndex,
                        SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);

现在我想将这些字符串应用于 EditTexts 而不是 TextViews。 一切都很好,只是现在不再点击可点击的字符串。 我想知道如何将此类跨度的点击传递给他们分配的点击侦听器?

更新:我对编辑文本的主要关注是我希望允许用户选择文本的某些部分并共享它,同时他/她可以单击 ClickableSpans。

您需要将 TextView/EditText 的移动方法设置为 LinkMovementMethod 才能获得点击链接。 不幸的是,这禁用了选择文本的能力,该文本仅在您将移动方法设置为 ArrowKeyMovementMethod 时才有效。 http://developer.android.com/reference/android/text/method/LinkMovementMethod.html http://developer.android.com/reference/android/text/method/ArrowKeyMovementMethod.html

为了解决这个问题,我创建了一个自定义的 MovementMethod 类,该类继承自 ArrowKeyMovementMethod 并添加了单击链接的功能。

/**
 * ArrowKeyMovementMethod does support selection of text but not the clicking of links.
 * LinkMovementMethod does support clicking of links but not the selection of text.
 * This class adds the link clicking to the ArrowKeyMovementMethod.
 * We basically take the LinkMovementMethod onTouchEvent code and remove the line
 *      Selection.removeSelection(buffer);
 * which deselects all text when no link was found.
 */
public class EnhancedMovementMethod extends ArrowKeyMovementMethod {

    private static EnhancedMovementMethod sInstance;

    public static MovementMethod getInstance() {
        if (sInstance == null) {
            sInstance = new EnhancedMovementMethod ();
        }
        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]));
                }

                return true;
            }
            /*else {
                Selection.removeSelection(buffer);
            }*/
        }

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

}

您需要做的就是设置 EditText 的移动方法,您就可以开始了:

yourEditTExt.setMovementMethod(EnhancedMovementMethod.getInstance());

上面的代码仅适用于未格式化的文本,这意味着一旦您决定使用文本样式(粗体、斜体等)或不同的字体大小来设置文本格式,它将不再找到点击的链接。 我确实有处理格式化文本的代码,但由于这不是问题的一部分,我使示例代码尽可能短。

以下代码示例应该适合您,我也进行了测试,它为您提供ClickableSpanString点击事件

可能你忘记添加setMovementMethod

    EditText spanEditText = (EditText)rootView.findViewById(R.id.edtEmailId);

    // this is the text we'll be operating on  
    SpannableStringBuilder text = new SpannableStringBuilder("World Super Power God LOVE");  

    // make "World" (characters 0 to 5) red  
    text.setSpan(new ForegroundColorSpan(Color.RED), 0, 5, 0); 

    // make "Super" (characters 6 to 11) one and a half time bigger than the textbox  
    text.setSpan(new RelativeSizeSpan(1.5f), 6, 11, 0);  

    // make "Power" (characters 12 to 17) display a toast message when touched  
    final Context context = getActivity().getApplicationContext();  
    ClickableSpan clickableSpan = new ClickableSpan() {  
        @Override  
        public void onClick(View view) {  
            Toast.makeText(context, "Power", Toast.LENGTH_LONG).show();  
        }  
    };  
    text.setSpan(clickableSpan, 12, 17, 0);  

    // make "God" (characters 18 to 21) struck through  
    text.setSpan(new StrikethroughSpan(), 18, 21, 0);  

    // make "LOVE" (characters 22 to 26) twice as big, green and a link to this site.  
    // it's important to set the color after the URLSpan or the standard  
    // link color will override it.  
    text.setSpan(new RelativeSizeSpan(2f), 22, 26, 0);  
    text.setSpan(new ForegroundColorSpan(Color.GREEN), 22, 26, 0);  

    // make our ClickableSpans and URLSpans work  
    spanEditText.setMovementMethod(LinkMovementMethod.getInstance());  

    // shove our styled text into the TextView          
    spanEditText.setText(text, BufferType.EDITABLE);
//try this way,hope this will help you...

**activity.xml** code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

   <EditText
       android:id="@+id/edtText1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:focusableInTouchMode="false"
       android:focusable="false"
       android:editable="false"/>

    <EditText
        android:id="@+id/edtText2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:focusable="false"
        android:editable="false"/>

    <EditText
        android:id="@+id/edtText3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:focusable="false"
        android:editable="false"/>
</LinearLayout>

**Activity** code
    private EditText edtText1;
    private EditText edtText2;
    private EditText edtText3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity);
        edtText1 = (EditText) findViewById(R.id.edtText1);
        edtText2 = (EditText) findViewById(R.id.edtText2);
        edtText3 = (EditText) findViewById(R.id.edtText3);

        String string1 = "Demo EditText First";
        edtText1.setText(setSpanColor(string1, "First",R.color.orange,new SpannableClickListener(){
            @Override
            public void onClickListener(View view) {
                view.performClick();
            }
        }));

        edtText1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MyActivity.this,"EditText First Click",Toast.LENGTH_SHORT).show();
            }
        });


        String string2 = "Demo EditText Second";
        edtText2.setText(setSpanColor(string2, "Second",R.color.orange,new SpannableClickListener(){
            @Override
            public void onClickListener(View view) {
                view.performClick();
            }
        }));

        edtText2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MyActivity.this,"EditText Second Click",Toast.LENGTH_SHORT).show();
            }
        });


        String string3 = "Demo EditText Third";
        edtText3.setText(setSpanColor(string3, "Third",R.color.orange,new SpannableClickListener(){
            @Override
            public void onClickListener(View view) {
                view.performClick();
            }
        }));

        edtText3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MyActivity.this,"EditText Third Click",Toast.LENGTH_SHORT).show();
            }
        });

    }
    private SpannableStringBuilder setSpanColor(final String str,final String text,final int color,final SpannableClickListener listener) {
        SpannableStringBuilder ssb = new SpannableStringBuilder(str);

        if (str.contains(text)) {
            ssb.setSpan(new ClickableSpan() {
                @Override
                public void onClick(View view) {
                    listener.onClickListener(view);
                }

                @Override
                public void updateDrawState(TextPaint ds) {
                    ds.setColor(getResources().getColor(color));
                }
            }, str.indexOf(text), str.indexOf(text)
                    + text.length(), 0);
        }
        return ssb;

    }

    interface SpannableClickListener{
        public void onClickListener(View view);
    }
}

以上回答很有帮助。 希望以下也能帮到你:

    android:linksClickable="true"
    android:autoLink="web"

 val message: String = String.format(
        getString(R.string.message_content),
        firstNameEditText.text,
        lastNameEditText.text,
        dateTextView.text,
        timeTextView.text
    )

    val gMapURL = getString(R.string.google_map_location)

    // Setup my Spannable with clickable URLs
    val spannable: Spannable = SpannableString(gMapURL)
    Linkify.addLinks(spannable, Linkify.WEB_URLS)

    // Append a zero-width space to the Spannable
    val gText = TextUtils.concat(spannable, "\u200B")

    val finalText = TextUtils.concat(message, gText)
    messageContentEditText.setText(finalText)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM