Адаптировал решение из к этому ответу . Разделяет ввод автоматически при вставке запятой (разделитель можно настроить). Создает ImageSpan и ClickableSpan (записи можно удалить, нажав на правую часть).
public class TagEditText extends EditText {
TextWatcher textWatcher;
String lastString;
String separator = ",";
public TagEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setMovementMethod(LinkMovementMethod.getInstance());
textWatcher = 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) {
String thisString = s.toString();
if (thisString.length() > 0 && !thisString.equals(lastString)) {
format();
}
}
};
addTextChangedListener(textWatcher);
}
private void format() {
SpannableStringBuilder sb = new SpannableStringBuilder();
String fullString = getText().toString();
String[] strings = fullString.split(separator);
for (int i = 0; i < strings.length; i++) {
String string = strings[i];
sb.append(string);
if (fullString.charAt(fullString.length() - 1) != separator.charAt(0) && i == strings.length - 1) {
break;
}
BitmapDrawable bd = (BitmapDrawable) convertViewToDrawable(createTokenView(string));
bd.setBounds(0, 0, bd.getIntrinsicWidth(), bd.getIntrinsicHeight());
int startIdx = sb.length() - (string.length());
int endIdx = sb.length();
sb.setSpan(new ImageSpan(bd), startIdx, endIdx, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
MyClickableSpan myClickableSpan = new MyClickableSpan(startIdx, endIdx);
sb.setSpan(myClickableSpan, Math.max(endIdx-2, startIdx), endIdx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (i < strings.length - 1) {
sb.append(separator);
} else if (fullString.charAt(fullString.length() - 1) == separator.charAt(0)) {
sb.append(separator);
}
}
lastString = sb.toString();
setText(sb);
setSelection(sb.length());
}
public View createTokenView(String text) {
LinearLayout l = new LinearLayout(getContext());
l.setOrientation(LinearLayout.HORIZONTAL);
l.setBackgroundResource(R.drawable.bordered_rectangle_rounded_corners);
TextView tv = new TextView(getContext());
l.addView(tv);
tv.setText(text);
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
ImageView im = new ImageView(getContext());
l.addView(im);
im.setImageResource(R.drawable.ic_cross_15dp);
im.setScaleType(ImageView.ScaleType.FIT_CENTER);
return l;
}
public Object convertViewToDrawable(View view) {
int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(spec, spec);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
c.translate(-view.getScrollX(), -view.getScrollY());
view.draw(c);
view.setDrawingCacheEnabled(true);
Bitmap cacheBmp = view.getDrawingCache();
Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
view.destroyDrawingCache();
return new BitmapDrawable(getContext().getResources(), viewBmp);
}
private class MyClickableSpan extends ClickableSpan{
int startIdx;
int endIdx;
public MyClickableSpan(int startIdx, int endIdx) {
super();
this.startIdx = startIdx;
this.endIdx = endIdx;
}
@Override
public void onClick(View widget) {
String s = getText().toString();
String s1 = s.substring(0, startIdx);
String s2 = s.substring(Math.min(endIdx+1, s.length()-1), s.length() );
TagEditText.this.setText(s1 + s2);
}
}
}
R.drawable.bordered_rectangle_ounded_corners:
Последнее, что нужно добавить, это png для «x-Button». Пока работает хорошо, единственная проблема в том, что длительное нажатие на клавишу удаления не работает (если у кого-то есть идея, как заставить его работать, не стесняйтесь комментировать)
Практически в любой ситуации, когда есть быстрый и безопасный режимы, вы найдете какой-то компромисс. В противном случае все работало бы в быстром и безопасном режиме: -).
И, если вы получаете разные результаты с одним и тем же входом, ваш процесс не детерминирован, как бы вы в это ни верите. быть (несмотря на эмпирические данные)
Я бы сказал, что ваше объяснение наиболее вероятно. Переведите его в безопасный режим и посмотрите, исчезнет ли недетерминизм. Это скажет вам наверняка.
Что касается других оптимизаций, если вы компилируете на том же оборудовании с тем же компилятором / компоновщиком и теми же параметрами этих инструментов , он должен сгенерировать идентичный код. Я могу' Я не вижу другой возможности, кроме быстрого режима (или битового гниения в памяти из-за космических лучей, но это маловероятно).
После вашего обновления:
У Intel есть документ здесь , который объясняет некоторые вещи, которые им не разрешено делать в безопасном режиме, включая, помимо прочего:
(a + b) + c -> a + (b + c)
. x + 0 -> x, x * 0 -> 0
. a / b -> a * (1 / b)
. Хотя вы утверждаете, что эти операции определяются во время компиляции, чипы Intel чертовски умны. Они могут переупорядочивать инструкции, чтобы конвейеры оставались заполненными в многопроцессорных конфигурациях, поэтому, если код специально не запрещает такое поведение, все может измениться во время выполнения (не во время компиляции), чтобы все работало на полной скорости.