今天看到美颜相机里的首页广告指示器有点好玩,就想着自己写一个
现在开始进行分析,首先需要测量指示器的宽高,大致分为这几个部分
所以我们重写onMeasured的时候只需要根据 间隔 space,R小圆圈半径,滑块长度
测量好后我们进行具体的绘制,小圆圈我们直接用 canvas.drawCircle,滑块直接使用一条横线就行,横线的strokeWIDth边缘必须是
小圆圈的直径。
vIEwPager 在当前页的时候当前小圆圈和下一个小圆圈之间会多出barWIDth - 2*R的空间用来填充滑块
所以他的画法是
先画第一个圆圈,如果是显示当前下标再画滑块 然后画布镜头右移 barWIDth + space - 2R(这里减2R是因为画滑块的画笔是 strokeWIDth =2R,
strokeCap=Paint.Cap.ROUND的)
最后贴出效果
全部代码如下(没做相关封装,只是实现)
import androID.animation.ValueAnimatorimport androID.content.Contextimport androID.graphics.Canvasimport androID.graphics.colorimport androID.graphics.Paintimport androID.graphics.RectFimport androID.graphics.drawable.Drawableimport androID.os.Buildimport androID.util.AttributeSetimport androID.vIEw.VIEwimport androID.vIEw.VIEwGroupimport androID.vIEw.animation.AccelerateDecelerateInterpolatorimport androID.vIEw.animation.linearInterpolatorimport androID.Widget.FrameLayoutimport androID.Widget.Scrollerimport androIDx.annotation.RequiresAPIimport androIDx.vIEwpager.Widget.VIEwPagerimport androIDx.vIEwpager2.Widget.VIEwPager2import com.lu.demoy.Widget.i.YIndicatorAdapterimport java.lang.Exceptionclass YIndicator @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : VIEw(context, attrs, defStyleAttr) { init { initproperty() } overrIDe fun onMeasure(wIDthMeasureSpec: Int, heightmeasureSpec: Int) { circleW = radius * 2 radiusdistancebar = (scrollbarWIDth-circleW).coerceAtLeast(0f) val w = (childamount -1)*spacing + circleW*childamount + radiusdistancebar setMeasuredDimension(w.toInt(),circleW.toInt()) } private var radiusdistancebar = 0f private var childamount = 0 private var spacing = 0f private var scrollbarWIDth = 0f private var radius = 0f private var circleW = 0f private var currentIndex = 1 private var currentOffset = 0f private var crossdistance = 0f private var valueAnimator:ValueAnimator?=null private var onPagerchangelistener:VIEwPager2.OnPageChangeCallback?=null private var pagerVIEwPager2:VIEwPager2? = null private var timeInterceptor = 0L fun setbarWIDth(setScrollbarWIDth:float):YIndicator{ this.scrollbarWIDth = setScrollbarWIDth return this } fun seTradius(radius:float):YIndicator{ this.radius = radius paintbar.strokeWIDth=radius*2 return this } fun setSpacing(spacing:float):YIndicator{ this.spacing = spacing return this } fun setPager(vIEwPager: VIEwPager2){ if (vIEwPager.adapter !is YIndicatorAdapter<*>) { throw Exception("adapter must be YIndicatorAdapter") } pagerVIEwPager2 = vIEwPager childamount = (vIEwPager.adapter as YIndicatorAdapter<*>).getVIEwSize() onPagerchangelistener?.let { pagerVIEwPager2?.unregisterOnPageChangeCallback(it) } onPagerchangelistener =object:VIEwPager2.OnPageChangeCallback(){ overrIDe fun onPageScrolled( position: Int, positionOffset: float, positionOffsetPixels: Int) { if(System.currentTimeMillis() - timeInterceptor>100){ timeInterceptor = System.currentTimeMillis() currentIndex = position % childamount +1 val crossAll = (currentIndex == childamount) && (positionOffset > 0) ||(currentIndex == 1) && (positionOffset < 0) crossdistance = (if (crossAll)(-spacing*(childamount-1)) else spacing) currentOffset =crossdistance * positionOffset invalIDate() } if (positionOffset == 0.0f){ currentIndex = position % childamount +1 currentOffset = 0f println("当前页:$currentIndex,positionOffset:$positionOffset") invalIDate() } } } vIEwPager.registerOnPageChangeCallback(onPagerchangelistener!!) if(childamount!=0){ requestLayout() } } private fun release(){ onPagerchangelistener?.let { pagerVIEwPager2?.unregisterOnPageChangeCallback(it) } pagerVIEwPager2 = null onPagerchangelistener = null valueAnimator?.removeAllUpdateListeners() valueAnimator?.cancel() valueAnimator = null } overrIDe fun onDetachedFromWindow() { super.onDetachedFromWindow() release() super.onDetachedFromWindow() } lateinit var paintIndicator:Paint lateinit var paintbar:Paint private fun initproperty(){ paintIndicator= Paint() paintbar = Paint() paintIndicator.color = color.WHITE paintIndicator.isAntiAlias = true paintbar.color = color.WHITE paintbar.isAntiAlias = true paintbar.strokeCap=Paint.Cap.ROUND } overrIDe fun onDraw(canvas: Canvas?) { canvas?.save() for (a in 1..childamount){ canvas?.drawCircle(radius,radius,radius,paintIndicator) if (a == currentIndex){ //画滚动条 canvas?.drawline(radius+currentOffset,radius,scrollbarWIDth-radius+currentOffset,radius,paintbar) } if(a == currentIndex){ canvas?.translate(radiusdistancebar,0f) } canvas?.translate(spacing+radius,0f) } canvas?.restore() }}
abstract class YIndicatorAdapter<T: RecyclerVIEw.VIEwHolder>:
RecyclerVIEw.Adapter<T>() {
abstract fun getVIEwSize():Int
}
总结
以上是内存溢出为你收集整理的一步一步,自定义viewPager指示器全部内容,希望文章能够帮你解决一步一步,自定义viewPager指示器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)