I want to make a chat application where the emoticons are necessary. I was trying to write my own TextBox to handle some unicode caracters and replace them with smiles and emoticons, but that was a hard work to do and I encountered many problems.
Then I tried to make a custom font that will have emoticons in it but I found that a font is made in black and white and cannot be colored.
I tried then to use different EditFields so when I find a Bitmap I draw it and start a different EditField but that didnt work for several lines and selection problems occured.
The best way was to write my own textField that will find a special unicode caracter, add 2 spaces to, get the location of the unicode caracter and then draw the bitmap image in this location. But that was very slow when the number of emoticons becomes bigger
Is there a tool or an API or a way that I missed that will do the emoticons for me on BlackBerry devices? Please help in this topic I searched everywhere and nothing found yet
We could try to use a web forums approach:
- allow users to input ASCII codes for emoticons
- in message edit mode show emoticons as a text codes
- in message history show emoticons as images (use BrowserField for this purpose)
- use additional html formatting
Try this code:
public final class ChatScreen extends MainScreen implements FieldChangeListener {
static final int INT_MSG_MAX_LEN = 200;
static final DateFormat FRMT_TIME = DateFormat
.getInstance(DateFormat.TIME_SHORT);
static final String STR_FRMT_IMG = "<img src=\"{0}\"></img>";
static final String STR_FRMT_MSG = "<b>{0}</b> [{1}]: {2}</p>";
// several emoticon ASCII codes
static final String STR_CODE_SMILE = ":)";
static final String STR_CODE_SADSMILE = ":(";
static final String STR_CODE_WINK = ";)";
// use emoticons from http://www.skypeemoticonslist.com
static final String STR_IMG_URL = "http://www.skypeemoticonslist.com/images/";
static final String STR_IMG_NAME_SMILE = "emoticon-0100-smile.png";
static final String STR_IMG_NAME_SADSMILE = "emoticon-0101-sadsmile.png";
static final String STR_IMG_NAME_WINK = "emoticon-0105-wink.png";
static final Hashtable TABLE_URL = new Hashtable();
static final Hashtable TABLE_IMG = new Hashtable();
private static void initCode(String code, String imgFName) {
String tag;
// prepare table for online use
// generate img tag with live url
tag = MessageFormat.format(STR_FRMT_IMG, new Object[] { STR_IMG_URL
+ imgFName });
TABLE_URL.put(code, tag);
// prepare table for offline use
// retrieve image from project resources
try {
EncodedImage img = EncodedImage.getEncodedImageResource(imgFName);
// generate img tag with embedded data url
String dataStr = getDataUrl(img.getData(), img.getMIMEType());
tag = MessageFormat.format(STR_FRMT_IMG, new Object[] { dataStr });
TABLE_IMG.put(code, tag);
} catch (IOException e) {
System.out.println("\n Troubles preparing res for code " + code
+ " \n");
}
}
static {
initCode(STR_CODE_SMILE, STR_IMG_NAME_SMILE);
initCode(STR_CODE_SADSMILE, STR_IMG_NAME_SADSMILE);
initCode(STR_CODE_WINK, STR_IMG_NAME_WINK);
}
boolean mIsOffline = true;
String mChatHistory = "";
BrowserField mBrowserField = new BrowserField();
EditField mTextField = new EditField("Input message: ", "",
INT_MSG_MAX_LEN, Field.USE_ALL_WIDTH);
ButtonField mBtnUserLeft = new ButtonField("Send as Mr. Left",
Field.FIELD_LEFT | ButtonField.CONSUME_CLICK);
ButtonField mBtnUserRight = new ButtonField("Send as Mr. Right",
Field.FIELD_RIGHT | ButtonField.CONSUME_CLICK);
public ChatScreen() {
super(Manager.NO_VERTICAL_SCROLL | Manager.NO_HORIZONTAL_SCROLLBAR);
add(mTextField);
HorizontalFieldManager hfm = new HorizontalFieldManager(
Field.USE_ALL_WIDTH | Field.FIELD_HCENTER);
mBtnUserLeft.setChangeListener(this);
mBtnUserRight.setChangeListener(this);
hfm.add(mBtnUserLeft);
hfm.add(mBtnUserRight);
add(hfm);
VerticalFieldManager vfm = new VerticalFieldManager(Field.USE_ALL_WIDTH
| Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
vfm.add(mBrowserField);
add(vfm);
}
protected void makeMenu(Menu menu, int instance) {
menu.add(new MenuItem(mIsOffline ? "Go Online" : "Go Offline", 0, 0) {
public void run() {
mIsOffline = !mIsOffline;
}
});
super.makeMenu(menu, instance);
}
public void fieldChanged(final Field field, int context) {
if (field == mBtnUserLeft) {
addMessage("Mr. Left");
} else if (field == mBtnUserRight) {
addMessage("Mr. Right");
}
}
private void addMessage(String userName) {
String message = mTextField.getText();
// update message with emoticons
message = replaceCodeWithImg(message, STR_CODE_SMILE);
message = replaceCodeWithImg(message, STR_CODE_SADSMILE);
message = replaceCodeWithImg(message, STR_CODE_WINK);
String timeStr = FRMT_TIME.format(new Date(System.currentTimeMillis()));
String text = MessageFormat.format(STR_FRMT_MSG, new Object[] {
userName, timeStr, message });
mChatHistory = text + mChatHistory;
mTextField.setText("");
// fix IllegalStateException up to
// http://supportforums.blackberry.com/t5/Java-Development/IllegalStateException-at-displayContent-on-browserfield/td-p/1071991
mBrowserField.setFocus();
mBrowserField.displayContent("<html>" + mChatHistory + "</html>", "");
}
private String replaceCodeWithImg(String message, String code) {
Hashtable table = mIsOffline ? TABLE_IMG : TABLE_URL;
int index = message.indexOf(code);
while (index != -1) {
String begin = message.substring(0, index);
String end = message.substring(index + code.length());
String tag = (String) table.get(code);
message = begin + tag + end;
index = message.indexOf(code, index + tag.length());
}
return message;
}
// src taken from http://bfo.com/blog/files/src/DataStreamHandler.java
private static final String getDataUrl(byte[] data, String mimetype)
throws IOException {
final StringBuffer sb = new StringBuffer();
sb.append("data:");
sb.append(mimetype);
sb.append(";base64,");
OutputStream out = new OutputStream() {
public void write(int c) {
sb.append((char) (c & 0xFF));
}
};
Base64OutputStream fout = new Base64OutputStream(out);
fout.write(data);
fout.close();
return sb.toString();
}
}