日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android 自定義 View 中使用 Spannable的實例詳解

瀏覽:107日期:2022-09-24 08:57:58

我們都知道 Android 中使用 Spannable 可以實現 TextView 富文本的顯示,但是在自定義控件中如何使用 Spannable 繪制不同樣式的文字呢?

Android 自定義 View 中使用 Spannable的實例詳解

例如這種效果,標題中的 分數字61 是粗體,分 是常規字體,并且相對于 61 更小些。第一反應可能是使用 SpannableString.setSpan() 設置 RelativeSizeSpan, 然后在 onDraw() 中進行繪制,事實是這樣實現是沒有效果的,因為 onDraw() 中只能獲取到 SpannableString 中的內容,拿不到 Span.

那如何在自定義View 中使用 Spannable 呢? 答案就是系統提供的 Layout 類,

/** * A base class that manages text layout in visual elements on * the screen. * <p>For text that will be edited, use a {@link DynamicLayout}, * which will be updated as the text changes. * For text that will not change, use a {@link StaticLayout}. */public abstract class Layout { }

Android 自定義 View 中使用 Spannable的實例詳解

Android 自定義 View 中使用 Spannable的實例詳解

可以看到 Layout 是一個抽象類,有三個子類,可以實現一些自動換行的顯示效果。

BoringLayout DynamicLayout StaticLayout

實現代碼

1. 定義自定義屬性

<?xml version='1.0' encoding='utf-8'?><resources> <declare-styleable name='ArcProgressView'> <attr name='arcBackgroundColor' format='color' /> <attr name='arcProgressColor' format='color' /> <attr name='arcSubTitleColor' format='color' /> <attr name='arcStrokeWidth' format='dimension' /> <attr name='arcTitleTextSize' format='dimension' /> <attr name='arcSubTitleTextSize' format='dimension' /> <attr name='arcProgress' format='float' /> <attr name='arcTitleNumber' format='integer' /> </declare-styleable></resources>

2. 繼承 View, 在 onDraw() 中繪制

public class ArcProgressView extends View { private int arcBackgroundColor; // 圓弧背景顏色 private int arcProgressColor; // 圓弧進度顏色 private int arcSubTitleColor; // 副標題顏色 private float arcStrokeWidth; // 圓弧線的厚度 private float arcTitleTextSize; // 標題文字大小 private float arcSubTitleTextSize; // 副標題文字大小 private float arcProgress; // 進度 private int arcTitleNumber; // 值 private Paint paint; private float centerX; private float centerY; private float radius; // 半徑 private RectF rectF; private int startAngle = 135; private int sweepAngle = 270; private String subTitle = '1月份'; private SpannableString spannableString; private TextPaint textPaint; private RelativeSizeSpan relativeSizeSpan; private DynamicLayout dynamicLayout; private String text = '11分'; private StyleSpan styleSpan; private float curProgress; // 當前進度 private int curNumber; public ArcProgressView(Context context) { this(context, null); } public ArcProgressView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ArcProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); readAttrs(context, attrs); init(context); } private void readAttrs(Context context, AttributeSet attributeSet) { TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.ArcProgressView); arcBackgroundColor = typedArray.getColor(R.styleable.ArcProgressView_arcBackgroundColor, 0x1c979797); arcProgressColor = typedArray.getColor(R.styleable.ArcProgressView_arcProgressColor, 0xff3372FF); arcSubTitleColor = typedArray.getColor(R.styleable.ArcProgressView_arcSubTitleColor, 0x66000000); arcStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.ArcProgressView_arcStrokeWidth, dp2px(5)); arcTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.ArcProgressView_arcTitleTextSize, dp2px(30)); arcSubTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.ArcProgressView_arcSubTitleTextSize, dp2px(14)); arcProgress = typedArray.getFloat(R.styleable.ArcProgressView_arcProgress, 1.0f); arcTitleNumber = typedArray.getInt(R.styleable.ArcProgressView_arcTitleNumber, 100); typedArray.recycle(); } private void init(Context context) { paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStrokeCap(Paint.Cap.ROUND); relativeSizeSpan = new RelativeSizeSpan(0.6f); styleSpan = new StyleSpan(android.graphics.Typeface.BOLD); textPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); textPaint.setColor(arcProgressColor);// textPaint.setTextAlign(Paint.Align.CENTER); // 設置該屬性導致文字間有間隔 textPaint.setTextSize(sp2px(22)); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); centerX = w / 2f; centerY = h / 2f; radius = (Math.min(w, h) - arcStrokeWidth) / 2f; rectF = new RectF(-radius, -radius, radius, radius); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredSize(widthMeasureSpec, dp2px(100)); int height = getMeasuredSize(heightMeasureSpec, dp2px(100)); setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 繪制圓弧和進度 drawArc(canvas); // 繪制文字 title drawTitleText(canvas); // 繪制文字副標題 drawSubTitle(canvas); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); startAnimation(); } private void startAnimation() { ValueAnimator progressAnimator = ValueAnimator.ofFloat(0f, arcProgress); ValueAnimator numberAnimator = ValueAnimator.ofInt(0, arcTitleNumber); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { curProgress = (float) animation.getAnimatedValue(); invalidate(); } }); numberAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { curNumber = (int) animation.getAnimatedValue(); text = curNumber + '分'; } }); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(progressAnimator, numberAnimator); animatorSet.setDuration(700); animatorSet.setInterpolator(new LinearInterpolator()); animatorSet.start(); } private void drawSubTitle(Canvas canvas) { canvas.save(); canvas.translate(centerX, centerY); paint.setTextSize(arcSubTitleTextSize); paint.setTextAlign(Paint.Align.CENTER); paint.setColor(arcSubTitleColor); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(0); canvas.drawText(subTitle, 0, 60, paint); canvas.restore(); } private void drawArc(Canvas canvas) { canvas.save(); canvas.translate(centerX, centerY); paint.setColor(arcBackgroundColor); paint.setStrokeWidth(arcStrokeWidth); paint.setStyle(Paint.Style.STROKE); canvas.drawArc(rectF, startAngle, sweepAngle, false, paint); paint.setColor(arcProgressColor); canvas.drawArc(rectF, startAngle, sweepAngle * curProgress, false, paint); canvas.restore(); } private void drawTitleText(Canvas canvas) { canvas.save(); textPaint.setTextSize(arcTitleTextSize); float textWidth = textPaint.measureText(text); // 文字寬度 float textHeight = -textPaint.ascent() + textPaint.descent(); // 文字高度 // 由于 StaticLayout 繪制文字時,默認畫在Canvas的(0,0)點位置,所以居中繪制居中位置,需要將畫布 translate到中間位置。 canvas.translate(centerX - textWidth * 2 / 5f, centerY - textHeight * 2 / 3f); spannableString = SpannableString.valueOf(text); spannableString.setSpan(styleSpan, 0, text.length() - 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); spannableString.setSpan(relativeSizeSpan, text.length() - 1, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); dynamicLayout = new DynamicLayout(spannableString, textPaint, getWidth(), Layout.Alignment.ALIGN_NORMAL, 0, 0, false); dynamicLayout.draw(canvas); canvas.restore(); } /** * 對外提供方法,設置進度 * * @param percent */ public void setArcProgress(float percent) { this.curProgress = percent; invalidate(); } private int getMeasuredSize(int measureSpec, int defvalue) { int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); if (mode == MeasureSpec.EXACTLY) { return size; } return Math.min(size, defvalue); } private int dp2px(int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); } private int sp2px(int sp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()); }}

3. 在布局中引用

<com.xing.bottomsheetsample.ArcProgressView android:layout_width='match_parent' android:layout_height='100dp' android:layout_marginTop='20dp' app:arcProgress='0.6' app:arcSubTitleTextSize='14sp' app:arcTitleNumber='61' app:arcTitleTextSize='28sp' />

總結

到此這篇關于Android 自定義 View 中使用 Spannable的文章就介紹到這了,更多相關Android 使用 Spannable內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
97欧美在线视频| 香蕉精品视频在线观看| 欧美日韩国产一区精品一区| 国产一区二区三区四区| 国产精品分类| 精品亚洲a∨| 女生影院久久| 国产一区亚洲| 国产精品女主播一区二区三区| jiujiure精品视频播放| 伊人影院久久| 在线日韩成人| 久久精品凹凸全集| 九九99久久精品在免费线bt| 国产精品毛片一区二区在线看| 色在线中文字幕| 亚洲不卡av不卡一区二区| 尤物在线精品| 欧美精品中文| 亚洲91精品| 91久久精品无嫩草影院| 亚洲女同av| 亚洲欧美专区| 伊人久久国产| 日本va欧美va瓶| 亚洲播播91| 97精品资源在线观看| 伊人精品一区| 国产日韩三级| 黄色亚洲大片免费在线观看| 国产精品男女| 国产超碰精品| 国产精品中文字幕制服诱惑| 色综合www| 婷婷成人av| 电影亚洲精品噜噜在线观看| 人人爱人人干婷婷丁香亚洲| 秋霞影院一区二区三区| 国产精品入口久久| 在线视频亚洲欧美中文| 久久久久国产一区二区| 欧美在线精品一区| 激情久久婷婷| 91视频久久| 国产精品日韩精品中文字幕| 先锋影音久久久| 久久只有精品| 国产精品久久久久久妇女| 麻豆精品网站| 欧美成人高清| 久久精品国产68国产精品亚洲| 欧美激情久久久久久久久久久| 蜜臀久久久久久久| 日韩一区二区免费看| 久久男女视频| 欧美aa在线观看| 福利一区和二区| 国产一区二区三区日韩精品 | 中文精品电影| 欧美福利一区| 久久精品成人| 999久久久亚洲| 激情综合自拍| 欧美特黄一区| 蘑菇福利视频一区播放| 好吊日精品视频| 蜜桃av一区二区三区电影| 在线免费观看亚洲| 日韩在线黄色| 国产精品久久久久久久久久白浆| 国产剧情一区| 国产91在线精品| 国产日韩电影| 国产高清久久| 亚洲在线一区| 蜜桃传媒麻豆第一区在线观看| 国产亚洲精品久久久久婷婷瑜伽| 99pao成人国产永久免费视频 | 日韩专区一卡二卡| 日本不卡视频在线| 牛牛精品成人免费视频| 久久久久久色| 精品一区二区男人吃奶| 久久精品导航| 视频在线在亚洲| 国产精品v日韩精品v欧美精品网站| 国产精品中文字幕亚洲欧美| 91一区二区三区四区| 亚洲电影在线一区二区三区| 石原莉奈在线亚洲三区| 精品国产一区二区三区性色av| 群体交乱之放荡娇妻一区二区| 视频一区中文字幕国产| 国产精品777777在线播放| 亚洲1234区| 国产欧美一区二区精品久久久| 色网在线免费观看| 日韩高清在线不卡| 香蕉久久99| 国产精品九九| 欧美精品一区二区三区精品| 亚洲另类av| 不卡福利视频| 国产乱人伦丫前精品视频| 日韩视频一区| 天堂а√在线最新版中文在线| 亚洲九九精品| 午夜免费一区| 日韩电影免费网站| 另类小说一区二区三区| 视频在线观看国产精品| 日韩另类视频| 麻豆视频一区| 欧美一级二级视频| 国产美女一区| 激情欧美日韩一区| 成人台湾亚洲精品一区二区 | 国产精品扒开腿做爽爽爽软件| 视频一区在线播放| 99热精品在线| 蜜臀91精品国产高清在线观看| 精品国产乱码久久久| 免费精品一区| 国产精品毛片aⅴ一区二区三区| 综合激情网站| 蜜臀国产一区二区三区在线播放| 激情综合网五月| 久久www成人_看片免费不卡| 亚洲激情社区| 国产视频亚洲| 免费久久久久久久久| 久久一区二区中文字幕| 国产+成+人+亚洲欧洲在线| 国产欧美日韩一级| 日本在线视频一区二区| 四虎成人精品一区二区免费网站| 亚洲涩涩av| 国产欧美三级| 国产一区二区三区四区| 日韩精品dvd| 在线一区电影| 亚洲18在线| 国产精品99精品一区二区三区∴| 麻豆成人av在线| 欧美亚洲国产激情| 亚洲午夜久久久久久尤物| 黄色日韩在线| 国产调教精品| 性欧美xxxx免费岛国不卡电影| 欧美专区一区二区三区| 国产精品亚洲二区| 亚洲播播91| 日本精品一区二区三区在线观看视频| 国产精品黄网站| 欧美不卡在线| 国产精品欧美三级在线观看| 黄色在线网站噜噜噜| 免费看的黄色欧美网站| 欧美91在线|欧美| 亚洲欧美日韩国产综合精品二区| 老鸭窝亚洲一区二区三区| 国产精品videosex极品| 在线日韩电影| 国产精品亚洲四区在线观看 | 国产精品97| 精品亚洲成人| 综合一区二区三区| 欧美一区二区三区激情视频| 97久久超碰| 丝袜美腿亚洲一区| 精品国产免费人成网站| 日韩黄色在线观看| 午夜久久黄色| 麻豆一区在线| 欧美日韩一区二区三区四区在线观看 | 久久久久国产精品一区二区| 亚洲三区欧美一区国产二区| 一本大道色婷婷在线| 国产欧美一区二区三区精品观看 | 国产精品密蕾丝视频下载| 麻豆9191精品国产| 99久久夜色精品国产亚洲1000部| 国产欧美三级| 欧美永久精品| 91精品丝袜国产高跟在线| 久久高清一区| 在线亚洲观看| 日韩一区二区久久| 黄色成人精品网站| 99热免费精品| 国产精品免费看| 欧美日韩国产综合网| 黄色亚洲免费| 日韩一级不卡| 999在线观看精品免费不卡网站| 欧美日韩在线网站| 亚洲一区二区三区免费在线观看 | 亚洲ww精品| 国产日韩欧美一区二区三区| 日韩一二三区在线观看|