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 {
}
이 를 통 해 알 수 있 듯 이
Layout
는 추상 적 인 유형 으로 세 가지 유형 이 있 으 며 자동 으로 줄 을 바 꾸 는 디 스 플레이 효 과 를 실현 할 수 있다.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" />
총결산안 드 로 이 드 사용자 정의 뷰 에서 Spannable 을 사용 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 안 드 로 이 드 가 Spannable 을 사용 하 는 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.