2012-12-28 25 views
0

我已經搜索了幾天,並終於編譯了足夠的答案來完成我想要的。首先,這似乎是一個經常被問到的問題,但沒有真正回答(至少不是我尋找它的方式)。我想我會分享我的發現,但我還有一個小問題,我想請求幫助。這裏有:TextView可編輯onLongClick - 但一個小問題,當返回按鈕按下

我有一個顯示分數的TextView。它從0開始,在onClick事件中,分數遞增並更新TextView(分數被跟蹤爲字節 - valScore)。

onLongClick:這是挑戰。我希望用戶能夠做一個LongClick來糾正/改變分數。我首先發現了一個只使用EditText元素和OK和CANCEL按鈕的另一個layout.xml文件的解決方案。這是非常繁瑣的改變分數,因爲它涉及LongClick,然後打開對話框,然後你必須點擊EditText元素打開鍵盤,然後輸入值,單擊完成,然後單擊確定。我通過弄清楚如何在對話框打開時自動打開軟件鍵盤來縮短它。但是,您仍然需要點擊完成然後確定。我不喜歡這個動作,所以我繼續搜索。

幾天後,我想出了一些代碼,然後越來越有很多的播放/黑客左右,我想出了以下解決方案:

// set the onLongClickListener for tvScoreHome 
    tvScoreHome.setOnLongClickListener(new View.OnLongClickListener() { 
     @Override 
     public boolean onLongClick(View v) { 
      tvScoreHome.setInputType(InputType.TYPE_CLASS_NUMBER); 
      tvScoreHome.setFocusable(true); 
      tvScoreHome.setFocusableInTouchMode(true); 
      tvScoreHome.requestFocus(); 

      InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE); 
      imm.showSoftInput(tvScoreHome, InputMethodManager.SHOW_FORCED); 

      tvScoreHome.setText(""); 

      tvScoreHome.setOnEditorActionListener(new TextView.OnEditorActionListener() { 

       @Override 
       public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 
        if (actionId == EditorInfo.IME_ACTION_DONE) { 
         valScoreHome = Byte.valueOf(tvScoreHome.getText().toString()); 

         // This part will hide the keyboard after input 
         InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE); 
         imm.hideSoftInputFromWindow(v.getWindowToken(), 0); 

         tvScoreHome.setFocusable(false); 
         tvScoreHome.setFocusableInTouchMode(false); 
         tvScoreHome.setText(Byte.toString(valScoreHome)); 

         return true; 
        } 

        return false; 
       } 

      }); 

      return true; 
     } 
    }); 

這工作正是我想要的。用戶執行LongClick鍵盤打開後,用戶輸入新值並單擊完成。 TextView被更新並且它工作的很棒!

如果用戶改變主意並點擊設備上的BACK按鈕,則會出現問題。鍵盤關閉(GOOD),但焦點仍然在TextView上,而不是像按下DONE按鈕時那樣去除焦點。因此,如果您在每次點擊後取消某個更改,則會導致鍵盤再次打開,而不僅僅是增加分數 - 直到您實際在鍵盤中輸入值並單擊完成(然後常規行爲再次執行。如果按下了BACK按鈕,則將setFocusableInTouchMode設置爲FALSE

另一個問題是,如果輸入了不同的值,即使按下BACK按鈕,setText()方法也會執行。即使valScoreHome未更新, TextView的變化。在它轉到正確的號碼再在下一個遞增,但如果按下BACK按鈕的setText()不應該執行。

有人可以幫我想出解決辦法嗎?

回答

2

這兩個問題都可以通過繼承TextView進行處理。

按下關閉鍵盤的後退按鈕將被重寫onKeyPreIme處理。

爲避免在用戶關閉鍵盤時更新文本,得分值將保存在變量mScore中,但前提是TextView當前不可對焦。這意味着,TextView「記住」得分的當前值,即用戶輸入的而不是。當用戶關閉鍵盤時,文本將恢復爲保存的值。

public class ScoreTextView extends TextView { 
    private CharSequence mScore; 

    public ScoreTextView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public void setText(CharSequence text, BufferType type) { 
     if (!isFocusable()) { 
      mScore = text; 
     } 
     super.setText(text, type); 
    } 

    @Override 
    public boolean onKeyPreIme(int keyCode, KeyEvent event) { 
     if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { 
      setFocusable(false); 
      setFocusableInTouchMode(false); 
      setText(mScore); 
     } 
     return super.onKeyPreIme(keyCode, event); 
    } 
} 
+0

感謝您使用此解決方案。我想我可以擴展TextView,但我沒有辦法知道如何去做。問題:是否有方法可以將onClick,onLongClick和onEditorAction監聽器嵌入到View中,因此它是默認行爲?或者,這仍然需要像我一樣留下來嗎? –

+0

應該可以將功能集成到自定義的「TextView」中。然而,在我看來,如果你保持它的分離,它就更加清楚了,因爲這與你使用默認的'TextView'完成的方式是一樣的。 –

+0

好吧......我只是在想,將它作爲默認行爲是有益的,因爲ScoreView字段是我在那裏有那種行爲的唯一原因。 –