php网站怎么做seo,h5入口,跨境电商开店流程及费用,网络营销是网络销售吗粘性控件 #xff08;对View的自定义#xff09;* 应用场景: 未读提醒的清除* 功能实现: 1. 画静态图 OK 2. 把静态的数值变成变量(计算得到真实的变量) OK 3. 不断地修改变量, 重绘界面, 动起来了. 4. 功能分析:a. 拖拽超出范围,断开, 松手, 消失b. 拖拽超…粘性控件 对View的自定义* 应用场景: 未读提醒的清除* 功能实现: 1. 画静态图 OK 2. 把静态的数值变成变量(计算得到真实的变量) OK 3. 不断地修改变量, 重绘界面, 动起来了. 4. 功能分析: a. 拖拽超出范围,断开, 松手, 消失 b. 拖拽超出范围,断开,放回去了,恢复 c. 拖拽没超出范围, 松手,弹回去没有布局MainActivitypublic class MainActivity extends Activity { Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(new GooView(MainActivity.this)); }}Utilspublic class Utils { public static Toast mToast; public static void showToast(Context mContext, String msg) { if (mToast null) { mToast Toast.makeText(mContext, , Toast.LENGTH_SHORT); } mToast.setText(msg); mToast.show(); } /** * dip 转换成 px * param dip * param context * return */ public static float dip2Dimension(float dip, Context context) { DisplayMetrics displayMetrics context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics); } /** * param dip * param context * param complexUnit {link TypedValue#COMPLEX_UNIT_DIP} {link TypedValue#COMPLEX_UNIT_SP}} * return */ public static float toDimension(float dip, Context context, int complexUnit) { DisplayMetrics displayMetrics context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(complexUnit, dip, displayMetrics); } /** 获取状态栏高度 * param v * return */ public static int getStatusBarHeight(View v) { if (v null) { return 0; } Rect frame new Rect(); v.getWindowVisibleDisplayFrame(frame); return frame.top; } public static String getActionName(MotionEvent event) { String action unknow; switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: action ACTION_DOWN; break; case MotionEvent.ACTION_MOVE: action ACTION_MOVE; break; case MotionEvent.ACTION_UP: action ACTION_UP; break; case MotionEvent.ACTION_CANCEL: action ACTION_CANCEL; break; case MotionEvent.ACTION_SCROLL: action ACTION_SCROLL; break; case MotionEvent.ACTION_OUTSIDE: action ACTION_SCROLL; break; default: break; } return action; }}GooView/** * 粘性控件 * author poplar * */public class GooView extends View { private static final String TAG TAG; private Paint mPaint; public GooView(Context context) { this(context, null); } public GooView(Context context, AttributeSet attrs) { this(context, attrs , 0); } public GooView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 做初始化操作 mPaint new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.RED); } PointF[] mStickPoints new PointF[]{ new PointF(250f, 250f), new PointF(250f, 350f) }; PointF[] mDragPoints new PointF[]{ new PointF(50f, 250f), new PointF(50f, 350f) }; PointF mControlPoint new PointF(150f, 300f); PointF mDragCenter new PointF(80f, 80f); float mDragRadius 14f; PointF mStickCenter new PointF(150f, 150f); float mStickRadius 12f; private int statusBarHeight; float farestDistance 80f; private boolean isOutofRange; private boolean isDisappear; Override protected void onDraw(Canvas canvas) { // 计算连接点值, 控制点, 固定圆半径 // 1. 获取固定圆半径(根据两圆圆心距离) float tempStickRadius getTempStickRadius(); // 2. 获取直线与圆的交点 float yOffset mStickCenter.y - mDragCenter.y; float xOffset mStickCenter.x - mDragCenter.x; Double lineK null; if(xOffset ! 0){ lineK (double) (yOffset / xOffset); } // 通过几何图形工具获取交点坐标 mDragPoints GeometryUtil.getIntersectionPoints(mDragCenter, mDragRadius, lineK); mStickPoints GeometryUtil.getIntersectionPoints(mStickCenter, tempStickRadius, lineK); // 3. 获取控制点坐标 mControlPoint GeometryUtil.getMiddlePoint(mDragCenter, mStickCenter); // 保存画布状态 canvas.save(); canvas.translate(0, -statusBarHeight); // 画出最大范围(参考用) mPaint.setStyle(Style.STROKE); canvas.drawCircle(mStickCenter.x, mStickCenter.y, farestDistance, mPaint); mPaint.setStyle(Style.FILL); if(!isDisappear){ if(!isOutofRange){ // 3. 画连接部分 Path path new Path(); // 跳到点1 path.moveTo(mStickPoints[0].x, mStickPoints[0].y); // 画曲线1 - 2 path.quadTo(mControlPoint.x, mControlPoint.y, mDragPoints[0].x, mDragPoints[0].y); // 画直线2 - 3 path.lineTo(mDragPoints[1].x, mDragPoints[1].y); // 画曲线3 - 4 path.quadTo(mControlPoint.x, mControlPoint.y, mStickPoints[1].x, mStickPoints[1].y); path.close(); canvas.drawPath(path, mPaint); // 画附着点(参考用) mPaint.setColor(Color.BLUE); canvas.drawCircle(mDragPoints[0].x, mDragPoints[0].y, 3f, mPaint); canvas.drawCircle(mDragPoints[1].x, mDragPoints[1].y, 3f, mPaint); canvas.drawCircle(mStickPoints[0].x, mStickPoints[0].y, 3f, mPaint); canvas.drawCircle(mStickPoints[1].x, mStickPoints[1].y, 3f, mPaint); mPaint.setColor(Color.RED); // 2. 画固定圆 canvas.drawCircle(mStickCenter.x, mStickCenter.y, tempStickRadius, mPaint); } // 1. 画拖拽圆 canvas.drawCircle(mDragCenter.x, mDragCenter.y, mDragRadius, mPaint); } // 恢复上次的保存状态 canvas.restore(); } // 获取固定圆半径(根据两圆圆心距离) private float getTempStickRadius() { float distance GeometryUtil.getDistanceBetween2Points(mDragCenter, mStickCenter); // if(distance farestDistance){// distance farestDistance;// } distance Math.min(distance, farestDistance); // 0.0f - 1.0f float percent distance / farestDistance; Log.d(TAG, percent: percent); // percent , 100% - 20% return evaluate(percent, mStickRadius, mStickRadius * 0.2f); } public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat startValue.floatValue(); return startFloat fraction * (endValue.floatValue() - startFloat); } Override public boolean onTouchEvent(MotionEvent event) { float x; float y; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isOutofRange false; isDisappear false; x event.getRawX(); y event.getRawY(); updateDragCenter(x, y); break; case MotionEvent.ACTION_MOVE: x event.getRawX(); y event.getRawY(); updateDragCenter(x, y); // 处理断开事件 float distance GeometryUtil.getDistanceBetween2Points(mDragCenter, mStickCenter); if(distance farestDistance){ isOutofRange true; invalidate(); } break; case MotionEvent.ACTION_UP: if(isOutofRange){ float d GeometryUtil.getDistanceBetween2Points(mDragCenter, mStickCenter); if(d farestDistance){ // a. 拖拽超出范围,断开, 松手, 消失 isDisappear true; invalidate(); }else { //b. 拖拽超出范围,断开,放回去了,恢复 updateDragCenter(mStickCenter.x, mStickCenter.y); } }else { // c. 拖拽没超出范围, 松手,弹回去 final PointF tempDragCenter new PointF(mDragCenter.x, mDragCenter.y); ValueAnimator mAnim ValueAnimator.ofFloat(1.0f); mAnim.addUpdateListener(new AnimatorUpdateListener() { Override public void onAnimationUpdate(ValueAnimator mAnim) { // 0.0 - 1.0f float percent mAnim.getAnimatedFraction(); PointF p GeometryUtil.getPointByPercent(tempDragCenter, mStickCenter, percent); updateDragCenter(p.x, p.y); } }); mAnim.setInterpolator(new OvershootInterpolator(4)); mAnim.setDuration(500); mAnim.start(); } break; default: break; } return true; } /** * 更新拖拽圆圆心坐标,并重绘界面 * param x * param y */ private void updateDragCenter(float x, float y) { mDragCenter.set(x, y); invalidate(); } Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); statusBarHeight Utils.getStatusBarHeight(this); } }GeometryUtil/** * 几何图形工具 */public class GeometryUtil { /** * As meaning of method name. * 获得两点之间的距离 * param p0 * param p1 * return */ public static float getDistanceBetween2Points(PointF p0, PointF p1) { float distance (float) Math.sqrt(Math.pow(p0.y - p1.y, 2) Math.pow(p0.x - p1.x, 2)); return distance; } /** * Get middle point between p1 and p2. * 获得两点连线的中点 * param p1 * param p2 * return */ public static PointF getMiddlePoint(PointF p1, PointF p2) { return new PointF((p1.x p2.x) / 2.0f, (p1.y p2.y) / 2.0f); } /** * Get point between p1 and p2 by percent. * 根据百分比获取两点之间的某个点坐标 * param p1 * param p2 * param percent * return */ public static PointF getPointByPercent(PointF p1, PointF p2, float percent) { return new PointF(evaluateValue(percent, p1.x , p2.x), evaluateValue(percent, p1.y , p2.y)); } /** * 根据分度值计算从start到end中fraction位置的值。fraction范围为0 - 1 * param fraction * param start * param end * return */ public static float evaluateValue(float fraction, Number start, Number end){ return start.floatValue() (end.floatValue() - start.floatValue()) * fraction; } /** * Get the point of intersection between circle and line. * 获取 通过指定圆心斜率为lineK的直线与圆的交点。 * * param pMiddle The circle center point. * param radius The circle radius. * param lineK The slope of line which cross the pMiddle. * return */ public static PointF[] getIntersectionPoints(PointF pMiddle, float radius, Double lineK) { PointF[] points new PointF[2]; float radian, xOffset 0, yOffset 0; if(lineK ! null){ radian (float) Math.atan(lineK); xOffset (float) (Math.sin(radian) * radius); yOffset (float) (Math.cos(radian) * radius); }else { xOffset radius; yOffset 0; } points[0] new PointF(pMiddle.x xOffset, pMiddle.y - yOffset); points[1] new PointF(pMiddle.x - xOffset, pMiddle.y yOffset); return points; }}来自为知笔记(Wiz)附件列表 转载于:https://www.cnblogs.com/sixrain/p/5041965.html