安卓framework美化手势导航侧滑返回UI

文章目录

安卓原生手势导航的侧滑返回效果很单一, 就一个箭头, 大部分手机厂商都会定制这块

手势导航的侧滑返回效果图

原生效果如下:

要实现的功能,:

  1. 美化箭头
  2. 显示一个动态的凸出画面
  3. 画面跟随手指位置上下滑动
    如下图

实现代码

主要修改

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 的方法:

视觉效果方面

  1. 添加渐变颜色:
    在绘制拖动 UI 的画笔(Paint)上设置渐变效果。例如,使用线性渐变(LinearGradient)或者径向渐变(RadialGradient)。这样在拖动过程中,颜色可以从一种过渡到另一种,增加视觉丰富度。
  2. 增加光影效果:
    使用不同的阴影绘制技巧。比如,在拖动元素的下方绘制一个半透明的、模糊的阴影,模拟出元素浮于界面之上的效果。可以通过设置 Paint 的阴影属性或者使用专门的图形处理库来实现更复杂的阴影效果。
  3. 粒子效果:
    当进行右滑拖动时,在拖动元素的周围产生一些粒子(如发光的小点、星尘等)。这些粒子可以随机运动、逐渐消失,给用户带来更加生动的交互体验。可以通过自定义粒子类和动画来实现。
    动画效果方面
  4. 弹性动画:
    当拖动接近最大距离或者释放拖动时,让拖动 UI 元素表现出弹性效果。例如,使用弹性插值器(如 OvershootInterpolator)来使元素在动画过程中超出目标位置然后再回弹,增加交互的趣味性。

形状和布局方面

  1. 复杂形状设计:
    设计更加复杂的拖动 UI 形状,不仅仅局限于常见的几何形状或者贝塞尔曲线。例如,设计一个类似花瓣形状、或者具有独特艺术风格的形状,通过路径绘制(Path)来实现。
  2. 嵌套布局:
    在拖动 UI 元素内部使用嵌套的布局和元素。比如,在一个主要的拖动形状内部包含一些小的装饰元素、图标或者文字,这些内部元素可以有自己独立的动画和交互效果。
    作者:帅得不敢出门
相关推荐
菜鸟233号20 小时前
力扣513 找树左下角的值 java实现
java·数据结构·算法·leetcode
Neoest21 小时前
【EasyExcel 填坑日记】“Syntax error on token )“: 一次编译错误在逃 Runtime 的灵异事件
java·eclipse·编辑器
モンキー・D・小菜鸡儿21 小时前
Android Jetpack Compose 基础控件介绍
android·kotlin·android jetpack·compose
自在极意功。21 小时前
Web开发中的分层解耦
java·microsoft·web开发·解耦
是一个Bug21 小时前
ConcurrentHashMap的安全机制详解
java·jvm·安全
断剑zou天涯21 小时前
【算法笔记】bfprt算法
java·笔记·算法
番石榴AI21 小时前
java版的ocr推荐引擎——JiaJiaOCR 2.0重磅升级!纯Java CPU推理,新增手写OCR与表格识别
java·python·ocr
无风之翼21 小时前
android15 休眠唤醒过程中有时候屏幕显示时间一闪而过
android·锁屏
鸽鸽程序猿1 天前
【项目】【抽奖系统】抽奖
java·spring
GoogleDocs1 天前
基于[api-football]数据学习示例
java·学习