Saturday, October 30, 2010

Custom Links

in one of my projects i needed to create custom links. My goal was to create few text views that will look and feel like normal links, but i wanted to catch the "OnClick" event for these text views.
normally, you could just create a style for the text view (make the text underlined, blue colored etc.) but i found
that this is not enough if the user is using the keys to navigate inside the view since the text views are not highlighted correctly, and also the click event doesn't get the text highlighted the way normal links are highlighted.
the solution to the problem was to create a simple class that will act in the same way as the framework Linkify class.

public class CustomLinkify {

 public static class CustomLinkSpan  extends ClickableSpan {

  private OnClickListener mListener;
  
  public void setOnClickListener(OnClickListener l){
   mListener = l;
  }
  
  @Override
  public void onClick(View widget) {
   if(mListener != null){
    mListener.onClick(widget);
   }
   if(widget instanceof TextView){
    final TextView tv = (TextView)widget;
    SpannableString s  = (SpannableString)tv.getText();
    Selection.setSelection(s, 0, 0);
   }
  } 
 }
 
 public static CustomLinkSpan addLinks(int resId, TextView v) {
  return addLinks(resId, v, null);
 }
 
 public static CustomLinkSpan addLinks(int resId, TextView v, OnClickListener l) {
  CharSequence text = v.getContext().getText(resId);
  return addLinks(text, v, l);
 }
 
 public static CustomLinkSpan addLinks(CharSequence text, TextView v) {
  return addLinks(text, v, null);
 }
 
 public static CustomLinkSpan addLinks(CharSequence text, TextView v, OnClickListener l) {
  SpannableString s = SpannableString.valueOf(text);
  CustomLinkSpan span = new CustomLinkSpan();
  span.setOnClickListener(l);
  s.setSpan(span, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  v.setText(s);
        v.setMovementMethod(LinkMovementMethod.getInstance());
  return span;
 }
 
}

The new class is called CustomLinkify and expose the desired functionality in a simple static method called addLinks.
the method takes the TextView target and a String that will be filled inside the TextView. (the method has another convieniet versions using resourceId or with ClickListener).
The method return value is an instance of CustomLinkSpan class, which can be used to attach the OnClick listener later on (i.e. if you don't have the listener at the time of calling the addLinks method)

i found that in android 1.6 when you click on the link, the highlight remains which is not the behavior i wanted, so i added the call to setSelection method to clear the highlighting after the click.

1 comment:

  1. Hi Yosi,
    i've made in a similar way custom links on my own, but i can't remove or make custom highlight on link click. Do you know how to do it?

    Great post by the way

    Thanks

    ReplyDelete