自定义带弹性效果的pageControl

分三部分实现,在drawrect方法里画出灰色背景,根据pageCount创建对应个数的dotView放置在对应位置,并隐藏,创建一个CAShapeView类型的layer,根据scrollView的偏移量 构建贝塞尔曲线,画出红色线条,以及形变的大圆。

大圆的形变以及构建思路:

(图引用自:http://kittenyang.com/deformationandgooey/)

下面就是构建A、B、C、D、c1、c2、c3、c4、c5、c6、c7、c8这些点,给A、B、C、D、四个点,一个关于contentOffset的形变量,以达到园形变的效果。value = (半径 * 比例)*形变因素,其中形变因素于contentOffset相关(在滑动一个页面时会形成这样的关系:0~0.5~0);CGFloat factor = MIN(0.5, MAX(0, (ABS(scrollView.contentOffset.x - last) / scrollView.frame.size.width)));,构建好点后,根据偏移量,更新点的坐标,生成新的贝塞尔曲线,便生成形变的 圆了。

下面是部分代码:

/** 根据scrollView 更新贝塞尔曲线 */
- (void)updateDotLayerScrollView:(UIScrollView *)scrollView{
    // 判断滑动方向
    BOOL left = (scrollView.contentOffset.x - self.lastOffsetX) >= 0?YES:NO;

    // 向左滑动就显示dotView
    if (left) {
        [self setDotViewShowWithScrollView:scrollView];
    }

    CGPoint dotCenter = [self calculateDotCenterWithScrollView:scrollView];

    // 计算当前偏移量的 归属地(超过一半 就归属后者,反之前者)
    int count = (int)(scrollView.contentOffset.x / scrollView.frame.size.width+0.5);

    // 根据count 计算归属地 的偏移量
    CGFloat last = scrollView.frame.size.width * count;

    CGFloat factor = MIN(0.5, MAX(0, (ABS(scrollView.contentOffset.x - last) / scrollView.frame.size.width)));

    // extra 是 A、B、C、D四点的 位移量,跟factor有关。而factor跟contentOffset相关,其关系为0~0.5~0;
    CGFloat extra = self.SeletedDotRadiu * 4 / 5 * factor;

    // 构成贝塞尔曲线的相关点 的计算
    A = CGPointMake(dotCenter.x, dotCenter.y - self.SeletedDotRadiu+extra);
    B = CGPointMake(left?(dotCenter.x+self.SeletedDotRadiu):(dotCenter.x+self.SeletedDotRadiu+extra * 2), dotCenter.y);
    C = CGPointMake(dotCenter.x, dotCenter.y+self.SeletedDotRadiu-extra);
    D = CGPointMake(left?(dotCenter.x-self.SeletedDotRadiu-extra*2):(dotCenter.x-self.SeletedDotRadiu), dotCenter.y);
    // 1.8 的得来应该是能计算出来的,不过不知道咋算,试出来
    CGFloat offset = self.SeletedDotRadiu / 1.8;

    c1 = CGPointMake(A.x + offset, A.y);
    c2 = CGPointMake(B.x, B.y - offset);
    c3 = CGPointMake(B.x, B.y + offset);
    c4 = CGPointMake(C.x + offset, C.y);
    c5 = CGPointMake(C.x - offset, C.y);
    c6 = CGPointMake(D.x, D.y + offset);
    c7 = CGPointMake(D.x, D.y - offset);
    c8 = CGPointMake(A.x - offset, A.y);

    UIBezierPath* ovalPath = [UIBezierPath bezierPath];
    CGPoint startPoint = CGPointMake(self.SeletedDotRadiu, CGRectGetHeight(self.frame) / 2.0);
    [ovalPath moveToPoint: startPoint];
    [ovalPath addLineToPoint:D];
    [ovalPath addCurveToPoint:C controlPoint1:c6 controlPoint2:c5];
    [ovalPath addCurveToPoint:B controlPoint1:c4 controlPoint2:c3];
    [ovalPath addCurveToPoint:A controlPoint1:c2 controlPoint2:c1];
    [ovalPath addCurveToPoint:D controlPoint1:c8 controlPoint2:c7];

    [ovalPath closePath];
    self.dotLayer.path = ovalPath.CGPath;

    self.lastOffsetX = scrollView.contentOffset.x;
}

drawRect 方法:

/** 画初始 的背景 */
- (void)drawRect:(CGRect)rect {

    // 控件垂直方向中心
    CGFloat verticalCenter = rect.size.height / 2.0;
    // 圆点 半径
    CGFloat dotR = self.dotRadiu;

    // 选中圆点 半径
    CGFloat selectedDotR = self.SeletedDotRadiu;
    // 圆心距离
    CGFloat distanceCenter = (rect.size.width - 2 * selectedDotR) / (self.pageCount - 1);

    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(selectedDotR, (rect.size.height - self.lineWidth) / 2.0, rect.size.width - 2 * selectedDotR, self.lineWidth)];

    [self.color setFill];

    for (int i = 0; i < self.pageCount; i++) {

        UIBezierPath *dotPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(selectedDotR + distanceCenter * i, verticalCenter) radius:dotR startAngle:0 endAngle:M_PI * 2 clockwise:YES];
        [path appendPath:dotPath];
    }
    [path fill];

}

完整代码:http://pan.baidu.com/s/1i4y78gt

时间: 2024-08-24 21:51:24

自定义带弹性效果的pageControl的相关文章

js+css实现带缓冲效果右键弹出菜单

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Typ

【Android】Android实现自定义带文字和图片的Button

在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就是利用系统自带的Button来实现,这种方式代码量最小.在Button的属性中有一个是drawableLeft,这个属性可以把图片设置在文字的左边,但是这种方式必须让icon的背景色是透明的,如果icon的背景色不是透明的话,会导致点击按钮时icon部分的背景色不会发生变化. 主要代码: <Button android:id="@+id/bt3

带弹性的导航栏

妙味的官网和智能社的官网上,会看到一个带弹性的导航栏,这个导航栏的效果非常流畅,其实这个效果并不难实现,说一下思路:正常的导航栏布局,只是在第一个li前加一个div,设置定位为绝对定位,并给div设置背景,设置其z-index值为1,设置li的z-index值为2,设置其父元素ul为相对定位,li设置成相对定位,li如果不设置成相对定位,会出现z-index失效的麻烦,然后用js调节背景的位置,当然了,还需要引入写好的弹性运动框架,弹性运动框架需要注意的问题是,检测终止条件,和终止之后直接将di

自定义控件(四)自定义点击效果Button

本节自定义带有点击效果的圆角矩形Button. 功能: 1.button点击变色 2.上面文字也是点击变色 3.button形状为圆角矩形 4.button具有渐变效果 主要分为五步: 首先你需要在res目录下建立一个drawable目录(与像素无关的drawable). 1.设置按钮正常状态 //button_shape_normal.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:

Android带动画效果的弹窗

在网络加载数据的时候通常需要很多时间,这个时候程序里面经常需要写一个提示正在加载数据的弹窗,这篇文章用两种方式实现带动画效果的Dialog:帧动画实现和GIF动态图实现,它们都能达到动画的效果 第一种.帧动画实现 自定义一个Dialog,先看一下布局文件dialog_animation.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=

Android使用xml自定义软键盘效果(附源码)

Android使用xml自定义软键盘效果原理: 1,软键盘其实是个控件,使用android.inputmethodserver.KeyboardView类定义. 2,主布局中使用帧布局,当我们需要显示软键盘时设置为可见,不需要时设置为不可见. 3,编写xml文件,定义键盘内容.使用xml文件填充KeyBoardView布局 4,设置EditText的监听事件. 完成键盘开发. 上效果图: 1,源码研究android.inputmethodserver.KeyboardView: /* * Cop

Android带弹性的View

在Android开发中ListView.ScrollView用到的频率相当高,可是一个优秀的应用我们能看到它里面的效果绝对不会那么死板,安卓原生的ListView和ScrollView都不能满足这个要求,所以开发的时候就会需要这种带弹性的View.在平时开发中的,我收集了上下拉带弹性的ListView和ScrollView,在这里分享给大家,有需要用到的可以直接下载. ElasticView下载地址:http://pan.baidu.com/s/1kTFvz07

Android 自定义带刻度的seekbar

自定义带刻度的seekbar 1.布局 <span style="font-family:SimHei;font-size:18px;"><com.imibaby.client.views.CustomSeekbar android:id="@+id/myCustomSeekBar" android:layout_width="wrap_content" android:layout_height="wrap_cont

自动播放——幻灯片缓冲效果&amp;&amp;带Loading效果的图片切换&amp;&amp;移动效果(按轨迹移动)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-