Как автоматически скрывать виртуальную клавиатуру при касании вне поля редактирования?

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

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    View v = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

    if (v instanceof EditText) {
        View w = getCurrentFocus();
        int scrcoords[] = new int[2];
        w.getLocationOnScreen(scrcoords);
        float x = event.getRawX() + w.getLeft() - scrcoords[0];
        float y = event.getRawY() + w.getTop() - scrcoords[1];

        if (event.getAction() == MotionEvent.ACTION_UP
                && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w
                        .getBottom())) {

            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus()
                    .getWindowToken(), 0);
        }
    }
    return ret;
}

А в ежевике? Я хочу баллотироваться только за VirtualKeyboard.isSupported().

Обновить

public class Custom_EditField extends EditField {
private int width, row, color;
private MainScreen mainscreen;

Custom_EditField(long style, int width, int row, MainScreen mainscreen) {
    super(style);
    this.width = width;
    this.row = row;
    this.mainscreen = mainscreen;
}

public int getPreferredHeight() {
    return Font.getDefault().getHeight() * row;
}

public int getPreferredWidth() {
    return width;
}

protected void onFocus(int direction) {
    if (VirtualKeyboard.isSupported())
        mainscreen.getVirtualKeyboard().setVisibility(
                VirtualKeyboard.SHOW_FORCE);
    invalidate();
    super.onFocus(direction);
}

protected void onUnfocus() {
    if (VirtualKeyboard.isSupported())
        mainscreen.getVirtualKeyboard().setVisibility(
                VirtualKeyboard.HIDE_FORCE);
    invalidate();
    super.onUnfocus();
}

public boolean isFocusable() {
    return true;
}

protected void layout(int maxWidth, int maxHeight) {
    super.layout(maxWidth,
            Math.min(maxHeight, Font.getDefault().getHeight() * row));
    super.setExtent(maxWidth,
            Math.min(maxHeight, Font.getDefault().getHeight() * row));
}

protected void paint(Graphics graphics) {
    int rectHeight = getPreferredHeight();
    int rectWidth = getPreferredWidth();
    try {
        color = Color.BLACK;
        graphics.setColor(color);
        graphics.drawRect(0, 0, rectWidth, rectHeight);
        super.paint(graphics);
    } finally {
        graphics.setColor(color);
    }
}
}

Это поле редактирования скроет клавиатуру, если вы нажмете на другое поле, но не на любую точку.


person Alan Lai    schedule 30.07.2012    source источник
comment
Итак, я только что опубликовал ответ о скрытии клавиатуры. но, прочитав ваш вопрос еще раз, я понимаю, что более сложной проблемой для вас, вероятно, является обнаружение касания снаружи EditField. Можете ли вы опубликовать часть кода, показывающего, как создается ваш EditField? это помещено в VerticalFieldManager? пользовательский подкласс Manager?   -  person Nate    schedule 30.07.2012
comment
При касании за пределами EditField фокус теряется. Переопределение метода onUnfocus для EditField может быть полезным. Но EditField не потеряет фокус, если коснуться нефокусируемого элемента.   -  person Rupak    schedule 30.07.2012
comment
Алан, посмотри мое обновление ... Я думаю, будет работать переопределение touchEvent() в Manager, содержащем ваш Custom_EditField, вместо переопределения unFocus(), что не совсем работает.   -  person Nate    schedule 30.07.2012


Ответы (1)


У меня есть этот код утилиты для отображения или скрытия клавиатуры. Это должно быть действительно для ОС 4.7 и выше. Дайте мне знать, если вам нужна поддержка более ранних версий ОС.

   /** Hides the virtual keyboard, if there is one showing. */
   public static void hideKeyboard() {
      VirtualKeyboard kb = UiApplication.getUiApplication().getActiveScreen().getVirtualKeyboard();
      if (kb != null) {
         kb.setVisibility(VirtualKeyboard.HIDE);
      }
   }

   /** @return TRUE if the virtual keyboard is hidden, or not supported */
   public static boolean isKeyboardHidden() {
      if (VirtualKeyboard.isSupported()) {
         VirtualKeyboard kb = UiApplication.getUiApplication().getActiveScreen().getVirtualKeyboard();
         if (kb != null) {
            int visibility = kb.getVisibility();
            return ((visibility == VirtualKeyboard.HIDE)
                    || (visibility == VirtualKeyboard.HIDE_FORCE));
         }
      }
      return true;
   }

Обратите внимание, что я сделал эти static функции. Итак, если вы поместите их в класс с именем UiUtilities, вы будете называть их так:

 if (!UiUtilities.isKeyboardHidden()) {
     UiUtilities.hideKeyboard();
 }

Что касается где запускать этот код, я рекомендую следующее: вместо переопределения onUnfocus(). Я не уверен, что это самый простой или самый эффективный способ решить проблему (поэтому я приветствую другие ответы!), но я думаю, что это сработает.

Пару ответов назад я говорил вам, что обычно вы не должны не переопределять метод touchEvent() в своем коде. Для таких вещей, как обычные кнопки, я думаю, это верно. Это может быть одним из примеров, когда вам нужно. У вас должен быть Manager (или VerticalFielManager, или аналогичный), который представляет экран, на котором находится этот EditField. В этом менеджере реализуйте метод touchEvent() следующим образом:

import net.rim.device.api.ui.TouchEvent;

   protected boolean touchEvent(TouchEvent event) {
      // We take action when the user completes a click (a.k.a. unclick)
      int eventCode = event.getEvent();
      if ((eventCode == TouchEvent.UNCLICK) || (eventCode == TouchEvent.DOWN)) {
         // Get the touch location, within this Manager
         int x = event.getX(1);
         int y = event.getY(1);

         if ((x >= 0) && (y >= 0) && (x < getWidth()) && (y < getHeight())) {
            int field = getFieldAtLocation(x, y);
            if (field >= 0) {
               // Let event propagate to child field
               return super.touchEvent(event);
            } else {
               if (eventCode == TouchEvent.UNCLICK) {
                  // A completed click anywhere else in this manager should dismiss the keyboard
                  UiUtilities.hideKeyboard();
               } else {
                  // This is just a soft touch (TouchEvent.DOWN), without full click
                  setFocus();
               }
               // Consume the event
               return true;
            }
         }
      }
      // Event wasn't for us, let superclass handle in default manner
      return super.touchEvent(event);
   }

Попробуй это. Возможно, вам придется изменить мою логику в зависимости от того, хотите ли вы скрыть клавиатуру для полного щелчка или простого касания вниз (если вы новичок в BlackBerry, может быть неясно, в чем разница между ними). Но, я думаю, это должно вас сблизить(r).

person Nate    schedule 30.07.2012
comment
@AlanLai, отлично. Спасибо за обновления. Похоже, ваш код делает почти то, что я предложил. Таким образом, похоже, проблема в том, что если пользователь щелкает за пределами EditField, но не в другом поле, это щелчок по чему-то, что не фокусируется. Таким образом, фокус на самом деле не переносится. В этом случае содержащему менеджеру может потребоваться обработать его. Позвольте мне взглянуть на это, и я посмотрю, есть ли у меня что-нибудь, что работает так же... - person Nate; 30.07.2012
comment
@AlanLai, да, можно. как я сказал выше, он должен быть в классе Manager, а не в классе EditField. Менеджер — это место, где существует getFieldAtLocation(). - person Nate; 30.07.2012