简体   繁体   中英

Android - get text position from textview with html data

I have set html data to my textview. When I select any word/characters from textview I want to bold that word and replace original html data with new one.

String html = "<p>hello this is android testing</p>";

Like this my html maybe have many html tags in it. If I want to make "android" word bold, how can I replace original html string with " android ".

I want <p>hello this is <strong>android</strong> testing</p> as result.

You can first set you string content into the TextView and then use setCustomSelectionActionModeCallback(...) to intercept the selection within the TextView.

In the example bellow a selected word will be surrounded by <strong>...</strong> .

For example selecting "testing" will make the following string visible into the TextView.

hello this is android testing android bla bla android bla bla android bla

Then selecting the last instance on "android" in the already transformed TextView content will make the following string visible into the TextVIew.

hello this is android testing android bla bla android bla bla android bla

Code :

public class MainActivity extends AppCompatActivity {

    String yourString = "<p>hello this is android testing android bla bla android bla bla android bla</p>";

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

        TextView tv = (TextView)findViewById(R.id.opening_today);
        tv.setText(Html.fromHtml(yourString));
        tv.setCustomSelectionActionModeCallback(new CallbackListener(tv));
    }

    class CallbackListener implements ActionMode.Callback{

        private TextView tv;
        private String strongS = "<strong>";
        private String strongE = "</strong>";

        public CallbackListener(TextView tv) {
            this.tv = tv;
        }

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            int start = tv.getSelectionStart();
            int end = tv.getSelectionEnd();

            if( start == 0 && end == 0)
                return false;

            String content = tv.getText().toString();
            String token = content.substring(start, end);
            String before = content.substring(0, start);
            String after = content.substring(end, content.length());
            content = makeItStrong(before, after, token);
            tv.setText(Html.fromHtml(content));
            return false;
        }

        private String makeItStrong(String before, String after, String token){
            return cleanTags(before, strongS, strongE) + strongS + token + strongE + cleanTags(after, strongS, strongE);
        }

        private String cleanTags(String source, String... exp){
            for(String s: exp){
                source = source.replace(s, "");
            }
            return source;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return true; }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }

        @Override
        public void onDestroyActionMode(ActionMode mode) {}
    }
}

Use SelectableTextView to get the selected text. You can see this implementation on github here .

Check the answer here . This might help you

And you can make bold using tag,

 String string= "<b>" + android + "</b> " + remainingString;   

 textView.setText(Html.fromHtml(string));

With the following code, you can highlight formatted text more than once and each time you can get the cumulative result of all highlights.

int getOccuranceNumber(String text ,String selection, int selectionStartIndex){
    int index = text.indexOf(selection);
    int occuranceNumber = 0;
    while (index >= 0) {
        if(index == selectionStartIndex){
            return occuranceNumber;
        }else {
            index = text.indexOf(selection, index + 1);
            occuranceNumber++;
        }
    }
    return occuranceNumber;
}
int getOccuranceIndex(String text ,String selection, int occuranceNumber){
    int index = text.indexOf(selection);
    int i = 0;
    while (i!=occuranceNumber) {

            index = text.indexOf(selection, index + 1);
            i++;

    }
    return index;
}
public String toHex(String arg) {
    TextView textV = new TextView(context);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        textV.setText(Html.fromHtml(arg,Html.FROM_HTML_MODE_LEGACY));
    }else{
        textV.setText(Html.fromHtml(arg));
    }
    String textFormated ="";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        textFormated =  Html.toHtml((Spanned) textV.getText(),TO_HTML_PARAGRAPH_LINES_CONSECUTIVE).toString();
    }else{
        textFormated =  Html.toHtml((Spanned) textV.getText()).toString();
    }
    return textFormated.replace("<p dir=\"rtl\">","").replace("</p>","").replace("\n","");
}
public void highLightText(TextView textView){
    String textFormated ="";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        textFormated =  Html.toHtml((Spanned) textView.getText(),TO_HTML_PARAGRAPH_LINES_CONSECUTIVE).toString();
    }else{
        textFormated =  Html.toHtml((Spanned) textView.getText()).toString();
    }

    String text = textView.getText().toString();
    String selection = text.substring(textView.getSelectionStart(),textView.getSelectionEnd());
    int occuranceNum = getOccuranceNumber(text,selection,textView.getSelectionStart());
    String selectionHex = toHex(selection);

    int formatedTextSelectionStart = getOccuranceIndex(textFormated,selectionHex,occuranceNum);
    if(formatedTextSelectionStart<0)return;
    int formatedTextSelectionEnd = formatedTextSelectionStart + selectionHex.length();
    String formatedTextPart1 = textFormated.substring(0,formatedTextSelectionStart);
    String formatedTextPart2 = textFormated.substring(formatedTextSelectionStart,formatedTextSelectionEnd);
    String formatedTextPart3 = textFormated.substring(formatedTextSelectionEnd,textFormated.length());
    String colorOpenTag="<font color=\"#f7c627\">";
    String colorCloseTag="</font>";
    String finalText = formatedTextPart1+colorOpenTag+formatedTextPart2+colorCloseTag+formatedTextPart3;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        textView.setText(Html.fromHtml(finalText,Html.FROM_HTML_MODE_LEGACY));
    }else{
        textView.setText(Html.fromHtml(finalText));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM