我想在android中创建我自己的表情符号键盘。用户应该能够选择这个键盘作为他的android手机的输入方法。
我试着创建了它,我可以在我的应用程序中使用它,但我不知道如何将其作为一种输入法,所以我手机中的所有其他应用程序都可以使用这个键盘。我在某个地方读到,我必须为此创建一个服务,以便它与输入服务绑定。除此之外,我无法理解剩下的内容。
以下是我所做的。虽然这与我想做的不同,但这是一个开始,不知道如何进一步。
public class MainActivity extends FragmentActivity implements EmoticonsGridAdapter.KeyClickListener {
private static final int NO_OF_EMOTICONS = 100;
private ListView chatList;
private View popUpView;
private ArrayList<Spanned> chats;
private ChatListAdapter mAdapter;
private LinearLayout emoticonsCover;
private PopupWindow popupWindow;
private int keyboardHeight;
private EditText content;
private LinearLayout parentLayout;
private boolean isKeyBoardVisible;
private Bitmap[] emoticons;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chatList = (ListView) findViewById(R.id.chat_list);
parentLayout = (LinearLayout) findViewById(R.id.list_parent);
emoticonsCover = (LinearLayout) findViewById(R.id.footer_for_emoticons);
popUpView = getLayoutInflater().inflate(R.layout.emoticons_popup, null);
// Setting adapter for chat list
chats = new ArrayList<Spanned>();
mAdapter = new ChatListAdapter(getApplicationContext(), chats);
chatList.setAdapter(mAdapter);
chatList.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (popupWindow.isShowing())
popupWindow.dismiss();
return false;
}
});
// Defining default height of keyboard which is equal to 230 dip
final float popUpheight = getResources().getDimension(
R.dimen.keyboard_height);
changeKeyboardHeight((int) popUpheight);
// Showing and Dismissing pop up on clicking emoticons button
ImageView emoticonsButton = (ImageView) findViewById(R.id.emoticons_button);
emoticonsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!popupWindow.isShowing()) {
popupWindow.setHeight((int) (keyboardHeight));
if (isKeyBoardVisible) {
emoticonsCover.setVisibility(LinearLayout.GONE);
} else {
emoticonsCover.setVisibility(LinearLayout.VISIBLE);
}
popupWindow.showAtLocation(parentLayout, Gravity.BOTTOM, 0, 0);
} else {
popupWindow.dismiss();
}
}
});
readEmoticons();
enablePopUpView();
checkKeyboardHeight(parentLayout);
enableFooterView();
}
/**
* Reading all emoticons in local cache
*/
private void readEmoticons () {
emoticons = new Bitmap[NO_OF_EMOTICONS];
for (short i = 0; i < NO_OF_EMOTICONS; i++) {
emoticons[i] = getImage((i+1) + ".png");
}
}
/**
* Enabling all content in footer i.e. post window
*/
private void enableFooterView() {
content = (EditText) findViewById(R.id.chat_content);
content.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (popupWindow.isShowing()) {
popupWindow.dismiss();
}
}
});
final Button postButton = (Button) findViewById(R.id.post_button);
postButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (content.getText().toString().length() > 0) {
Spanned sp = content.getText();
chats.add(sp);
content.setText("");
mAdapter.notifyDataSetChanged();
}
}
});
}
/**
* Overriding onKeyDown for dismissing keyboard on key down
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (popupWindow.isShowing()) {
popupWindow.dismiss();
return false;
} else {
return super.onKeyDown(keyCode, event);
}
}
/**
* Checking keyboard height and keyboard visibility
*/
int previousHeightDiffrence = 0;
private void checkKeyboardHeight(final View parentLayout) {
parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
parentLayout.getWindowVisibleDisplayFrame(r);
int screenHeight = parentLayout.getRootView()
.getHeight();
int heightDifference = screenHeight - (r.bottom);
if (previousHeightDiffrence - heightDifference > 50) {
popupWindow.dismiss();
}
previousHeightDiffrence = heightDifference;
if (heightDifference > 100) {
isKeyBoardVisible = true;
changeKeyboardHeight(heightDifference);
} else {
isKeyBoardVisible = false;
}
}
});
}
/**
* change height of emoticons keyboard according to height of actual
* keyboard
*
* @param height
* minimum height by which we can make sure actual keyboard is
* open or not
*/
private void changeKeyboardHeight(int height) {
if (height > 100) {
keyboardHeight = height;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, keyboardHeight);
emoticonsCover.setLayoutParams(params);
}
}
/**
* Defining all components of emoticons keyboard
*/
private void enablePopUpView() {
ViewPager pager = (ViewPager) popUpView.findViewById(R.id.emoticons_pager);
pager.setOffscreenPageLimit(3);
pager.setBackgroundColor(Color.WHITE);
ArrayList<String> paths = new ArrayList<String>();
for (short i = 1; i <= NO_OF_EMOTICONS; i++) {
paths.add(i + ".png");
}
EmoticonsPagerAdapter adapter = new EmoticonsPagerAdapter(MainActivity.this, paths, this);
pager.setAdapter(adapter);
// Creating a pop window for emoticons keyboard
popupWindow = new PopupWindow(popUpView, LayoutParams.MATCH_PARENT,
(int) keyboardHeight, false);
/*TextView backSpace = (TextView) popUpView.findViewById(R.id.back);
backSpace.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL);
content.dispatchKeyEvent(event);
}
});*/
popupWindow.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
emoticonsCover.setVisibility(LinearLayout.GONE);
}
});
}
/**
* For loading smileys from assets
*/
private Bitmap getImage(String path) {
AssetManager mngr = getAssets();
InputStream in = null;
try {
in = mngr.open("emoticons/" + path);
} catch (Exception e) {
e.printStackTrace();
}
Bitmap temp = BitmapFactory.decodeStream(in, null, null);
return temp;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
@Override
public void keyClickedIndex(final String index) {
ImageGetter imageGetter = new ImageGetter() {
public Drawable getDrawable(String source) {
StringTokenizer st = new StringTokenizer(index, ".");
Drawable d = new BitmapDrawable(getResources(),emoticons[Integer.parseInt(st.nextToken()) - 1]);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
return d;
}
};
Spanned cs = Html.fromHtml("<img src ='"+ index +"'/>", imageGetter, null);
int cursorPosition = content.getSelectionStart();
content.getText().insert(cursorPosition, cs);
}
}
编辑:这是我实现的自定义键盘的代码,但我无法找到如何将表情符号添加到该键盘。
public class SimpleIME extends InputMethodService
implements KeyboardView.OnKeyboardActionListener {
private KeyboardView kv;
private Keyboard keyboard;
private View popUpView;
private boolean caps = false;
@Override
public View onCreateInputView() {
kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null);
keyboard = new Keyboard(this, R.xml.qwerty);
kv.setKeyboard(keyboard);
kv.setOnKeyboardActionListener(this);
kv.invalidateAllKeys();
popUpView = getLayoutInflater().inflate(R.layout.emoticons_popup, null);
return kv;
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
InputConnection ic = getCurrentInputConnection();
playClick(primaryCode);
switch(primaryCode){
case Keyboard.KEYCODE_DELETE :
ic.deleteSurroundingText(1, 0);
break;
case Keyboard.KEYCODE_SHIFT:
caps = !caps;
keyboard.setShifted(caps);
kv.invalidateAllKeys();
break;
case Keyboard.KEYCODE_DONE:
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
break;
case -80 :
Log.d("smiley", "smiley pressed");
break;
default:
char code = (char)primaryCode;
if(Character.isLetter(code) && caps){
code = Character.toUpperCase(code);
}
ic.commitText(String.valueOf(code),1);
}
}
private void playClick(int keyCode){
AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
switch(keyCode){
case 32:
am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
break;
case Keyboard.KEYCODE_DONE:
case 10:
am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
break;
case Keyboard.KEYCODE_DELETE:
am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
break;
default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
}
}
@Override
public void onPress(int primaryCode) {
}
@Override
public void onRelease(int primaryCode) {
}
@Override
public void onText(CharSequence text) {
}
@Override
public void swipeDown() {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeUp() {
}
}
编辑:我们可以从图片列表中复制一张图片并粘贴到键盘打开的地方吗??
我发现表情符号键盘的最佳实现是滑动表情键盘这是一个非常好的实现,可能有一些多余的代码,但对于理解如何实现不适合普通"按钮到文本"键盘的键盘仍然非常好。
更新
好吧,经过两个项目的大量重构,我现在已经能够成功地将滑动表情板集成到我自己的项目8Vim中。
从本质上讲,你为表情符号键盘所做的就是创建一个键盘大小的视图,然后用与表情符号对应的PNG文件填充该视图。每个图像就像一个按钮,并将适当的表情符号传递给inputConnection。
更新2
我扩展了滑动表情板,创建了一个更干净的版本,应该更容易理解。看看我的表情-键盘