Skip to content

Instantly share code, notes, and snippets.

@Cheesebaron
Last active September 15, 2020 14:21
Show Gist options
  • Save Cheesebaron/5034440 to your computer and use it in GitHub Desktop.
Save Cheesebaron/5034440 to your computer and use it in GitHub Desktop.
Sample showing how to use Spannables to replace text with Images in Mono for Android.
using Android.App;
using Android.Text;
using Android.Text.Style;
using Android.Widget;
using Android.OS;
namespace MonoDroid.TextViewWithImages
{
[Activity(Label = "Text with Images", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity
{
private EditText _editText;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
var textView = FindViewById<TextView>(Resource.Id.textView1);
var imageSpan = new ImageSpan(this, Resource.Drawable.Icon); //Find your drawable.
var spannableString = new SpannableString(textView.Text); //Set text of SpannableString from TextView
spannableString.SetSpan(imageSpan, textView.Text.Length -1, textView.Text.Length, 0); //Add image at end of string
textView.TextFormatted = spannableString; //Assign string to TextView (Use TextFormatted for Spannables)
_editText = FindViewById<EditText>(Resource.Id.editText1);
_editText.AfterTextChanged += (sender, args) => SpannableTools.AddSmiles(this, args.Editable);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minWidth="25px"
android:minHeight="25px">
<TextView
android:text="Hey there, I am a TextView with an image inside!"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textView1" />
<EditText
android:inputType="textMultiLine"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/editText1"
android:hint="Type some text here" />
</LinearLayout>
using System.Collections.Generic;
using Android.Content;
using Android.Text;
using Android.Text.Style;
using Java.Lang;
namespace MonoDroid.TextViewWithImages
{
public static class SpannableTools
{
private static readonly Dictionary<string, int> Emoticons;
static SpannableTools()
{
Emoticons = new Dictionary<string, int>
{
{":-)", Resource.Drawable.Icon},
{":)", Resource.Drawable.Icon}
};
}
public static bool AddSmiles(Context context, ISpannable spannable)
{
var hasChanges = false;
foreach (var entry in Emoticons)
{
var smiley = entry.Key;
var smileyImage = entry.Value;
var indices = spannable.ToString().IndexesOf(smiley);
foreach (var index in indices)
{
var set = true;
foreach (ImageSpan span in spannable.GetSpans(index, index + smiley.Length, Java.Lang.Class.FromType(typeof(ImageSpan))))
{
if (spannable.GetSpanStart(span) >= index && spannable.GetSpanEnd(span) <= index + smiley.Length)
spannable.RemoveSpan(span);
else
{
set = false;
break;
}
}
if (set)
{
hasChanges = true;
spannable.SetSpan(new ImageSpan(context, smileyImage), index, index + smiley.Length, SpanTypes.ExclusiveExclusive );
}
}
}
return hasChanges;
}
public static ISpannable GetSmiledText(Context context, ICharSequence text)
{
var spannable = SpannableFactory.Instance.NewSpannable(text);
AddSmiles(context, spannable);
return spannable;
}
public static void AddSmiley(string textSmiley, int smileyResource)
{
Emoticons.Add(textSmiley, smileyResource);
}
}
//Taken from http://stackoverflow.com/a/767788/368379
public static class StringExtensions
{
public static IEnumerable<int> IndexesOf(this string haystack, string needle)
{
var lastIndex = 0;
while (true)
{
var index = haystack.IndexOf(needle, lastIndex);
if (index == -1)
{
yield break;
}
yield return index;
lastIndex = index + needle.Length;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment