For those who are interested, I got this to work, keeping the cursor location (the "styleStart" variable below) when ToggleButton was pressed, and then when the user types more characters, I actually delete the corresponding StyleSpan style with removeSpan (), then add it again using setSpan (), using the saved source cursor location + length of the characters that are currently typed.
You also need to keep track of whether the user changes the cursor position so that style text is not needed for you. Here is the TextWatcher code:
final EditText contentEdit = (EditText) findViewById(R.id.content); contentEdit.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { //add style as the user types if a toggle button is enabled ToggleButton boldButton = (ToggleButton) findViewById(R.id.bold); ToggleButton emButton = (ToggleButton) findViewById(R.id.em); ToggleButton bquoteButton = (ToggleButton) findViewById(R.id.bquote); ToggleButton underlineButton = (ToggleButton) findViewById(R.id.underline); ToggleButton strikeButton = (ToggleButton) findViewById(R.id.strike); int position = Selection.getSelectionStart(contentEdit.getText()); if (position < 0){ position = 0; } if (position > 0){ if (styleStart > position || position > (cursorLoc + 1)){ //user changed cursor location, reset styleStart = position - 1; } cursorLoc = position; if (boldButton.isChecked()){ StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class); for (int i = 0; i < ss.length; i++) { if (ss[i].getStyle() == android.graphics.Typeface.BOLD){ s.removeSpan(ss[i]); } } s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } if (emButton.isChecked()){ StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class); boolean exists = false; for (int i = 0; i < ss.length; i++) { if (ss[i].getStyle() == android.graphics.Typeface.ITALIC){ s.removeSpan(ss[i]); } } s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } if (bquoteButton.isChecked()){ QuoteSpan[] ss = s.getSpans(styleStart, position, QuoteSpan.class); for (int i = 0; i < ss.length; i++) { s.removeSpan(ss[i]); } s.setSpan(new QuoteSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } if (underlineButton.isChecked()){ UnderlineSpan[] ss = s.getSpans(styleStart, position, UnderlineSpan.class); for (int i = 0; i < ss.length; i++) { s.removeSpan(ss[i]); } s.setSpan(new UnderlineSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } if (strikeButton.isChecked()){ StrikethroughSpan[] ss = s.getSpans(styleStart, position, StrikethroughSpan.class); for (int i = 0; i < ss.length; i++) { s.removeSpan(ss[i]); } s.setSpan(new StrikethroughSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } public void beforeTextChanged(CharSequence s, int start, int count, int after) { //unused } public void onTextChanged(CharSequence s, int start, int before, int count) { //unused } });
And here is one of the Clickgle ToggleButton actions:
final ToggleButton boldButton = (ToggleButton) findViewById(R.id.bold); boldButton.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { EditText contentText = (EditText) findViewById(R.id.content); int selectionStart = contentText.getSelectionStart(); styleStart = selectionStart; int selectionEnd = contentText.getSelectionEnd(); if (selectionStart > selectionEnd){ int temp = selectionEnd; selectionEnd = selectionStart; selectionStart = temp; } if (selectionEnd > selectionStart) { Spannable str = contentText.getText(); StyleSpan[] ss = str.getSpans(selectionStart, selectionEnd, StyleSpan.class); boolean exists = false; for (int i = 0; i < ss.length; i++) { if (ss[i].getStyle() == android.graphics.Typeface.BOLD){ str.removeSpan(ss[i]); exists = true; } } if (!exists){ str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } boldButton.setChecked(false); } } });
There may be a better solution, glad to hear it if you have one!