97

我想要一个 EditText ,它在按下时创建一个 DatePicker 。所以我写了以下代码:

    mEditInit = (EditText) findViewById(R.id.date_init);
    mEditInit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showDialog(DATEINIT_DIALOG);
        }

    });

但是当我按下 EditText 时,动作是典型的:等待输入文本的光标而不是显示我想要的对话框。

4

15 回答 15

137

当 EditText 获得焦点时,键盘似乎弹出。为防止这种情况,请将 focusable 设置为 false:

<EditText
    ...
    android:focusable="false"
    ... />

这种行为可能因不同制造商的 Android OS 风格而异,但在我测试过的设备上,我发现这已经足够了。如果键盘仍然弹出,使用提示而不是文本似乎也有帮助:

myEditText.setText("My text");    // instead of this...
myEditText.setHint("My text");    // try this

完成此操作后,您的点击监听器应该可以按需要工作:

myEditText.setOnClickListener(new OnClickListener() {...});
于 2011-05-15T17:00:54.033 回答
65

通常,您希望最大程度地兼容EditText的正常行为。

所以你不应该使用android:focusable="false"是的,视图将不再是可聚焦的,这看起来很糟糕。例如,背景可绘制对象将不再显示其“按下”状态。

你应该做的是:

myEditText.setInputType(InputType.TYPE_NULL);
myEditText.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // showMyDialog();
    }
});
myEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            // showMyDialog();
        }
    }
});

通过将输入类型设置为TYPE_NULL,可以防止弹出软件键盘。

通过设置OnClickListenerand OnFocusChangeListener,您可以确保您的对话框在用户点击该EditText字段时始终打开,无论是在获得焦点(第一次点击)时还是在后续点击时。

仅仅设置android:inputType="none"orsetInputType(InputType.TYPE_NULL)并不总是足够的。对于某些设备,您也应该android:editable="false"在 XML 中设置,尽管它已被弃用。如果它不再起作用,它将被忽略(因为所有不受支持的 XML 属性)。

于 2013-09-08T06:09:21.533 回答
31

我有同样的问题。代码很好,但请确保将 EditText 的可聚焦值更改为 false。

<EditText
android:id="@+id/date"
android:focusable="false"/>

我希望这可以帮助遇到类似问题的任何人!

于 2012-01-19T11:19:38.060 回答
28

默认工作EditText:第一次单击它会聚焦,第二次单击它会处理onClickListener,因此您需要禁用焦点。然后在第一次单击onClickListener将句柄。

为此,您需要将此android:focusableInTouchMode="false"属性添加到您的EditText. 而已!

像这样的东西:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />
于 2017-05-04T07:17:49.503 回答
17

这是我实施的解决方案

mPickDate.setOnKeyListener(new View.OnKeyListener() {

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        showDialog(DATE_DIALOG_ID);
        return false;
    }
});

或者

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        showDialog(DATE_DIALOG_ID);

    }
});

自己看差异。问题是因为(如 RickNotFred 所说)TextView 通过 DatePicker 显示日期和编辑。TextEdit 不用于其主要目的。如果要重新弹出 DatePicker,则需要输入 delete(第一种情况)或 de focus(第二种情况)。

射线

于 2010-11-22T10:30:24.530 回答
13

If you use OnClick action on EditText like:

java:

mEditInit = (EditText) findViewById(R.id.date_init);
mEditInit.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showDialog(DATEINIT_DIALOG);
    }

});

or kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

So, it will work perfectly if you put into xml of your EditText the following lines:

android:inputType="none"
android:focusable="false"
android:cursorVisible="false"

For example:

<EditText
            android:id="@+id/date_init" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:hint="Select Date"
            android:inputType="none"
            android:focusable="false"
            android:cursorVisible="false"/>

or for MaterialDesign

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/layoutEditTextChooseDate"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">

    <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/date_init" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:hint="Select Date"
            android:inputType="none"
            android:focusable="false"                      
            android:cursorVisible="false"/>

</com.google.android.material.textfield.TextInputLayout>
于 2019-08-02T15:09:31.237 回答
8

恕我直言,我不同意 RickNotFred 的说法:

当 EditText 获得焦点时弹出一个对话框似乎是一个非标准界面。

当用户按下一个EditText时显示一个编辑日期的对话框与默认的非常相似,即显示一个键盘一个数字小键盘。日期与 EditText 一起显示的事实向用户表明日期可能会更改。将日期显示为不可编辑的 TextView 向用户表明日期可能不会更改。

于 2011-03-01T18:48:15.733 回答
7

不错的话题。好吧,我已经这样做了。在 XML 文件中:

<EditText
    ...
    android:editable="false"
    android:inputType="none" />

在 Java 代码中:

txtDay.setOnClickListener(onOnClickEvent);
txtDay.setOnFocusChangeListener(onFocusChangeEvent);

private View.OnClickListener onOnClickEvent = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        dpDialog.show();
    }
};
private View.OnFocusChangeListener onFocusChangeEvent = new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus)
            dpDialog.show();
    }
};
于 2014-09-05T14:22:52.760 回答
6

以下内容非常适合我。

首先将日期选择器小部件的输入设置为“无”以防止弹出软键盘:

<EditText android:inputType="none" ... ></EditText>

然后添加这些事件侦听器以显示包含日期选择器的对话框:

// Date picker
EditText dateEdit = (EditText) findViewById(R.id.date);
dateOfBirthEdit.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            showDialog(DIALOG_DATE_PICKER);
        }
        return false;
    }
});

dateEdit.setOnFocusChangeListener(new OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            showDialog(DIALOG_DATE_PICKER);
        } else {
            dismissDialog(DIALOG_DATE_PICKER);
        }
    }
});

最后一件事。要确保从日期选择器中正确复制键入的日、月或年,请datePicker.clearFocus()在检索值之前调用,例如通过getMonth().

于 2012-01-16T17:11:03.037 回答
5

这对我有用:

mEditInit = (EditText) findViewById(R.id.date_init);
mEditInit.setKeyListener(null);
mEditInit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
            {
                mEditInit.callOnClick();
            }
        }
    });
mEditInit.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showDialog(DATEINIT_DIALOG);
    }

});
于 2016-10-03T22:47:10.990 回答
3

这对我有用

将可编辑设置为 false

<EditText android:id="@+id/dob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Date of Birth"
android:inputType="none"
android:editable="false"

/>

然后为 OnFocusChange 添加一个事件监听器

private  View.OnFocusChangeListener onFocusChangeDOB= new View.OnFocusChangeListener() {

@Override
 public void onFocusChange(View v, boolean hasFocus) {
   if (hasFocus){
     showDialog(DATE_DIALOG_ID);
   }
 }
};
于 2012-05-26T14:09:15.637 回答
2

正如 Dillon Kearns 建议的那样,将 focusable 设置为 false 效果很好。但是,如果您的目标是在单击 EditText 时取消键盘,您可能需要使用:

mEditText.setInputType(0);
于 2011-07-22T00:07:12.200 回答
2

为什么没有人提及setOnTouchListener?使用setOnTouchListener很简单也很好,如果监听器已经消费了事件,则返回 true,否则返回 false。

于 2016-09-01T06:25:15.290 回答
1

使用 OnFocusChangeListener 的解决方案的问题在于它们将任何焦点增益解释为单击。这不是 100% 正确的:您的 EditText 可能会通过点击以外的其他方式获得焦点。

如果您严格关心点击并希望始终检测点击(无论焦点如何),您可以使用GestureDetector

editText.setOnConsistentClickListener { /* do something */ }

fun EditText.setOnConsistentClickListener(doOnClick: (View) -> Unit) {
    val gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapUp(event: MotionEvent?): Boolean {
            doOnClick(this@setOnConsistentClickListener)
            return false
        }
    })

    this.setOnTouchListener { _, motionEvent -> gestureDetector.onTouchEvent(motionEvent) }
}
于 2020-11-20T10:29:48.007 回答
0

对于 kotlin,你可以使用这个

    editText!!.showSoftInputOnFocus = false
于 2022-02-24T19:02:36.007 回答