ghertyish ghertyish - 4 months ago 87
JSON Question

How to replace text with an image from a url in Android?

I have an app which is reading its information from a json file online, the format of which is like so:

{
"title":"Title",
"introParagraph":"Text for introParagraph",
"heading1":"Text for heading1",
"paragraph1":"Text for paragraph1 \n\n image1"
"heading2":"Text for heading2",
"paragraph2":"Text for paragraph2 \n\n image2"
"image1":"http://url.for.image1",
"image2":"http://url.for.image2",
},


I've shortened the json for simplicity. Each json object can have up to 7 headings and paragraphs and 5 images though they don't all have this and some don't have any images.

I'm trying to find a way to check if any of the paragraphs contain the text "image1", "image2", "image3" etc. and if so to replace it with the image from the url correlating to that key.

I've found similar questions such as this: How to replace String with an image inside an EditText?, however that shows how to replace the text with a drawable not an image from a url (i'm using Picasso to make this easier but I still don't know how to replace the text).

My layout file looks like this:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">

<LinearLayout android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="300dp">

<TextView
android:id="@+id/wiki_header_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</RelativeLayout>

<TextView
android:id="@+id/wiki_intro_paragraph"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/wiki_heading1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/wiki_paragraph1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/wiki_heading2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/wiki_paragraph2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</LinearLayout>

</ScrollView>


just with more formatting and the headings and paragraphs go up to 7.

I can't put imageViews into my layout file because I don't know whether there will be any images from the json or where the text to be replaced will appear in the json i.e. sometimes the "image1" text is in the middle of the paragraph text, sometimes "image1" is in "paragraph1" sometimes it is in "paragraph7" etc.

Any help would be appreciated.




Update: Based on the answers below I am now working with this code:

private WikiItem mWikiItem;
private TextView mHeading1;
private TextView mParagraph1;
private Drawable image0;

@Override
protected void onCreate(Bundle savedInstanceBundle) {
super.onCreate(savedInstanceBundle);

mHeading1 = (TextView) findViewById(R.id.wiki_heading1);
mParagraph1 = (TextView) findViewById(R.id.wiki_paragraph1);

if (!(mWikiItem.getHeading1() == null)) {
mHeading1.setText(mWikiItem.getHeading1());
mParagraph1.setText(mWikiItem.getParagraph1());
} else {
mHeading1.setVisibility(View.GONE);
mParagraph1.setVisibility(View.GONE);
}

if (!(mWikiItem.getImage0() == null)) {
Picasso.with(this)
.load(Uri.parse(mWikiItem.getImage0()))
.into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
image0 = new BitmapDrawable(getResources(), bitmap);
}

@Override
public void onBitmapFailed(Drawable errorDrawable) {

}

@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {

}
});

ImageSpan span;
String abc = mParagraph1.getText().toString();
SpannableString ss = new SpannableString(abc);
for(int i = 0; i<abc.length();i++){//loop to check presence of other emoji strings.
if (abc.contains("image0")){
int startSpan = abc.indexOf("image0");
image0.setBounds(0, 0, image0.getIntrinsicWidth(), image0.getIntrinsicHeight());
span = new ImageSpan(image0, ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, startSpan, startSpan+2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
abc = abc.replaceFirst("image0"," "); //replace with two blank spaces.
}
//to check other types of emoji, use else if ladder and place the similar code.
}
mParagraph1.append(ss);
}
}


but I keep getting a Null Pointer error on the drawable "image0":

java.lang.RuntimeException: Unable to start activity ComponentInfo{xyz.jameslester.cryptozoologytoday/xyz.jameslester.cryptozoologytoday.WikiSection.WikiDetailActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicWidth()' on a null object reference


and I can't figure out why.




Update 2: Seems the way to fix it is by putting the code at the end within the internal method "onBitmapLoaded":

Picasso.with(this)
.load(uri2)
.into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Drawable image0 = new BitmapDrawable(getResources(), bitmap);

ImageSpan span;
String abc = mParagraph1.getText().toString();
SpannableString ss = new SpannableString(abc);

for(int i = 0; i<abc.length();i++){//loop to check presence of other emoji strings.
if (abc.contains("image0")){
int startSpan = abc.indexOf("image0");
image0.setBounds(0, 0, image0.getIntrinsicWidth(), image0.getIntrinsicHeight());
span = new ImageSpan(image0, ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, startSpan, startSpan+2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
abc = abc.replaceFirst("image0"," "); //replace with two blank spaces.
}

}
mParagraph1.append(ss);
}

@Override
public void onBitmapFailed(Drawable errorDrawable) {

}

@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {

}
});

Answer

Create drawable from bitmap :

Drawable drawable;
Picasso.with(this)
   .load("youUrl")
   .into(new Target() {
       @Override
       public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
          drawable = new BitmapDrawable(getResources(), bitmap);
       }

       @Override
       public void onBitmapFailed(Drawable errorDrawable) {

       }

       @Override
       public void onPrepareLoad(Drawable placeHolderDrawable) {

       }
   });

And then use it on span like the link you provided.

Comments