2015-11-30 4 views
2

Я хочу создать свою собственную клавиатуру emoji в Android. Пользователь должен иметь возможность выбрать эту клавиатуру в качестве метода ввода для своего телефона Android.Пользовательская клавиатура Emoji в 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: Можно ли скопировать изображение из списка изображений и вставить его там, где клавиатура открыта ??

+0

проверить эту ссылку http://code.tutsplus.com/tutorials/create-a-custom-keyboard-on-android--cms-22615 – rajahsekar

+0

Создание редактора настраиваемых методов ввода [документация] (http://developer.android.com/guide/topics/text/creating-input-method.html). – CommonsWare

+0

@rajahsekar Я следую приведенной ниже ссылке. Будет обновляться, если я попаду в какую-то другую проблему. –

ответ

1

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

UPDATE

Хорошо, я сейчас был в состоянии успешно смогли интегрировать sliding emoji-keyboard в свой собственный проект 8Vim после того, как много рефакторинга в обоих проектах.

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

UPDATE 2

я продлил sliding emoji-keyboard и создали более чистый вариант, который должен быть легче понять. Взгляните на мой emoji-keyboard

+0

Я хотел попробовать 8vim, но он сбой при запуске, вызванный: java.lang.NullPointerException: попытка вызвать виртуальный метод 'java.lang.String android.content.Context.getString (int)' на нулевой ссылке объекта at inc.flide.eightvim.Setting. (Setting.java:11), как вы реализовали emojis? с popupwindow? – yanivtwin

+0

@yanivtwin: Я исправил проблему, когда открытие настроек отключается, если клавиатура не открывается в первую очередь. Вы можете попробовать это сейчас. – flide

+0

спасибо, я попробую еще раз, вы используете popupwindow для реализации? или клавиатура xml? – yanivtwin

Смежные вопросы