我的自定义EditText无法正常工作 [英] My Custom EditText not working correctly

查看:92
本文介绍了我的自定义EditText无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个EditText,它可以接受此问题中提到的粗体,斜体和下划线字符..

I am working on a EditText which can take Bold, Italics and Underline characters as mentioned in this question.

我扩展了EditText并覆盖了onTextChanged()方法. 对于任何粗体,斜体,带下划线的输入,我的代码都可以正常工作,但第二次出现后,第一次出现的情况将变为普通文本.

I have extended EditText and overrided the onTextChanged() method. My code works fine for the first occcurence of any bold, italics, underlined input but after my second occurence the first occurence gets changed to normal text.

这是一个尊重问题的gif

这是MainActivity.java

    package com.example.syed.andtexteditor;

import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    int helperCounterB = 0;
    int helperCounterI = 0;
    int helperCounterU = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button boldButton = (Button) findViewById(R.id.bold_button);
        boldButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Button boldButton = (Button) findViewById(R.id.bold_button);
                helperCounterB++;

                if (helperCounterB % 2 != 0)
                //The EditText is in Bold mode when the Bold button is pressed odd-th time
                    boldButton.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                else

                    boldButton.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.grey));

                TextArea t = (TextArea) findViewById(R.id.textInput);
                t.applyTypeface(helperCounterI, helperCounterB, helperCounterU);

            }

        });

        Button italicsButton = (Button) findViewById(R.id.italics_button);
        italicsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Button italicsButton = (Button) findViewById(R.id.italics_button);
                helperCounterI++;
                if (helperCounterI % 2 != 0) //The EditText is in Italics mode when the Italics button is pressed odd-th time
                    italicsButton.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                else
                    italicsButton.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.grey));

                TextArea t = (TextArea) findViewById(R.id.textInput);
                t.applyTypeface(helperCounterI, helperCounterB, helperCounterU);

            }

        });

        Button underlineButton = (Button) findViewById(R.id.underline_button);
        underlineButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Button underlineButton = (Button) findViewById(R.id.underline_button);
                helperCounterU++;
                if (helperCounterU % 2 != 0)//The EditText is in Underline mode when the Underline button is pressed odd-th time

                    underlineButton.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                else

                    underlineButton.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.grey));

                TextArea t = (TextArea) findViewById(R.id.textInput);
                t.applyTypeface(helperCounterI, helperCounterB, helperCounterU);

            }
        });

    }
}

这是扩展的EditText类,即TextArea.java

package com.example.syed.andtexteditor;


import android.content.Context;
import android.graphics.Typeface;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.util.Log;


/**
 * Created by Syed on 29-05-2017.
 */

public class TextArea extends AppCompatEditText {
    Context c;
    public static final int TYPEFACE_NORMAL = 0;
    public static final int TYPEFACE_BOLD = 1;
    public static final int TYPEFACE_ITALICS = 2;
    public static final int TYPEFACE_BOLD_ITALICS = 3;
    public static final int TYPEFACE_UNDERLINE = 4;
    public static final int TYPEFACE_BOLD_UNDERLINE = 5;
    public static final int TYPEFACE_ITALICS_UNDERLINE = 6;
    public static final int TYPEFACE_BOLD_ITALICS_UNDERLINE = 7;

    private int currentTypeface;
    private int lastCursorPosition;

    private StyleSpan normalspan = new StyleSpan(Typeface.NORMAL);
    private StyleSpan boldspan = new StyleSpan(Typeface.BOLD);
    private StyleSpan italicspan = new StyleSpan(Typeface.ITALIC);
    private StyleSpan boldItalicspan = new StyleSpan(Typeface.BOLD_ITALIC);
    private UnderlineSpan underlinespan = new UnderlineSpan();

    public TextArea(Context context) {
        super(context);
        c = context;
        lastCursorPosition = this.getSelectionStart();

    }

    public TextArea(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void changeTypeface(int tfId) {
        currentTypeface = tfId;
        lastCursorPosition = this.getSelectionStart();
    }

    public void applyTypeface(int helperCounterI, int helperCounterB, int helperCounterU) {
        int min = 0;
        int max = this.getText().length();
        if (this.isFocused()) {
            final int selStart = this.getSelectionStart();
            final int selEnd = this.getSelectionEnd();

            min = Math.max(0, Math.min(selStart, selEnd));
            max = Math.max(0, Math.max(selStart, selEnd));
        }
        Spannable s = this.getText();
        Editable selectedText = new SpannableStringBuilder(s, min, max);

        SpannableStringBuilder s1 = new SpannableStringBuilder(s, 0, min);

        String selectedTextString = selectedText.toString();
        SpannableStringBuilder selectedSpannedString = new SpannableStringBuilder(selectedTextString);
        Log.d(VIEW_LOG_TAG, "Helper Counter I: " + helperCounterI + " Helper Counter B: " + helperCounterB);
        if (helperCounterI % 2 != 0 && helperCounterB % 2 != 0 && helperCounterU % 2 == 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {
                this.changeTypeface(TextArea.TYPEFACE_BOLD_ITALICS);

            }
            //ignore this part as there are no issues with this
            else {

                StyleSpan styleSpan = new StyleSpan(Typeface.BOLD_ITALIC);
                selectedSpannedString.setSpan(styleSpan, min, max, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }

        } else if (helperCounterI % 2 != 0 && helperCounterB % 2 == 0 && helperCounterU % 2 == 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {
                this.changeTypeface(TextArea.TYPEFACE_ITALICS);

            }
            //ignore this part as there are no issues with this
            else {
                StyleSpan styleSpan = new StyleSpan(Typeface.ITALIC);
                selectedSpannedString.setSpan(styleSpan, min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }
        } else if (helperCounterI % 2 == 0 && helperCounterB % 2 != 0 && helperCounterU % 2 == 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {

                this.changeTypeface(TextArea.TYPEFACE_BOLD);

            }
            //ignore this part as there are no issues with this
            else {
                StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
                selectedSpannedString.setSpan(styleSpan, min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }
        } else if (helperCounterB % 2 == 0 && helperCounterI % 2 == 0 && helperCounterU % 2 == 0) {

            this.changeTypeface(TextArea.TYPEFACE_NORMAL);

        } else if (helperCounterU % 2 != 0 && helperCounterI % 2 == 0 && helperCounterB % 2 == 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {
                this.changeTypeface(TYPEFACE_UNDERLINE);

            }
            //ignore this part as there are no issues with this
            else {
                selectedSpannedString.setSpan(new UnderlineSpan(), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }
        } else if (helperCounterU % 2 != 0 && helperCounterI % 2 == 0 && helperCounterB % 2 != 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {
                this.changeTypeface(TYPEFACE_BOLD_UNDERLINE);

            }
            //ignore this part as there are no issues with this
            else {
                selectedSpannedString.setSpan(new StyleSpan(Typeface.BOLD), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                selectedSpannedString.setSpan(new UnderlineSpan(), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }
        } else if (helperCounterU % 2 != 0 && helperCounterI % 2 != 0 && helperCounterB % 2 == 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {

                this.changeTypeface(TYPEFACE_ITALICS_UNDERLINE);

            } else
            //ignore this part as there are no issues with this
            {
                selectedSpannedString.setSpan(new StyleSpan(Typeface.ITALIC), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                selectedSpannedString.setSpan(new UnderlineSpan(), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }
        } else if (helperCounterU % 2 != 0 && helperCounterI % 2 != 0 && helperCounterB % 2 != 0) {
            if (this.getSelectionEnd() == this.getSelectionStart()) {
                this.changeTypeface(TYPEFACE_BOLD_ITALICS_UNDERLINE);

            }
            //ignore this part as there are no issues with this
            else {
                selectedSpannedString.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                selectedSpannedString.setSpan(new UnderlineSpan(), min, max, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                SpannableStringBuilder s3 = new SpannableStringBuilder(s, max, s.length());
                CharSequence finalSpannable = TextUtils.concat(s1, selectedSpannedString, s3);
                this.setText(finalSpannable);
            }
        }
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {


        Log.d(VIEW_LOG_TAG, "Start: " + start + " Length before: " + lengthBefore + " Length After: " + lengthAfter + " TextLength: " + text.length());

        CharacterStyle ss = null;
        UnderlineSpan ss1 = null;
        int endLength = text.toString().length();


        switch (currentTypeface) {
            case TYPEFACE_NORMAL:
                ss = normalspan;
                break;
            case TYPEFACE_BOLD:
                ss = boldspan;
                break;
            case TYPEFACE_ITALICS:
                ss = italicspan;
                break;
            case TYPEFACE_BOLD_ITALICS:
                ss = boldItalicspan;
                break;
            case TYPEFACE_UNDERLINE:
                ss = underlinespan;
                break;
            case TYPEFACE_BOLD_UNDERLINE:
                ss = boldspan;
                ss1 = underlinespan;
                break;
            case TYPEFACE_ITALICS_UNDERLINE:
                ss = italicspan;
                ss1 = underlinespan;
                break;
            case TYPEFACE_BOLD_ITALICS_UNDERLINE:
                ss = boldItalicspan;
                ss1 = underlinespan;
                break;
        }
        if (lastCursorPosition > endLength)
            return;
        Log.d(TextArea.class.getSimpleName(), new Integer(lastCursorPosition).toString() + new Integer(endLength).toString());
        this.getText().setSpan(ss, lastCursorPosition, endLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        this.getText().setSpan(ss1, lastCursorPosition, endLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    }
}

推荐答案

您的问题是您正在重新使用跨度实例.根据

Your problem is that you are re-using instances of the spans. Per the documentation of setSpan (emphasis mine):

将指定的标记对象附加到文本的开始范围...结尾处,或将对象移动到该范围,如果该对象已经附加在其他地方.

因此,每次您要为文本添加属性时,只需创建新的跨度即可.

So you simply need to create new Spans each time you want to attribute text.

希望有帮助!

这篇关于我的自定义EditText无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆