EditText onClickListener trong Android


86

Tôi muốn một EditText tạo DatePicker khi được nhấn. Vì vậy, tôi viết đoạn mã sau:

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

    });

Nhưng khi tôi nhấn EditText, hành động là điển hình: một con trỏ đang chờ nhập văn bản thay vì hiển thị Hộp thoại tôi muốn.


Bạn nên sử dụng một spinner thay vì hộp thoại EditText.
Ryan R

Câu trả lời:


129

Bàn phím dường như bật lên khi EditText lấy được tiêu điểm. Để tránh điều này, hãy đặt có thể lấy tiêu điểm thành sai:

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

Hành vi này có thể khác nhau tùy theo hương vị hệ điều hành Android của các nhà sản xuất khác nhau, nhưng trên các thiết bị tôi đã thử nghiệm, tôi thấy điều này là đủ. Nếu bàn phím vẫn bật lên, sử dụng gợi ý thay vì văn bản dường như cũng hữu ích:

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

Khi bạn đã thực hiện xong việc này, trình nghe khi nhấp của bạn sẽ hoạt động như mong muốn:

myEditText.setOnClickListener(new OnClickListener() {...});

Điều này có vẻ hiệu quả, nhưng khi bạn nhập vào một trường và nhấp vào Tiếp theo trên bàn phím, nó sẽ bỏ qua trường có tiêu điểm là false.
Sterling Diaz

60

Thông thường, bạn muốn khả năng tương thích tối đa với EditTexthành vi bình thường của.

Vì vậy, bạn không nên sử dụng android:focusable="false"như, vâng, chế độ xem sẽ không thể lấy nét được nữa và trông rất tệ. Ví dụ: nền có thể vẽ sẽ không hiển thị trạng thái "được nhấn" nữa.

Những gì bạn nên làm thay vào đó là:

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();
        }
    }
});

Bằng cách đặt kiểu nhập liệu thành TYPE_NULL, bạn ngăn bàn phím phần mềm bật lên.

Bằng cách thiết lập OnClickListenerOnFocusChangeListener , bạn đảm bảo rằng hộp thoại của mình sẽ luôn mở khi người dùng nhấp vào EditTexttrường, cả khi nó lấy được tiêu điểm (nhấp chuột đầu tiên) và khi nhấp chuột tiếp theo.

Chỉ cần thiết lập android:inputType="none"hoặc setInputType(InputType.TYPE_NULL)không phải lúc nào cũng đủ. Đối với một số thiết bị, bạn cũng nên đặt android:editable="false"bằng XML, mặc dù nó không được dùng nữa. Nếu nó không hoạt động nữa, nó sẽ chỉ bị bỏ qua (vì tất cả các thuộc tính XML không được hỗ trợ).


Khi tôi làm điều này, hộp thoại sẽ mở lại sau khi nó đóng lại vì văn bản chỉnh sửa được lấy tiêu điểm trở lại. Bất kỳ cách nào xung quanh điều này?
AdamMc331

@ McAdam331 Có lẽ EditTextthành phần đó là widget duy nhất trong bố cục của bạn? Bạn có thể thử thêm android:focusable="true"vào bố cục mẹ của mình không?
caw

1
@caw Cảm ơn bạn đã phản hồi, nhưng cuối cùng tôi đã làm cho nó hoạt động bằng onTouch. Cảm ơn!
AdamMc331

Đó là nó. Làm việc tốt.
XueQing

31

Tôi có vấn đề này như nhau. Mã vẫn ổn nhưng hãy đảm bảo rằng bạn thay đổi giá trị có thể lấy tiêu điểm của EditText thành false.

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

Tôi hy vọng điều này sẽ giúp bất cứ ai đã gặp vấn đề tương tự!


4
Cũng không đặt enable = "false", sẽ tắt onClickListener
OatsMantou

25

Hoạt động mặc định của EditText: Trong lần nhấp đầu tiên, nó tập trung và trong lần nhấp thứ hai, nó xử lý, onClickListenervì vậy bạn cần phải tắt tiêu điểm. Sau đó, lần đầu tiên nhấp vào onClickListenersẽ xử lý.

Để làm điều đó, bạn cần thêm android:focusableInTouchMode="false"thuộc tính này vào của bạn EditText. Đó là nó!

Một cái gì đó như thế này:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />

4
Nó hoạt động, nhưng EditTextkhông thể chỉnh sửa được và con trỏ không xuất hiện.
CoolMind

17

Đây là giải pháp tôi đã triển khai

mPickDate.setOnKeyListener(new View.OnKeyListener() {

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

HOẶC LÀ

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

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

    }
});

Hãy tự mình xem sự khác biệt. Vấn đề là vì (như RickNotFred đã nói) TextView hiển thị ngày tháng và chỉnh sửa thông qua DatePicker. TextEdit không được sử dụng cho mục đích chính của nó. Nếu bạn muốn DatePicker bật lên, bạn cần nhập xóa (trường hợp thứ nhất) hoặc de focus (trường hợp thứ hai).

cá đuối


2
trừ khi bạn thêm onClickListener mà tôi vừa làm cùng với onFocusChangeListener. Điều này sẽ hoạt động :-)
neteinstein

Giải pháp thứ hai đã làm việc cho tôi, cảm ơn bạn! :)
Celtik

9

Nếu bạn sử dụng hành động OnClick trên EditText như:

java:

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

});

hoặc kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

Vì vậy, nó sẽ làm việc một cách hoàn hảo nếu bạn đưa vào xmlcác bạn EditTextnhững dòng sau:

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

Ví dụ:

<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"/>

hoặc cho 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>

8

IMHO Tôi không đồng ý với tuyên bố của RickNotFred:

Việc bật hộp thoại khi một EditText được lấy tiêu điểm có vẻ giống như một giao diện không chuẩn.

Hiển thị hộp thoại để chỉnh sửa ngày khi sử dụng nhấn EditText rất giống với mặc định, đó là hiển thị bàn phím hoặc bàn phím số. Thực tế là ngày được hiển thị cùng với EditText báo hiệu cho người dùng rằng ngày đó có thể bị thay đổi. Hiển thị ngày dưới dạng TextView không thể chỉnh sửa báo hiệu cho người dùng rằng ngày đó không thể bị thay đổi.


7

Chủ đề hay. Vâng, tôi đã làm như vậy. Trong tệp XML:

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

Trong mã 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();
    }
};

6

Những điều sau đây hoạt động hoàn hảo đối với tôi.

Trước tiên, hãy đặt đầu vào của tiện ích con chọn ngày của bạn thành 'không có' để ngăn bàn phím mềm bật lên:

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

Sau đó, thêm các trình nghe sự kiện này để hiển thị hộp thoại chứa bộ chọn ngày:

// 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);
        }
    }
});

Một điều cuối cùng. Để đảm bảo ngày, tháng hoặc năm đã nhập được sao chép chính xác từ bộ chọn ngày, hãy gọi datePicker.clearFocus()trước khi truy xuất các giá trị, chẳng hạn qua getMonth().


Cách khắc phục đơn giản: Hãy bỏ qua bỏ qua các chương trình trước mỗi showDialog, chỉ để đảm bảo.
Lukas Batteau,

5

Điều này làm việc cho tôi:

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);
    }

});

3

Đây là những gì đã làm việc cho tôi

Đặt có thể chỉnh sửa thành sai

<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"

/>

Sau đó, thêm trình nghe sự kiện cho OnFocusChange

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

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

3
Cẩn thận với điện thoại Motorola chạy Android 2.3.x. Nếu EditText ở đâu đó trong vùng có thể cuộn, Motorola sẽ tự động di chuyển tiêu điểm xung quanh khi bạn cuộn. Điều này có nghĩa là bạn có thể cuộn xuống và khi EditText lấy được tiêu điểm, hộp thoại ngày của bạn sẽ bật lên, điều này thật bất ngờ và tồi tệ.
Eric Burke

2

Như Dillon Kearns đã đề xuất, việc đặt có thể lấy tiêu điểm thành sai hoạt động tốt. Nhưng nếu mục tiêu của bạn là hủy bàn phím khi bạn nhấp vào EditText, bạn có thể muốn sử dụng:

mEditText.setInputType(0);

2

Tại sao không thấy ai nhắc đến setOnTouchListener? Việc sử dụng setOnTouchListenerrất dễ dàng và đúng, và chỉ trả về true nếu người nghe đã sử dụng sự kiện, ngược lại là false.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.