2012-07-30 30 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