当前位置: 首页 > news >正文

赤峰网站策划上海建设工程咨询网官网

赤峰网站策划,上海建设工程咨询网官网,仪器网站模板,传奇手游官网之前一直把基础理论与项目实践放在一起,导致文章太长失去了阅读欲望,特此精简 关联篇 Android进阶之路 - 一串儿多样式富文本Android实战进阶 - 富文本 业务实战基础场景html 拼接(简单、便捷、适用静态显示)SpannableStringBuil…

之前一直把基础理论与项目实践放在一起,导致文章太长失去了阅读欲望,特此精简

关联篇

  • Android进阶之路 - 一串儿多样式富文本
  • Android实战进阶 - 富文本

    业务实战

      • 基础场景
        • html 拼接(简单、便捷、适用静态显示)
        • SpannableStringBuilder 拼接(基础核心,扩展性强)
      • 项目场景
        • 文本不同字号(字体大小)
        • 文本加粗、多色、含图标、点击事件
        • 未读消息的小红点
        • 文本渐变
      • 定制Span
        • MediumSmallSpan(加粗)
        • LinearGradientFontSpan(渐变)
        • ClickableSpan(点击)
      • SpannableStringBuilder扩展函数(篇中多次使用,重要!)
      • 常见问题
        • 设置字体Size和理想中有区别?
        • 样式未生效?
        • 点击事件未生效?
        • 超链接要注意什么?

可自行根据业务需求,选择适合自己的

基础场景

html 拼接(简单、便捷、适用静态显示)

在这里插入图片描述

这种方式我以前在 Android进阶之路 - 常用小功能 中有记录过,为了方便特在此重新记录一下

//主要代码Html.fromHtml("第一段文本信息" + "<font color=\"#757575\">" + "第二段文本信息(为灰色)" + "</font>")//使用方式(如要设置颜色,可以如第二段一般进行颜色填充~)mContext.setText(Html.fromHtml("希望" + "<font color=\"#757575\">" + "我们都不会老" + "</font>"));//展示结果:希望(黑色字体)、我们不会老(灰色字体)//上图效果
tvRisk.setText(Html.fromHtml("您的风险偏好是" + "<font color=\"#1760EA\">" + "C1稳健型" +  "</font>"));

SpannableStringBuilder 拼接(基础核心,扩展性强)

这里写图片描述

基础实现方式,务必掌握

package com.example.yongliu.spannablestringbuilder;import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.URLSpan;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {private TextView mContent;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContent = findViewById(R.id.content);SpannableStringBuilder data = new SpannableStringBuilder("开始的开始,我们只是孩子!表情");/* * * 创建对应的Span样式*///前景色ForegroundColorSpan forColorSpan = new ForegroundColorSpan(Color.RED);//背景色BackgroundColorSpan backColorSpan = new BackgroundColorSpan(Color.BLUE);//字体大小RelativeSizeSpan textSizeSpan = new RelativeSizeSpan(1.0f);//设置超链接URLSpan urlSpan = new URLSpan("https://blog.csdn.net/qq_20451879/article/details/80094968");//删除线StrikethroughSpan strikethroughSpan = new StrikethroughSpan();//上标SuperscriptSpan superscriptSpan = new SuperscriptSpan();//图片Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher);drawable.setBounds(0, 0, 42, 42);ImageSpan imageSpan = new ImageSpan(drawable);//设置字体StyleStyleSpan styleSpan  = new StyleSpan(Typeface.BOLD);/* * 将上方创建好的Span样式,设置到对应的角标位* start 起始角标值* end 终点角标值*///设置前景色spannableBuilder.setSpan(forColorSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);//设置背景色spannableBuilder.setSpan(backColorSpan, 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);//设置字体大小spannableBuilder.setSpan(textSizeSpan, 0, data.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);//设置删除线spannableBuilder.setSpan(strikethroughSpan, 10, 12, Spannable.SPAN_INCLUSIVE_INCLUSIVE);//设置超链接spannableBuilder.setSpan(urlSpan, 0, data.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);//设置上标spannableBuilder.setSpan(superscriptSpan, 3, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);//设置图片spannableBuilder.setSpan(imageSpan, 13, data.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);//设置字体风格spannableBuilder.setSpan(styleSpan, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);//点击spannableBuilder.setSpan(new ClickableSpan() {@Overridepublic void onClick(View view) {Toast.makeText(MainActivity.this,"我想说,你可好?",Toast.LENGTH_SHORT).show();}},0,9,Spannable.SPAN_INCLUSIVE_INCLUSIVE);mContent.setText(spannableBuilder);mContent.setMovementMethod(LinkMovementMethod.getInstance());}
}

activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.yongliu.spannablestringbuilder.MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="45dp"android:gravity="center"android:id="@+id/content"/>
</LinearLayout>

项目场景

文本不同字号(字体大小)

感觉当设置同等字体 Size 后,显示效果不同,主要是因为屏幕适配导致的,我们可以采用对应的 dp、px转换工具 试一试

实现效果

在这里插入图片描述

起初我使用的就是以下 RelativeSizeSpan 声明的字体大小,但是实验效果不佳

  val data = SpannableStringBuilder("您还未领取0折购基打折卡,无法享受\n0折购基的优惠,是否现在去领取?")val startSize = RelativeSizeSpan(13.0f)val endSize = RelativeSizeSpan(17.0f)data.setSpan(startSize, 0, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);data.setSpan(endSize, 5, data.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);content.text = data

后续我改用为 AbsoluteSizeSpan 声明的字体大小,效果不错

  val data = SpannableStringBuilder("您还未领取0折购基打折卡,无法享受\n0折购基的优惠,是否现在去领取?")data.setSpan(AbsoluteSizeSpan(13,true),0,4, Spannable.SPAN_INCLUSIVE_INCLUSIVE)data.setSpan(AbsoluteSizeSpan(17,true),5,9, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)data.setSpan(AbsoluteSizeSpan(13,true),9,data.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)content.text = data

文本加粗、多色、含图标、点击事件

Tips:通过 Kotlin扩展函数快速实现 字体颜色不同、区分加粗效果、添加图片等多样式富文本效果

场景一
在这里插入图片描述

实现方式

  val drawable = resources.getDrawable(R.drawable.icon_config_scheme_arrow_blue)drawable.setBounds(0, 0, 12.dp, 12.dp);val imageSpan = ImageSpan(drawable, ImageSpan.ALIGN_BASELINE)val spannable = SpannableStringBuilder()spannable.appendMore("#666666".toColorInt(), "根据你的风险偏好及期望的投资时长,通过资产配置测算,建议你")spannable.mediumSmall {color("#333333".toColorInt()) {append("稳健类资产配置${"40%"},权益类资产配置${"60%"}。")}}spannable.appendMore("#1760EA".toColorInt(), "了解更多>") {//如果是在组件中的话,可以直接在这里写对应逻辑,如果是在一些容器内部就需要写接口回调了!//callback?.invoke("")}spannable.setSpan(imageSpan, spannable.length-1, spannable.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)bind.tvAssetDesc.text = spannablebind.tvAssetDesc.movementMethod = LinkMovementMethod.getInstance();

场景二
在这里插入图片描述

实现方式

   //尾部图标val drawable = ContextCompat.getDrawable(this.context, R.drawable.icon_base_blue_arrow_right)var imageSpan: ImageSpan? = nulldrawable?.let {it.setBounds(0, -5, drawable.intrinsicWidth, drawable.intrinsicHeight);imageSpan = ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM)}val spannable = SpannableStringBuilder()spannable.appendMore(//data为显示的文本"#EA6B17".toColorInt(), data.string())spannable.appendMore("#1760EA".toColorInt(), "查看分红详情>") {//这里我是回调到外部组件使用的,如果在当前组件使用的话,直接写逻辑就行callback?.invoke("")}imageSpan?.let {spannable.setSpan(imageSpan, spannable.length - 1, spannable.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)}textView.text = spannabletextView.movementMethod = LinkMovementMethod.getInstance()

未读消息的小红点

TextView 尾部在特定时间加入小红点图片,此为我项目中一段代码,当做自我笔记,以防遗忘

 SpannableString spannableString = new SpannableString(content);//设置图片的方法Drawable drawable = GarageApp.getAppContext().getResources().getDrawable(R.drawable.shape_msg_red_dot);drawable.setBounds(0, 0, DeviceUtils.dp2px(GarageApp.getAppContext(), 8), DeviceUtils.dp2px(GarageApp.getAppContext(), 8));ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);spannableString.setSpan(imageSpan, content.length() - 1, content.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);tvContent.setText(spannableString);

DeviceUtils.dp2px(尺寸转换方法)

 /*** dp 转化为 px* @param context context* @param dpValue dpValue* @return int*/public static int dp2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}/*** px 转化为 dp* @param context context* @param pxValue pxValue*/public static int px2dp(Context context, float pxValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);}public static int px2sp(Context context, float pxValue) {final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (pxValue / fontScale + 0.5f);}public static int sp2px(Context context, float spValue) {final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (spValue * fontScale + 0.5f);}

文本渐变

  //渐变色值组private val titleColors = intArrayOf("#F0F3FF".toColorInt(), "#9BB3FF".toColorInt())//设置效果textView.text = buildSpannedString { linearGradient(colors = titleColors, orientation = LinearGradientFontSpan.VERTICAL) { append("能幼稚一生,何尝不是一种幸福}") }}

定制Span

MediumSmallSpan(加粗)

import android.graphics.Paint
import android.text.TextPaint
import android.text.style.MetricAffectingSpanclass MediumSmallSpan : MetricAffectingSpan() {override fun updateDrawState(paint: TextPaint?) = apply(paint)override fun updateMeasureState(paint: TextPaint) = apply(paint)private fun apply(paint: Paint?) {if (paint == null) returnpaint.strokeWidth = 0.6fpaint.style = Paint.Style.FILL_AND_STROKE}}

LinearGradientFontSpan(渐变)

import android.graphics.Canvas
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Shader
import android.text.style.ReplacementSpan
import android.widget.LinearLayoutclass LinearGradientFontSpan(val colors: IntArray, val orientation: Int = HORIZONTAL) : ReplacementSpan() {companion object {const val HORIZONTAL = LinearLayout.HORIZONTAL   // 水平渐变方向const val VERTICAL = LinearLayout.VERTICAL       // 垂直渐变方向}private var mMeasureTextWidth = 0  // 测量的文本宽度override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fontMetricsInt: Paint.FontMetricsInt?): Int {mMeasureTextWidth = paint.measureText(text ?: "", start, end).toInt()// 这段不可以去掉,字体高度没设置,会出现 draw 方法没有被调用的问题// 详情请见:https://stackoverflow.com/questions/20069537/replacementspans-draw-method-isnt-calledval metrics = paint.fontMetricsfontMetricsInt?.top = metrics.top.toInt()fontMetricsInt?.ascent = metrics.ascent.toInt()fontMetricsInt?.descent = metrics.descent.toInt()fontMetricsInt?.bottom = metrics.bottom.toInt()return mMeasureTextWidth}override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {if (text.isNullOrEmpty()) returnval linearGradient = if (orientation == VERTICAL) {LinearGradient(0f, 0f, 0f, paint.descent() - paint.ascent(), colors, null, Shader.TileMode.REPEAT)} else {LinearGradient(x, 0f, x + mMeasureTextWidth, 0f, colors, null, Shader.TileMode.REPEAT)}val shader = paint.shaderval alpha = paint.alpha//paint.shader = linearGradientpaint.alpha = 255                    //  如果是则设置不透明//canvas.drawText(text, start, end, x, y.toFloat(), paint)//绘制完成之后将画笔的透明度还原回去paint.shader = shaderpaint.alpha = alpha}}

ClickableSpan(点击)

import android.text.TextPaint
import android.view.View
import cn.com.huaan.fund.acts.core.android.listener.OnClickWrapListenerclass ClickableSpan(val listener: View.OnClickListener) : android.text.style.ClickableSpan() {override fun onClick(widget: View) {OnClickWrapListener(listener).onClick(widget)}override fun updateDrawState(ds: TextPaint) {ds.isUnderlineText = false}
}

SpannableStringBuilder扩展函数(篇中多次使用,重要!)

package cn.com.xximport android.graphics.Typeface
import android.os.Build
import android.text.SpannableStringBuilder
import android.text.style.*
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.RequiresApi
import androidx.core.graphics.toColorInt
import androidx.core.text.inSpans
import cn.com.huaan.fund.acts.core.android.text.spannable.ClickableSpan
import cn.com.huaan.fund.acts.core.android.text.spannable.LinearGradientFontSpan
import cn.com.huaan.fund.acts.core.android.text.spannable.MediumSmallAndLSpan
import cn.com.huaan.fund.acts.core.android.text.spannable.MediumSmallSpaninline fun SpannableStringBuilder.mediumSmall(builderAction: SpannableStringBuilder.() -> Unit
) = inSpans(MediumSmallSpan(), builderAction = builderAction)inline fun SpannableStringBuilder.mediumSmallAndRelativeSize(builderAction: SpannableStringBuilder.() -> Unit
) = inSpans(MediumSmallAndLSpan(), builderAction = builderAction)inline fun SpannableStringBuilder.linearGradient(colors: IntArray, orientation: Int = LinearGradientFontSpan.HORIZONTAL, builderAction: SpannableStringBuilder.() -> Unit
): SpannableStringBuilder {return inSpans(LinearGradientFontSpan(colors, orientation), builderAction = builderAction)
}inline fun SpannableStringBuilder.clickable(listener: View.OnClickListener, builderAction: SpannableStringBuilder.() -> Unit
): SpannableStringBuilder {return inSpans(ClickableSpan(listener), builderAction = builderAction)
}//
fun SpannableStringBuilder.appendClickable(text: CharSequence, listener: View.OnClickListener
): SpannableStringBuilder = inSpans(ClickableSpan(listener)) { append(text) }fun SpannableStringBuilder.appendColor(@ColorInt color: Int,text: CharSequence,
): SpannableStringBuilder = inSpans(ForegroundColorSpan(color)) { append(text) }fun SpannableStringBuilder.appendStrikeThrough(text: CharSequence,
): SpannableStringBuilder = inSpans(StrikethroughSpan()) { append(text) }fun SpannableStringBuilder.appendRelativeSize(proportion: Float,text: CharSequence,
): SpannableStringBuilder = inSpans(RelativeSizeSpan(proportion)) { append(text) }fun SpannableStringBuilder.appendAbsoluteSize(proportion: Int,text: CharSequence,
): SpannableStringBuilder = inSpans(AbsoluteSizeSpan(proportion, true)) { append(text) }//
fun SpannableStringBuilder.appendMore(@ColorInt color: Int? = null,text: CharSequence,listener: View.OnClickListener? = null,
): SpannableStringBuilder {val spans = mutableListOf<Any>()color?.also { spans.add(ForegroundColorSpan(color)) }listener?.also { spans.add(ClickableSpan(listener)) }inSpans(*spans.toTypedArray()) { append(text) }return this
}fun SpannableStringBuilder.appendMediumSmallMore(@ColorInt color: Int? = null,text: CharSequence,listener: View.OnClickListener? = null,
): SpannableStringBuilder {val spans = mutableListOf<Any>()color?.also { spans.add(ForegroundColorSpan(color)) }listener?.also { spans.add(ClickableSpan(listener)) }spans.add(MediumSmallSpan())inSpans(*spans.toTypedArray()) { append(text) }return this
}fun SpannableStringBuilder.appendLabel(@ColorInt color: Int? = null,text: String,listener: View.OnClickListener? = null,
): SpannableStringBuilder {val splits = text.replace("</b>", "<b>").split("<b>")splits.forEachIndexed { index, s ->if (index % 2 == 1) {appendMore(color = color, s, listener)} else {append(s)}}return this
}@RequiresApi(Build.VERSION_CODES.P)
fun SpannableStringBuilder.appendTypeface(typeface: Typeface,text: CharSequence,
) = inSpans(TypefaceSpan(typeface)) { append(text) }fun SpannableStringBuilder.appendColorAbsoluteSizeMediumSmall(text: CharSequence,@ColorInt color: Int? = "#333333".toColorInt(),proportion: Int = 14,
): SpannableStringBuilder {val spans = mutableListOf<Any>()color?.also { spans.add(ForegroundColorSpan(color)) }proportion.also { spans.add(AbsoluteSizeSpan(proportion, true)) }spans.add(MediumSmallSpan())inSpans(*spans.toTypedArray()) { append(text) }return this
}

常见问题

可能是常见使用场景,也可能常见的出错场景,希望可以帮到你我

设置字体Size和理想中有区别?

提示:我在项目中有一个需求是不同区间,字体显示的大小有所区别,在使用 RelativeSizeSpan 方式设置后,效果不太理想,后续改为了AbsoluteSizeSpan 方式(具体实现在该篇的项目经验

  val data = SpannableStringBuilder("少年可知,鲜衣怒马?")val startSize = RelativeSizeSpan(13.0f)val endSize = RelativeSizeSpan(17.0f)data.setSpan(startSize, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);data.setSpan(endSize, 5, data.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);content.text = data

样式未生效?

设置文本时 不能使用后builder的toString()方法!!! ,如果您这样做了,那么辛辛苦苦设置的样式可能就被覆盖了,并不会显示出来

  1. 首先检查是否设置对应的 Span,区间是否为有效区间?
  2. 设置 span 后,是否有调用toString()方法?

点击事件未生效?

设置了点击事件却无效的时候, 查看是否有 setMovementMethod,如没有的话,那么像下面一样进行设置

  //mContent TextView控件mContent.setMovementMethod(LinkMovementMethod.getInstance());

超链接要注意什么?

  1. 如果要使用超链接的设置,需要同时设置点击事件,不然无法触发!
  2. 如果超链接在点击事件内生效的话,那么会优先超链接,同时消耗此事件,其他操作点击操作将无法触发(个人Demo察觉)
  3. 超链接正常跳转之后你会发现你没有加入Intent的网络权限!神不神奇!~
http://www.dtcms.com/a/464265.html

相关文章:

  • 超炫网站欣赏信息流优化师是什么
  • 网站备案需要多久安全的网站
  • 杭州做网站的新乐企业网站建设
  • 优秀的网站有哪些阜阳企业网站推广
  • 阿里云模板建站怎么样做程序员需要什么条件
  • 做网站需要懂哪些语言自适应网站开发教程
  • 厦门电信网站备案那个网站上找工程造价私活做
  • 江苏省现代化示范校建设网站大专学广告设计有用吗
  • 免费网站seo软件网站空间到期时间查询
  • 棋牌论坛网站怎么做建设局主要负责什么
  • 怎么进行网站备案成都网站建设及推广
  • 网站推广的优点网站空间提供商
  • 建网站公司锦程免费咨询服务费合同范本
  • 单页网站排名广告推广媒体
  • 温州市营销网站建设建设银行哈尔滨分行网站
  • 化妆品网站建设案例企业建设网站的
  • 极速云建站中国航发网上商城废旧物资
  • 13个优质平面设计网站推荐软文营销的优势
  • 郑州视频网站建设大概多少钱南昌seo站内优化
  • 自己做一个购物网站给公司建网站 深圳
  • 学网站开发难吗网站建设行业的前景
  • html5 wap网站网站显示内容不显示
  • 做网站需要固定ip么平台网站模板素材图片
  • 如何做网站301重定向寻找昆明网站建设
  • 求个网站没封的2021教育网站开发文档
  • 石排做网站中国外贸企业100强
  • 北京什么网站找工作网站建站加盟
  • 网站建设基本技术媒介平台
  • 用什么做公司宣传网站北京注册公司哪个区好
  • 网站提示建设中黑wordpress网站