文章目录
- 手势导航的侧滑返回效果图
- 实现代码
-
- [1. 初始化代码](#1. 初始化代码)
- [2. 修改绘制的代码,进行箭头与退出UI的显示](#2. 修改绘制的代码,进行箭头与退出UI的显示)
- [3. 拖动的时候手指上下移动时,箭头ui跟着移动](#3. 拖动的时候手指上下移动时,箭头ui跟着移动)
- [以下是一些其他可以美化安卓右滑手势拖动 UI 的方法:](#以下是一些其他可以美化安卓右滑手势拖动 UI 的方法:)
安卓原生手势导航的侧滑返回效果很单一, 就一个箭头, 大部分手机厂商都会定制这块
手势导航的侧滑返回效果图
原生效果如下:
要实现的功能,:
- 美化箭头
- 显示一个动态的凸出画面
- 画面跟随手指位置上下滑动
如下图
实现代码
主要修改
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
1. 初始化代码
java
//初始化代码
private float mLastY;
private Paint mWavePaint;
private Path mBezierPath;
private Paint mArrowPaint;
mBezierPath = new Path();
mWavePaint = new Paint();
mWavePaint.setAntiAlias(true);
mWavePaint.setStrokeWidth(dp(1.5f));
mWavePaint.setStyle(Paint.Style.FILL);
mWavePaint.setColor(mProtectionColor);
mArrowPaint = new Paint();
mArrowPaint.setStrokeWidth(mArrowThickness);
mArrowPaint.setStrokeCap(Paint.Cap.ROUND);
mArrowPaint.setAntiAlias(true);
mArrowPaint.setColor(Color.WHITE);
mArrowPaint.setStyle(Paint.Style.STROKE);
mArrowPaint.setStrokeJoin(Paint.Join.ROUND);
mLastY用于记录上次手势UI显示的坐标, 在手指按下的瞬间, 更新mLastY的值.
java
@Override
public void onMotionEvent(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mDragSlopPassed = false;
resetOnDown();
mStartX = event.getX();
mStartY = event.getY();
mLastY = mStartY; // 手势按下时,重新赋值mLastY
2. 修改绘制的代码,进行箭头与退出UI的显示
添加的UI基于贝塞尔曲线实现的
java
@Override
protected void onDraw(Canvas canvas) {
float pointerPosition = mCurrentTranslation - mArrowThickness / 2.0f;
/*
canvas.save();
canvas.translate(
mIsLeftPanel ? pointerPosition : getWidth() - pointerPosition,
(getHeight() * 0.5f) + mVerticalTranslation);
// Let's calculate the position of the end based on the angle
float x = (polarToCartX(mCurrentAngle) * mArrowLength);
float y = (polarToCartY(mCurrentAngle) * mArrowLength);
Path arrowPath = calculatePath(x,y);
if (mShowProtection) {
canvas.drawPath(arrowPath, mProtectionPaint);
}
canvas.drawPath(arrowPath, mPaint);
canvas.restore();
*/
float height = getHeight();
float maxWidth = getWidth();
float centerY = height / 2;
float progress = currentWidth / maxWidth;
if (progress == 0) {
return;
}
float footX = mIsLeftPanel ? 0 : getWidth();
mWavePaint.setAlpha((int) (200 * progress));
float bezierWidth = mIsLeftPanel ? currentWidth / 2 : (getWidth() - currentWidth / 2);
mBezierPath.reset();
mBezierPath.moveTo(footX, 0);
// 使用常量代替重复计算的分数值
final float quarterHeight = height / 4f;
final float threeEighthsHeight = height * 3f / 8;
final float fiveEighthsHeight = height * 5f / 8;
final float threeQuartersHeight = height * 3f / 4;
mBezierPath.cubicTo(footX, quarterHeight, bezierWidth, threeEighthsHeight, bezierWidth, centerY);
mBezierPath.cubicTo(bezierWidth, fiveEighthsHeight, footX, threeQuartersHeight, footX, height);
canvas.drawPath(mBezierPath, mWavePaint);
mArrowPaint.setAlpha((int) (255 * progress));
// 画箭头
float arrowLeft = mIsLeftPanel? currentWidth / 6 : getWidth() - currentWidth / 6;
float arrowEnd = arrowLeft + mArrowLength * progress;
float[] lines = {arrowEnd, centerY - mArrowLength, arrowLeft, centerY,
arrowLeft, centerY, arrowEnd, centerY + mArrowLength};
canvas.drawLines(lines, mArrowPaint);
}
3. 拖动的时候手指上下移动时,箭头ui跟着移动
java
private void handlemoveevent(motionevent event) {
float x = event.getx();
float y = event.gety();
if ((x - mstartx)<0){
// 忽略左滑
return;
}
// .....
// 拖动的时候手指上下移动时,箭头ui跟着移动
float movey = event.gety() - mlasty;
if (movey != 0) {
mlasty = event.gety();
mlayoutparams.y += movey;
// 更新位置
mwindowmanager.updateviewlayout(this, mlayoutparams);
}
}
以下是一些其他可以美化安卓右滑手势拖动 UI 的方法:
视觉效果方面
- 添加渐变颜色:
在绘制拖动 UI 的画笔(Paint)上设置渐变效果。例如,使用线性渐变(LinearGradient)或者径向渐变(RadialGradient)。这样在拖动过程中,颜色可以从一种过渡到另一种,增加视觉丰富度。 - 增加光影效果:
使用不同的阴影绘制技巧。比如,在拖动元素的下方绘制一个半透明的、模糊的阴影,模拟出元素浮于界面之上的效果。可以通过设置 Paint 的阴影属性或者使用专门的图形处理库来实现更复杂的阴影效果。 - 粒子效果:
当进行右滑拖动时,在拖动元素的周围产生一些粒子(如发光的小点、星尘等)。这些粒子可以随机运动、逐渐消失,给用户带来更加生动的交互体验。可以通过自定义粒子类和动画来实现。
动画效果方面 - 弹性动画:
当拖动接近最大距离或者释放拖动时,让拖动 UI 元素表现出弹性效果。例如,使用弹性插值器(如 OvershootInterpolator)来使元素在动画过程中超出目标位置然后再回弹,增加交互的趣味性。
形状和布局方面
- 复杂形状设计:
设计更加复杂的拖动 UI 形状,不仅仅局限于常见的几何形状或者贝塞尔曲线。例如,设计一个类似花瓣形状、或者具有独特艺术风格的形状,通过路径绘制(Path)来实现。 - 嵌套布局:
在拖动 UI 元素内部使用嵌套的布局和元素。比如,在一个主要的拖动形状内部包含一些小的装饰元素、图标或者文字,这些内部元素可以有自己独立的动画和交互效果。
作者:帅得不敢出门