9

CCPメニューとキーボードを表示するロングクリックのデフォルトの動作とは対照的に、タッチ+ドラッグでテキストを選択し、キーボードを上げないカスタムテキストインターフェイスを実装したいと考えています。私の理解は、このアプローチが必要であることを示唆しています。

onTouchEvent(event){
  case touch_down:
    get START text position

  case drag
    get END text position
    set selection range from START to END
}

getSelectStart()や範囲を設定するためのさまざまなメソッドなどについてはすべて知りましたが、タッチイベントgetX()およびgetY()に基づいてテキストの位置を取得する方法がわかりません。これを行う方法はありますか?他のオフィスアプリで必要な動作を見てきました。

また、手動で要求されるまでキーボードの表示を停止するにはどうすればよいですか?

4

5 に答える 5

12

「mText.setInputType(InputType.TYPE_NULL)」はソフトキーボードを抑制しますが、Android3.0以降ではEditTextボックスのカーソルの点滅も無効にします。onTouchListenerをコーディングし、trueを返してキーボードを無効にし、モーションイベントからタッチ位置を取得してカーソルを正しい場所に設定する必要がありました。これをACTION_MOVEモーションイベントで使用して、ドラッグするテキストを選択できる場合があります。

これが私が使用したコードです:

  mText = (EditText) findViewById(R.id.editText1);
  OnTouchListener otl = new OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent event) {
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
          Layout layout = ((EditText) v).getLayout();
          float x = event.getX() + mText.getScrollX();
          int offset = layout.getOffsetForHorizontal(0, x);
          if(offset>0)
              if(x>layout.getLineMax(0))
                  mText.setSelection(offset);     // touch was at end of text
              else
                  mText.setSelection(offset - 1);
          break;
          }
      return true;
      }
  };
  mText.setOnTouchListener(otl);
于 2013-01-06T18:09:50.843 に答える
11

開始コードを共有してくれたWaineKailに感謝しますが、イベントの「x」軸のみを処理しました。複数行のEditTextの場合は、次のことも行う必要があります。

1-垂直位置(y)を計算します
。2-垂直位置による線のオフセットを
取得します。3-線と水平位置を使用してテキストオフセットを取得します。

EditText et = (EditText) findViewById(R.id.editText1);

long offset = -1; //text position will be corrected when touching.

et.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
      case MotionEvent.ACTION_UP:
          Layout layout = ((EditText) v).getLayout();
          float x = event.getX() + et.getScrollX();
          float y = event.getY() + et.getScrollY();            
          int line = layout.getLineForVertical((int) y);                      

 // Here is what you wanted:

          offset = layout.getOffsetForHorizontal( line,  x);

          break;
        }
    return false;
}
});
于 2013-04-24T04:44:10.330 に答える
6

私も同じ問題に直面しています。そして、「int offset = layout.getOffsetForHorizo​​ntal(0、x);」を使おうとすると ウェイン・ケイルが言ったように、このラインでもNPEを獲得しました。だから私は試し、最後に次のように書きます:

mText = (EditText) findViewById(R.id.editText1);
OnTouchListener otl = new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      EditText editText = (EditText) v;
      float x = event.getX();
      float y = event.getY();
      int touchPosition = editText.getOffsetForPosition(x, y);
      if (touchPosition>0){
          editText.setSelection(touchPosition);
      }
      return true;
    }
};
mText.setOnTouchListener(otl); 
于 2015-09-10T08:30:51.763 に答える
2

私のアプリケーションでは、タッチリスナー内の位置を取得する必要がありましたが、上記の解決策では正確な位置がわからないようです。私の場合、テキストカーソルに対して1〜2文字ずれていることがよくあります。以下のコードはこれを解決します。これを機能させるための鍵は、post()を使用して、カーソル位置が更新されるまでコードを延期することです。したがって、私が取得する位置はEditTextの位置と一致することが保証されており、コードも単純です。

setOnTouchListener(new OnTouchListener()
    {
    @Override
    public boolean onTouch(View view, MotionEvent event)
        {
        if(event.getAction()==MotionEvent.ACTION_UP)
            {
            //At this point the selection has not been updated. So post an
            //event at the end of the event queue to check where cursor
            //has been moved
            post(new Runnable()
                {
                public void run()
                    {
                    Editable sb=getText();
                    int currentPos=getSelectionStart();
                    //TODO
                    }
                });
            }
        return false;
        }
    });
于 2013-09-20T14:32:00.087 に答える
0

EditTextでは、onTouchイベントが2回呼び出されます:ACTION_DOWNとACTION_UPの場合。これが、getLayoutがnullになる理由です。ニーズの検証と処理を含む、機能するコードをここに投稿します

@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View view, MotionEvent motionEvent) {
    final EditText editText = (EditText) view;
    final int editTextSelectionStart = editText.getSelectionStart();
    final int editTextSelectionEnd = editText.getSelectionEnd();
    final Layout layout = editText.getLayout();
    final int inType = editText.getInputType(); // Backup the input type.
    editText.setInputType(InputType.TYPE_NULL); // Disable standard keyboard.
    editText.onTouchEvent(motionEvent); // Call native handler.
    editText.setInputType(inType);// Restore input type.

    switch (motionEvent.getAction()) {
        case MotionEvent.ACTION_DOWN:
            float x = motionEvent.getX() + editText.getScrollX();
            if (layout != null) {
                int offset = layout.getOffsetForHorizontal(0, x);
                if (offset > 0) {
                    if (x > layout.getLineMax(0)) {
                        editText.setSelection(offset);
                    } else {
                        editText.setSelection(offset - 1);
                    }
                }
            }
            break;
        case MotionEvent.ACTION_UP:
            editText.setSelection(editTextSelectionStart, editTextSelectionEnd);
        break;
    }

    return true; // Consume touch event.
}
于 2020-10-02T19:14:28.247 に答える