我怎样才能拥有带有可点击 Spannables 的 EditText 并且仍然可以通过 longClick 选择?
Posted
技术标签:
【中文标题】我怎样才能拥有带有可点击 Spannables 的 EditText 并且仍然可以通过 longClick 选择?【英文标题】:How can i have EditText with Clickable Spannables and still selectable by longClick? 【发布时间】:2014-06-15 07:42:56 【问题描述】:我有 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。
【问题讨论】:
你打算奖励赏金还是让它过期? @EmanuelMoecklin 你能再次发布你的答案吗?我有一段时间没上网了:) 【参考方案1】:您需要将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());
上面的代码只适用于未格式化的文本,这意味着一旦您决定使用文本样式(粗体、斜体等)或不同的字体大小来格式化文本,它就不会再找到点击的链接。我确实有处理格式化文本的代码,但由于这不是问题的一部分,所以我使示例代码尽可能短。
【讨论】:
我会检查并告诉你结果,问候;) 我试过了,但我遇到了一些问题。请你帮帮我好吗?我的问题在这里描述:***.com/questions/23769532/… @user3132352:在此处查看我的评论【参考方案2】:下面的代码示例应该适合你,我也测试过它给你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);
【讨论】:
我对 EditText 的主要兴趣是因为我想通过长按来选择它的文本。然而,这种方式文本不再可选择:(【参考方案3】://try this way,hope this will help you...
**activity.xml** code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical"
android:gravity="center">
<EditText
android:id="@+id/edtText1"
android:layout_
android:layout_
android:focusableInTouchMode="false"
android:focusable="false"
android:editable="false"/>
<EditText
android:id="@+id/edtText2"
android:layout_
android:layout_
android:focusableInTouchMode="false"
android:focusable="false"
android:editable="false"/>
<EditText
android:id="@+id/edtText3"
android:layout_
android:layout_
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);
【讨论】:
还是同样的问题。在编辑文本中不再可选择文本。【参考方案4】:以上答案很有帮助。希望以下内容也对您有所帮助:
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)
【讨论】:
虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!以上是关于我怎样才能拥有带有可点击 Spannables 的 EditText 并且仍然可以通过 longClick 选择?的主要内容,如果未能解决你的问题,请参考以下文章
我怎样才能拥有一个同时包含图像和文本的 UIBarButtonItem?