Я работаю над визуальным редактором в Android. В основном это имеет полужирный, курсив и кнопки ссылки, которые связываются с EditText для изменения стиля содержания. У меня есть он работать отлично, если Вы выбираете текст, Вы хотите разработать сначала, и затем нажать кнопку с помощью этого метода: http://developer.android.com/guide/appendix/faq/commontasks.html#selectingtext.
То, что я пытаюсь сделать, имеют его работа как визуальный редактор, где можно использовать кнопки в качестве переключателя для моделирования текста столько, сколько Вы хотели бы, затем нажмите переключатель снова, чтобы прекратить использовать стиль. Таким образом, если я хотел ввести, 'Обращают внимание на это!' полужирным, я нажал бы кнопку 'B', затем начать вводить текст и все, что я ввожу, было бы полужирным, пока я не нажимаю кнопку 'B' снова.
Какие-либо идеи о том, как осуществить это? Я надеюсь, что был достаточно ясен :)
Вы можете просто обновить стиль после каждого набранного символа, используя TextWatcher
и метод addTextChangedListener ()
.
Хорошо, это всего лишь пример кода.
int mStart = -1;
// Bold onClickListener
public void onClick(View view)
{
if(mStart == -1) mStart = mEditText.getText().length();
else mStart = -1;
}
// TextWatcher
onTextChanged(CharSequence s, int start, int before, int count)
{
if(mStart > 0)
{
int end = mEditText.getText().length();
mEditText.getText().setSpan(new StyleSpan(android.graphics.Typeface.BOLD), mStart, end - mStart, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
Для тех, кому интересно, я добился этого, сохранив местоположение курсора (переменная styleStart ниже) при нажатии кнопки ToggleButton, а затем, когда пользователь набирает больше символов, я фактически удаляю соответствующий StyleSpan с помощью removeSpan(), а затем добавляю его обратно с помощью setSpan(), используя сохраненное исходное местоположение курсора + длину символов, набранных в данный момент.
Вам также необходимо отслеживать, изменяет ли пользователь положение курсора, чтобы не стилизовать текст, который вам не нужен. Вот код TextWatcher:
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
}
});
А вот одно из действий по нажатию ToggleButton:
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);
}
}
});
Возможно, есть лучшее решение, буду рад услышать его, если оно у вас есть!
Только одна возможность, не уверен, что это лучшее решение, но это то, что приходит в голову, и кто знает, но это вдохновит вас на более элегантное решение:
Может быть, вы могли бы подумать внутренне отслеживание иерархической стилевой структуры «документа» со всеми его тегами стиля и реконструкция / замена окончательного вывода с каждым набранным символом? Конечно, вам также придется отслеживать положение курсора.