Стиль EditText контента «на лету»? - PullRequest
5 голосов
/ 22 июня 2010

Я работаю над многофункциональным текстовым редактором в Android. В основном это полужирный курсив и кнопки ссылки, которые связаны с EditText, чтобы изменить стиль содержимого. У меня отлично работает, если сначала выбрать текст, который вы хотите оформить, а затем выбрать кнопку, используя этот метод: http://developer.android.com/guide/appendix/faq/commontasks.html#selectingtext.

То, что я пытаюсь сделать, это заставить его работать как текстовый редактор, где вы можете использовать кнопки в качестве переключателя для стилизации текста столько раз, сколько вы хотите, а затем снова нажать переключатель, чтобы прекратить использование стиль. Поэтому, если бы я хотел набрать ' Обратите внимание на это! ' жирным шрифтом, я бы нажал кнопку 'B', затем начал печатать текст, и все, что я набрал, было бы жирным, пока я не нажму 'B' кнопка снова.

Есть идеи, как это осуществить? Я надеюсь, что я достаточно ясно:)

Ответы [ 5 ]

9 голосов
/ 23 июня 2010

Для тех, кто заинтересован, я заставил это работать, сохранив местоположение курсора (переменная 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);
                    }
                }
        });

Может быть, есть лучшее решение, рад услышать его, если оно у вас есть!

5 голосов
/ 23 июня 2010

Вы можете просто обновить стиль после каждого набираемого символа, используя 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);
    }
}
1 голос
/ 05 сентября 2014

Я знаю, что это старая ветка, но мой коллега заметил DroidWriter в Интернете.Я немного поиграл с этим, и он довольно понятен и очень прост в использовании и модификации.Надеюсь, это поможет любому, кто хочет создать текстовый редактор.

1 голос
/ 16 декабря 2011

Существует открытый текстовый редактор EditText с открытым исходным кодом, который называется android-richtexteditor , но код был необъяснимым образом удален в r5.Код все еще там в старых ревизиях;просто используйте SVN, чтобы проверить r4 или ранее, чтобы получить к нему доступ.Код, по-видимому, поддерживает курсив, подчеркивание, палитру цветов, размер текста и т. Д.

Также ответил на следующие вопросы: 1 , 2

0 голосов
/ 23 июня 2010

Только одна возможность, не уверен, что это лучшее решение, но это то, что приходит на ум, и кто знает, что это вдохновит вас на более элегантное решение:

Возможно, вы могли бы рассмотреть внутреннее отслеживание иерархического стиляструктура «документа», со всеми его тегами стиля, и восстановление / замена окончательного вывода каждым напечатанным символом?Конечно, вам также придется отслеживать положение курсора.

...