Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
205 views
in Technique[技术] by (71.8m points)

android - Style EditText content 'on the fly'?

I'm working on a rich text editor in Android. Basically it has bold, italics and link buttons that are tied to an EditText to change the style of the content. I have it working great if you select the text you want to style first, and then select the button using this method: http://developer.android.com/guide/appendix/faq/commontasks.html#selectingtext.

What I'm trying to do is have it work like a rich text editor, where you can use the buttons as a toggle to style the text for as long as you'd like, then click the toggle again to stop using the style. So if I wanted to type 'Pay attention to this!' in bold, I would click the 'B' button, then start typing the text and everything I type would be bold until I click the 'B' button again.

Any ideas on how to pull this off? I hope I've been clear enough :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For those interested, I got this to work by saving the cursor location ('styleStart' variable below) when the ToggleButton was pressed, and then as the user types more characters, I actually remove the matching StyleSpan with removeSpan(), then re-add it back with setSpan() by using the saved original cursor location + the length of characters currently typed.

You also need to track if the user changes cursor position so that you don't style text that you don't want to. Here's 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's one of the ToggleButton click 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, happy to hear it if you have one!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...