15

How would I go about adding clickable links inside a ListView?

Legend
  • 113,822
  • 119
  • 272
  • 400

5 Answers5

23

This is done using the autoLink attribute of a TextView. Took me some time to dig through the documentation so putting it here with an example in case someone else is looking for it:

Let us assume that you are binding your listview to a custom adapter. In that case, the following piece of code goes into your getView call:

Code:

textcontent.setText(Html.fromHtml(item.get_text()));
textcontent.setAutoLinkMask(Linkify.WEB_URLS);

Just put the link inside the text being passed to the setText call and you're done.

XML:

<TextView
                android:id="@+id/txtview"
                android:autoLink="web"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:text="put your link here"/>

Hope that helps...

Legend
  • 113,822
  • 119
  • 272
  • 400
19

If you have text that is already in HTML format, the best thing to do is the following:

TextView textcontent = (TextView) findViewById(...);
textcontent.setMovementMethod(LinkMovementMethod.getInstance());

String text = "<a href="http://www.stackoverflow.com">stackoverflow.com</a>";
textcontent.setText(Html.fromHtml(text));

This will cause any link tags to be clickable in your text view. Alternately, you could use android:autoLink="web" as suggested by Legend, but this has the side-effect of a) linkifying urls that are not wrapped in anchor tags, and b) potentially missing urls or linkifying things that aren't urls. If you want the smarts of autoLink then you should use it, but if all you want is to linkify the tags that are already there, you're better off using setMovementMethod().

See this bug report for more details: http://code.google.com/p/android/issues/detail?id=2219

emmby
  • 99,783
  • 65
  • 191
  • 249
  • 3
    Hmm, it seems that adding textcontent.setMovementMethod(LinkMovementMethod.getInstance()); makes it so that the clicks on the textview's text parts are no longer passed through to the listview below. – Artem Russakovskii Jun 06 '11 at 20:22
  • This is the most correct answer to the question asked. BeerMe's answers fixes the problems with the ListView item becoming unclickable. – juil Jul 10 '16 at 01:31
11

Hmm, it seems that adding textcontent.setMovementMethod(LinkMovementMethod.getInstance()); makes it so that the clicks on the textview's text parts are no longer passed through to the listview below.

I found a simple workaround under Issue 3414, Comment 27:

An easy way to work around this problem is to call "setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);" on the listView views as they are added. You'll be able to select rows, click on rows and click on child checkboxes and buttons.

It worked perfectly for me, although some casting was required:

View v;
((ViewGroup)v).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
Beer Me
  • 492
  • 1
  • 7
  • 15
  • Where do you add the desecendantFocusability? To the ListView or to the ListItem? I followed your example to add clickable links, however when clicking on non link parts of my textview, the event isn't passed to the parent view of the listitem or to the listview... – ffleandro Jun 25 '13 at 03:47
  • I use it like this: public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(itemLayout, null); } ... ((ViewGroup) v).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); return v; } I haven't checked to see what happens to the event if a non-link portion is clicked. (Not sure why I can't get the code to format...sorry.) – Beer Me Sep 09 '13 at 17:54
1

You need to set a function setOnItemClickListener() and inside it declare something like this:

Uri uri = Uri.parse( "http://www.google.com" );
startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
Duc Tran
  • 6,016
  • 4
  • 34
  • 42
0

The tricky part of listview is nothing within (for instance a TextView of a Button) is clickable!

Basically you need two string arrays:

  1. names that users see on the list_view;
  2. hyperlinks that you want to direct them to go.

In the array.xml:

<string-array name="search_provider_name_array">
    <item>Google</item>
    <item>Yahoo</item>
    <item>Bing</item>
    <item>Baidu</item>
</string-array>
<string-array name="search_provider_link_array">
    <item>https://www.google.com</item>
    <item>https://www.yahoo.com</item>
    <item>https://www.bing.com</item>
    <item>https://www.baidu.com</item>
</string-array>

In the layout_search_provider.xml it contains a list view:

<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/lv_search"
    android:dividerHeight="1dp"/>

In your activity:

public class SearchProvider implements  AdapterView.OnItemClickListener {
    private ListView lv_search;
    private String[] names = getResources().getStringArray(R.array.search_provider_name_array);
    private String[] links = getResources().getStringArray(R.array.search_provider_link_array);

    //..

    @Override
    public View onCreateView(View v, String name, Context context, AttributeSet attrs) {
        lv_search= (ListView) v.findViewById(R.id.lv_search);

        ArrayAdapter sAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, names);
        lv_search.setAdapter(sAdapter);
        lv_search.setOnItemClickListener(this);

        return v;
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        if(i<links.length){
            Uri uri = Uri.parse(links[i]); 
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        }
    }

}

When your list is dynamic, you can the following method(s) to update your listview.

  • move the code in onCreateView() into onResume().
  • sAdapter.notifyDataSetChanged();
Diiiiii
  • 209
  • 3
  • 8