EditText:允许滚动但禁止选择

EditText: allow scrolling but disable selecting

我正在尝试创建一个 EditText,其中无法选择任何文本,但用户仍然可以浏览。 为了归档第一个函数,a 创建了一个自定义 OnTouchListener 并且只响应 ACTION_DOWN 事件,如下所示:

View.OnTouchListener otl = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    scroll_down_x = event.getX();
                    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);

但这也会禁用滚动。然后我尝试 reimplement ACTION_MOVE 事件

             case MotionEvent.ACTION_MOVE:
                    String input = ((EditText)v).getText().toString();
                    float width = ((EditText) v).getPaint().measureText(input);
                    float cwidth = ((EditText)v).getWidth();
                    //only scroll when the text is too long for the control
                    if (width >cwidth )
                    {
                        layout = ((EditText) v).getLayout();

                        x = event.getX() - scroll_down_x;
                        offset = layout.getOffsetForHorizontal(0, x);
                        mText.scrollBy((int) x, mText.getScrollY());
                    }
                    return true;

但这根本不起作用 - 滚动不是很流畅,也很不准确。 那么,我该如何改进此 "scrolling" 代码或解决无法选择文本但用户仍可以滚动的 EditText 问题?

编辑:此外,用户应该仍然能够更改光标位置。

如果你想在不编辑的情况下显示任何信息,你可以使用 TextView(参见 post )而不是 Edittext,但如果你想要 EditText,请尝试使用下面的代码:

<EditText
    android:id="@+id/edittext"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:cursorVisible="false"
    android:focusable="false"
    android:inputType="textMultiLine"
    android:scrollbars="vertical"
    android:text="Long Text here" />

如果您想启用用户版,请使用此代码:

EditText edittext = (EditText) findViewById(R.id.edittext);

edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    public void onDestroyActionMode(ActionMode mode) {
    }

    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
    }
});
}

经过更多的试验,我终于想到了一些可行的方法。

final EditText mText = (EditText) findViewById(R.id.input);
View.OnTouchListener otl = new View.OnTouchListener() {
   private float scroll_down_x;
   final static int right_border = 20;

   @Override
   public boolean onTouch(View v, MotionEvent event) {
     switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            scroll_down_x = event.getX();
            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;
        case MotionEvent.ACTION_MOVE:
            String input = ((EditText)v).getText().toString();
            float width = ((EditText) v).getPaint().measureText(input);
            float cwidth = ((EditText)v).getWidth();

            //only scroll when the text is too long for the control
            if (width >= cwidth) {
                layout = ((EditText) v).getLayout();
                x = event.getX() - scroll_down_x;
                scroll_down_x = event.getX();
                //do not scroll over the left border
                if (((EditText) v).getScrollX() + (int)x >= 0) {
                    //do not scroll over the right border
                    if ((int)cwidth+((EditText) v).getScrollX()-right_border + x <= (int)width)
                    {
                        offset = layout.getOffsetForHorizontal(0, x);
                        mText.scrollBy((int) x, 0);
                    }
                    else
                    {
                        mText.scrollTo((int)(width-cwidth+right_border), 0);
                    }
                }
                else
                {
                    mText.scrollTo(0, 0);
                }
            }
       }
       return true;
   }
};

此代码允许用户设置光标并滚动一行 EditText 并且它会隐藏系统键盘。 我希望它能帮助别人。如果没有更方便的方法来存档此行为,我仍然很感兴趣。