11

I am creating a small Android app. I would like to display a text in a textview with multiple parts to click on. (Each should show some different message)

Finally I managed to find out how to display mutiple spans in one textview, however unfortunately the onClick methods don't work. Simply nothing happens, not even a logcat line.

I have something like this:

SpannableStringBuilder ssb=new SpannableStringBuilder();
ssb.append("first  second")

ssb.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View v) {
    //Eredmeny2.this is just the context, name of the whole class
    Toast.makeText(Eredmeny2.this, "first", Toast.LENGTH_LONG).show();
    }
}, 1, 3, 0);

ssb.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View v) {
    Toast.makeText(Eredmeny2.this, "second", Toast.LENGTH_LONG).show();
    }
}, 7, 10, 0);

TextView t1=new TextView(this);
t1.setText(ssb);
...

The text is underlined fine, but nothing happens when i click them. It is a part of a TableView, although I do not think this is relevant. Do you have any ideas why it does not do anything? What do I miss? Or should I do it on some totally different way?

Thanks in advance.


The layout file this part would use is the following:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
    android:id="@+id/ScrollView01"
    android:background="#FF0000">


    <TableLayout
        android:id="@+id/TableLayout01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:stretchColumns="0"
        android:showDividers="middle"
        android:padding="3dp">
    <TableRow
        android:id="@+id/TableRow01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/TextView01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="3dp"
            android:background="#000000"
            android:textColor="#FFFFFF"
            android:padding="6dp"
            android:text="Hour"
            android:textSize="20sp"
            android:textStyle="bold" >

        </TextView>
        <TextView android:id="@+id/TextView02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textStyle="bold"
            android:text="Minute"
            android:padding="6dp"
            android:textColor="#FFFFFF"
            android:background="#000000">
        </TextView>

    </TableRow>

    </TableLayout>


</ScrollView>

And the TextView layout that the TextView uses directly is the following:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv" 
android:layout_width="fill_parent" 
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="16sp"
android:background="#000000"
android:textIsSelectable="false"
android:textColor="#FFFFFF">
</TextView>
skandigraun
  • 741
  • 8
  • 21
  • Can you post your layout file? – Noundla Sandeep May 12 '13 at 18:57
  • Sure, here you go, in the updated question. – skandigraun May 12 '13 at 19:05
  • change this to true... android:textIsSelectable="true" – Noundla Sandeep May 12 '13 at 19:09
  • You can get the answer from this link. http://stackoverflow.com/questions/5183645/android-clickablespan-in-clickable-textview?rq=1 Try it. – Noundla Sandeep May 12 '13 at 19:11
  • Why complicate things? what's wrong with multiple textviews? – tbkn23 May 12 '13 at 19:16
  • It is going to be a kind of schedule app for public transportation. On this layout the whole schedule is displayed. If there are any exceptions (like a bus goes only to xx stop insteas of the terminal) I would like to make it clickable, showing this information. I belive using a separate textview for each starting bus would be more complicated (although i am not 100% sure... might give it a try). – skandigraun May 12 '13 at 19:25
  • Posted too early: Imagine it like a real schedule: on the left you can see the hour and in the right cloumn you can see the minutes. If the bus starting at 15:45 is a special bus, the word '45' will be clickable (at least this is what I would like) showing this information. – skandigraun May 12 '13 at 19:27
  • At this moment I am trying noundla's answer. – skandigraun May 12 '13 at 19:27
  • Unfortunately it did not work out. But finally I have solved the problem on another way: I used a webview (i have generated the html content to display) and have overriden the shouldOverrideUrlLoading method to show the message instead of following the link. (I have set the text to display as the URL - clicking on the link it is displayed) Anyway, thanks for the answers! – skandigraun May 13 '13 at 17:31

2 Answers2

30

as i understand you want to make multiple part of textview clickable.

this code worked for me!

SpannableString ss = new SpannableString("this is a text");
ss.setSpan(new myClickableSpan(1),0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new myClickableSpan(2),5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new myClickableSpan(3),8, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

mTextView.setText(ss);
mTextView.setMovementMethod(LinkMovementMethod.getInstance());

just make custom ClickableSpan to handle the click event

public class myClickableSpan extends ClickableSpan{

    int pos;
    public myClickableSpan(int position){
        this.pos=position;
    }

    @Override
    public void onClick(View widget) {
        Toast.makeText(getApplicationContext(), "Position "  + pos + " clicked!", Toast.LENGTH_LONG).show();
    }

}
Manian Rezaee
  • 1,012
  • 12
  • 26
0

it's rather old, but I just encounter this situation too.

For me I use difference clickable span for two or more clickable text in Text View. So to saving time I declare it by using List in Kotlin.

Here is the code.

val listClickSpan = List<ClickableSpan>(2) {
    object : ClickableSpan() {
        override fun onClick(widget: View) {
            startActivity(Intent(mContext, SomeActivity::class.java))
        }

        override fun updateDrawState(ds: TextPaint) {
            super.updateDrawState(ds)
            ds.isUnderlineText = false
            ds.color = ContextCompat.getColor(mContext, R.color.dark_blue)
        }
    }
}

val font = ResourcesCompat.getFont(mContext, R.font.roboto_bold)
SpannableString(mContext.getString(R.string.multiple_text)).apply {
    if (font != null)
        setSpan(
            CustomTypefaceSpan(font), 67, 83, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    setSpan(listClickSpan[0], 67, 83, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    if (font != null)
        setSpan(
            CustomTypefaceSpan(font), 88, 105, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    setSpan(listClickSpan[1], 88, 105, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    bind.tvLink.setText(this, TextView.BufferType.SPANNABLE)
    bind.tvLink.movementMethod = LinkMovementMethod.getInstance()
    bind.tvLink.linksClickable = true
}

Hope it will help you

Liong
  • 1,324
  • 12
  • 18