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

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

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

瀏覽:104日期: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久久,三上悠亚国产精品一区二区三区
精品国产欧美日韩| 国产精品调教| 日韩精品永久网址| 精品视频亚洲| 久久久久免费| 电影91久久久| 国产精品xx| 日韩av自拍| 久久久久美女| 尤物精品在线| 石原莉奈一区二区三区在线观看| 日韩精品一级中文字幕精品视频免费观看 | 麻豆视频在线看| 麻豆国产在线| 丝袜av一区| 激情综合自拍| 亚洲综合丁香| 蜜桃视频一区二区三区在线观看| 中文字幕av一区二区三区人| 日本成人在线视频网站| 欧美天堂在线| 91欧美在线| 今天的高清视频免费播放成人| 五月天综合网站| 中文视频一区| 国产精品丝袜在线播放| 福利视频一区| 国产精品美女| 国产另类在线| 日韩久久精品| 亚洲一区二区三区无吗| 欧美在线91| 神马久久午夜| 久久亚洲图片| 美日韩一区二区三区| 99久久精品费精品国产| 蜜臀av性久久久久蜜臀aⅴ四虎| 天堂av一区| 色一区二区三区四区| 亚洲综合电影一区二区三区| 国产精选久久| 国产99亚洲| 国产一精品一av一免费爽爽| 日韩免费福利视频| 亚洲综合另类| 国产黄色一区| 婷婷成人基地| 国产日韩欧美一区| 亚洲手机视频| 国产精品成人国产| 亚洲精品123区| 国产精品1luya在线播放| 99精品电影| 在线看片日韩| 亚洲精品福利电影| 亚洲狼人精品一区二区三区| 精品国产一区二区三区2021| 国产精品毛片一区二区三区| 欧美国产三级| 久久午夜精品| 亚洲免费福利| 国产欧美日韩在线观看视频 | 成人亚洲一区| 最新国产精品久久久| 欧美aa在线观看| 国产欧美日韩一区二区三区四区| 欧美色图国产精品| 久久不卡日韩美女| 亚洲综合精品| 人人香蕉久久| 免费在线观看一区| 亚洲色图综合| 久久国产小视频| 欧美aaaaaa午夜精品| 蜜臀av亚洲一区中文字幕| 久久电影tv| 国产精品久久久久久久久久齐齐| 老牛影视一区二区三区| 日本久久精品| 91福利精品在线观看| 在线亚洲欧美| 六月婷婷综合| 国产日产精品_国产精品毛片| 国产高清久久| 涩涩av在线| 美女久久99| 国产一区 二区| 亚洲影院天堂中文av色| 日韩精品一区二区三区免费观看| 国产激情精品一区二区三区| 五月亚洲婷婷 | 日韩一二三区在线观看| 亚洲a在线视频| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 国产黄色一区| 欧美一区=区三区| 中文一区一区三区免费在线观 | 婷婷成人在线| 欧美久久天堂| 国产精品黑丝在线播放| 国产精品xxx| 国产欧美日韩一区二区三区在线| 蜜桃视频免费观看一区| 悠悠资源网久久精品| 欧美日中文字幕| 日韩欧美国产精品综合嫩v| 美女视频网站久久| 国产高清精品二区| 国产毛片久久久| 久久国产三级精品| 久久精品 人人爱| 日韩1区2区3区| 日韩高清一区在线| 中文字幕一区二区三区四区久久| 美女国产精品| 综合激情网站| 亚洲日产av中文字幕| 亚洲色图国产| 日本中文字幕一区二区| 日韩精品免费一区二区夜夜嗨| 亚洲欧美网站在线观看| 最新国产精品| 色狠狠一区二区三区| 蜜臀av性久久久久蜜臀aⅴ流畅| 丝袜美腿亚洲色图| 国产色综合网| 国产免费成人| 亚洲性视频在线| 日韩三区四区| 国产精品videosex极品| 精品免费视频| 电影亚洲精品噜噜在线观看| 久久网站免费观看| 2023国产精品久久久精品双| 日韩视频中文| 亚洲人成亚洲精品| 国产日韩欧美一区在线| 国产精品xxx| 国产一区丝袜| 视频小说一区二区| 午夜在线播放视频欧美| 在线观看视频免费一区二区三区| 天堂va欧美ⅴa亚洲va一国产| 欧美亚洲自偷自偷| 久久免费福利| 色婷婷精品视频| 老司机精品久久| 欧美一区精品| 国产精品久久观看| 亚洲激情久久| 日本不卡一区二区| 精品国产乱码久久久| 日韩和的一区二在线| 国产亚洲网站| 国产精品一区二区av日韩在线| 国产一区二区三区亚洲综合| 91看片一区| 日韩影院在线观看| 国产精品蜜月aⅴ在线| 伊伊综合在线| 国产视频久久| 国产精品丝袜在线播放| 人在线成免费视频| 亚洲综合丁香| 久久99影视| 欧美不卡视频| 日韩av中文字幕一区二区三区| 精品资源在线| 亚洲精品电影| 国产欧美一区二区精品久久久 | 日韩精品久久久久久久软件91| 久久99蜜桃| 激情五月综合网| 日本aⅴ精品一区二区三区| 都市激情国产精品| 丝袜a∨在线一区二区三区不卡| 国产亚洲精品美女久久久久久久久久| sm捆绑调教国产免费网站在线观看| 亚洲午夜精品久久久久久app| 一区二区三区四区在线看| 日韩精品视频中文字幕| 午夜精品久久久久久久久久蜜桃| 视频精品一区二区| 成人精品国产亚洲| 中文无码日韩欧| av高清不卡| 欧美一区网站| 九九久久婷婷| 久久精品一区二区三区中文字幕| 99在线观看免费视频精品观看| 另类小说一区二区三区| 美女精品在线| 色偷偷色偷偷色偷偷在线视频| 午夜亚洲福利| 色老板在线视频一区二区| 日韩激情网站| 欧美日韩国产一区二区三区不卡| 国产精品xxxav免费视频| 亚洲一区欧美激情| 麻豆网站免费在线观看|