Пользовательская клавиатура Emoji в Android с изображениями

Я хочу создать свою собственную клавиатуру emoji в 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);

}

}

EDIT: это код для пользовательской клавиатуры, которую я внедрил, но не могу найти, как добавить смайлики на эту клавиатуру.

  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() {
    }

}

EDIT: Можем ли мы скопировать изображение из списка изображений и вставить его туда, где открыта клавиатура??


person Vivek Mishra    schedule 30.11.2015    source источник
comment
проверьте эту ссылку code.tutsplus.com/ учебники/   -  person rajahsekar    schedule 30.11.2015
comment
Создание редактора пользовательского метода ввода описано в документации.   -  person CommonsWare    schedule 30.11.2015
comment
@rajahsekar Я перехожу по предоставленной вами ссылке. Будет обновляться, если я столкнусь с какой-то другой проблемой   -  person Vivek Mishra    schedule 30.11.2015
comment
@rajahsekar с помощью учебника я могу создать собственную клавиатуру. Но я тоже хочу добавить эмодзи на клавиатуру. Как это сделать??   -  person Vivek Mishra    schedule 30.11.2015
comment
попробуйте использовать юникоды для смайлов   -  person rajahsekar    schedule 30.11.2015
comment
Я должен использовать изображения, что является обязательным   -  person Vivek Mishra    schedule 30.11.2015
comment
какой должен быть код для значка смайлика??   -  person Vivek Mishra    schedule 30.11.2015


Ответы (1)


Лучшей реализацией клавиатуры с эмодзи, которую я нашел, была скользящая клавиатура с эмодзи. реализация, возможно, с некоторым избыточным кодом, но все же действительно полезная для понимания того, как реализовать клавиатуры, которые не подходят к обычным клавиатурам «кнопка-к-тексту».

ОБНОВЛЕНИЕ

Итак, теперь мне удалось успешно интегрировать скользящую клавиатуру с эмодзи. в свой собственный проект 8Vim после большого рефакторинга в обоих проектах.

По сути, все, что вы делаете для клавиатуры emoji, — это создаете представление размера клавиатуры, а затем заполняете это представление файлами PNG, соответствующими emoji. каждое изображение действует как кнопка и доставляет соответствующие смайлики в inputConnection.

ОБНОВЛЕНИЕ 2

Я расширил скользящую клавиатуру с эмодзи и создал более чистую версию, которая должна быть более понятной. . Взгляните на мою emoji-клавиатуру.

person flide    schedule 30.11.2016
comment
Я хотел попробовать 8vim, но он вылетает при запуске. Причина: java.lang.NullPointerException: попытка вызвать виртуальный метод 'java.lang.String android.content.Context.getString(int)' для ссылки на нулевой объект в inc. flide.eightvim.Setting.‹clinit›(Setting.java:11) , как вы реализовали эмодзи? с всплывающим окном? - person yanivtwin; 29.12.2016
comment
@yanivtwin: я исправил проблему, из-за которой открытие настроек приводило к сбою, если сначала не была открыта клавиатура. Вы можете попробовать прямо сейчас. - person flide; 31.12.2016
comment
спасибо, я попробую еще раз, вы используете popupwindow для реализации? или клавиатура xml? - person yanivtwin; 31.12.2016
comment
На самом деле я новичок в Android и не совсем понимаю термин popupwindow в целом, но, насколько я понимаю, это не всплывающее окно и не клавиатура xml. Это просто другой вид с высотой клавиатуры. - person flide; 01.01.2017