Skip to content

Instantly share code, notes, and snippets.

@pmachapman
Last active June 19, 2019 02:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmachapman/a988348a93933ac359ebe0d6a5314467 to your computer and use it in GitHub Desktop.
Save pmachapman/a988348a93933ac359ebe0d6a5314467 to your computer and use it in GitHub Desktop.
A Xamarin Android TextView that supports Linkify and gestures
// -----------------------------------------------------------------------
// <copyright file="LinkifyTextView.cs" company="Conglomo">
// Copyright 2019 Peter Chapman. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Conglomo.AndroidSupport
{
using Android.Content;
using Android.Runtime;
using Android.Text;
using Android.Text.Style;
using Android.Text.Util;
using Android.Util;
using Android.Views;
using Android.Widget;
using Java.Lang;
/// <summary>
/// A TextView that supports linkifying of hyperlinks and gestures.
/// </summary>
/// <seealso cref="Android.Widget.TextView" />
public class LinkifyTextView : TextView
{
/// <summary>
/// Initialises a new instance of the <see cref="LinkifyTextView"/> class.
/// </summary>
/// <param name="context">The context.</param>
public LinkifyTextView(Context context)
: base(context)
{
this.Initialise();
}
/// <summary>
/// Initialises a new instance of the <see cref="LinkifyTextView"/> class.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="attrs">The attributes.</param>
public LinkifyTextView(Context context, IAttributeSet attrs)
: base(context, attrs)
{
this.Initialise();
}
/// <summary>
/// Initialises a new instance of the <see cref="LinkifyTextView"/> class.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="attrs">The attributes.</param>
/// <param name="defStyleAttr">The definition style attribute.</param>
public LinkifyTextView(Context context, IAttributeSet attrs, int defStyleAttr)
: base(context, attrs, defStyleAttr)
{
this.Initialise();
}
/// <summary>
/// Initialises a new instance of the <see cref="LinkifyTextView"/> class.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="attrs">The attributes.</param>
/// <param name="defStyleAttr">The definition style attribute.</param>
/// <param name="defStyleRes">The definition style resource.</param>
public LinkifyTextView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes)
: base(context, attrs, defStyleAttr, defStyleRes)
{
this.Initialise();
}
/// <summary>
/// Initialises a new instance of the <see cref="LinkifyTextView"/> class.
/// </summary>
/// <param name="javaReference">The java reference.</param>
/// <param name="transfer">The transfer.</param>
protected LinkifyTextView(System.IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
this.Initialise();
}
/// <inheritdoc/>
public override bool OnTouchEvent(MotionEvent e)
{
if (e != null && this.TextFormatted is SpannableString buffer)
{
if (e.Action == MotionEventActions.Up || e.Action == MotionEventActions.Down)
{
int x = (int)e.GetX();
int y = (int)e.GetY();
x -= this.TotalPaddingLeft;
y -= this.TotalPaddingTop;
x += this.ScrollX;
y += this.ScrollY;
Layout layout = this.Layout;
int line = layout.GetLineForVertical(y);
int off = layout.GetOffsetForHorizontal(line, x);
Object[] link = buffer.GetSpans(off, off, Class.FromType(typeof(ClickableSpan)));
if (link.Length != 0)
{
if (e.Action == MotionEventActions.Up)
{
((ClickableSpan)link[0]).OnClick(this);
}
else if (e.Action == MotionEventActions.Down)
{
Selection.SetSelection(buffer, buffer.GetSpanStart(link[0]), buffer.GetSpanEnd(link[0]));
}
return true;
}
}
}
return false;
}
/// <inheritdoc/>
public override void SetText(ICharSequence text, BufferType type)
{
base.SetText(text, type);
this.MovementMethod = default;
}
/// <summary>
/// Initialises this instance.
/// </summary>
private void Initialise()
{
this.AutoLinkMask = MatchOptions.All;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment