前言
最近一直忙,没空写博客,也不知道写一些啥,突然想起之前挺有意思的一个小功能,实现一下。大致如下图,大家可以看一下,很简单也很有意思。其实我想写这个的仿QQ未读消息拖动。写着写着感觉这个效果也挺好玩。。。觉得有意思的就看看吧,没啥实用性。
实现思路
就是记录小球的运动轨迹就行了,一个小球看成一个对象,然后让它从哪来滚哪去。
实现主要代码
package com.maxi.slidepoint.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Mao Jiqing on 2016/5/3.
*/
public class SlidePointView extends View {
private Paint paint = new Paint();
private final float radius = 60;
private ArrayList<Circle> circlePaths = new ArrayList<>();
public SlidePointView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint.setColor(0xffff0000);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
}
private class Circle {
float[] center;
float radius;
private List<Float> roadX = new ArrayList<Float>();
private List<Float> roadY = new ArrayList<Float>();
private boolean isSlide = false;
}
private void initMetaballs() {
Circle circlePath = new Circle();
circlePath.center = new float[]{(radius), radius};
circlePath.radius = radius;
circlePath.roadX.add(radius);
circlePath.roadY.add(radius);
circlePaths.add(circlePath);
circlePath = new Circle();
circlePath.center = new float[]{this.getMeasuredWidth() / 2, this.getMeasuredHeight() / 3};
circlePath.radius = radius;
circlePath.roadX.add(this.getMeasuredWidth() / 2f);
circlePath.roadY.add(this.getMeasuredHeight() / 3f);
circlePaths.add(circlePath);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (circlePaths.size() == 0) {
initMetaballs();
}
final Circle circle1 = circlePaths.get(0);
RectF ball1 = new RectF();
ball1.left = circle1.center[0] - circle1.radius;
ball1.top = circle1.center[1] - circle1.radius;
ball1.right = ball1.left + circle1.radius * 2;
ball1.bottom = ball1.top + circle1.radius * 2;
canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle1.radius, paint);
final Circle circle2 = circlePaths.get(1);
RectF ball2 = new RectF();
ball2.left = circle2.center[0] - circle2.radius;
ball2.top = circle2.center[1] - circle2.radius;
ball2.right = ball2.left + circle2.radius * 2;
ball2.bottom = ball2.top + circle2.radius * 2;
canvas.drawCircle(ball2.centerX(), ball2.centerY(), circle2.radius, paint);
}
private Circle touchCircle;
private int backPosition = -1;
@Override
public boolean onTouchEvent(MotionEvent event) {
float slideX, slideY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int circlePosition = getCircle(event.getX(),event.getY());
if (circlePosition != -1) {
touchCircle = circlePaths.get(circlePosition);
backPosition = circlePosition;
}
break;
case MotionEvent.ACTION_MOVE:
if(touchCircle != null && !touchCircle.isSlide) {
slideX = event.getX();
slideY = event.getY();
touchCircle.roadX.add(slideX);
touchCircle.roadY.add(slideY);
touchCircle.center[0] = slideX;
touchCircle.center[1] = slideY;
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if(touchCircle != null && backPosition != -1 && !touchCircle.isSlide) {
back(backPosition);
}
break;
}
return true;
}
private void back(final int position) {
new Thread(new Runnable() {
@Override
public void run() {
Circle circle = circlePaths.get(position);
circle.isSlide = true;
for (int i = circle.roadX.size() - 1; i >= 0; i--) {
circle.center[0] = circle.roadX.get(i);
circle.center[1] = circle.roadY.get(i);
try {
Thread.sleep(10);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
float startX = circle.roadX.get(0);
float startY = circle.roadY.get(0);
circle.roadX.clear();
circle.roadY.clear();
circle.roadX.add(startX);
circle.roadY.add(startY);
circle.isSlide = false;
}
}).start();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
invalidate();
}
}
};
private int getCircle(float x, float y) {
int i = 0;
for (Circle circle : circlePaths){
if(isOnPoint(circle,x,y)){
return i;
}
i++;
}
return -1;
}
private boolean isOnPoint(Circle circle,float x, float y){
return (x > circle.center[0] - radius && x < circle.center[0] + radius
&& y > circle.center[1] - radius && y < circle.center[1] + radius);
}
}
后续
代码很简单,就不做介绍了,写着玩也就没注意太多,大家可以看一下为后期自定义动画做铺垫。
点此下载:下载地址
有疑问或者更好地实现方式的话 请加QQ群:135451435。共同进步!