webentwicklung-frage-antwort-db.com.de

Wie Sie den Teil der Textansicht einstellen, ist anklickbar

Ich habe den Text " Android ist ein Software-Stack ". In diesem Text möchte ich festlegen, dass der Text " stack " anklickbar ist. In dem Sinne, wenn Sie darauf klicken, wird zu einer neuen Aktivität umgeleitet (nicht im Browser). 

Ich habe es versucht, aber ich bekomme es nicht. 

171
naresh

Android.text.style.ClickableSpan kann Ihr Problem lösen.

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"

461
Dipesh Rathod

Meine Funktion zum Erstellen mehrerer Links in TextView

public void makeLinks(TextView textView, String[] links, ClickableSpan[] clickableSpans) {
    SpannableString spannableString = new SpannableString(textView.getText());
    for (int i = 0; i < links.length; i++) {
        ClickableSpan clickableSpan = clickableSpans[i];
        String link = links[i];

        int startIndexOfLink = textView.getText().toString().indexOf(link);
        spannableString.setSpan(clickableSpan, startIndexOfLink,
                startIndexOfLink + link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    textView.setHighlightColor(
            Color.TRANSPARENT); // prevent TextView change background when highlight
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setText(spannableString, TextView.BufferType.SPANNABLE);
}

MIT

textView.setLinkTextColor(Color.BLUE); // default link color for clickable span, we can also set it in xml by Android:textColorLink=""
ClickableSpan normalLinkClickSpan = new ClickableSpan() {
    @Override
    public void onClick(View view) {
        Toast.makeText(getApplicationContext(), "Normal Link", Toast.LENGTH_SHORT).show();
    }

};

ClickableSpan noUnderLineClickSpan = new ClickableSpan() {
    @Override
    public void onClick(View view) {
        Toast.makeText(getApplicationContext(), "NoUnderLine Link", Toast.LENGTH_SHORT)
                .show();
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setUnderlineText(false);
        ds.setColor(Color.Magenta); // specific color for this link
    }
};

ClickableSpan highlightClickSpan = new ClickableSpan() {
    @Override
    public void onClick(View view) {
        Toast.makeText(getApplicationContext(), "Highlight Link", Toast.LENGTH_SHORT)
                .show();
        view.invalidate(); // need put invalidate here to make text change to GREEN after clicked
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setUnderlineText(false);
        if (textView.isPressed() && textView.getSelectionStart() != -1 && textView.getText()
                    .toString()
                    .substring(textView.getSelectionStart(), textView.getSelectionEnd())
                    .equals("Highlight Link")) {
                ds.setColor(Color.RED); // need put invalidate here to make text change to RED when pressed on Highlight Link                    textView.invalidate();
            } else {
                ds.setColor(Color.GREEN);
            }
            // dont put invalidate here because if you put invalidate here `updateDrawState` will called forever
    }
};

makeLinks(textView, new String[] {
        "Normal Link", "NoUnderLine Link", "Highlight Link"
}, new ClickableSpan[] {
        normalLinkClickSpan, noUnderLineClickSpan, highlightClickSpan
});

XML

<TextView
    Android:id="@+id/myText"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Please read Normal Link and NoUnderLine Link and Highlight Link"
    Android:textSize="30sp"
    />

 enter image description here

57
Linh

Sie können ClickableSpan wie in diesem Beitrag beschrieben verwenden.

Beispielcode:

TextView myTextView = new TextView(this);
String myString = "Some text [clickable]";
int i1 = myString.indexOf("[");
int i2 = myString.indexOf("]");
myTextView.setMovementMethod(LinkMovementMethod.getInstance());
myTextView.setText(myString, BufferType.SPANNABLE);
Spannable mySpannable = (Spannable)myTextView.getText();
ClickableSpan myClickableSpan = new ClickableSpan() {
   @Override
   public void onClick(View widget) { /* do something */ }
};
mySpannable.setSpan(myClickableSpan, i1, i2 + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Referenz

32
Imran Rana

Sie können Beispielcode verwenden. Sie möchten Details zu ClickableSpan erfahren. Bitte überprüfen Sie 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());
11
Tarık Yurtlu

Ich habe diese Hilfsmethode erstellt, falls jemand die Start- und Endposition eines Strings benötigt.

public static TextView createLink(TextView targetTextView, String completeString,
    String partToClick, ClickableSpan clickableAction) {

    SpannableString spannableString = new SpannableString(completeString);

    // make sure the String is exist, if it doesn't exist
    // it will throw IndexOutOfBoundException
    int startPosition = completeString.indexOf(partToClick);
    int endPosition = completeString.lastIndexOf(partToClick) + partToClick.length();

    spannableString.setSpan(clickableAction, startPosition, endPosition,
        Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

    targetTextView.setText(spannableString);
    targetTextView.setMovementMethod(LinkMovementMethod.getInstance());

    return targetTextView;
}

Und so verwenden Sie es

private void initSignUp() {
    String completeString = "New to Reddit? Sign up here.";
    String partToClick = "Sign up";
    ClickableTextUtil
        .createLink(signUpEditText, completeString, partToClick,
            new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    // your action
                    Toast.makeText(activity, "Start Sign up activity",
                        Toast.LENGTH_SHORT).show();
                }

                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    // this is where you set link color, underline, typeface etc.
                    int linkColor = ContextCompat.getColor(activity, R.color.blumine);
                    ds.setColor(linkColor);
                    ds.setUnderlineText(false);
                }
            });
}
9
aldok
 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());
7
Ather

Kotlin Version von Phan Van Linhs Antwort.

Bitte beachten Sie, dass es einige kleinere Änderungen gibt.

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))
}
3
Rammohan Raja

Hier ist eine Kotlin-Methode, um Teile einer TextView anklickbar zu machen:

private fun makeTextLink(textView: TextView, str: String, underlined: Boolean, color: Int?, action: (() -> Unit)? = null) {
    val spannableString = SpannableString(textView.text)
    val textColor = color ?: textView.currentTextColor
    val clickableSpan = object : ClickableSpan() {
        override fun onClick(textView: View) {
            action?.invoke()
        }
        override fun updateDrawState(drawState: TextPaint) {
            super.updateDrawState(drawState)
            drawState.isUnderlineText = underlined
            drawState.color = textColor
        }
    }
    val index = spannableString.indexOf(str)
    spannableString.setSpan(clickableSpan, index, index + str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    textView.text = spannableString
    textView.movementMethod = LinkMovementMethod.getInstance()
    textView.highlightColor = Color.TRANSPARENT
}

Es kann mehrmals aufgerufen werden, um mehrere Links in einer TextView zu erstellen:

makeTextLink(myTextView, str, false, Color.RED, action = { Log.d("onClick", "link") })
makeTextLink(myTextView, str1, true, null, action = { Log.d("onClick", "link1") })
2
Dan Bray

Für fett,

mySpannable.setSpan(new StyleSpan(Typeface.BOLD),termStart,termStop,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
1
mustafasevgi

Dies ist meine MovementMethod zum Erkennen von Link/Text/Bild-Klicks. Es wird LinkMovementMethod geändert.

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
Ufkoku

Ich würde einen anderen Ansatz vorschlagen, der meiner Meinung nach weniger Code erfordert und "lokalisierungsfreundlicher" ist.

Angenommen, Ihre Zielaktivität heißt "ActivityStack". Definieren Sie im Manifest einen Absichtsfilter mit einem benutzerdefinierten Schema (z. B. "myappscheme") in AndroidManifest.xml:

<activity
    Android:name=".ActivityStack">
    <intent-filter>
        <action Android:name="Android.intent.action.VIEW" />
        <category Android:name="Android.intent.category.DEFAULT" />
        <data Android:Host="stack"/>
        <data Android:scheme="myappscheme" />
    </intent-filter>
</activity>

Definieren Sie das TextView ohne ein spezielles Tag (es ist wichtig, dass Sie NICHT das "Android: autoLink" -Tag verwenden, siehe: https://stackoverflow.com/a/20647011/1699702 ):

<TextView
    Android:id="@+id/stackView"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="@string/stack_string" />

verwenden Sie dann einen Link mit benutzerdefiniertem Schema und Host im Text des TextView als (in String.xml):

<string name="stack_string">Android is a Software <a href="myappscheme://stack">stack</a></string>

und "aktivieren" die Verknüpfung mit setMovementMethod () (in onCreate () für Aktivitäten oder onCreateView () für Fragmente):

TextView stack = findViewById(R.id.stackView);
stack.setMovementMethod(LinkMovementMethod.getInstance());

Dadurch wird die Stapelaktivität mit einem Tippen auf das "Stapel" -Wort geöffnet.

0
fledge

Sie können diese Methode verwenden, um den anklickbaren Wert festzulegen 

public void setClickableString(String clickableValue, String wholeValue, TextView yourTextView){
    String value = wholeValue;
    SpannableString spannableString = new SpannableString(value);
    int startIndex = value.indexOf(clickableValue);
    int endIndex = startIndex + clickableValue.length();
    spannableString.setSpan(new ClickableSpan() {
                                @Override
                                public void updateDrawState(TextPaint ds) {
                                    super.updateDrawState(ds);
                                    ds.setUnderlineText(false); // <-- this will remove automatic underline in set span
                                }

                                @Override
                                public void onClick(View widget) {
                                    // do what you want with clickable value
                                }
                            }, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    yourTextView.setText(spannableString);
    yourTextView.setMovementMethod(LinkMovementMethod.getInstance()); // <-- important, onClick in ClickableSpan won't work without this
}

So verwenden Sie es:

TextView myTextView = findViewById(R.id.myTextView);
setClickableString("stack", "Android is a Software stack", myTextView);
0
shinta