package cl.monsoon.s1next.util;
import android.annotation.SuppressLint;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.text.Spannable;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import java.lang.reflect.Method;
import cl.monsoon.s1next.R;
public final class ViewUtil {
private ViewUtil() {}
/**
* Concatenates with the specified text (two spaces and appendix) to the TextView
* with RTL support.
*
* @param text the String that is concatenated to the TextView
*/
@SuppressLint("SetTextI18n")
public static void concatWithTwoSpacesForRtlSupport(TextView textView, CharSequence text) {
if (ResourceUtil.isRTL(textView.getResources())) {
textView.setText(text + StringUtil.TWO_SPACES + textView.getText());
} else {
textView.append(StringUtil.TWO_SPACES + text);
}
}
/**
* Concatenates with the specified text (two spaces and appendix) to the TextView
* with RTL support.
*
* @param text the String that is concatenated to the TextView
* @param textColor the <code>text</code> color
*/
@SuppressLint("SetTextI18n")
public static void concatWithTwoSpacesForRtlSupport(TextView textView, CharSequence text, @ColorInt int textColor) {
if (ResourceUtil.isRTL(textView.getResources())) {
textView.setText(text + StringUtil.TWO_SPACES + textView.getText());
ViewUtil.setForegroundColor(textView, textColor, 0, text.length());
} else {
int start = textView.length();
textView.append(StringUtil.TWO_SPACES + text);
ViewUtil.setForegroundColor(textView, textColor, start, textView.length());
}
}
/**
* Sets foreground color for {@code textView}.
*/
private static void setForegroundColor(TextView textView, int color, int start, int end) {
Spannable spannable = Spannable.Factory.getInstance().newSpannable(textView.getText());
spannable.setSpan(new ForegroundColorSpan(color), start, end,
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannable);
}
/**
* Consumes a {@link Runnable} when an IME action in the {@link TextView} is performed.
* This method uses {@link TextView#setOnEditorActionListener(TextView.OnEditorActionListener)}
* to achieve this function.
*
* @param textView The view where an IME action is preformed on.
* @param runnable The consumer when an IME action is performed.
*/
public static void consumeRunnableWhenImeActionPerformed(TextView textView, Runnable runnable) {
textView.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == v.getResources().getInteger(R.integer.ime_action_id) ||
actionId == EditorInfo.IME_ACTION_DONE) {
runnable.run();
}
return false;
});
}
/**
* Backports {@link TextView#setShowSoftInputOnFocus} to API 20 and below.
*
* @see TextView#setShowSoftInputOnFocus(boolean)
*/
public static void setShowSoftInputOnFocus(EditText editText, Boolean show) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
editText.setShowSoftInputOnFocus(show);
} else {
try {
Method method;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
method = TextView.class.getMethod("setShowSoftInputOnFocus", boolean.class);
} else {
method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
}
method.setAccessible(true);
method.invoke(editText, show);
} catch (Exception e) {
// multi-catch with those reflection exceptions requires API level 19
// so we use Exception instead of multi-catch
throw new RuntimeException("Failed to invoke TextView#setShowSoftInputOnFocus(boolean).", e);
}
}
}
}