Diberikan HTML berikut:
<p>This is text and this is an image <img src="http://www.example.com/image.jpg" />.</p>
Apakah mungkin membuat gambar dirender? Saat menggunakan cuplikan ini:, mContentText.setText(Html.fromHtml(text));
saya mendapatkan kotak cyan dengan batas hitam, membuat saya percaya bahwa TextView memiliki beberapa gagasan tentang apa itu tag img.
Jawaban:
Jika Anda melihat dokumentasi untuk
Html.fromHtml(text)
Anda akan melihatnya mengatakan:Jika Anda tidak ingin melakukan penggantian ini sendiri, Anda dapat menggunakan metode lain
Html.fromHtml()
yang menggunakan argumen anHtml.TagHandler
dan anHtml.ImageGetter
sebagai serta teks yang akan diurai.Dalam kasus Anda, Anda dapat mengurai
null
seperti untuk ituHtml.TagHandler
tetapi Anda harus menerapkannya sendiriHtml.ImageGetter
karena tidak ada implementasi default.Namun, masalah yang akan Anda hadapi adalah
Html.ImageGetter
kebutuhan untuk berjalan secara sinkron dan jika Anda mengunduh gambar dari web, Anda mungkin ingin melakukannya secara asinkron. Jika Anda dapat menambahkan gambar apa pun yang ingin ditampilkan sebagai sumber daya dalam aplikasi Anda,ImageGetter
implementasi Anda menjadi jauh lebih sederhana. Anda bisa lolos dengan sesuatu seperti:private class ImageGetter implements Html.ImageGetter { public Drawable getDrawable(String source) { int id; if (source.equals("stack.jpg")) { id = R.drawable.stack; } else if (source.equals("overflow.jpg")) { id = R.drawable.overflow; } else { return null; } Drawable d = getResources().getDrawable(id); d.setBounds(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight()); return d; } };
Anda mungkin ingin mencari tahu sesuatu yang lebih cerdas untuk memetakan string sumber ke ID sumber daya.
sumber
Saya telah menerapkan di aplikasi saya, banyak mengambil referensi dari pskink .thanx
package com.example.htmltagimg; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; import android.os.AsyncTask; import android.os.Bundle; import android.text.Html; import android.text.Html.ImageGetter; import android.text.Spanned; import android.util.Log; import android.widget.TextView; public class MainActivity extends Activity implements ImageGetter { private final static String TAG = "TestImageGetter"; private TextView mTv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String source = "this is a test of <b>ImageGetter</b> it contains " + "two images: <br/>" + "<img src=\"http://developer.android.com/assets/images/dac_logo.png\"><br/>and<br/>" + "<img src=\"http://www.hdwallpapersimages.com/wp-content/uploads/2014/01/Winter-Tiger-Wild-Cat-Images.jpg\">"; String imgs="<p><img alt=\"\" src=\"http://images.visitcanberra.com.au/images/canberra_hero_image.jpg\" style=\"height:50px; width:100px\" />Test Article, Test Article, Test Article, Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,v</p>"; String src="<p><img alt=\"\" src=\"http://stylonica.com/wp-content/uploads/2014/02/Beauty-of-nature-random-4884759-1280-800.jpg\" />Test Attractions Test Attractions Test Attractions Test Attractions</p>"; String img="<p><img alt=\"\" src=\"/site_media/photos/gallery/75b3fb14-3be6-4d14-88fd-1b9d979e716f.jpg\" style=\"height:508px; width:640px\" />Test Article, Test Article, Test Article, Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,v</p>"; Spanned spanned = Html.fromHtml(imgs, this, null); mTv = (TextView) findViewById(R.id.text); mTv.setText(spanned); } @Override public Drawable getDrawable(String source) { LevelListDrawable d = new LevelListDrawable(); Drawable empty = getResources().getDrawable(R.drawable.ic_launcher); d.addLevel(0, 0, empty); d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight()); new LoadImage().execute(source, d); return d; } class LoadImage extends AsyncTask<Object, Void, Bitmap> { private LevelListDrawable mDrawable; @Override protected Bitmap doInBackground(Object... params) { String source = (String) params[0]; mDrawable = (LevelListDrawable) params[1]; Log.d(TAG, "doInBackground " + source); try { InputStream is = new URL(source).openStream(); return BitmapFactory.decodeStream(is); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap bitmap) { Log.d(TAG, "onPostExecute drawable " + mDrawable); Log.d(TAG, "onPostExecute bitmap " + bitmap); if (bitmap != null) { BitmapDrawable d = new BitmapDrawable(bitmap); mDrawable.addLevel(1, 1, d); mDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); mDrawable.setLevel(1); // i don't know yet a better way to refresh TextView // mTv.invalidate() doesn't work as expected CharSequence t = mTv.getText(); mTv.setText(t); } } } }
Sesuai di bawah komentar @rpgmaker saya menambahkan jawaban ini
ya, Anda dapat melakukannya dengan menggunakan kelas ResolveInfo
periksa file Anda didukung dengan aplikasi yang sudah diinstal atau tidak
menggunakan kode di bawah ini:
private boolean isSupportedFile(File file) throws PackageManager.NameNotFoundException { PackageManager pm = mContext.getPackageManager(); java.io.File mFile = new java.io.File(file.getFileName()); Uri data = Uri.fromFile(mFile); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(data, file.getMimeType()); List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); if (resolveInfos != null && resolveInfos.size() > 0) { Drawable icon = mContext.getPackageManager().getApplicationIcon(resolveInfos.get(0).activityInfo.packageName); Glide.with(mContext).load("").placeholder(icon).into(binding.fileAvatar); return true; } else { Glide.with(mContext).load("").placeholder(R.drawable.avatar_defaultworkspace).into(binding.fileAvatar); return false; } }
sumber
Inilah yang saya gunakan, yang tidak mengharuskan Anda untuk mengubah nama sumber daya Anda dan akan mencari sumber daya yang dapat digambar terlebih dahulu di sumber daya aplikasi Anda dan kemudian di sumber daya android stok jika tidak ada yang ditemukan - memungkinkan Anda untuk menggunakan ikon default dan semacamnya.
private class ImageGetter implements Html.ImageGetter { public Drawable getDrawable(String source) { int id; id = getResources().getIdentifier(source, "drawable", getPackageName()); if (id == 0) { // the drawable resource wasn't found in our package, maybe it is a stock android drawable? id = getResources().getIdentifier(source, "drawable", "android"); } if (id == 0) { // prevent a crash if the resource still can't be found return null; } else { Drawable d = getResources().getDrawable(id); d.setBounds(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight()); return d; } } }
Yang bisa digunakan seperti itu (contoh):
String myHtml = "This will display an image to the right <img src='ic_menu_more' />"; myTextview.setText(Html.fromHtml(myHtml, new ImageGetter(), null);
sumber
source
- hati mungkin nol, dangetIdentifier()
crash dalam kasus ini. Lebih baik tambahkan pemeriksaan eksplisit.Saya menghadapi masalah yang sama dan saya telah menemukan solusi yang cukup bersih: Setelah Html.fromHtml () Anda dapat menjalankan AsyncTask yang mengulangi semua tag, mengambil gambar dan kemudian menampilkannya.
Di sini Anda dapat menemukan beberapa kode yang dapat Anda gunakan (tetapi perlu beberapa penyesuaian): https://gist.github.com/1190397
sumber
Saya menggunakan jawaban Dave Webb tetapi sedikit menyederhanakannya. Selama ID sumber daya akan tetap sama selama waktu proses dalam kasus penggunaan Anda, sebenarnya tidak perlu menulis implementasi kelas Anda sendiri
Html.ImageGetter
dan mengotak-atik string sumber.Apa yang saya lakukan adalah menggunakan ID sumber daya sebagai string sumber:
final String img = String.format("<img src=\"%s\"/>", R.drawable.your_image); final String html = String.format("Image: %s", img);
dan gunakan secara langsung:
Html.fromHtml(html, new Html.ImageGetter() { @Override public Drawable getDrawable(final String source) { Drawable d = null; try { d = getResources().getDrawable(Integer.parseInt(source)); d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); } catch (Resources.NotFoundException e) { Log.e("log_tag", "Image not found. Check the ID.", e); } catch (NumberFormatException e) { Log.e("log_tag", "Source string not a valid resource ID.", e); } return d; } }, null);
sumber
Anda juga dapat menulis parser Anda sendiri untuk menarik URL dari semua gambar dan kemudian secara dinamis membuat tampilan gambar baru dan memasukkan url.
sumber
Selain itu, jika Anda ingin melakukan pergantian sendiri, karakter yang perlu Anda cari adalah [].
Tetapi jika Anda menggunakan Eclipse, itu akan menjadi aneh saat Anda mengetik huruf itu ke dalam pernyataan [replace] yang memberi tahu Anda bahwa itu bertentangan dengan Cp1252 - ini adalah bug Eclipse. Untuk memperbaikinya, buka
dan pilih
[UTF-8]
sumber
KOTLIN
Ada juga kemungkinan untuk digunakan
sufficientlysecure.htmltextview.HtmlTextView
Gunakan seperti di bawah ini dalam file gradle:
File gradle proyek:
repositories { jcenter() }
File gradle aplikasi:
dependencies { implementation 'org.sufficientlysecure:html-textview:3.9' }
Di dalam file xml, ganti textView Anda dengan:
<org.sufficientlysecure.htmltextview.HtmlTextView android:id="@+id/allNewsBlockTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="2dp" android:textColor="#000" android:textSize="18sp" app:htmlToString="@{detailsViewModel.selectedText}" />
Baris terakhir di atas adalah jika Anda menggunakan adaptor Binding dimana kodenya akan seperti:
@BindingAdapter("htmlToString") fun bindTextViewHtml(textView: HtmlTextView, htmlValue: String) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { textView.setHtml( htmlValue, HtmlHttpImageGetter(textView, "n", true) ); } else { textView.setHtml( htmlValue, HtmlHttpImageGetter(textView, "n", true) ); } }
Info lebih lanjut dari halaman github dan terima kasih banyak untuk penulis !!!!!
sumber
Jika seseorang berpikir bahwa sumber daya harus deklaratif dan menggunakan Spannable untuk banyak bahasa berantakan, saya melakukan beberapa tampilan khusus
import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.text.Html; import android.text.Html.ImageGetter; import android.text.Spanned; import android.util.AttributeSet; import android.widget.TextView; /** * XXX does not support android:drawable, only current app packaged icons * * Use it with strings like <string name="text"><![CDATA[Some text <img src="some_image"></img> with image in between]]></string> * assuming there is @drawable/some_image in project files * * Must be accompanied by styleable * <declare-styleable name="HtmlTextView"> * <attr name="android:text" /> * </declare-styleable> */ public class HtmlTextView extends TextView { public HtmlTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HtmlTextView); String html = context.getResources().getString(typedArray.getResourceId(R.styleable.HtmlTextView_android_text, 0)); typedArray.recycle(); Spanned spannedFromHtml = Html.fromHtml(html, new DrawableImageGetter(), null); setText(spannedFromHtml); } private class DrawableImageGetter implements ImageGetter { @Override public Drawable getDrawable(String source) { Resources res = getResources(); int drawableId = res.getIdentifier(source, "drawable", getContext().getPackageName()); Drawable drawable = res.getDrawable(drawableId, getContext().getTheme()); int size = (int) getTextSize(); int width = size; int height = size; // int width = drawable.getIntrinsicWidth(); // int height = drawable.getIntrinsicHeight(); drawable.setBounds(0, 0, width, height); return drawable; } } }
melacak pembaruan, jika ada, di https://gist.github.com/logcat/64234419a935f1effc67
sumber