EditText에서 텍스트가 변경된 후 0.5 초 후에 어떻게해야합니까?
EditText를 사용하여 내 목록을 필터링하고 있습니다. 사용자가 EditText 입력을 마친 후 0.5 초 후에 목록을 필터링하고 싶습니다 . 이 목적으로 의 afterTextChanged
이벤트를 사용했습니다 TextWatcher
. 그러나이 이벤트는 EditText에서 문자가 변경 될 때마다 발생합니다.
어떻게해야합니까?
editText.addTextChangedListener(
new TextWatcher() {
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
private Timer timer=new Timer();
private final long DELAY = 1000; // milliseconds
@Override
public void afterTextChanged(final Editable s) {
timer.cancel();
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
}
},
DELAY
);
}
}
);
비결은 Timer
텍스트 EditText
가 변경 될 때마다 취소하고 일정을 다시 잡는 것 입니다. 행운을 빕니다!
업데이트 지연 시간 설정에 관심이있는 사람들은 이 게시물을 참조하십시오 .
postDelayed () 메서드와 함께 Handler를 더 잘 사용하십시오. Android의 구현에서 Timer는 작업을 실행할 때마다 새 스레드를 만듭니다. 그러나 Handler는 원하는 스레드에 연결할 수있는 자체 Looper를 가지고 있으므로 스레드를 생성하는 데 추가 비용을 지불하지 않습니다.
예
Handler handler = new Handler(Looper.getMainLooper() /*UI thread*/);
Runnable workRunnable;
@Override public void afterTextChanged(Editable s) {
handler.removeCallbacks(workRunnable);
workRunnable = () -> doSmth(s.toString());
handler.postDelayed(workRunnable, 500 /*delay*/);
}
private final void doSmth(String str) {
//
}
RxBindings 를 사용할 수 있으며 이는 최상의 솔루션입니다. RxJava 연산자 디 바운스에 대한 가이드를 참조하십시오. 귀하의 경우에는 이것이 훌륭 할 것이라고 확신합니다.
RxTextView.textChanges(editTextVariableName)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<String>() {
@Override
public void call(String value) {
// do some work with the updated text
}
});
http://reactivex.io/documentation/operators/debounce.html
위의 솔루션 중 어느 것도 나를 위해 일했습니다.
TextWatcher가 검색보기에 입력 한 모든 문자에 대해 실행하지 않고 진행 상황을 표시하는 방법이 필요했습니다. 즉, UI 스레드에 액세스해야합니다.
private final TextWatcher textWatcherSearchListener = new TextWatcher() {
final android.os.Handler handler = new android.os.Handler();
Runnable runnable;
public void onTextChanged(final CharSequence s, int start, final int before, int count) {
handler.removeCallbacks(runnable);
}
@Override
public void afterTextChanged(final Editable s) {
//show some progress, because you can access UI here
runnable = new Runnable() {
@Override
public void run() {
//do some work with s.toString()
}
};
handler.postDelayed(runnable, 500);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
};
모든 onTextChanged에서 핸들러 제거 (사용자가 새 문자를 입력 할 때 호출 됨). afterTextChanged는 새 Runnable을 시작할 수있는 입력 필드 내에서 텍스트가 변경된 후 호출되지만 사용자가 더 많은 문자를 입력하면 취소됩니다 (이 콜백이 호출 될 때 자세한 정보는 this 참조 ). 사용자가 더 이상 문자를 입력하지 않으면 간격이 postDelayed로 전달되고 해당 텍스트로 수행해야하는 작업을 호출합니다.
이 코드는 모든 주요 사용자 입력이 아닌 간격 당 한 번만 실행됩니다. 미래의 누군가에게 도움이되기를 바랍니다.
그들이 글을 다 읽었는지 어떻게 알 수 있습니까? 편집 텍스트가 초점을 잃는다 고요? 그런 다음 setOnFocusChangedListener가 있습니다.
문제의 최근 편집에 응답 : 최신 키 입력 후 특정 시간을 기다리려면 첫 번째 키 누름 (TextWatcher 사용)에서 스레드를 시작해야합니다. 최신 키 입력 시간을 지속적으로 등록하십시오. 스레드가 최근 키 입력 시간 + 0.5 초까지 잠자기 상태로 둡니다. 최신 키 입력의 타임 스탬프가 업데이트되지 않은 경우 의도 한대로 수행하십시오.
당신은 또한 사용할 수 있습니다 TextWatcher의 인터페이스 및 사용자 정의 클래스를 만들 구현이 여러 번하여 다시 사용하는 것을 CustomTextWatcher을 하고 또한 당신이 의견을 전달할 수 있습니다 또는 무엇이든 당신이 생성자에해야 할 수도 있습니다 :
public abstract class CustomTextWatcher implements TextWatcher { //Notice abstract class so we leave abstract method textWasChanged() for implementing class to define it
private final TextView myTextView; //Remember EditText is a TextView so this works for EditText also
public AddressTextWatcher(TextView tView) { //Notice I'm passing a view at the constructor, but you can pass other variables or whatever you need
myTextView= tView;
}
private Timer timer = new Timer();
private final int DELAY = 500; //milliseconds of delay for timer
@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(final Editable s) {
timer.cancel();
timer = new Timer();
timer.schedule(
new TimerTask() {
@Override
public void run() {
textWasChanged();
}
},
DELAY
);
}
public abstract void textWasChanged(); //Notice abstract method to leave implementation to implementing class
}
이제 활동에서 다음과 같이 사용할 수 있습니다.
myEditText.addTextChangedListener(new CustomTextWatcher(myEditText) { //Notice I'm passing in constructor of CustomTextWatcher myEditText I needed to use
@Override
public void textWasChanged() {
//doSomething(); this is method inside your activity
}
});
Kotlin 확장 기능 및 코 루틴 사용 :
fun AppCompatEditText.afterTextChangedDebounce(delayMillis: Long, input: (String) -> Unit) {
var lastInput = ""
var debounceJob: Job? = null
val uiScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
this.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable?) {
if (editable != null) {
val newtInput = editable.toString()
debounceJob?.cancel()
if (lastInput != newtInput) {
lastInput = newtInput
debounceJob = uiScope.launch {
delay(delayMillis)
if (lastInput == newtInput) {
input(newtInput)
}
}
}
}
}
override fun beforeTextChanged(cs: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(cs: CharSequence?, start: Int, before: Int, count: Int) {}
})}
타이머를 사용할 수 있으며 텍스트를 입력 한 후 600ms 동안 대기합니다. 600ms의 지연을 사용하여 afterTextChanged () 안에 코드를 넣습니다.
@Override
public void afterTextChanged(Editable arg0) {
// user typed: start the timer
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// do your actual work here
editText.setText(et.getText().toString());
}
}, 600); // 600ms delay before the timer executes the „run“ method from TimerTask
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// nothing to do here
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// user is typing: reset already started timer (if existing)
if (timer != null) {
timer.cancel();
}
}
};
그것은 입력을 마치는 동안과 후에 이벤트입니다 ... textWatcher를 추가하고 onTextChanged 메소드에 다음을 추가하십시오.
if (charSequence.length() > 0){// your code }
textWatcher를 처음으로 만 건너 뛰려면 다음 코드를 추가하십시오. 이렇게하면 textWatcher가 두 번째부터 변경할 수 있습니다.
Boolean firstchange=false;
profileEmailEditText.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) {
if (firstchange) {
emailAlertText.setVisibility(View.VISIBLE);
}
else {
firstchange=true;
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
Kotlin 언어에서는 이렇게 할 수 있습니다.
tv_search.addTextChangedListener(mTextWatcher)
private val mTextWatcher: TextWatcher = object : TextWatcher {
private var timer = Timer()
private val DELAY: Long = 1000
override fun afterTextChanged(s: Editable?) {
timer.cancel();
timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
//DO YOUR STUFF HERE
}
}, 1000)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
}
EditorActionListener
그 목적으로 사용할 수 있습니다 .
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
//Do something here
return true;
}
return false;
}
});
귀하의 경우에 타이머를 사용하는 것은 매번 새로운 개체를 만들기 때문에 최선의 해결책이 아닙니다. Timer 문서 ( http://developer.android.com/reference/java/util/Timer.html ) 에 따르면 ScheduledThreadPoolExecutor를 사용하는 것이 좋습니다.
"Timers schedule one-shot or recurring tasks for execution. Prefer ScheduledThreadPoolExecutor for new code."
Here is better approach
Runnable runnabledelayedTask = new Runnable(){
@Override
public void run(){
//TODO perform any operation here
}
};
editText.addTextChangedListener(
new TextWatcher() {
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
private final long DELAY = 500; // milliseconds
@Override
public void afterTextChanged(final Editable s) {
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(1);
ScheduledFuture sf = scheduledPool.schedule(callabledelayedTask, DELAY, TimeUnit.MILLISECONDS);
//you can cancel ScheduledFuture when needed
}
}
);
'IT박스' 카테고리의 다른 글
클릭시 입력 텍스트의 기본값 삭제 (0) | 2020.12.06 |
---|---|
C ++ 전 처리기 : 멤버 변수 목록의 코드 반복 방지 (0) | 2020.12.06 |
동일한 ID를 가진 객체는 ==와 비교할 때 항상 동일합니까? (0) | 2020.12.06 |
Android에서 인터넷 연결을 어떻게 확인합니까? (0) | 2020.12.06 |
.gitignore는 디렉토리를 무시하지 않습니다. (0) | 2020.12.06 |