2012-07-30 29 views
1

在android中,我可以这样做,用户可以在editview之外单击来隐藏虚拟键盘。如何在触摸编辑区时自动隐藏虚拟键盘?

@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); 
    } 
} 
} 

这EditField中会隐藏键盘,如果你点击其它字段,但不anypoint。

+0

所以,我刚刚发布了一个关于隐藏键盘的答案。但是,在再次阅读您的问题之后,我意识到对您而言,更难的问题可能是检测到“EditField”外**的触摸**。你可以发布一些代码来显示你的EditField是如何创建的吗?它被放入一个'VerticalFieldManager'中?一个自定义的'管理器'子类? – Nate 2012-07-30 09:52:30

+1

当在“EditField”之外进行触摸时,它将失去焦点。重写'EditField'的'onUnfocus'方法可能会有所帮助。但是,如果不可调焦的项目被触及,那么'EditField'不会失去它的焦点。 – Rupak 2012-07-30 10:07:39

+0

Alan,请参阅我的更新...我认为它可以覆盖包含'Custom_EditField'的'Manager'中的'touchEvent()',而不是重写'unFocus()',这不起作用。 – Nate 2012-07-30 10:36:20

回答

1

我有用于显示或隐藏键盘的此实用程序代码。这应该适用于OS 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)。

+0

我刚刚更新了'editfield' – 2012-07-30 09:55:29

+0

@AlanLai,太好了。感谢更新。看起来你的代码几乎完成了我的建议。所以,看起来问题在于,如果用户在“EditField”之外点击,而不在另一个字段中点击,那就是点击不可聚焦**的东西。所以,焦点实际上并没有转移。在这种情况下,包含管理器可能需要处理它。让我看看这个,我会看看我是否有这样的工作... – Nate 2012-07-30 10:02:54

+0

我认为我们在同一时间完成。 – 2012-07-30 10:33:20