I want to set ClickableSpans for each character in an EditText, but their positions do not match the character at the end of each line.
Each letter has a ClickableSpan set to it using BreakIterator. Each Clickable opens an AlertDialog showing the clicked letter. It works fine if the letter is not at the end of the line. A red cross shows the click position:
'S' clicked in middle of line works fine:
BUT, clicking letters at the end of a line activates the previous letter's ClickableSpan:
'Y' was clicked but 'X' ClickableSpan activated:
And clicking in the area just before the first letter of the next line will activate the previous line's last letter:
Area just before 'Z' clicked, and 'X' of previous line activated:
How can I get the ClickableSpans to position correctly at the end of lines?
Java code:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText et = findViewById(R.id.editText);
et.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abc");
String text = et.getText().toString();
et.setMovementMethod(LinkMovementMethod.getInstance());
Spannable spannable = et.getText();
BreakIterator iterator = BreakIterator.getCharacterInstance();
iterator.setText(text);
int iteratorStart = iterator.first();
for (int iteratorEnd = iterator.next(); iteratorEnd != BreakIterator.DONE;
iteratorStart = iteratorEnd, iteratorEnd = iterator.next()) {
String letter = text.substring(iteratorStart, iteratorEnd);
ClickableSpan cs = generateClickableSpan(letter);
spannable.setSpan(cs, iteratorStart, iteratorEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
private ClickableSpan generateClickableSpan(final String letter) {
return new ClickableSpan() {
final String currentLetter;
{
currentLetter = letter;
}
@Override
public void onClick(View widget) {
AlertDialog.Builder adBuilder = new AlertDialog.Builder(MainActivity.this);
AlertDialog ad = adBuilder.create();
ad.setMessage(letter);
ad.show();
TextView tv = ad.findViewById(android.R.id.message);
tv.setTextSize(24);
ad.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
}
};
}
EditText xml:
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="#00000000"
android:inputType="none"
android:textIsSelectable="true"
android:layout_gravity="top"
android:textSize="42sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
I've tried the solutions and suggestions in the following answers including making a custom LinkMovementMethod class but nothing has worked:
ClickableSpan in the EditText to the end of text calls click() to the end of line
ClickableSpan strange behavior:onClick() called when clicking empty space
Thanks!!