1

I have an android app that lists baby names for people ..... it has a textview that connects different strings of text and data and then displays them...... (the baby name + "means" + the meaning of the name)

I am trying to change the font size and color and bold the first string of the text (the baby name) and then add a horizontal line or divider or spacer after it.

Then I would like to style the second text string (the "means" text) font size and color separately and make it bold as well.

then i would like to style the third string font size and color separately and make it bold as well.

I have been reading about SpannableString and tried to implement it for the last 3 hours with no luck.If anyone could help with this it would be greatly appreciated!

Here is the current working code I have

MY TextView

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/common_name_description_text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textSize="24dp"
    android:layout_gravity="center"
    android:gravity="center"
    android:padding="16dp">

MY JAVA

package mypackage.android;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import mypackage.android.database.CommonNamesAdapter;

public class CommonNameDescription extends AppCompatActivity {

    String common_name;
    String common_name_meaning;
    long common_name_rowid;

    CharSequence mybreak = "\n";
    CharSequence text = "Means";
    CharSequence description;

    public static TextView tv;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Bundle extras = getIntent().getExtras();

        common_name_rowid = extras.getLong(CommonNamesAdapter.COMMON_NAME_ROWID );
        common_name = extras.getString(CommonNamesAdapter.COMMON_NAME);
        common_name_meaning = extras.getString(CommonNamesAdapter.COMMON_NAME_MEANING).toString();


        description = common_name+mybreak+text+mybreak+common_name_meaning;
        tv = (TextView)findViewById(R.id.common_name_description_text);

        tv.setText(description);



    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        boolean bRet=false;//set true is menu selection handled
        switch (item.getItemId()) {
            case R.id.action_settings_get_pro:
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(getString(R.string.pro_version_url)));
                startActivity(intent);
                bRet=true;
                break;
            case R.id.action_settings_get_pro2:
                Intent intent2 = new Intent(Intent.ACTION_VIEW);
                intent2.setData(Uri.parse(getString(R.string.pro_version_url)));
                startActivity(intent2);
                bRet=true;
                break;
            case R.id.action_settings_app_help:
                Toast.makeText(this, this.getString(R.string.action_settings_app_help_text), Toast.LENGTH_SHORT).show();
                bRet=true;
                break;
            case R.id.action_settings_about_app:
                Toast.makeText(this, this.getString(R.string.action_settings_about_text), Toast.LENGTH_SHORT).show();
                bRet=true;
                break;
            case R.id.action_settings_rate_app:
                Intent intent3 = new Intent(Intent.ACTION_VIEW);
                intent3.setData(Uri.parse(getString(R.string.rate_this_app_url)));
                startActivity(intent3);
                bRet=true;
                break;
            case R.id.action_settings_privacy_policy:
                Intent intentprivacy = new Intent(Intent.ACTION_VIEW);
                intentprivacy.setData(Uri.parse(getString(R.string.privacy_policy_url)));
                startActivity(intentprivacy);
                bRet=true;
                break;
            case R.id.action_settings_all_our_apps:
                Intent intent4 = new Intent(Intent.ACTION_VIEW);
                intent4.setData(Uri.parse(getString(R.string.all_our_apps_url)));
                startActivity(intent4);
                bRet=true;
                break;
            default:
                bRet=super.onOptionsItemSelected(item);
        }
        return bRet;
    }

}

and here is an example of what i am trying to do
(Note I know html tags don't work .... that is just to show what i am trying to wrap the text in and where i am trying to put the divider)

package mypackage.android;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import mypackage.android.database.CommonNamesAdapter;

public class CommonNameDescription extends AppCompatActivity {

    String common_name; < --- NEED TO CHANGE FONT SIZE AND COLOR AND MAKE BOLD
    String common_name_meaning; < --- NEED TO CHANGE FONT SIZE AND COLOR AND MAKE BOLD SEPERATLY FROM THE STRING ABOVE
    long common_name_rowid;

    CharSequence mybreak = "\n";
    CharSequence text = "Means"; < --- NEED TO CHANGE FONT SIZE AND COLOR AND MAKE BOLD SEPERATLY FROM THE OTHER 2 STRINGS ABOVE
    CharSequence description;

    public static TextView tv;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Bundle extras = getIntent().getExtras();

        common_name_rowid = extras.getLong(CommonNamesAdapter.COMMON_NAME_ROWID );
        common_name = extras.getString(CommonNamesAdapter.COMMON_NAME);
        common_name_meaning = extras.getString(CommonNamesAdapter.COMMON_NAME_MEANING).toString();


        description = <b><font size="size here" color="color here">common_name</b></font>+horizontal_line_or_divder+<b><font size="size here" color="color here">text</b></font>+mybreak+<b><font size="size here" color="color here">common_name_meaning</b></font>;

        tv.setText(description);



    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        boolean bRet=false;//set true is menu selection handled
        switch (item.getItemId()) {
            case R.id.action_settings_get_pro:
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(getString(R.string.pro_version_url)));
                startActivity(intent);
                bRet=true;
                break;
            case R.id.action_settings_get_pro2:
                Intent intent2 = new Intent(Intent.ACTION_VIEW);
                intent2.setData(Uri.parse(getString(R.string.pro_version_url)));
                startActivity(intent2);
                bRet=true;
                break;
            case R.id.action_settings_app_help:
                Toast.makeText(this, this.getString(R.string.action_settings_app_help_text), Toast.LENGTH_SHORT).show();
                bRet=true;
                break;
            case R.id.action_settings_about_app:
                Toast.makeText(this, this.getString(R.string.action_settings_about_text), Toast.LENGTH_SHORT).show();
                bRet=true;
                break;
            case R.id.action_settings_rate_app:
                Intent intent3 = new Intent(Intent.ACTION_VIEW);
                intent3.setData(Uri.parse(getString(R.string.rate_this_app_url)));
                startActivity(intent3);
                bRet=true;
                break;
            case R.id.action_settings_privacy_policy:
                Intent intentprivacy = new Intent(Intent.ACTION_VIEW);
                intentprivacy.setData(Uri.parse(getString(R.string.privacy_policy_url)));
                startActivity(intentprivacy);
                bRet=true;
                break;
            case R.id.action_settings_all_our_apps:
                Intent intent4 = new Intent(Intent.ACTION_VIEW);
                intent4.setData(Uri.parse(getString(R.string.all_our_apps_url)));
                startActivity(intent4);
                bRet=true;
                break;
            default:
                bRet=super.onOptionsItemSelected(item);
        }
        return bRet;
    }

}
Charuක
  • 12,953
  • 5
  • 50
  • 88
skapaid
  • 169
  • 4
  • 17
  • Spannable string? http://stackoverflow.com/a/5169604/2308683 – OneCricketeer Feb 07 '17 at 02:49
  • http://stackoverflow.com/questions/14371092/how-to-make-a-specific-text-on-textview-bold – Aditya Vyas-Lakhan Feb 07 '17 at 05:09
  • every example is confusing because they are on single strings or dont use a database can anyone give me an example of a code like mine? – skapaid Feb 07 '17 at 05:18
  • @skapaid String is always a String doesnt matter where it comes from, you can say String myName = "skapaid"; and apply myName to the place where you want to put a String or you can simply put "skapaid" where you want to put a String. – Charuක Feb 07 '17 at 06:14

6 Answers6

2

Try doing

tv.setText(Html.fromHtml(description));

With the <b> and </b> tags in your description string.

Jesse Buss
  • 833
  • 6
  • 13
  • I'm sure this is a correct answer if your `description` is right format with `'` wrapped – Harry T. Feb 07 '17 at 02:52
  • it throws 2 errors ... 'fromHtml(java.lang.String)' is deprecated and 'fromHtml(java.lang.String)' in 'android.text.Html' cannot be applied to '(java.lang.CharSequence)' – skapaid Feb 07 '17 at 02:59
0

Simply

  TextView text=(TextView)findViewById(R.id.text);
        final SpannableStringBuilder str = new SpannableStringBuilder("the  baby name  means  the meaning of the nam");
        str.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), STAT_CHAR_POSITION_INT_FOR_STYLE, END_CHAR_POSITION_INT_FOR_STYLE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        text.setText(str);

or custom method

TextView text=(TextView)findViewById(R.id.text);
setTextWithSpan(text,"the  baby name  means  the meaning of the nam","baby",new android.text.style.StyleSpan(android.graphics.Typeface.BOLD));


// call this method 
  void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style) {
        SpannableStringBuilder sb = new SpannableStringBuilder(text);
        int start = text.indexOf(spanText);
        int end = start + spanText.length();
        sb.setSpan(style, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        textView.setText(sb);
    }

Edit :

As I mentioned you can use the same function same concept! This will work and might not as the one you expect.So change it then you will learn.

You have main three changes to do in your Sting.My answer will demo bold , italic and different font size in a same String. Apply the same concept and adjust as you want!

  void setTextWithSpan(TextView textView, String text, String spanTextBold,String secondPartItalic,String thirdPartLargeFont ,StyleSpan style) {

        SpannableStringBuilder sb = new SpannableStringBuilder(text);

        int start = text.indexOf(spanTextBold);
        int end = start + spanTextBold.length();
        sb.setSpan(style, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
        sb.setSpan(new ForegroundColorSpan(Color.BLUE), start, end ,0);

        int startTwo = text.indexOf(secondPartItalic);
        int endTwo = startTwo + secondPartItalic.length();
        sb.setSpan(new StyleSpan(Typeface.ITALIC),startTwo,endTwo , 0);

        int startThree = text.indexOf(thirdPartLargeFont);
        int endThree = startThree + thirdPartLargeFont.length();
        sb.setSpan(new RelativeSizeSpan(2.8f), startThree, endThree, 0);

        textView.setText(sb);
    }

You can call this by,

setTextWithSpan(text,"The baby name means  the meaning of the name","baby", "means","the name",new android.text.style.StyleSpan(android.graphics.Typeface.BOLD));

Output

enter image description here

Refer How to set the font style to bold, italic and underlined in an Android TextView? for extra knowledge of attributes.

Community
  • 1
  • 1
Charuක
  • 12,953
  • 5
  • 50
  • 88
  • im so lost now..... the baby name is a variable.. i think the method you posted above is only for one static piece of text i have 2 different variables and one static text im trying to do things to... description = common_name+horizontal_line_or_divder+text+mybreak+common_name_meaning; – skapaid Feb 07 '17 at 03:38
  • @skapaid have a look ^_^ – Charuක Feb 07 '17 at 03:38
  • i think setTextWithSpan(text,"the baby name means the meaning of the nam","baby",new android.text.style.StyleSpan(android.graphics.Typeface.BOLD)); handles everything at once does it not? – skapaid Feb 07 '17 at 03:38
  • no it is not static for a single text.. its just and example you can haven n number of bold ones in your string.. yes in my example it takes baby string as the one needs to be bold – Charuක Feb 07 '17 at 03:42
  • String common_name; String common_name_meaning; are pulled from a database and not static resources in my .xml strings the only text i can directly access is the word "means" however i wants to style common_name + "means" + common_name_meaning each one needs to have a different and not have the same style applied to it ... sorry if my question is confusing – skapaid Feb 07 '17 at 03:43
  • ok thank you i will try and do some more reading to see if i can understand it better, thanks for a point in the right direction! – skapaid Feb 07 '17 at 03:44
  • you dont need to have static ones i just hardcode it to grab it easily pass your string varibale then you dont need that doubble quotes – Charuක Feb 07 '17 at 03:45
  • ill add some links but im on the mobile ;) got a power cut take the example of cricket in his comment read once you know that its better than html.form one – Charuක Feb 07 '17 at 03:47
  • may be you shoud update your question by showing the expected output of the full sentence will be easy for us then ;) – Charuක Feb 07 '17 at 03:50
  • ive updated the question with my full java file and a better example of what i am trying to do – skapaid Feb 07 '17 at 04:00
  • @skapaid updated my answer! have fun ^_^ you can pass your variable insted of my hard-coded strings – Charuක Feb 07 '17 at 06:08
0

Just build your String in HTML and set it:

String sourceString = "<b>" + id + "</b> " + name; 
mytextview.setText(Html.fromHtml(sourceString));
Akp
  • 259
  • 1
  • 9
  • how do i build the string when they are already there??? it makes no sense to me.... String common_name; String common_name_meaning; long common_name_rowid; CharSequence mybreak = "\n"; CharSequence text = "Means"; CharSequence description; they are all already there how do i build a string and set it? it makes no sense to me cause i cant go String common_name = "" + common_name + " "; – skapaid Feb 07 '17 at 05:59
  • im just gonna give up on this one im still learning and teaching myself and this will kill me before i figure it out.... im sure one of the answers are right so i will leave the question up for other people incase they can use it and thanks for trying to help me out!... i've got a lot of reading to do before i understand this unfortunately – skapaid Feb 07 '17 at 06:01
0

try this,

CharSequence mybreak = "\n";
CharSequence text = "Means"; 
CharSequence description;


Bundle extras = getIntent().getExtras();

common_name_rowid = extras.getLong(CommonNamesAdapter.COMMON_NAME_ROWID );
common_name = extras.getString(CommonNamesAdapter.COMMON_NAME);
common_name_meaning = extras.getString(CommonNamesAdapter.COMMON_NAME_MEANING).toString();

description ="<b><font size=13 color=cc0029>"+common_name+"</b></font>+horizontal_line_or_divder+<b><font size=7 color=#000000>"+text+"</b></font>"+mybreak+"<b><font size=7 color=#FF6D00>"+common_name_meaning+"</b></font>";

tv.setText(Html.fromHtml((String) description));
Komal12
  • 3,340
  • 4
  • 16
  • 25
  • turns out by changing CharSequence description; to String description; it worked... dunno why... but its working now – skapaid Feb 07 '17 at 06:41
0
TextView textView = (TextView) findViewById(R.id.text_view);
SpannableString spString = new SpannableString("Background text");
spString.setSpan(new BackgroundColorSpan(Color.GREEN), 5, spString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spString);

For Detail go through this link

https://way2androidtutorials.blogspot.in/2017/08/spannablestring-is-class-its-extends.html

prabhakaran
  • 147
  • 2
  • 13
-1

i figured it out.......

to call the database resources i needed String description = "<b>" + String.valueOf(common_name) + "</b> " + String.valueOf(common_name);

and then tv.setText(Html.fromHtml(description ));

no one was adding String.valueOf(common_name) so i didnt know how to reference it

skapaid
  • 169
  • 4
  • 17
  • you figured nothing. Why you take a **String value of a String** ? it will work normally `String description = "" + common_name + " " + common_name;` – Charuක Feb 07 '17 at 08:02