Skip to content

Instantly share code, notes, and snippets.

@sbaar
Created April 14, 2016 04:33
Show Gist options
  • Save sbaar/2374b6bba8ff425fb3b6d162456f5c32 to your computer and use it in GitHub Desktop.
Save sbaar/2374b6bba8ff425fb3b6d162456f5c32 to your computer and use it in GitHub Desktop.
MAdapter with clickable hashtags and @
//the magic happens just before return convertView; in getView()
package com.makemoji.sbaar.mojilist;
import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.makemoji.mojilib.HyperMojiListener;
import com.makemoji.mojilib.Moji;
import com.makemoji.mojilib.ParsedAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Scott Baar on 12/3/2015.
*/
public class MAdapter extends ArrayAdapter<MojiMessage> {
Context context;
List<MojiMessage> messages;
private float mTextSize = -1;
private boolean mSimple = true;
public MAdapter (Context context, List<MojiMessage> messages, boolean simple){
super(context,R.layout.message_item,messages);
this.context = context;
this.messages = messages;
mSimple = simple;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
Holder holder;
MojiMessage message = getItem(position);
if (convertView==null){
convertView = LayoutInflater.from(context).inflate(R.layout.message_item,parent,false);
holder = new Holder();
holder.messageTV = (TextView)convertView.findViewById(R.id.item_message_tv);
holder.fromIV = (ImageView) convertView.findViewById(R.id.from_iv);
holder.toIV = (ImageView) convertView.findViewById(R.id.to_iv);
convertView.setTag(holder);
holder.messageTV.setTag(R.id._makemoji_hypermoji_listener_tag_id, new HyperMojiListener() {
@Override
public void onClick(String url) {
Toast.makeText(getContext(),"hypermoji clicked from adapter url " + url,Toast.LENGTH_SHORT).show();
}
});
if (mTextSize== -1) mTextSize = holder.messageTV.getTextSize()/getContext().getResources().getDisplayMetrics().density;
}
holder = (Holder) convertView.getTag();
if (holder.simple!=mSimple){//simple has changed, destroy cached spanned
message.parsedAttributes = null;
}
if (!message.id.equals(holder.id)){
holder.id = message.id;
ParsedAttributes parsedAttributes = message.parsedAttributes;
if (parsedAttributes==null) {
parsedAttributes = Moji.parseHtml(message.messageRaw, holder.messageTV, mSimple);
message.parsedAttributes =parsedAttributes;
}
Moji.setText(message.parsedAttributes.spanned,holder.messageTV);
holder.simple = mSimple;
}
if (holder.messageTV.getTextSize()!= mTextSize){
holder.messageTV.setTextSize(mTextSize);
Moji.setText(message.messageRaw,holder.messageTV,mSimple);
}
message.parsedAttributes.spanned = hashAndAtClickable(holder.messageTV,message.parsedAttributes.spanned);
Moji.setText(message.parsedAttributes.spanned,holder.messageTV);
return convertView;
}
public void changeTextSize(float increase){
mTextSize+=increase;
notifyDataSetChanged();
}
public void setSimple(boolean simple){
mSimple = simple;
notifyDataSetChanged();
}
private static class Holder{
public TextView messageTV;
public String id;
public ImageView fromIV;
public ImageView toIV;
public boolean simple;
}
Spanned hashAndAtClickable(TextView tv,final CharSequence cs){
SpannableStringBuilder ssb = new SpannableStringBuilder(cs);
ArrayList<int[]> hashtagSpans = getSpans(cs.toString(), '#');
ArrayList<int[]> atSpans = getSpans(cs.toString(), '@');
for(int i = 0; i < hashtagSpans.size(); i++) {
int[] span = hashtagSpans.get(i);
final int hashTagStart = span[0];
final int hashTagEnd = span[1];
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
CharSequence hashtag = cs.subSequence(hashTagStart,hashTagEnd);
Toast.makeText(context,"# clicked "+ hashtag,Toast.LENGTH_LONG).show();
}
},
hashTagStart,
hashTagEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setMovementMethod(LinkMovementMethod.getInstance());
}
for(int i = 0; i < atSpans.size(); i++) {
int[] span = atSpans.get(i);
final int atStart = span[0];
final int atEnd = span[1];
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
CharSequence at = cs.subSequence(atStart,atEnd);
Toast.makeText(context,"@ clicked "+ at,Toast.LENGTH_LONG).show();
}
},
atStart,
atEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setMovementMethod(LinkMovementMethod.getInstance());
}
return ssb;
}
//https://zunostudios.com/blog/development/176-how-to-implment-hashtags-and-callouts-in-android
public ArrayList<int[]> getSpans(String body, char prefix) {
ArrayList<int[]> spans = new ArrayList<>();
Pattern pattern = Pattern.compile(prefix + "\\w+");
Matcher matcher = pattern.matcher(body);
// Check all occurrences
while (matcher.find()) {
int[] currentSpan = new int[2];
currentSpan[0] = matcher.start();
currentSpan[1] = matcher.end();
spans.add(currentSpan);
}
return spans;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment