android 自定义indicator,Android自定义Indicator

本文介绍如何使用贝塞尔曲线在Android中自定义指示器,包括圆形绘制、平滑过渡和分裂粘合效果。通过三阶贝塞尔曲线实现圆弧效果,代码示例详细展示了关键步骤和计算逻辑。
摘要由CSDN通过智能技术生成

最近利用空闲时间,通过贝塞尔曲线写了一个Indicator,效果如下(视频转换gif效果不好)

完整代码传送门

f5dc04f13c97

对于原点的绘制及变化,需要对贝塞尔曲线及通过三阶贝塞尔曲线绘制圆形有初步了解,请参考以下文章

Bézier curve;Composite Bézier curve;Approximate a circle with cubic Bézier curves

对于贝塞尔曲线理论,没有较为扎实的数学基础还是很难理解的,笔者的高等数学早已把我抛弃了,很多符号都不记得,断断续续写了一个月才完成编写,主要是在分裂与粘合效果这碰了壁,很是汗颜~~~,好了直接上代码吧!

public class CustomIndicator extends View {

private static final double factor = 0.55191502449;

public static final int INDICATOR_TYPE_SCALE = 0;

public static final int INDICATOR_TYPE_GRADUAL = 1;

public static final int INDICATOR_TYPE_SPLIT = 2;

public static final int INDICATOR_TYPE_SCALE_AND_GRADUAL = 3;

private static final int DEFAULT_NORMAL_POINT_RADIUS = 8;

private static final int DEFAULT_SELECTED_POINT_RADIUS = 12;

private int heightMeasureSpec;

private Paint normalPointPaint;

private Paint selectedPointPaint;

private Paint targetPointPaint;

private float normalPointRadius;

private float selectedPointRadius;

private int pointInterval;

private int normalPointColor;

private int selectedPointColor;

private int indicatorType;

private int pointCount;

private List relativeControlPoints;

// private int selectedPagePosition;

private int currentPagePosition;

private int targetPagePosition;

private int width;

private int height;

private Path arcPath;

private Path splitArcPath;

private float translationFactor;

private PagerAdapter adapter;

private DataSetObserver dataSetObserver;

private static final int SPLIT_OFFSET = DisplayUtil.dp2px(10);

private static final float SPLIT_RADIUS_FACTOR = 1.4f;

@IntDef({INDICATOR_TYPE_SCALE, INDICATOR_TYPE_GRADUAL, INDICATOR_TYPE_SCALE_AND_GRADUAL, INDICATOR_TYPE_SPLIT})

@Retention(RetentionPolicy.SOURCE)

private @interface IndicatorType {

}

public CustomIndicator(Context context) {

this(context, null);

}

public CustomIndicator(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public CustomIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(attrs);

}

private void init(AttributeSet attrs) {

TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CustomIndicator);

indicatorType = typedArray.getInt(R.styleable.CustomIndicator_indicatorType, 0);

normalPointRadius = typedArray.getDimensionPixelSize(R.styleable.CustomIndicator_normalPointRadius, DEFAULT_NORMAL_POINT_RADIUS);

selectedPointRadius = typedArray.getDimensionPixelSize(R.styleable.CustomIndicator_selectedPointRadius, indicatorType == INDICATOR_TYPE_GRADUAL ? DEFAULT_NORMAL_POINT_RADIUS : DEFAULT_SELECTED_POINT_RADIUS);

pointInterval = typedArray.getDimensionPixelSize(R.styleable.CustomIndicator_pointInterval, 20);

normalPointColor = typedArray.getColor(R.styleable.CustomIndicator_normalPointColor, Color.parseColor("#FFFFFF"));

selectedPointColor = typedArray.getColor(R.styleable.CustomIndicator_selectedPointColor, Color.parseColor("#11EEEE"));

typedArray.recycle();

normalPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

normalPointPaint.setStyle(Paint.Style.FILL);

normalPointPaint.setColor(normalPointColor);

if (indicatorType == INDICATOR_TYPE_GRADUAL || indicatorType == INDICATOR_TYPE_SCALE_AND_GRADUAL) {

selectedPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

selectedPointPaint.setStyle(Paint.Style.FILL);

selectedPointPaint.setColor(selectedPointColor);

targetPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

targetPointPaint.setStyle(Paint.Style.FILL);

targetPointPaint.setColor(selectedPointColor);

} else if (indicatorType == INDICATOR_TYPE_SPLIT) {

if (selectedPointRadius < normalPointRadius * SPLIT_RADIUS_FACTOR) {

selectedPointRadius = (int) (normalPointRadius * SPLIT_RADIUS_FACTOR);

}

if (pointInterval < SPLIT_RADIUS_FACTOR * normalPointRadius * 2 + SPLIT_OFFSET) {

pointInterval = (int) (SPLIT_RADIUS_FACTOR * normalPointRadius * 2 + SPLIT_OFFSET);

}

}

arcPath = new Path

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值