如何使Checkbox文本的一部分可单击?

我正在尝试在文本框的相邻文本中创建一个链接。 但是,此链接不是URL,而应充当按钮,以便我可以在onItemClick事件中执行一些任务。 我基本上将此连接到显示我们的最终用户许可协议(硬编码)的视图。

我怎么能做到这一点?

提前致谢。

Solutions Collecting From Web of "如何使Checkbox文本的一部分可单击?"

实际上有一个优雅的解决方案,使用CheckBox和单个TextView 。 与TextView.setClickable() ,Intent Filter和TextView.setMovementMethod()的组合一起使用。

你有主视图(这里,我称之为ClickableTextViewExample ):

 package id.web.freelancer.example; import android.app.Activity; import android.os.Bundle; import android.text.Html; import android.text.method.LinkMovementMethod; import android.widget.CheckBox; import android.widget.TextView; public class ClickableTextViewExampleActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); CheckBox checkbox = (CheckBox)findViewById(R.id.checkBox1); TextView textView = (TextView)findViewById(R.id.textView2); checkbox.setText(""); textView.setText(Html.fromHtml("I have read and agree to the " + "TERMS AND CONDITIONS")); textView.setClickable(true); textView.setMovementMethod(LinkMovementMethod.getInstance()); } } 

main.xml中

 < ?xml version="1.0" encoding="utf-8"?>       

TCActivity.java

 package id.web.freelancer.example; import android.app.Activity; import android.os.Bundle; public class TCActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tc); } } 

tc.xml

 < ?xml version="1.0" encoding="utf-8"?>    

AndroidManifest.xml是最后一段将它粘合在一起的代码:

        

来了,解释:

 textView.setText(Html.fromHtml("I have read and agree to the " + "TERMS AND CONDITIONS")); textView.setClickable(true); textView.setMovementMethod(LinkMovementMethod.getInstance()); 

setClickable将允许您单击textView 。 但不是HREF链接。 为此,您必须使用setMovementMethod()并将其设置为LinkMovementMethod

之后,您需要捕获URL。 我是在AndroidManifest.xml中使用intent-filter完成的

   

它捕获VIEW命令,它只过滤以id.web.freelancer.example.TCActivity://开头的URL id.web.freelancer.example.TCActivity://

这是你试用它的包 , 这里是github存储库 。 希望这有帮助

以下代码在KitKat上为我工作。 我还没有测试Android的以下版本。

 String checkBoxText = "I agree to all the  Terms and Conditions"; checkBoxView.setText(Html.fromHtml(checkBoxText)); checkBoxView.setMovementMethod(LinkMovementMethod.getInstance()); 

您可能只希望文本的一部分是可单击的链接,而checkbox的其余部分与往常一样,即您可以单击其他文本以切换状态。

您可以设置您的checkbox,如下所示:

 CheckBox checkBox = (CheckBox) findViewById(R.id.my_check_box); ClickableSpan clickableSpan = new ClickableSpan() { @Override public void onClick(View widget) { // Prevent CheckBox state from being toggled when link is clicked widget.cancelPendingInputEvents(); // Do action for link text... } @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); // Show links with underlines (optional) ds.setUnderlineText(true); } }; SpannableString linkText = new SpannableString("Link text"); linkText.setSpan(clickableSpan, 0, linkText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); CharSequence cs = TextUtils.expandTemplate( "CheckBox text with link: ^1 , and after link", linkText); checkBox.setText(cs); // Finally, make links clickable checkBox.setMovementMethod(LinkMovementMethod.getInstance()); 

我遇到了同样的问题,希望在checkbox的文本中有多个可点击的链接,而不会失去单击文本中任何位置(没有URL)的选项/取消选中checkbox的function。

与此问题的其他答案的不同之处在于,使用此解决方案,您可以在checkbox文本中包含多个可单击链接,并且这些链接不必位于文本的末尾。

布局看起来类似于ariefbayu的回答:

     

我现在以编程方式设置文本。 我要显示的文字是:

 "I have read and accepted the privacy statement and terms of service." 

由于它包含HTML,我首先将其转换为Spanned。 为了使链接可单击,我还将TextView的移动方法设置为LinkMovementMethod:

 mTosTextView = (TextView) findViewById(R.id.tosTextView); mTosTextView.setText(Html.fromHtml(getString(R.string.TOSInfo))); mTosTextView.setMovementMethod(LinkMovementMethod.getInstance()); 

这里有更棘手的部分。 到目前为止,按TabView时没有选中CheckBox。 为了实现这一点,我在TextView中添加了一个触摸处理程序:

 mTosCheckBox = (CheckBox) findViewById(R.id.tosCheckBox); mTosTextView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { CharSequence text = mTosTextView.getText(); // find out which character was touched int offset = getOffsetForPosition(mTosTextView, event.getX(), event.getY()); // check if this character contains a URL URLSpan[] types = ((Spanned)text).getSpans(offset, offset, URLSpan.class); if (types.length > 0) { // a link was clicked, so don't handle the event Log.d("Some tag", "link clicked: " + types[0].getURL()); return false; } // no link was touched, so handle the touch to change // the pressed state of the CheckBox switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTosCheckBox.setPressed(true); break; case MotionEvent.ACTION_UP: mTosCheckBox.setChecked(!mTosCheckBox.isChecked()); mTosCheckBox.setPressed(false); break; default: mTosCheckBox.setPressed(false); break; } return true; } }); 

最后,正如您可能已经注意到的那样,还没有方法getOffsetForPosition(...) 。 如果你的目标是API等级14+,你可以简单地使用getOffsetForPosition() , 正如Dheeraj VS所指出的那样 。 当我针对API级别8+时,我使用了我在此处find的实现: 确定在android textview中单击了哪个单词 。

 public int getOffsetForPosition(TextView textView, float x, float y) { if (textView.getLayout() == null) { return -1; } final int line = getLineAtCoordinate(textView, y); final int offset = getOffsetAtCoordinate(textView, line, x); return offset; } private int getOffsetAtCoordinate(TextView textView2, int line, float x) { x = convertToLocalHorizontalCoordinate(textView2, x); return textView2.getLayout().getOffsetForHorizontal(line, x); } private float convertToLocalHorizontalCoordinate(TextView textView2, float x) { x -= textView2.getTotalPaddingLeft(); // Clamp the position to inside of the view. x = Math.max(0.0f, x); x = Math.min(textView2.getWidth() - textView2.getTotalPaddingRight() - 1, x); x += textView2.getScrollX(); return x; } private int getLineAtCoordinate(TextView textView2, float y) { y -= textView2.getTotalPaddingTop(); // Clamp the position to inside of the view. y = Math.max(0.0f, y); y = Math.min(textView2.getHeight() - textView2.getTotalPaddingBottom() - 1, y); y += textView2.getScrollY(); return textView2.getLayout().getLineForVertical((int) y); } 

创建一个没有文本的CheckBox ,并在其旁边添加两个TextView 。 第一个是不可点击的视图,文字如“我已阅读并同意”。 第二个是可点击的视图,其中包含“条款和条件”等文本。 将TextView并排放置,没有任何边距。 注意第一个视图末尾的额外空格,以进行自然文本对齐。 这样您就可以根据需要设置两种文本的样式。

示例xml代码:

      

然后在代码中添加一个onClick()处理程序。 瞧。

 public class SignUpActivity extends Activity { public void onClick(View v) { ... } } 

如果您使用URL查找解决方案,我建议您使用以下解决方案。 使用CheckBoxTextView

  final TextView tvTerms = (TextView)findViewById(R.id.tvTerms); Pattern pattern = Pattern.compile(getString(R.string.terms_and_conds)); TransformFilter transFilter = new TransformFilter() { @Override public String transformUrl(Matcher match, String url) { return ""; }}; Linkify.addLinks(tvTerms, pattern, Constants.URL_TERMS_AND_CONDS, null, transFilter); 

其中URL_TERMS_AND_CONDS = "yourUrl.com";R.string.terms_and_conds =具有可点击字符串的资源的id。

我不喜欢使用checkBox + textView的解决方案,因为您的自定义视图将扩展ViewGroup而不是CheckBox,因此强制您包装CheckBox行为。

对我来说很重要的是,自定义CheckBox可以像xml一样在xml中使用。

对我来说可接受的行为是,当你按下它的盒子而不是它的文本时,这个CheckBox才会被切换。

所以我扩展了CheckBox,并且为了实现这种行为,我已经使用了整个触摸机制,完整的代码在下面,并且对于任何想知道它是如何工作的人都可以在它之后进行解释。

 public class CheckBoxWithLinks extends CheckBox { public CheckBoxWithLinks(Context context) { super(context); } public CheckBoxWithLinks(Context context, AttributeSet attrs) { super(context, attrs); } public CheckBoxWithLinks(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean performClick() { if ( !onTextClick) return super.performClick(); return false; } private boolean onTextClick = false; @Override public boolean onTouchEvent(MotionEvent event) { onTextClick = !isLeftDrawableClick(event) && !isRightDrawableClick(event); return super.onTouchEvent(event); } private boolean isRightDrawableClick(MotionEvent event) { return event.getX() >= getRight() - getTotalPaddingRight(); } private boolean isLeftDrawableClick(MotionEvent event) { return event.getX() < = getTotalPaddingLeft(); } } 

它inheritance了这样一个事实:performClick方法是由CheckBox扩展的TextView机制内部调用的,ClickableSpan也是由TextView机制调用的。 所以当你触摸CheckBox的文本时它会调用两者。

所以我所做的是检测点击是否在文本区域,如果是,我们将禁用perfomClick,从而禁用切换。 但仍会调用可点击的范围。

用法:

您仍然需要像以前一样添加可点击范围和setMovementMethod,就像常规TextView一样。