Android自定义view之path类描绘二阶贝塞尔曲线+属性动画(模仿QQ账号信息曲线动画)
来源:互联网 发布:sony系统更新挂起网络 编辑:程序博客网 时间:2024/05/24 07:23
写之前先简单的介绍一下后面代码中用到二阶贝塞尔曲线,Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生化。
/** * 二阶贝塞尔曲线 * B(t)=(1-t)*(1-t)*p0+2t(1-t)*p1+t*t*p2 */ private int getCurvePoint(int start, int control, int end) { return (int) ((1.0 - t) * (1.0 - t) * start + 2.0 * t * (1.0 - t) * control + t * t * end); }
设置二阶贝塞尔曲线的方法:
moveTo(float x,float y)
其中x,y的坐标代表图中曲线左边起点的位置坐标
quadTo(float x1, float y1, float x2, float y2 )
其中x1,y1的坐标就是图中小圆点的位置,也就是控制点的坐标
x2,y2的坐标就是图中曲线右边终点的位置坐标
在代码中具体实现如下:
mPath = new Path(); startX = 0; startY = getHeight() / 2 + 100; mPath.moveTo(startX, startY); controlX = getWidth() / 2 + 300; controlY = getHeight() / 2 + 100; endX = getWidth() + 100; endY = 0; mPath.quadTo(controlX, controlY, endX, endY); canvas.drawPath(mPath, mPaint);我们具体要实现的效果图
上述代码描绘的曲线:
用一个类来记录头像的坐标位置:
public class TheCoordinate { private int coordinateX; private int coordinateY; public int getCoordinateX() { return coordinateX; } public void setCoordinateX(int coordinateX) { this.coordinateX = coordinateX; } public int getCoordinateY() { return coordinateY; } public void setCoordinateY(int coordinateY) { this.coordinateY = coordinateY; }}
记录四个头像的位置:
public void addView(int vNum) { Log.e("test", 1 + ""); for (int i = 0; i < VIEWNUM; i++) { t = ((double) i) / ((double) VIEWNUM); int x = getCurvePoint(startX, controlX, endX); int y = getCurvePoint(startY, controlY, endY); TheCoordinate coordinate = new TheCoordinate(); coordinate.setCoordinateX(x); coordinate.setCoordinateY(y); mList.add(coordinate); Log.e("test" + i + "", "t:" + t + "x:" + x + "y:" + y); } initImageView(mList); }添加图片View:
private void initImageView(List<TheCoordinate> list) { for (int i = 0; i < list.size(); i++) { ImageView imageView = new ImageView(getContext()); RelativeLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.width = VIEWWIDTH; params.height = VIEWHEIGHT; if (i < 4) { if (i == 0) { params.setMargins(list.get(i).getCoordinateX(), list.get(i).getCoordinateY() - params.height / 2, list.get(i).getCoordinateX() + params.width, list.get(i).getCoordinateY() + params.height); } else { params.setMargins(list.get(i).getCoordinateX() - params.width / 2, list.get(i).getCoordinateY() - params.height / 2, list.get(i).getCoordinateX() + params.width, list.get(i).getCoordinateY() + params.height); } imageView.setBackgroundColor(Color.WHITE); imageView.setLayoutParams(params); imageView.setId(i); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageResource(R.mipmap.amap_location_pressed); this.addView(imageView); } iList.add(imageView); } }给View添加点击事件:
private void setViewClickEvent() { for (int i = 0; i < iList.size(); i++) { iList.get(i).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.e("test", "tag:" + tag + "" + "vid:" + v.getId() + ""); clickAnimation(v.getId()); tag = v.getId(); } }); } moveView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { moveViewAnimation(); } }); }其中移动头像单独提出来为moveView.先看看效果:
ok,下面附上完整代码和动画代码:
public class MyCViewLayout extends RelativeLayout { private Paint mPaint; private Path mPath; // 贝赛尔曲线成员变量(起始点,控制(操作点),终止点,3点坐标) private int startX, startY, controlX, controlY, endX, endY; //添加view的个数 public static int VIEWNUM = 5; //控制坐标平均分的比例的 private double t; //坐标点集合 private List<TheCoordinate> mList; private List<ImageView> iList; //移动的view private ImageView moveView; private int tag = 0; private Handler handler; public static int VIEWWIDTH;//moveview的宽度 public static int VIEWHEIGHT;//moveview的高度 public MyCViewLayout(Context context) { this(context, null); } public MyCViewLayout(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mList = new ArrayList<TheCoordinate>(); iList = new ArrayList<ImageView>(); moveView = new ImageView(getContext()); VIEWWIDTH=dip2px(context,34); VIEWHEIGHT=dip2px(context,34); moveView.setImageDrawable(getResources().getDrawable(R.mipmap.amap_call_normal)); handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what==1){ firstLoadAniomation(); } } }; } public MyCViewLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.e("test", 2 + ""); mPath = new Path(); startX = 0; startY = getHeight() / 2 + 100; mPath.moveTo(startX, startY); controlX = getWidth() / 2 + 300; controlY = getHeight() / 2 + 100; endX = getWidth() + 100; endY = 0; mPath.quadTo(controlX, controlY, endX, endY); canvas.drawPath(mPath, mPaint); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); startX = 0; startY = getHeight() / 2 + 100; controlX = getWidth() / 2 + 300; controlY = getHeight() / 2 + 100; endX = getWidth() + 100; endY = 0; addView(4); addMoveView(moveView); setViewClickEvent(); this.setBackgroundColor(Color.parseColor("#ffffff")); handler.sendEmptyMessageDelayed(1,1500); } private void setViewClickEvent() { for (int i = 0; i < iList.size(); i++) { iList.get(i).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.e("test", "tag:" + tag + "" + "vid:" + v.getId() + ""); clickAnimation(v.getId()); tag = v.getId(); } }); } moveView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { moveViewAnimation(); } }); } /** * 根据点击的view移动moveview * * @param vId */ private void clickAnimation(int vId) { if (tag == 0 && vId == 1) { moveAnimation(mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY()); } if (tag == 0 && vId == 2) { moveAnimation(0, 0, mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY()); } if (tag == 0 && vId == 3) { moveAnimation(0, 0, mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY() ); } if (tag == 1 && vId == 2) { moveAnimation(mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY()); } if (tag == 2 && vId == 3) { moveAnimation( mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY() ); } if (tag == 3 && vId == 0) { moveAnimation( mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), 0, 0 ); } if (tag == 3 && vId == 1) { moveAnimation( mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY() ); } if (tag == 3 && vId == 2) { moveAnimation(mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY()); } if (tag == 2 && vId == 1) { moveAnimation( mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY() ); } if (tag == 2 && vId == 0) { moveAnimation( mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), 0, 0 ); } if (tag == 1 && vId == 0) { moveAnimation( mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), 0, 0 ); } if (tag == 1 && vId == 3) { moveAnimation(mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY() ); } } private void moveAnimation(int startPointX, int startPointY) { ObjectAnimator animatorX = ObjectAnimator.ofFloat(moveView, "TranslationX", 0, startPointX); ObjectAnimator animatorY = ObjectAnimator.ofFloat(moveView, "TranslationY", 0, startPointY); AnimatorSet set = new AnimatorSet(); set.setDuration(800); set.setInterpolator(new FastOutSlowInInterpolator()); set.playTogether(animatorX, animatorY); set.start(); } private void moveAnimation(int startPointX, int startPointY, int X1, int Y1, int endPointX, int endPointY) { Log.e("test", "startPointX:" + startPointX + "startPointY:" + startPointY + "endPointX:" + endPointX + "endPointY:" + endPointY + ""); ObjectAnimator animatorX = ObjectAnimator.ofFloat(moveView, "TranslationX", startPointX, X1, endPointX); ObjectAnimator animatorY = ObjectAnimator.ofFloat(moveView, "TranslationY", startPointY, Y1, endPointY); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.setInterpolator(new FastOutSlowInInterpolator()); set.playTogether(animatorX, animatorY); set.start(); } private void moveAnimation(int startPointX, int startPointY, int X1, int Y1, int X2, int Y2, int endPointX, int endPointY) { Log.e("test", "startPointX:" + startPointX + "startPointY:" + startPointY + "endPointX:" + endPointX + "endPointY:" + endPointY + ""); ObjectAnimator animatorX = ObjectAnimator.ofFloat(moveView, "TranslationX", startPointX, X1, X2, endPointX); ObjectAnimator animatorY = ObjectAnimator.ofFloat(moveView, "TranslationY", startPointY, Y1, Y2, endPointY); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.setInterpolator(new FastOutSlowInInterpolator()); set.playTogether(animatorX, animatorY); set.start(); } private void moveAnimation(int startPointX, int startPointY, int X1, int Y1, int X2, int Y2, int endPointX, int endPointY,int X3,int Y3,int X4,int Y4) { Log.e("test", "startPointX:" + startPointX + "startPointY:" + startPointY + "endPointX:" + endPointX + "endPointY:" + endPointY + ""); ObjectAnimator animatorX = ObjectAnimator.ofFloat(moveView, "TranslationX", startPointX, X1, X2, endPointX,X3,X4,0); ObjectAnimator animatorY = ObjectAnimator.ofFloat(moveView, "TranslationY", startPointY, Y1, Y2, endPointY,Y3,Y4,0); AnimatorSet set = new AnimatorSet(); set.setDuration(3000);// set.setInterpolator(new FastOutSlowInInterpolator()); set.setInterpolator(new LinearInterpolator()); set.playTogether(animatorX, animatorY); set.start(); } private void moveAnimation(int startPointX, int startPointY, int endPointX, int endPointY) { Log.e("test", "startPointX:" + startPointX + "startPointY:" + startPointY + "endPointX:" + endPointX + "endPointY:" + endPointY + ""); ObjectAnimator animatorX = ObjectAnimator.ofFloat(moveView, "TranslationX", startPointX, endPointX); ObjectAnimator animatorY = ObjectAnimator.ofFloat(moveView, "TranslationY", startPointY, endPointY); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.setInterpolator(new FastOutSlowInInterpolator()); set.playTogether(animatorX, animatorY); set.start(); } private void moveViewAnimation() { ObjectAnimator mAnimator = ObjectAnimator.ofFloat(moveView, "rotation", 0F, 720f); mAnimator.setDuration(800); mAnimator.start(); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); } public void addView(int vNum) { Log.e("test", 1 + ""); for (int i = 0; i < VIEWNUM; i++) { t = ((double) i) / ((double) VIEWNUM); int x = getCurvePoint(startX, controlX, endX); int y = getCurvePoint(startY, controlY, endY); TheCoordinate coordinate = new TheCoordinate(); coordinate.setCoordinateX(x); coordinate.setCoordinateY(y); mList.add(coordinate); Log.e("test" + i + "", "t:" + t + "x:" + x + "y:" + y); } initImageView(mList); } public void addMoveView(ImageView imageView) { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.width = VIEWWIDTH; params.height = VIEWHEIGHT; params.setMargins(mList.get(0).getCoordinateX(), mList.get(0).getCoordinateY() - params.height / 2, mList.get(0).getCoordinateX() + params.width, mList.get(0).getCoordinateY() + params.height); tag = 0; imageView.setLayoutParams(params); imageView.setScaleType(ImageView.ScaleType.FIT_XY); removeView(imageView); this.addView(imageView); } private void initImageView(List<TheCoordinate> list) { for (int i = 0; i < list.size(); i++) { ImageView imageView = new ImageView(getContext()); RelativeLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.width = VIEWWIDTH; params.height = VIEWHEIGHT; if (i < 4) { if (i == 0) { params.setMargins(list.get(i).getCoordinateX(), list.get(i).getCoordinateY() - params.height / 2, list.get(i).getCoordinateX() + params.width, list.get(i).getCoordinateY() + params.height); } else { params.setMargins(list.get(i).getCoordinateX() - params.width / 2, list.get(i).getCoordinateY() - params.height / 2, list.get(i).getCoordinateX() + params.width, list.get(i).getCoordinateY() + params.height); } imageView.setBackgroundColor(Color.WHITE); imageView.setLayoutParams(params); imageView.setId(i); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageResource(R.mipmap.amap_location_pressed); this.addView(imageView); } iList.add(imageView); } } /** * 二阶贝塞尔曲线 * B(t)=(1-t)*(1-t)*p0+2t(1-t)*p1+t*t*p2 */ private int getCurvePoint(int start, int control, int end) { return (int) ((1.0 - t) * (1.0 - t) * start + 2.0 * t * (1.0 - t) * control + t * t * end); } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } /** * 获取屏幕的宽度 * * @return */ private int getScreenWidth() { WindowManager wm = (WindowManager) getContext().getSystemService( Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * 获取屏幕的高度 * * @return */ private int getScreenHeight() { WindowManager wm = (WindowManager) getContext().getSystemService( Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } public void firstLoadAniomation(){ moveAnimation( 0, 0, mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(3).getCoordinateX() - mList.get(2).getCoordinateX() + mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(3).getCoordinateY() - mList.get(2).getCoordinateY() + mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(2).getCoordinateX() - mList.get(1).getCoordinateX() - VIEWWIDTH / 2 + mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX(), mList.get(2).getCoordinateY() - mList.get(1).getCoordinateY() + mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY(), mList.get(1).getCoordinateX() - mList.get(0).getCoordinateX() - VIEWWIDTH / 2, mList.get(1).getCoordinateY() - mList.get(0).getCoordinateY() ); }}说明一下,动画的坐标由于只是demo就写死了,后续可以提取出来封装一个方法.
that's all .THX!!!
1 0
- Android自定义view之path类描绘二阶贝塞尔曲线+属性动画(模仿QQ账号信息曲线动画)
- Android自定义曲线动画
- 自定义View动画-贝塞尔曲线动画
- Android 利用二阶贝塞尔曲线自定义弧形动画
- Android自定义View阻尼动画&贝塞尔曲线的实现
- android动画入门,进阶,提高----自定义控件绘图篇和Path之贝赛尔曲线
- 贝塞尔曲线--属性动画
- Android 属性动画-绘制贝塞尔曲线路径
- Android自定义曲线路径动画框架
- Android 动画-贝塞尔曲线
- Android自定义view之属性动画初见
- 自定义view进阶-贝塞尔曲线实现水波动画、粘性控件
- 自定义日出日落曲线动画
- Android自定义View之贝塞尔曲线
- 安卓自定义View进阶-Path之贝塞尔曲线
- 安卓自定义View进阶-Path之贝塞尔曲线
- android自定义View创建一个Path绘制多边形,贝塞尔曲线,
- 爱的贝塞尔曲线之属性动画之美
- C++之构造函数(二) 构造函数初始化
- 开源RTP/RTCP传输库jrtplib与live555优缺点简单总结笔记
- Arrays.asList方法概括
- SQLServer数据导出导入到Oracle数据库
- Tomcat服务器自配置相关环境变量
- Android自定义view之path类描绘二阶贝塞尔曲线+属性动画(模仿QQ账号信息曲线动画)
- Java之动态绑定(多态)
- 使用js实现用户评论的星级
- train\predict\cross_validation demo include almost all Classifier from scikit-learning
- Android多媒体整体架构图
- 开端-且做个年末总结吧
- java先下载excel文件,然后与其它文件、图片压缩
- awk 系统学习,转载
- 递归