사용자가 EditText 편집을 마치면 이벤트를 포착하고 싶습니다.
어떻게 할 수 있습니까?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
사용자가 EditText 편집을 마치면 이벤트를 포착하고 싶습니다.
어떻게 할 수 있습니까?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
답변:
사용자가 편집을 마치면 Done
또는Enter
((EditText)findViewById(R.id.youredittext)).setOnEditorActionListener(
new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
event != null &&
event.getAction() == KeyEvent.ACTION_DOWN &&
event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (event == null || !event.isShiftPressed()) {
// the user is done typing.
return true; // consume.
}
}
return false; // pass on to other listeners.
}
}
);
더 좋은 방법은 EditText onFocusChange 리스너를 사용하여 사용자가 편집을 완료했는지 확인할 수도 있습니다. ( 사용자가 소프트 키보드에서 완료 또는 Enter 버튼을 누르는 것에 의존하지 않아도됩니다)
((EditText)findViewById(R.id.youredittext)).setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) { {
// Validate youredittext
}
}
});
참고 : 하나 이상의 EditText의 경우 클래스가 구현하도록 View.OnFocusChangeListener
한 다음 각 EditText에 리스너를 설정하고 아래와 같이 유효성을 검사 할 수도 있습니다.
((EditText)findViewById(R.id.edittext1)).setOnFocusChangeListener(this);
((EditText)findViewById(R.id.edittext2)).setOnFocusChangeListener(this);
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) {
switch (view.getId()) {
case R.id.edittext1:
// Validate EditText1
break;
case R.id.edittext2:
// Validate EditText2
break;
}
}
}
EditText
. 초점을 잃지 않을 것입니다.
EditText
? 사용해야 onEditorAction
합니까?
EditText
사용자가 화면에서 나가기 위해 수행하는 작업에 대해 유효성을 검사합니다.
W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=605.52246, y[0]=969.4336, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=238238, downTime=235422, deviceId=0, source=0x1002 }
됩니다. 입력 한 내용이 있어도 숫자 만 허용하는 편집 텍스트입니다.
개인적으로 입력이 끝나면 자동 제출을 선호합니다. 이 이벤트를 감지하는 방법은 다음과 같습니다.
선언 및 초기화 :
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
예를 들어 onCreate ()의 리스너
EditText editTextStop = (EditText) findViewById(R.id.editTextStopId);
editTextStop.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before,
int count) {
if(timer != null)
timer.cancel();
}
@Override
public void afterTextChanged(final Editable s) {
//avoid triggering event when text is too short
if (s.length() >= 3) {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO: do what you need here (refresh list)
// you will probably need to use
// runOnUiThread(Runnable action) for some specific
// actions
serviceConnector.getStopPoints(s.toString());
}
}, DELAY);
}
}
});
따라서 텍스트가 변경되면 타이머는 다음 변경 사항이 발생할 때까지 기다리기 시작합니다. 그들이 발생하면 타이머가 취소되고 다시 시작됩니다.
Handler
대신에
setOnKeyListener를 사용하거나 다음과 같은 textWatcher를 사용하여 수행 할 수 있습니다.
텍스트 감시자 설정 editText.addTextChangedListener(textWatcher);
그런 다음 전화
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//after text changed
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
};
많은 답변이 올바른 방향을 가리키고 있지만 질문 작성자가 생각한 것에 대한 답변은 아무도 없다고 생각합니다. 또는 적어도 비슷한 문제에 대한 답을 찾고 있었기 때문에 질문을 다르게 이해했습니다. 문제는 "사용자가 버튼을 누르지 않고 입력을 중지하는 경우를 아는 방법"이고 일부 작업 (예 : 자동 완성)을 트리거하는 것입니다. 이 작업을 수행하려면 사용자가 입력을 중지 한 것으로 간주 할 수있는 지연 시간 (예 : 500-700ms)을 사용하여 onTextChanged에서 타이머를 시작하고, 타이머를 시작할 때 새 문자마다 이전 문자를 취소하거나 적어도 체크 표시를하면 아무것도하지 않습니다.) 다음은 내가 사용한 것과 유사한 코드입니다.
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
비동기 작업 내에서 실행중인 부울 플래그를 수정합니다 (작업은 자동 완성을 위해 서버에서 json을 가져옴).
또한 이것은 많은 타이머 작업을 생성한다는 것을 명심하십시오 (나는 그들이 동일한 스레드에 예약되어 있다고 생각하지만 이것을 확인해야 할 것입니다), 아마도 개선해야 할 곳이 많지만이 접근 방식도 작동하고 결론은 당신이해야한다는 것입니다 "사용자가 입력 중지 이벤트"가 없으므로 타이머를 사용합니다.
작업 후 키보드를 숨기려면 @Reno와 @Vinayak B가 함께 대답합니다.
textView.setOnEditorActionListener(new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(textView.getWindowToken(), 0);
return true;
}
return false;
}
});
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// your action here
}
}
});
다른 접근 방식 ... 여기에 예가 있습니다. 사용자가 입력 할 때 600-1000ms의 지연이있는 경우 사용자가 중지 된 것으로 간주 할 수 있습니다.
myEditText.addTextChangedListener(new TextWatcher() {
private String s;
private long after;
private Thread t;
private Runnable runnable_EditTextWatcher = new Runnable() {
@Override
public void run() {
while (true) {
if ((System.currentTimeMillis() - after) > 600)
{
Log.d("Debug_EditTEXT_watcher", "(System.currentTimeMillis()-after)>600 -> " + (System.currentTimeMillis() - after) + " > " + s);
// Do your stuff
t = null;
break;
}
}
}
};
@Override
public void onTextChanged(CharSequence ss, int start, int before, int count) {
s = ss.toString();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable ss) {
after = System.currentTimeMillis();
if (t == null)
{
t = new Thread(runnable_EditTextWatcher);
t.start();
}
}
});
좋습니다. 확실히 100 % 작동합니다.
먼저 키보드가 표시되거나 숨겨지는 경우 리스너를 설정해야합니다. 키보드가 표시되면 사용자가 입력 중일 수 있으며 그렇지 않으면 입력이 완료된 것입니다.
final View activityRootView = findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
isTyping = true;
} else {
//to make sure this will call only once when keyboard is hide.
if(isTyping){
isTyping = false;
}
}
}
});
heightDiff > 100
물건은 무서운 imho입니다.
이 문제를 이렇게 해결했습니다. kotlin을 사용했습니다.
var timer = Timer()
var DELAY:Long = 2000
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
Log.e("TAG","timer start")
timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
//do something
}
}, DELAY)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
Log.e("TAG","timer cancel ")
timer.cancel() //Terminates this timer,discarding any currently scheduled tasks.
timer.purge() //Removes all cancelled tasks from this timer's task queue.
}
})
나는 같은 문제가 있었고 Done 또는 Enter를 누르는 사용자에게 의존하고 싶지 않았습니다.
내 첫 번째 시도는 onFocusChange 리스너를 사용하는 것이었지만 내 EditText가 기본적으로 포커스를 얻었습니다. 사용자가 다른 뷰를 눌렀을 때 사용자가 포커스를 할당하지 않은 상태에서 onFocusChange가 트리거되었습니다.
다음 솔루션은 사용자가 EditText를 터치하면 onFocusChange가 첨부되는 곳입니다.
final myEditText = new EditText(myContext); //make final to refer in onTouch
myEditText.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
myEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
// user is done editing
}
}
}
}
}
제 경우에는 사용자가 편집을 마치면 화면이 다시 렌더링되어 myEditText 객체가 갱신되었습니다. 동일한 객체가 유지되는 경우이 게시물의 시작 부분에서 설명한 onFocusChange 문제를 방지하려면 onFocusChange에서 onFocusChange 리스너를 제거해야합니다.
채팅 앱에서 '지금 입력'을 구현하려고 할 때 동일한 문제가 발생했습니다. 다음과 같이 EditText를 확장하십시오.
public class TypingEditText extends EditText implements TextWatcher {
private static final int TypingInterval = 2000;
public interface OnTypingChanged {
public void onTyping(EditText view, boolean isTyping);
}
private OnTypingChanged t;
private Handler handler;
{
handler = new Handler();
}
public TypingEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.addTextChangedListener(this);
}
public TypingEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.addTextChangedListener(this);
}
public TypingEditText(Context context) {
super(context);
this.addTextChangedListener(this);
}
public void setOnTypingChanged(OnTypingChanged t) {
this.t = t;
}
@Override
public void afterTextChanged(Editable s) {
if(t != null){
t.onTyping(this, true);
handler.removeCallbacks(notifier);
handler.postDelayed(notifier, TypingInterval);
}
}
private Runnable notifier = new Runnable() {
@Override
public void run() {
if(t != null)
t.onTyping(TypingEditText.this, false);
}
};
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { }
}
나는 그녀를 같은 문제로 끝내고 onEditorAction 또는 onFocusChange와 함께 솔루션을 사용할 수 없었고 타이머를 시도하고 싶지 않았습니다. 타이머는 코드가 실행되는시기를 모르기 때문에 모든 스레드와 너무 예측할 수 없기 때문에 맛보기에는 너무 위험합니다.
onEditorAction은 사용자가 버튼을 사용하지 않고 떠날 때 포착하지 않으며, 버튼을 사용하면 KeyEvent가 null 일 수 있습니다. 포커스는 양쪽 끝에서 신뢰할 수 없습니다. 사용자는 텍스트를 입력하거나 필드를 선택하지 않고 포커스를 얻고 떠날 수 있으며 사용자는 마지막 EditText 필드를 떠날 필요가 없습니다.
내 솔루션은 사용자가 텍스트 편집을 시작할 때 onFocusChange 및 플래그 설정을 사용하고 필요할 때 호출하는 마지막 포커스 뷰에서 텍스트를 가져 오는 함수를 사용합니다.
나가기 텍스트보기 코드를 속이기 위해 모든 텍스트 필드의 포커스를 지 웁니다. clearFocus 코드는 필드에 포커스가있는 경우에만 실행됩니다. onSaveInstanceState에서 함수를 호출하므로 플래그 (mEditing)를 EditText보기의 상태로 저장할 필요가없고 중요한 버튼을 클릭 할 때와 활동이 닫힐 때가 없습니다.
자주 호출되는 TexWatcher는 onRestoreInstanceState 코드가 텍스트를 입력 할 때 반응하지 않도록 포커스 조건을 사용하므로주의하십시오. 나는
final EditText mEditTextView = (EditText) getView();
mEditTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!mEditing && mEditTextView.hasFocus()) {
mEditing = true;
}
}
});
mEditTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus && mEditing) {
mEditing = false;
///Do the thing
}
}
});
protected void saveLastOpenField(){
for (EditText view:getFields()){
view.clearFocus();
}
}
TextView.OnEditorActionListener 유형 대신 사용할 수있는이 추상 클래스와 같은 작업을 수행했습니다.
abstract class OnTextEndEditingListener : TextView.OnEditorActionListener {
override fun onEditorAction(textView: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if(actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
actionId == EditorInfo.IME_ACTION_NEXT ||
event != null &&
event.action == KeyEvent.ACTION_DOWN &&
event.keyCode == KeyEvent.KEYCODE_ENTER) {
if(event == null || !event.isShiftPressed) {
// the user is done typing.
return onTextEndEditing(textView, actionId, event)
}
}
return false // pass on to other listeners
}
abstract fun onTextEndEditing(textView: TextView?, actionId: Int, event: KeyEvent?) : Boolean
}
EditText에서 입력 완료를 트리거하는 간단한 방법
나를 위해 일했습니다 .Java를 사용하는 경우 변환하십시오.
Kotlin에서
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}