Android Studio中获取API数据后修改HTML属性的方法
修改Html.fromHtml()渲染的HTML链接样式方案
我通过API获取到包含HTML格式文本的食谱数据,其中summary字段带有<b>和<a>标签。目前用Html.fromHtml()方法将其渲染为可样式化文本显示,但希望修改其中链接的颜色等属性。
API返回数据示例
{"id": 4632,"title": "Soy-and-Ginger-Glazed Salmon with Udon Noodles","summary": "Soy-and-Ginger-Glazed Salmon with Udon Noodles might be a good recipe to expand your main course collection. This dairy free and pescatarian recipe serves 4 and costs <b>$5.91 per serving</b>. One serving contains <b>552 calories</b>, <b>48g of protein</b>, and <b>17g of fat</b>. 1 person were impressed by this recipe. From preparation to the plate, this recipe takes roughly <b>1 hour and 35 minutes</b>. This recipe from Food and Wine requires sesame seeds, lime juice, olive oil, and salmon fillets. Taking all factors into account, this recipe <b>earns a spoonacular score of 92%</b>, which is great. If you like this recipe, take a look at these similar recipes: <a href=\"https://spoonacular.com/recipes/soy-and-ginger-glazed-salmon-with-udon-noodles-1309259\">Soy-and-Ginger-Glazed Salmon with Udon Noodles</a>, <a href=\"https://spoonacular.com/recipes/soy-and-ginger-glazed-salmon-with-udon-noodles-1360935\">Soy-and-Ginger-Glazed Salmon with Udon Noodles</a>, and <a href=\"https://spoonacular.com/recipes/soy-and-ginger-glazed-salmon-with-udon-noodles-1321839\">Soy-and-Ginger-Glazed Salmon with Udon Noodles</a>."}
当前代码实现(RecipeDetails.java)
private final RecipeDetailsListeners recipeDetailsListeners = new RecipeDetailsListeners() { @SuppressLint("SetTextI18n") @Override public void didFetch(RecipeDetailsResponse response, String message) { Picasso.get().load(response.image).into(recipeImage); RecipeName.setText(response.title); recipeSource.setText(response.sourceName); if (response.sourceName == null){ recipeSource.setText("Unknown"); } recipeServing.setText(response.servings + " Serving"); recipeTimePrepared.setText(response.readyInMinutes + " Min"); recipeScore.setText(String.valueOf(response.aggregateLikes) + " Likes"); recipeSummary.setText(Html.fromHtml(response.summary, Html.FROM_HTML_MODE_COMPACT)); IngredientListRecipeDetails.setHasFixedSize(true); IngredientListRecipeDetails.setLayoutManager(new LinearLayoutManager(getBaseContext(), LinearLayoutManager.VERTICAL, false )); adapter = new recipeDetailsIngredientAdapter(getBaseContext(), response.extendedIngredients); IngredientListRecipeDetails.setAdapter(adapter); } @Override public void didError(String message) { customToast("Unsuccessful", message, "Failure"); } };
解决方案
方法1:自定义TagHandler处理a标签
实现Html.TagHandler接口,在HTML解析阶段为a标签设置自定义颜色:
public class CustomTagHandler implements Html.TagHandler { private int linkColor; public CustomTagHandler(int linkColor) { this.linkColor = linkColor; } @Override public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { if (tag.equalsIgnoreCase("a") && !opening) { int start = output.length(); int end = output.length(); // 定位链接文本的起止位置 while (start > 0 && output.charAt(start - 1) != '<') { start--; } while (end < output.length() && output.charAt(end) != '>') { end++; } // 设置链接颜色 output.setSpan(new ForegroundColorSpan(linkColor), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } }
修改调用Html.fromHtml()的代码:
// 替换原有的recipeSummary.setText(...) int customLinkColor = ContextCompat.getColor(getBaseContext(), R.color.your_custom_color); Spanned htmlSpanned = Html.fromHtml(response.summary, Html.FROM_HTML_MODE_COMPACT, null, new CustomTagHandler(customLinkColor)); recipeSummary.setText(htmlSpanned);
方法2:直接修改HTML字符串,添加style属性
对response.summary中的a标签进行字符串替换,插入颜色样式:
String modifiedSummary = response.summary.replace("<a href=\"", "<a style=\"color:#FF5722;\" href=\""); recipeSummary.setText(Html.fromHtml(modifiedSummary, Html.FROM_HTML_MODE_COMPACT));
注:将#FF5722替换为你需要的颜色值。
方法3:修改已渲染的Spanned对象
先获取Html.fromHtml()的渲染结果,再遍历替换其中的URLSpan样式:
Spanned originalSpanned = Html.fromHtml(response.summary, Html.FROM_HTML_MODE_COMPACT); SpannableStringBuilder spannableBuilder = new SpannableStringBuilder(originalSpanned); URLSpan[] urlSpans = spannableBuilder.getSpans(0, originalSpanned.length(), URLSpan.class); for (URLSpan urlSpan : urlSpans) { int start = spannableBuilder.getSpanStart(urlSpan); int end = spannableBuilder.getSpanEnd(urlSpan); spannableBuilder.removeSpan(urlSpan); // 创建自定义样式的URLSpan spannableBuilder.setSpan(new URLSpan(urlSpan.getURL()) { @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); ds.setColor(ContextCompat.getColor(getBaseContext(), R.color.your_custom_color)); ds.setUnderlineText(false); // 可选:去掉链接下划线 } }, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } recipeSummary.setText(spannableBuilder);
内容的提问来源于stack exchange,提问作者Muhammad Zarith
相关产品推荐
相关产品推荐

