fixed suggestion list flashing when typing fast or holding backspace (rendering is now debounced)
This commit is contained in:
parent
f8d7af669d
commit
02af8561e2
3 changed files with 60 additions and 58 deletions
|
|
@ -57,7 +57,7 @@ public class SuggestionOps {
|
|||
|
||||
@NonNull
|
||||
public String get(int index) {
|
||||
return suggestionBar != null ? suggestionBar.getSuggestion(index) : "";
|
||||
return suggestionBar != null ? suggestionBar.get(index) : "";
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -69,20 +69,20 @@ public class SuggestionOps {
|
|||
|
||||
public void set(ArrayList<String> suggestions) {
|
||||
if (suggestionBar != null) {
|
||||
suggestionBar.setSuggestions(suggestions, 0, false);
|
||||
suggestionBar.setMany(suggestions, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(ArrayList<String> suggestions, boolean containsGenerated) {
|
||||
if (suggestionBar != null) {
|
||||
suggestionBar.setSuggestions(suggestions, 0, containsGenerated);
|
||||
suggestionBar.setMany(suggestions, 0, containsGenerated);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void set(ArrayList<String> suggestions, int selectIndex, boolean containsGenerated) {
|
||||
if (suggestionBar != null) {
|
||||
suggestionBar.setSuggestions(suggestions, selectIndex, containsGenerated);
|
||||
suggestionBar.setMany(suggestions, selectIndex, containsGenerated);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ public class SettingsStore extends SettingsHotkeys {
|
|||
public final static int SUGGESTIONS_MAX = 20;
|
||||
public final static int SUGGESTIONS_MIN = 8;
|
||||
public final static int SUGGESTIONS_POSITIONS_LIMIT = 100;
|
||||
public final static int SUGGESTIONS_RENDER_DEBOUNCE_TIME = 25; // ms
|
||||
public final static int SUGGESTIONS_RENDER_CLEAR_DEBOUNCE_TIME = 60; // ms
|
||||
public final static int SUGGESTIONS_SELECT_ANIMATION_DURATION = 66;
|
||||
public final static int SUGGESTIONS_TRANSLATE_ANIMATION_DURATION = 0;
|
||||
public final static int TEXT_INPUT_DEBOUNCE_TIME = 500; // ms
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ public class SuggestionsBar {
|
|||
private final String STEM_PUNCTUATION_VARIATION_PREFIX = "";
|
||||
@NonNull private String stem = "";
|
||||
|
||||
private int backgroundColor = Color.TRANSPARENT;
|
||||
private int defaultBackgroundColor = Color.TRANSPARENT;
|
||||
private int backgroundColor;
|
||||
|
||||
private double lastClickTime = 0;
|
||||
private int lastScrollIndex = 0;
|
||||
private int selectedIndex = 0;
|
||||
|
|
@ -47,7 +49,7 @@ public class SuggestionsBar {
|
|||
private SuggestionsAdapter mSuggestionsAdapter;
|
||||
private Vibration vibration;
|
||||
|
||||
private final Handler alternativeScrollingHandler = new Handler();
|
||||
private final Handler delayedDisplayHandler = new Handler();
|
||||
|
||||
|
||||
public SuggestionsBar(@NonNull SettingsStore settings, @NonNull ResizableMainView mainView, @NonNull Runnable onItemClick) {
|
||||
|
|
@ -136,7 +138,7 @@ public class SuggestionsBar {
|
|||
|
||||
|
||||
@NonNull
|
||||
public String getSuggestion(int id) {
|
||||
public String get(int id) {
|
||||
if (id < 0 || id >= visibleSuggestions.size()) {
|
||||
return "";
|
||||
}
|
||||
|
|
@ -186,17 +188,17 @@ public class SuggestionsBar {
|
|||
}
|
||||
|
||||
|
||||
public void setSuggestions(@Nullable List<String> newSuggestions, int initialSel, boolean containsGenerated) {
|
||||
public void setMany(@Nullable List<String> newSuggestions, int initialSel, boolean containsGenerated) {
|
||||
suggestions = newSuggestions;
|
||||
ecoSetBackground(newSuggestions);
|
||||
|
||||
visibleSuggestions.clear();
|
||||
selectedIndex = newSuggestions == null || newSuggestions.isEmpty() ? 0 : Math.max(initialSel, 0);
|
||||
|
||||
visibleSuggestions.clear();
|
||||
setStem(newSuggestions, containsGenerated);
|
||||
addManySuggestions(newSuggestions, mView != null ? SettingsStore.SUGGESTIONS_MAX : Integer.MAX_VALUE);
|
||||
addMany(newSuggestions, mView != null ? SettingsStore.SUGGESTIONS_MAX : Integer.MAX_VALUE);
|
||||
|
||||
selectedIndex = Math.min(selectedIndex, visibleSuggestions.size() - 1);
|
||||
displaySuggestions();
|
||||
|
||||
renderDebounced();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -235,13 +237,13 @@ public class SuggestionsBar {
|
|||
* for performance reasons, hence the "limit" parameter. When they are too many, the SHOW_MORE_SUGGESTION,
|
||||
* will be displayed at the end.
|
||||
*/
|
||||
private void addManySuggestions(List<String> newSuggestions, int limit) {
|
||||
private void addMany(List<String> newSuggestions, int limit) {
|
||||
if (newSuggestions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, end = Math.min(limit, newSuggestions.size()); i < end; i++) {
|
||||
addSuggestion(newSuggestions.get(i));
|
||||
add(newSuggestions.get(i));
|
||||
}
|
||||
|
||||
if (newSuggestions.size() > limit) {
|
||||
|
|
@ -250,14 +252,14 @@ public class SuggestionsBar {
|
|||
}
|
||||
|
||||
|
||||
private void addSuggestion(@NonNull String suggestion) {
|
||||
private void add(@NonNull String suggestion) {
|
||||
// shorten the stem variations
|
||||
if (!stem.isEmpty() && suggestion.length() == stem.length() + 1 && suggestion.toLowerCase().startsWith(stem.toLowerCase())) {
|
||||
String trimmedSuggestion = suggestion.substring(stem.length());
|
||||
char firstChar = trimmedSuggestion.charAt(0);
|
||||
|
||||
String prefix = Character.isAlphabetic(firstChar) && !Characters.isCombiningPunctuation(firstChar) ? STEM_VARIATION_PREFIX : STEM_PUNCTUATION_VARIATION_PREFIX;
|
||||
prefix = Characters.isFathatan(firstChar) ? " " : prefix; // Fix incorrect display of fathatan without a base character. It is a combining character, but since it is a letter, we must include a base character not to break it, with a "..." prefix
|
||||
prefix = Characters.isFathatan(firstChar) ? " " : prefix; // Fix incorrect display of Fathatan without a base character. It is a combining character, but since it is a letter, we must include a base character not to break it, with a "..." prefix
|
||||
visibleSuggestions.add(prefix + formatUnreadableSuggestion(trimmedSuggestion));
|
||||
return;
|
||||
}
|
||||
|
|
@ -266,11 +268,24 @@ public class SuggestionsBar {
|
|||
}
|
||||
|
||||
|
||||
private void displaySuggestions() {
|
||||
/**
|
||||
* Reduces flashing of the suggestions bar when the suggestions are empty and saves some resources
|
||||
* by reducing the calls to render().
|
||||
*/
|
||||
private void renderDebounced() {
|
||||
final int delay = visibleSuggestions.isEmpty() ? SettingsStore.SUGGESTIONS_RENDER_CLEAR_DEBOUNCE_TIME : SettingsStore.SUGGESTIONS_RENDER_DEBOUNCE_TIME;
|
||||
delayedDisplayHandler.removeCallbacksAndMessages(null);
|
||||
delayedDisplayHandler.postDelayed(this::render, delay);
|
||||
}
|
||||
|
||||
|
||||
private void render() {
|
||||
if (mView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setBackground(false);
|
||||
|
||||
boolean smooth = settings.getSuggestionSmoothScroll() && visibleSuggestions.size() <= SettingsStore.SUGGESTIONS_MAX + 1;
|
||||
mView.setItemAnimator(smooth ? animator : null);
|
||||
|
||||
|
|
@ -282,9 +297,10 @@ public class SuggestionsBar {
|
|||
|
||||
|
||||
/**
|
||||
* If addManySuggestions() constrained the visible suggestions, the end of the list will contain
|
||||
* the SHOW_MORE_SUGGESTION. This method will display remove the SHOW_MORE_SUGGESTION and display
|
||||
* all the hidden suggestions. It also scrolls correctly to the new visible suggestion.
|
||||
* If addMany() constrained the visible suggestions, the end of the list will contain
|
||||
* the SHOW_MORE_SUGGESTION. This method will remove the SHOW_MORE_SUGGESTION, prepare
|
||||
* all hidden suggestions for displaying, and will scroll correctly to the new visible suggestion.
|
||||
* After that, you must call render(), to visualize the changes.
|
||||
*/
|
||||
private boolean appendHiddenSuggestionsIfNeeded(boolean scrollBack) {
|
||||
if (mView == null || !visibleSuggestions.get(selectedIndex).equals(SHOW_MORE_SUGGESTION)) {
|
||||
|
|
@ -292,7 +308,7 @@ public class SuggestionsBar {
|
|||
}
|
||||
|
||||
visibleSuggestions.clear();
|
||||
addManySuggestions(suggestions, Integer.MAX_VALUE);
|
||||
addMany(suggestions, Integer.MAX_VALUE);
|
||||
selectedIndex = scrollBack || selectedIndex >= visibleSuggestions.size() ? visibleSuggestions.size() - 1 : selectedIndex;
|
||||
|
||||
return true;
|
||||
|
|
@ -320,9 +336,9 @@ public class SuggestionsBar {
|
|||
|
||||
calculateScrollIndex(increment);
|
||||
if (appendHiddenSuggestionsIfNeeded(increment < 0)) {
|
||||
displaySuggestions();
|
||||
render();
|
||||
}
|
||||
scrollToIndex();
|
||||
scrollToSelected();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -338,7 +354,7 @@ public class SuggestionsBar {
|
|||
}
|
||||
|
||||
|
||||
private void scrollToIndex() {
|
||||
private void scrollToSelected() {
|
||||
if (mView == null) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -346,19 +362,19 @@ public class SuggestionsBar {
|
|||
mSuggestionsAdapter.setSelection(selectedIndex);
|
||||
|
||||
if (settings.getSuggestionScrollingDelay() > 0) {
|
||||
alternativeScrollingHandler.removeCallbacksAndMessages(null);
|
||||
alternativeScrollingHandler.postDelayed(this::scrollView, settings.getSuggestionScrollingDelay());
|
||||
delayedDisplayHandler.removeCallbacksAndMessages(null);
|
||||
delayedDisplayHandler.postDelayed(this::renderScroll, settings.getSuggestionScrollingDelay());
|
||||
} else {
|
||||
scrollView();
|
||||
renderScroll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells the adapter to scroll. Always call scrollToIndex() first,
|
||||
* Tells the adapter to scroll. Always call scrollToSelected() first,
|
||||
* to set the selected index in the adapter.
|
||||
*/
|
||||
private void scrollView() {
|
||||
private void renderScroll() {
|
||||
if (mView == null) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -383,12 +399,12 @@ public class SuggestionsBar {
|
|||
|
||||
Context context = mView.getContext();
|
||||
|
||||
backgroundColor = ContextCompat.getColor(context, R.color.keyboard_background);
|
||||
defaultBackgroundColor = ContextCompat.getColor(context, R.color.keyboard_background);
|
||||
mSuggestionsAdapter.setColorDefault(ContextCompat.getColor(context, R.color.keyboard_text));
|
||||
mSuggestionsAdapter.setColorHighlight(ContextCompat.getColor(context, R.color.suggestion_selected_text));
|
||||
mSuggestionsAdapter.setBackgroundHighlight(ContextCompat.getColor(context, R.color.suggestion_selected_background));
|
||||
|
||||
setBackground(visibleSuggestions);
|
||||
setBackground(true);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -397,36 +413,20 @@ public class SuggestionsBar {
|
|||
* Makes the background transparent, when there are no suggestions and theme-colored,
|
||||
* when there are suggestions.
|
||||
*/
|
||||
private void setBackground(List<String> newSuggestions) {
|
||||
private void setBackground(boolean force) {
|
||||
if (mView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newSuggestionsSize = newSuggestions != null ? newSuggestions.size() : 0;
|
||||
if (newSuggestionsSize == 0) {
|
||||
mView.setBackgroundColor(Color.TRANSPARENT);
|
||||
return;
|
||||
boolean mustChange = (
|
||||
(backgroundColor == Color.TRANSPARENT && !visibleSuggestions.isEmpty()) ||
|
||||
(backgroundColor == defaultBackgroundColor && visibleSuggestions.isEmpty())
|
||||
);
|
||||
|
||||
if (force || mustChange) {
|
||||
backgroundColor = visibleSuggestions.isEmpty() ? Color.TRANSPARENT : defaultBackgroundColor;
|
||||
mView.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
mView.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ecoSetBackground
|
||||
* A performance-optimized version of "setBackground().
|
||||
* Determines if the suggestions have changed and only then it changes the background.
|
||||
*/
|
||||
private void ecoSetBackground(List<String> newSuggestions) {
|
||||
int newSuggestionsSize = newSuggestions != null ? newSuggestions.size() : 0;
|
||||
if (
|
||||
(newSuggestionsSize == 0 && visibleSuggestions.isEmpty())
|
||||
|| (newSuggestionsSize > 0 && !visibleSuggestions.isEmpty())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setBackground(newSuggestions);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ public class SuggestionsBar {
|
|||
vibration.vibrate();
|
||||
selectedIndex = position;
|
||||
if (appendHiddenSuggestionsIfNeeded(false)) {
|
||||
displaySuggestions();
|
||||
render();
|
||||
} else {
|
||||
onItemClick.run();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue