贝塞尔曲线简介和安卓实现动画效果展示(代码区)

Android 贝塞尔曲线实现水纹波动效果 曲线AD我们可以用贝塞尔曲线分别画出曲线AC和曲线CD,我们之所以从屏幕外开始画是因为水波纹要不断的波动要确保任何时刻都能看到水波纹,所以我们需要在屏幕前后及屏幕内画满水波纹。好吧,对不起观众的地方来了,我实在找不到一种好的画图软件可以代替手工随心所欲的画,要么就是鼠标操作太费劲,要么就是不能达到想要的效果。设置水波纹的高度WAVE_HEGHT为100,曲线AD的长度即水波纹的波长WAVE_LENGTH为1500(具体值根据显示效果修改)绘制AD曲线,最主要的是计算ABCD的坐标,根据我们的定义不难得出。 阅读详情
public class MyView extends View {

    private Point controlPoint = new Point(200, 200); //控制点坐标
   
    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(10);//设置画笔风格

        Path path = new Path();
        path.moveTo(100, 500);
        path.quadTo(controlPoint.x, controlPoint.y, 700, 500);
        //绘制路径
        canvas.drawPath(path, paint);
        //绘制辅助点
        canvas.drawPoint(controlPoint.x,controlPoint.y,paint);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                controlPoint.x = (int) event.getX();
                controlPoint.y = (int) event.getY();
                invalidate();//得到手触摸屏幕的坐标
                break;
        }
        return true;
    }
}
public class MyView1 extends View {

    private Point controlPointOne = new Point(200, 200);
    private Point controlPointTwo = new Point(500, 200);

    private boolean isControlPointTwo ;

    private Paint paintBezier;
    private Paint paintLine;

    public MyView1(Context context) {
        this(context, null);
    }

    public MyView1(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        paintBezier = new Paint();
        paintBezier.setStyle(Paint.Style.STROKE);
        paintBezier.setColor(Color.BLACK);
        paintBezier.setStrokeWidth(10);


        paintLine = new Paint();
        paintLine.setStyle(Paint.Style.STROKE);
        paintLine.setColor(Color.RED);
        paintLine.setStrokeWidth(3);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        Path path = new Path();
        path.moveTo(100, 500);
        path.cubicTo(controlPointOne.x, controlPointOne.y,controlPointTwo.x, controlPointTwo.y, 900, 500);
        //绘制路径
        canvas.drawPath(path, paintBezier);
        //绘制辅助点
        canvas.drawPoint(controlPointOne.x, controlPointOne.y, paintBezier);
        canvas.drawPoint(controlPointTwo.x, controlPointTwo.y, paintBezier);
        //绘制连线
//        canvas.drawLine(100, 500, controlPointOne.x, controlPointOne.y, paintLine);
//        canvas.drawLine(900, 500, controlPointOne.x, controlPointOne.y, paintLine);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (isControlPointTwo){
                    controlPointOne.x = (int) event.getX();
                    controlPointOne.y = (int) event.getY();
                }else {
                    controlPointTwo.x = (int) event.getX();
                    controlPointTwo.y = (int) event.getY();
                }
                invalidate();
                break;
        }
        return true;
    }


    public boolean isControlPointTwo() {
        return isControlPointTwo;
    }

    public void setControlPointTwo(boolean controlPointTwo) {
        isControlPointTwo = controlPointTwo;
    }
}
public class LikeStar extends ViewGroup {
    private List<Drawable> mStarDrawable;
    private List<Interpolator> mInterpolators;
    private int mWidth;
    private int mHeight;
    //定义贝塞尔曲线的数据点和两个控制点
    private PointF mStartPoint, mEndPoint, mControllPointOne, mControllPointTwo;

   private Random random = new Random();

    public LikeStar(Context context) {
        this(context, null);
    }

    public LikeStar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LikeStar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(final Context context) {
        mStarDrawable = new ArrayList<>();
        mInterpolators = new ArrayList<>();
        mStartPoint = new PointF();
        mEndPoint = new PointF();
        mControllPointOne = new PointF();
        mControllPointTwo = new PointF();

        //初始化图片资源
        mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_red));
        mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_blue));
        mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_yellow));
        mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_green));

        //初始化插补器
        mInterpolators.add(new LinearInterpolator());
        mInterpolators.add(new AccelerateDecelerateInterpolator());
        mInterpolators.add(new AccelerateInterpolator());
        mInterpolators.add(new DecelerateInterpolator());

        ImageView image_heard = new ImageView(context);
        image_heard.setImageDrawable(mStarDrawable.get(0));

        image_heard.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT));

        image_heard.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //点击之后开始动画,添加红心到布局文件并开始动画
                final ImageView image_random = new ImageView(context);
                image_random.setImageDrawable(mStarDrawable.get(random.nextInt(4)));

                image_random.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                        LayoutParams.WRAP_CONTENT));
                addView(image_random);

                invalidate();

                //开始做动画效果
                PointF endPointRandom = new PointF(random.nextInt(mWidth), mEndPoint.y);
   //             BezierTypeEvaluator bezierTypeEvaluator = new BezierTypeEvaluator(mControllPointOne, mControllPointTwo);
                BezierTypeEvaluator bezierTypeEvaluator = new BezierTypeEvaluator(new PointF( random.nextInt(mWidth ),random.nextInt(mHeight)), new PointF( random.nextInt(mWidth),random.nextInt(mHeight)));
                ValueAnimator valueAnimator = ValueAnimator.ofObject(bezierTypeEvaluator, mStartPoint, endPointRandom);
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        PointF pointF = (PointF) animation.getAnimatedValue();
                        image_random.setX(pointF.x);
                        image_random.setY(pointF.y);
                    }
                });

                valueAnimator.setDuration(2000);
                valueAnimator.start();

            }
        });

        addView(image_heard);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();

        // 初始化各个点

        //借用第一个子view控件中的宽高
        View child = getChildAt(0);
        int childW = child.getMeasuredWidth();
        int childH = child.getMeasuredHeight();

        mStartPoint.x = (mWidth - childW) / 2;
        mStartPoint.y = mHeight - childH;
        mEndPoint.x = (mWidth - childW) / 2;
        mEndPoint.y = 0 - childH;

        mControllPointOne.x = random.nextInt(mWidth / 2);
        mControllPointOne.y = random.nextInt(mHeight / 2) + mHeight / 2;

        mControllPointTwo.x = random.nextInt(mWidth / 2) + mWidth / 2;
        mControllPointTwo.y = random.nextInt(mHeight / 2);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        //获取view的宽高测量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        //保存测量高度
        setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.i("zhangyubin", "l:" + l + ",t:" + t + ",r:" + r + ",b:" + b);
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            int childW = child.getMeasuredWidth();
            int childH = child.getMeasuredHeight();
            child.layout((mWidth - childW) / 2, (mHeight - childH), (mWidth - childW) / 2 + childW, mHeight);
        }
    }

//    /**
//     * 开始动画
//     */

    //向外提供方法,用于点击事件触发动画发生
    public void startRunning() {
        BezierTypeEvaluator bezierTypeEvaluator = new BezierTypeEvaluator(mControllPointOne, mControllPointTwo);
        ValueAnimator valueAnimator = ValueAnimator.ofObject(bezierTypeEvaluator, mStartPoint, mEndPoint);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
               PointF pointF = (PointF) animation.getAnimatedValue();
               getChildAt(0).setX(pointF.x);
               getChildAt(0).setY(pointF.y);
            }
       });

       valueAnimator.setDuration(3000);
        valueAnimator.start();
    }


    public class BezierTypeEvaluator implements TypeEvaluator<PointF> {
        private PointF mControllPoint1, mControllPoint2;

        public BezierTypeEvaluator(PointF mControllPointOne, PointF mControllPointTwo) {
            mControllPoint1 = mControllPointOne;
            mControllPoint2 = mControllPointTwo;
        }

        @Override
        public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
            PointF pointCur = new PointF();
            pointCur.x = mStartPoint.x * (1 - fraction) * (1 - fraction) * (1 - fraction) + 3
                    * mControllPoint1.x * fraction * (1 - fraction) * (1 - fraction) + 3
                    * mControllPoint2.x * (1 - fraction) * fraction * fraction + endValue.x * fraction * fraction * fraction;// 实时计算最新的点X坐标
            pointCur.y = mStartPoint.y * (1 - fraction) * (1 - fraction) * (1 - fraction) + 3
                    * mControllPoint1.y * fraction * (1 - fraction) * (1 - fraction) + 3
                    * mControllPoint2.y * (1 - fraction) * fraction * fraction + endValue.y * fraction * fraction * fraction;// 实时计算最新的点Y坐标
            return pointCur;
        }
    }

}

 

安卓自定义View进阶 - 贝塞尔曲线 在上一篇文章Path之基本图形中我们了解了Path的基本使用方法,本次了解Path中非常非常非常重要的内容-贝塞尔曲线。 阅读详情

相关推荐

Android 贝塞尔曲线的魅力

前几天在手机优快云客户端看到一个QQ红点拖拽消失的效果,感觉挺好的,又回想到以前见到的诸如一下效果,感觉挺炫酷的,于是就看了下QQ拖拽的代码,记下笔记。 , 这个是在泡网上找到 还有一个指示器的效果,那个一时半会找不见了。UC浏览器新闻那一块的下拉刷新也是用了贝塞尔曲线的。什么是贝塞尔曲线 在数学的数值分析领域中,贝塞尔曲线, 又称贝赛尔曲线(Bézier曲线)是电脑图形学中

_StriveG的专栏 8759

从Android动画到贝塞尔曲线

基础知识: 动画通过连续播放一系列画面,给视觉造成连续变化的图画。很通俗的一种解释。也很好理解。那么我们先来一个案例看看。 动画案例:百度贴吧小熊奔跑 效果: topic.gif 代码: &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;animation-list xmlns:android="http:...

weixin_33811961的博客 193

贝塞尔曲线在Android中的应用

       今天要讲解的内容是Android中贝塞尔曲线的应用。可能很多人对贝塞尔曲线不甚了解,这里先对它的概念做一下简单介绍。        贝塞尔曲线由多个点组成:起始点、终止点以及0到n个相互分离的中间点。根据中间点的不同,可以分为线性贝塞尔曲线、二阶贝塞尔曲线、三阶贝塞尔曲线和高阶贝塞尔曲线。一般的矢量图形软件通过它来精确画出曲线,贝塞尔曲线由线段与节点组成,节点是可拖动的支点,线段像...

viclee 5705

Android-贝塞尔曲线

前言: 从去年开始了解贝塞尔曲线之后,发现开发中,不管是Android/iOS平台,还是web前端等,都有贝塞尔曲线的应用,通过绘制贝塞尔曲线,可以帮助开发者实现很多效果,例如一段时间内很流行的粘合型的下拉刷新、又如天气曲线图,同时,以贝塞尔曲线为基础的贝塞尔工具是所有绘图软件的最常用最实用的工具。 什么是贝塞尔曲线: 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝

Happy_Develop_的专栏 800

Android 贝塞尔曲线

Android 贝塞尔曲线一阶贝塞尔曲线二阶贝塞尔曲线三阶贝塞尔曲线: 今天给大家介绍的是贝塞尔曲线,什么是贝塞尔曲线呢?就是一个叫贝塞尔的人,发现了这个东西,然后就以他的名字命名为贝塞尔曲线,就像司马光砸缸一样,人家为啥要叫司马光砸缸,不叫小明砸缸小马砸缸呢?明明是司马光砸的刚功劳不能被别人抢走呀,好了好了这100多字都是废话,因为我在别的博客看的太多了,粘贴过来是真没意思。直接看效果上代码给大家介绍喽。 效果图(1.1): 咱们先来看一阶贝塞尔曲线: 一阶贝塞尔曲线 @Override

高级开发者进阶ing... QaQ 2518

Android学习小Demo(4)贝塞尔曲线跟翻页效果

第一次看到翻页效果的时候,觉得真是厉害,真是想不出是怎么做的呢(唉,牛人的智商真是只能仰望!)。 直到看了Android 实现书籍翻页效果----原理篇 一文,看了何明桂对翻页效果的一张图解,看到贝塞尔曲线,才恍然大悟,只能内心赞叹了。 下面先看看图(这张图是直接拿何明桂大牛的,请多多包涵): 这里是是以右下角为起点来翻页的,但其实只要将右下角的 f 点设成一个变量(它可以是任何一个

持剑 6086

一个贝塞尔曲线动画演示

经常写动画,好的动画效果,可以是应用level提升几个档次,下面有一个动画显得很舒服!个人表示很喜欢,在此做个记录。 //贝塞尔曲线动画 - (IBAction)clickAction:(UIButton *)sender { //把图片加到view上 UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRect

biyuhuaping的专栏 4515

Android 贝塞尔曲线动画 拿去直接用

Android 贝塞尔曲线动画 拿去直接用

动画神器:贝塞尔曲线——Property Animation

Property Animation中最重要,最基础的一个类就是ValueAnimator了。Property Animation利用ValueAnimator来跟踪记录对象属性已经变化了多长时间及当前这个时间点的值。 而在ValueAnimator中,又封装了两个类: 1)TimeInterpolator,也称插值器,是来计算当前动画运动的一个跟时间有关系的比例因子。 2)Ty

jia635的专栏 2062

Android贝塞尔曲线属性动画(中)

应用属性动画控制某物体在随机生成的一个始点两个控制点一个终点所绘出的贝塞尔曲线上运动的列子

Android贝塞尔曲线实现粘性动画

Android上贝塞尔曲线实现粘性动画,类似QQ未读。其中也有贝塞尔曲线的入门实例。 博客地址:http://blog.youkuaiyun.com/savelove911

贝塞尔曲线实践-动画框架

前言动画有多么重要,相信大家都清楚。它可以让一个枯燥乏味的静态界面变成一个充满动力的动画世界,提高用户体验。反正现在都是用户体验至上。android也是前端。苦逼的大前端。想想之前刚毕业的时候搞javaWeb,那个时候感觉前端好low。。现在不这么认为了。废话不多少。直接上效果图 主要就是中间那部分的动画效果。 理解Android中动画实现的本质在理解Android中动画实现的本质之前,首先要理

Xiemarc的博客 1861

Android 画布Canvas之连线动画Demo

实现在画布中连线的动画的效果,可以控制连线动画的速度,连线的颜色及线宽!!!!!!!!!!!11!!!!!

Android贝塞尔曲线实现Loading效果

在自己开发项目过程中,经常会用到加载框,如:网络请求等待等,这时我们则需要一段时间的等待以保证数据加载完毕,此时加一个等待框则显得非常具有必要性,以提高用户体验性。本文将通过GABottleLoading插件实现水滴飞溅的加载效果,贝塞尔曲线的又一次运用。 一、贝塞尔曲线     贝塞尔曲线,又称贝兹曲线或贝济埃曲线,主要应用于二维图形应用程序的数学曲线。贝塞尔曲线是计算机图形图像造型的基本工

夏天的夏,夏天的天。 6527

蓝桥杯FPGA赛道积分赛

代码如下: 按键驱动 代码如下 按键驱动 代码如下: 顶层文件 按键驱动 数码管驱动 声明:本代码借鉴网络资料,如有侵权和错误请联系作者删除。我是从寒假开始备赛的,由于我基础不行,备赛过程中也是混混呃呃的,备赛效率不高,总体来说备赛不认真,有点拖拉,但是最后我也坚持备赛到了今天,在备赛过程中,即复习了旧的东西,也学到了新的东西,总结起来还是有点收获的,后天北京、天津、河北地区就要进行省赛了,我会全力以赴,不管结果怎么样,尽力就好,最后祝大家都能

weixin_69804913的博客 1983

多路输出电源的交叉调整率:从理论到无源优化实践

本文深入探讨了多路输出电源中的交叉调整率问题,分析了其物理根源及无源优化方法。通过漏感与耦合的理论分析,结合加权反馈、电感耦合等五种无源优化技术,帮助工程师有效解决交叉调整率挑战。文章还以TDK-Lambda CUT75系列为例,展示了优化技术的实际应用与效果。

weixin_26886855的博客 280

Android 贝塞尔曲线的实现(一)

什么是贝塞尔曲线 简单的来说贝塞尔曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,带来视觉上的冲击,我们可以利用它来画出各种意想不到的曲线, 这里就不在列出贝塞尔曲线的繁琐定义及推导了,感兴趣的小伙伴可自行百度。 贝塞尔曲线分为一阶贝塞尔曲线,二阶贝塞尔曲线,三阶贝塞尔曲线甚至多阶。 对于Android开发十分友好,已经为我们封装好了简单的api供使用。 AndroidApi 二阶贝...

WormholeStack 7680

基于STM32L4XX、HAL库的SIM65M定位模块驱动程序设计

SIM65M是一款基于4G LTE Cat.1的无线通信模块,支持最大下行速率10Mbps和上行速率5Mbps。它兼容多种网络协议(TCP/UDP/HTTP/HTTPS/FTP/MQTT等),适用于物联网应用。PC0 <---> PWRKEY (模块电源控制)PC1 <---> RESET (模块复位)支持LTE-FDD/LTE-TDD。工作电压:3.4V~4.2V。

zhusl6688的博客 196

Android开发 之 曲线运动动画(贝塞尔曲线)

曲线运动动画(贝塞尔曲线) 贝塞尔曲线:维基百科中这样说到:在数学的数值分析领域中,贝塞尔曲线(英语:Bézier curve)是计算机图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝塞尔曲面,其中贝塞尔三角是一种特殊的实例。贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初

z_x_Qiang的博客 6494

利用恒源云云端GPU高效训练YOLOv11模型全流程:从环境搭建到模型部署,让你摆脱硬件束缚

记住,云端GPU的核心优势是“弹性算力+一键环境”,只要把握好这一工具特性,再结合YOLOv11的高性能模型架构,你也能在计算机视觉领域快速落地项目。接下来,我们从工具准备到模型部署,一步步带你实现高效训练,真正帮你解决资源与效率的核心痛点。凭借其在目标检测、实例分割任务上的卓越性能,成为众多开发者的首选。据统计,使用云端GPU训练YOLOv11,在处理百万级数据集时,训练效率较本地普通GPU提升。在安防监控中,YOLOv11可实时检测人员、车辆异常行为,某园区采用该方案后,异常事件识别准确率达。

LXY_LOVE36的博客 213

SAP CDS View association 的工作原理,与数据库传统 join 操作的区别讲解

笔者前一篇教程,介绍了 SAP CDS View 里如何创建 association:本文就来一一对这些问题进行解答。首先我们来研究如何消费创建好的 SAP CDS View 中的 association 数据。在上图 ABAP Development Tool 里展示的 CDS View 界面,点击 F8 快捷键,进入 Data Preview 即数据预览界面。我们随便选中一条行项目,右键,发现右键菜单里,赫然有一条的菜单项。看来这个功能肯定和 association 相关了。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1002
上一篇: ViewPager实现Tab(2)
下一篇: 自定义View实现网易云音乐留声机效果(代码区)
OneLinee
博客等级 码龄10年 11粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值