How to set the part of the text view is clickable

后端 未结 20 979
无人共我
无人共我 2020-11-22 01:29

I have the text \"Android is a Software stack\". In this text i want to set the \"stack\" text is clickable. in the sense if you click on t

相关标签:
20条回答
  • 2020-11-22 02:16

    Kotlin Version of Phan Van Linh's answer.

    Please note it has some minor modifications.

    fun makeLinks(textView: TextView, links: Array<String>, clickableSpans: Array<ClickableSpan>) {
        val spannableString = SpannableString(textView.text)
    
        for (i in links.indices) {
            val clickableSpan = clickableSpans[i]
            val link = links[i]
    
            val startIndexOfLink = textView.text.indexOf(link)
    
            spannableString.setSpan(clickableSpan, startIndexOfLink, startIndexOfLink + link.length,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    
        textView.movementMethod = LinkMovementMethod.getInstance()
        textView.setText(spannableString, TextView.BufferType.SPANNABLE)
    }
    
    fun setupClickableTextView() {
        val termsOfServicesClick = object : ClickableSpan() {
            override fun onClick(p0: View?) {
                Toast.makeText(applicationContext, "ToS clicked", Toast.LENGTH_SHORT).show()
            }
        }
    
        val privacyPolicyClick = object : ClickableSpan() {
            override fun onClick(p0: View?) {
                Toast.makeText(applicationContext, "PP clicked", Toast.LENGTH_SHORT).show()
            }
        }
    
        makeLinks(termsTextView, arrayOf("terms", "privacy policy"), arrayOf(termsOfServicesClick, privacyPolicyClick))
    }
    
    0 讨论(0)
  • 2020-11-22 02:17

    You can use sample code. You want to learn detail about ClickableSpan. Please check this documentaion

      SpannableString myString = new SpannableString("This is example");
    
                ClickableSpan clickableSpan = new ClickableSpan() {
                        @Override
                        public void onClick(View textView) {
                            ToastUtil.show(getContext(),"Clicked Smile ");
                        }
                    };
    
            //For Click
             myString.setSpan(clickableSpan,startIndex,lastIndex,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    
            //For UnderLine
             myString.setSpan(new UnderlineSpan(),startIndex,lastIndex,0);
    
            //For Bold
            myString.setSpan(new StyleSpan(Typeface.BOLD),startIndex,lastIndex,0);
    
            //Finally you can set to textView. 
    
            TextView textView = (TextView) findViewById(R.id.txtSpan);
            textView.setText(myString);
            textView.setMovementMethod(LinkMovementMethod.getInstance());
    
    0 讨论(0)
  • 2020-11-22 02:18

    android.text.style.ClickableSpan can solve your problem.

    SpannableString ss = new SpannableString("Android is a Software stack");
    ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(View textView) {
            startActivity(new Intent(MyActivity.this, NextActivity.class));
        }
        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setUnderlineText(false);
        }
    };
    ss.setSpan(clickableSpan, 22, 27, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
    TextView textView = (TextView) findViewById(R.id.hello);
    textView.setText(ss);
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setHighlightColor(Color.TRANSPARENT);
    

    In XML:

    <TextView 
      ...
      android:textColorLink="@drawable/your_selector"
    />
    
    0 讨论(0)
  • 2020-11-22 02:19

    This is my MovementMethod for detecting link/text/image clicks. It is modified LinkMovementMethod.

    import android.text.Layout;
    import android.text.NoCopySpan;
    import android.text.Selection;
    import android.text.Spannable;
    import android.text.method.ScrollingMovementMethod;
    import android.text.style.ClickableSpan;
    import android.text.style.ImageSpan;
    import android.text.style.URLSpan;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    public class ClickMovementMethod extends ScrollingMovementMethod {
    private Object FROM_BELOW = new NoCopySpan.Concrete();
    
    private static final int CLICK = 1;
    private static final int UP = 2;
    private static final int DOWN = 3;
    
    private Listener listener;
    
    public void setListener(Listener listener) {
        this.listener = listener;
    }
    
    @Override
    public boolean canSelectArbitrarily() {
        return true;
    }
    
    @Override
    protected boolean handleMovementKey(TextView widget, Spannable buffer, int keyCode,
                                        int movementMetaState, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_ENTER:
                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
                    if (event.getAction() == KeyEvent.ACTION_DOWN &&
                            event.getRepeatCount() == 0 && action(CLICK, widget, buffer)) {
                        return true;
                    }
                }
                break;
        }
        return super.handleMovementKey(widget, buffer, keyCode, movementMetaState, event);
    }
    
    @Override
    protected boolean up(TextView widget, Spannable buffer) {
        if (action(UP, widget, buffer)) {
            return true;
        }
    
        return super.up(widget, buffer);
    }
    
    @Override
    protected boolean down(TextView widget, Spannable buffer) {
        if (action(DOWN, widget, buffer)) {
            return true;
        }
    
        return super.down(widget, buffer);
    }
    
    @Override
    protected boolean left(TextView widget, Spannable buffer) {
        if (action(UP, widget, buffer)) {
            return true;
        }
    
        return super.left(widget, buffer);
    }
    
    @Override
    protected boolean right(TextView widget, Spannable buffer) {
        if (action(DOWN, widget, buffer)) {
            return true;
        }
    
        return super.right(widget, buffer);
    }
    
    private boolean action(int what, TextView widget, Spannable buffer) {
        Layout layout = widget.getLayout();
    
        int padding = widget.getTotalPaddingTop() +
                widget.getTotalPaddingBottom();
        int areatop = widget.getScrollY();
        int areabot = areatop + widget.getHeight() - padding;
    
        int linetop = layout.getLineForVertical(areatop);
        int linebot = layout.getLineForVertical(areabot);
    
        int first = layout.getLineStart(linetop);
        int last = layout.getLineEnd(linebot);
    
        ClickableSpan[] candidates = buffer.getSpans(first, last, URLSpan.class);
    
        int a = Selection.getSelectionStart(buffer);
        int b = Selection.getSelectionEnd(buffer);
    
        int selStart = Math.min(a, b);
        int selEnd = Math.max(a, b);
    
        if (selStart < 0) {
            if (buffer.getSpanStart(FROM_BELOW) >= 0) {
                selStart = selEnd = buffer.length();
            }
        }
    
        if (selStart > last)
            selStart = selEnd = Integer.MAX_VALUE;
        if (selEnd < first)
            selStart = selEnd = -1;
    
        switch (what) {
            case CLICK:
                if (selStart == selEnd) {
                    return false;
                }
    
                if (listener != null) {
                    URLSpan[] link = buffer.getSpans(selStart, selEnd, URLSpan.class);
                    if (link.length >= 1) {
                        listener.onClick(link[0].getURL());
                    } else {
                        ImageSpan[] image = buffer.getSpans(selStart, selEnd, ImageSpan.class);
                        if (image.length >= 1) {
                            listener.onImageClicked(image[0].getSource());
                        } else {
                            listener.onTextClicked();
                        }
                    }
                }
                break;
    
            case UP:
                int beststart, bestend;
    
                beststart = -1;
                bestend = -1;
    
                for (int i = 0; i < candidates.length; i++) {
                    int end = buffer.getSpanEnd(candidates[i]);
    
                    if (end < selEnd || selStart == selEnd) {
                        if (end > bestend) {
                            beststart = buffer.getSpanStart(candidates[i]);
                            bestend = end;
                        }
                    }
                }
    
                if (beststart >= 0) {
                    Selection.setSelection(buffer, bestend, beststart);
                    return true;
                }
    
                break;
    
            case DOWN:
                beststart = Integer.MAX_VALUE;
                bestend = Integer.MAX_VALUE;
    
                for (int i = 0; i < candidates.length; i++) {
                    int start = buffer.getSpanStart(candidates[i]);
    
                    if (start > selStart || selStart == selEnd) {
                        if (start < beststart) {
                            beststart = start;
                            bestend = buffer.getSpanEnd(candidates[i]);
                        }
                    }
                }
    
                if (bestend < Integer.MAX_VALUE) {
                    Selection.setSelection(buffer, beststart, bestend);
                    return true;
                }
    
                break;
        }
    
        return false;
    }
    
    @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);
    
            URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
    
            if (action == MotionEvent.ACTION_UP) {
                if (listener != null) {
                    if (link.length >= 1) {
                        listener.onClick(link[0].getURL());
                    } else {
                        ImageSpan[] image = buffer.getSpans(off, off, ImageSpan.class);
                        if (image.length >= 1) {
                            listener.onImageClicked(image[0].getSource());
                        } else if (Selection.getSelectionStart(buffer) == Selection.getSelectionEnd(buffer)) {
                            listener.onTextClicked();
                        }
                    }
                }
            }
    
            if (action == MotionEvent.ACTION_DOWN && link.length != 0) {
                Selection.setSelection(buffer,
                        buffer.getSpanStart(link[0]),
                        buffer.getSpanEnd(link[0]));
                return true;
            }
    
            if (link.length == 0) {
                Selection.removeSelection(buffer);
            }
        }
    
        return super.onTouchEvent(widget, buffer, event);
    }
    
    @Override
    public void initialize(TextView widget, Spannable text) {
        Selection.removeSelection(text);
        text.removeSpan(FROM_BELOW);
    }
    
    @Override
    public void onTakeFocus(TextView view, Spannable text, int dir) {
        Selection.removeSelection(text);
    
        if ((dir & View.FOCUS_BACKWARD) != 0) {
            text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT);
        } else {
            text.removeSpan(FROM_BELOW);
        }
    }
    
    public interface Listener {
    
        void onClick(String clicked);
    
        void onTextClicked();
    
        void onImageClicked(String source);
    
    }
    
    }
    
    0 讨论(0)
  • 2020-11-22 02:19

    Created elegant Kotlin way with extension:

    fun TextView.setClickableText(text: Spanned,
                                  clickableText: String,
                                  @ColorInt clickableColor: Int,
                                  clickListener: () -> Unit) {
        val spannableString = SpannableString(text)
    
        val startingPosition: Int = text.indexOf(clickableText)
    
        if (startingPosition > -1) {
            val clickableSpan: ClickableSpan = object : ClickableSpan() {
                override fun onClick(textView: View) {
                    clickListener()
                }
    
                override fun updateDrawState(textPaint: TextPaint) {
                    super.updateDrawState(textPaint)
                    textPaint.isUnderlineText = false
                }
            }
    
            val endingPosition: Int = startingPosition + clickableText.length
            spannableString.setSpan(clickableSpan, startingPosition,
                    endingPosition, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            spannableString.setSpan(ForegroundColorSpan(clickableColor), startingPosition,
                    endingPosition, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            movementMethod = LinkMovementMethod.getInstance()
            highlightColor = Color.TRANSPARENT
        }
    
        setText(spannableString)
    }
    
    0 讨论(0)
  • 2020-11-22 02:21
     t= (TextView) findViewById(R.id.PP1);
    
     t.setText(Html.fromHtml("<bThis is normal text </b>" +
                    "<a href=\"http://www.xyz-zyyx.com\">This is cliclable text</a> "));
     t.setMovementMethod(LinkMovementMethod.getInstance());
    
    0 讨论(0)
提交回复
热议问题