本篇文章主要介绍了Android 利用三阶贝塞尔曲线绘制运动轨迹的示例,分享给大家,具体如下:

实现点赞效果,自定义起始点以及运动轨迹

效果图:

xml布局:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/rl_root"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="stone.wshh.com.touch.MainActivity">

android:layout_marginBottom="100dp"

android:layout_marginRight="15dp"

android:id="@+id/love_layout"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/bt_bottom"

android:text="begin"

android:layout_alignParentBottom="true"

android:layout_centerHorizontal="true"

android:layout_marginBottom="20dp"

android:layout_width="100dp"

android:layout_height="50dp" />

MainActivity类:

public class MainActivity extends Activity implements View.OnClickListener{

private Button btBottom;

// private WaitNoticeDialog dialog;

// public Handler handler;

private MyLoveLayout love;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

btBottom = (Button) findViewById(R.id.bt_bottom);

love = (MyLoveLayout) findViewById(R.id.love_layout);

btBottom.setOnClickListener(this);

// handler=new IHandler(this);

// dialog = new WaitNoticeDialog(this);

}

static class IHandler extends Handler {

private WeakReference ui;

IHandler(MainActivity ui) {

this.ui = new WeakReference(ui);

}

@Override

public void handleMessage(Message msg) {

if(ui!=null&&ui.get()!=null){

ui.get().handleMsg(msg);

}

}

}

/**

* 线程消息处理

* @param msg

*/

public void handleMsg(Message msg){

switch (msg.what) {

}

}

@Override

public void onClick(View v) {

switch (v.getId()){

case R.id.bt_bottom:

love.addHeart();

break;

}

}

@Override

protected void onDestroy() {

super.onDestroy();

// handler.removeCallbacksAndMessages(null);

}

}

自定义view:MyLoveLayout

public class MyLoveLayout extends RelativeLayout {

private Drawable[] drawables;

private Interpolator[] mInterpolators;

private int dWidth, mWidth;

private int dHeight, mHeight;

private LayoutParams lp;

private Random random = new Random();

public MyLoveLayout(Context context, AttributeSet attrs) {

super(context, attrs);

//imageView位置是相对于MyLoveLayout

init();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//得到本布局的宽高

mWidth = getMeasuredWidth();

mHeight = getMeasuredHeight();

}

private void init() {

// 初始化显示的图片

drawables = new Drawable[7];

drawables[0] = getResources().getDrawable(R.drawable.heart_1);

drawables[1] = getResources().getDrawable(R.drawable.heart_2);

drawables[2] = getResources().getDrawable(R.drawable.heart_3);

drawables[3] = getResources().getDrawable(R.drawable.heart_4);

drawables[4] = getResources().getDrawable(R.drawable.heart_5);

drawables[5] = getResources().getDrawable(R.drawable.heart_6);

drawables[6] = getResources().getDrawable(R.drawable.heart_7);

// 初始化插补器

mInterpolators = new Interpolator[4];

mInterpolators[0] = new LinearInterpolator();// 线性

mInterpolators[1] = new AccelerateInterpolator();// 加速

mInterpolators[2] = new DecelerateInterpolator();// 减速

mInterpolators[3] = new AccelerateDecelerateInterpolator();// 先加速后减速

// 获取图片宽高

// dWidth = drawables[0].getIntrinsicWidth();

// dHeight = drawables[0].getIntrinsicHeight();

//手动设置宽高

dWidth = dip2px(getContext(), 40);

dHeight = dip2px(getContext(), 40);

lp = new LayoutParams(dWidth, dHeight);

//设置view控件的起始位置

// lp.addRule(CENTER_HORIZONTAL, TRUE);// 这里的TRUE 要注意 不是true

lp.addRule(ALIGN_PARENT_RIGHT, TRUE);

lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);

}

/**

* dp转px值

*/

private int dip2px(Context context, float dpValue) {

float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

/**

* 进场动画,三种同时播放

* alpha透明度 (80%-0%)

* scaleX 宽度 target(20%-100%)

* scaleY 高度

* @param target

* @return

*/

private AnimatorSet getEnterAnimator(final View target) {

ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f);

ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 0.2f, 1f);

ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.2f, 1f);

AnimatorSet enter = new AnimatorSet();

enter.setTarget(target);

enter.setInterpolator(new LinearInterpolator());

enter.setDuration(500).playTogether(alpha, scaleX, scaleY);

return enter;

}

private ValueAnimator getBezierValueAnimator(final View target) {

// 初始化贝塞尔估值器

//随机产生两个点,以确定一条3阶贝塞尔曲线

BezierEvaluator evaluator = new BezierEvaluator(getPointF(2), getPointF(1));

// 起点在底部中心位置,终点在底部随机一个位置,改变new PointF()中值来改变起始位置

// ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) /

// 2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0));

// 起点在右下角位置,终点在左上角位置

ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF(mWidth - dWidth, mHeight - dHeight), new PointF(0, 0));

animator.setTarget(target);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator valueAnimator) {

// 这里获取到贝塞尔曲线计算出来的的x y值 赋值给view 这样就能让爱心随着曲线走啦

PointF pointF = (PointF) valueAnimator.getAnimatedValue();

target.setX(pointF.x);

target.setY(pointF.y);

// alpha动画,根据运动距离改变透明度

// target.setAlpha(1 - valueAnimator.getAnimatedFraction());

target.setAlpha(1 - valueAnimator.getAnimatedFraction() + 0.3f);

}

});

animator.setDuration(3000);

return animator;

}

private PointF getPointF(int i) {

PointF pointF = new PointF();

//pointF.x,pointF.y都是随机,因此可以产生n多种轨迹

pointF.x = random.nextInt(mWidth);//0~loveLayout.Width

//为了美观,建议尽量保证P2在P1上面,那怎么做呢??

//只需要将该布局的高度分为上下两部分,让p1只能在下面部分范围内变化(1/2height~height),让p2只能在上面部分范围内变化(0~1/2height),因为坐标系是倒着的;

//0~loveLayout.Height/2

if (i == 1) {

pointF.y = random.nextInt(mHeight / 2) + mHeight / 2;//P1点Y轴坐标变化

} else if (i == 2) {//P2点Y轴坐标变化

pointF.y = random.nextInt(mHeight / 2);

}

// 写死的一条轨迹

// if (i == 1) {

// pointF.x=mWidth-dWidth*2;

// pointF.y = 3*dHeight;

// } else if (i == 2) {

// pointF.x=dWidth*2;

// pointF.y = mHeight -dHeight;

// }

return pointF;

}

public void addHeart() {

final ImageView imageView = new ImageView(getContext());

// 随机选一个爱心

imageView.setImageDrawable(drawables[random.nextInt(6)]);

imageView.setLayoutParams(lp);

addView(imageView);

AnimatorSet finalSet = new AnimatorSet();

AnimatorSet enterAnimatorSet = getEnterAnimator(imageView);//入场动画

ValueAnimator bezierValueAnimator = getBezierValueAnimator(imageView);//贝塞尔曲线路径动画

finalSet.playSequentially(enterAnimatorSet, bezierValueAnimator);

// finalSet.playSequentially(bezierValueAnimator);

finalSet.setInterpolator(mInterpolators[random.nextInt(4)]);

finalSet.setTarget(imageView);

finalSet.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

super.onAnimationEnd(animation);

removeView((imageView));//删除爱心

}

});

finalSet.start();

}

}

贝塞尔估值器:BezierEvaluator

public class BezierEvaluator implements TypeEvaluator {

private PointF mControlP1;

private PointF mControlP2;

public BezierEvaluator(PointF controlP1, PointF controlP2) {

this.mControlP1 = controlP1;

this.mControlP2 = controlP2;

}

@Override

public PointF evaluate(float time, PointF start, PointF end) {

float timeLeft = 1.0f - time;

PointF point = new PointF();

point.x = timeLeft * timeLeft * timeLeft * (start.x) + 3 * timeLeft * timeLeft * time *

(mControlP1.x) + 3 * timeLeft * time *

time * (mControlP2.x) + time * time * time * (end.x);

point.y = timeLeft * timeLeft * timeLeft * (start.y) + 3 * timeLeft * timeLeft * time *

(mControlP1.y) + 3 * timeLeft * time *

time * (mControlP2.y) + time * time * time * (end.y);

return point;

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android运动轨迹怎么画,Android 利用三阶贝塞尔曲线绘制运动轨迹的示例相关推荐

  1. android翻书效果实现原理( 贝塞尔曲线绘制原理/点坐标计算)

    为什么80%的码农都做不了架构师?>>>    实现真实的翻页效果,为了能在翻页的过程中看到下一页的内容,在翻页之前必须准备两张页面,一张是当前页,另一张是下一页.翻页的过程就是对这 ...

  2. 【Android UI】贝塞尔曲线 ⑦ ( 使用 德卡斯特里奥算法 公式计算的 方法绘制三阶贝塞尔曲线示例 )

    文章目录 一.使用 德卡斯特里奥算法 公式计算的 方法绘制三阶贝塞尔曲线 二.代码示例 贝塞尔曲线参考 : https://github.com/venshine/BezierMaker 一.使用 德 ...

  3. 有趣的自定义View — 玫瑰·三阶贝塞尔曲线

    "玫瑰贝塞尔曲线"效果如下: 一.效果要求 1)在布局中某个位置处玫瑰开始由小而大,淡入出现: 2)出现的玫瑰,颜色随机而定,玫瑰可在布局内做动画亦可在整个界面中做动画,如上图: ...

  4. 【Android UI】贝塞尔曲线 ② ( 二阶贝塞尔曲线公式 | 三阶贝塞尔曲线及公式 | 高阶贝塞尔曲线 )

    文章目录 一.二阶贝塞尔曲线公式 二.三阶贝塞尔曲线 三.高阶贝塞尔曲线 贝塞尔曲线参考 : https://github.com/venshine/BezierMaker 一.二阶贝塞尔曲线公式 二 ...

  5. android 贝塞尔曲线_OpenGL 实践之贝塞尔曲线绘制

    说到贝塞尔曲线,大家肯定都不陌生,网上有很多关于介绍和理解贝塞尔曲线的优秀文章和动态图. 以下两个是比较经典的动图了. 二阶贝塞尔曲线: 三阶贝塞尔曲线: 由于在工作中经常要和贝塞尔曲线打交道,所以简 ...

  6. flutter绘图基础之三阶贝塞尔曲线cubicTo

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精. 重要消息 [经验分享视频教程 感兴趣的伙伴可以瞅瞅] 1 flutter 中绘制基础引言 Flutter 中实现绘制的主要是Custo ...

  7. 贝塞尔曲线是什么?如何用 Canvas 绘制三阶贝塞尔曲线?

    大家好,我是前端西瓜哥. 今天谈谈贝塞尔曲线是什么以及它的原理,并说说如何用 Canvas 技术绘制一条三阶贝塞尔曲线. 贝塞尔曲线是什么? 贝塞尔曲线,是通过几个简单的参数描述一条曲线的一种参数曲线 ...

  8. 三阶贝塞尔曲线选点_用三阶贝塞尔曲线拟合圆

    前言 由于贝塞尔曲线控制简便且具有极强的描述能力,它常被用来生成复杂的平滑曲线:圆形是一种很常用的普通图形,在计算机图形学中也有很多画圆的算法,本文想探究一下如何用三阶贝塞尔曲线拟合圆形. 在研究这个 ...

  9. ai钢笔工具怎么描线_AI钢笔工具技巧,怎么画出完美的贝塞尔曲线

    AI钢笔工具技巧,怎么画出完美的贝塞尔曲线 我们在刚开始学习UI的时候,通常会临摹很多作品,一般临摹都分为两个步骤,第一步是使用钢笔工具把物体勾勒出来,但是很多人在勾轮廓的时候往往都不流畅,其实这是钢 ...

最新文章

  1. 技术进阶:Kubernetes高级架构与应用状态部署
  2. NameValueCollection详解
  3. mac下,svn配置
  4. 机器人动力学建模实例(二):三连杆机械臂
  5. IMAP和POP3的相关知识与区别
  6. 时空上下文视觉跟踪(STC)算法的解读与代码复现
  7. Loadrunner学习笔记(二)
  8. [error]Cannot create __weak reference in file using manual refer XCode7.3
  9. tfpose与openpose区别_人体姿态识别--Openpose+Tensorflow
  10. AtCoder Regular Contest 061
  11. 老码农90%的程序员都是瞎努力!这份路线教你成为高手
  12. oracle序列的描述,Oracle同义词和序列的基本使用方法
  13. linux6 ftp配置,centos6.x vsftpd配置FTP服务器详细教程
  14. 关于python随机抽取各类型不重复值的思考(sample与randint的区别)
  15. 秒秒钟解决打开ps图片显示无法完成请求,因为程序错误
  16. 数字万用表常用功能使用
  17. 无线网络dns服务器设置,netgear 无线dns设置教程
  18. 菜鸟实战UML——包图
  19. centos7子系统 win10_Windows10内置Linux子系统初体验
  20. API接口管理平台eoLinker-AMS V3.2.0

热门文章

  1. ulimit限制 新系统_说来惭愧,我被ulimit摔了一跤...
  2. 钰群的USB3.0采集,可以实现哪些采集卡方案?
  3. Qt操作SQLite数据库练习(20200215)
  4. AngularJS 的自定义指令
  5. CSS简介及常用标签及属性
  6. Android IOS WebRTC 音视频开发总结(十一)-- stunturn部署
  7. 报表设计器条形码支持类型
  8. Resin3.19 连接池配置
  9. “尽快成立国家级权威信息安全部门”
  10. 关于海量数据的SQL查询优化.........