Android 14 修改侧滑手势动画效果

涉及关键类

SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java

SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt

修改如下:

一,覆盖系统的默认手势效果

SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt

Kotlin 复制代码
//start add code
private var slideBackView: SlideBackView? = null
//end add code

override fun setLayoutParams(layoutParams: WindowManager.LayoutParams) {
    this.layoutParams = layoutParams
    //start add code
    slideBackView = SlideBackView(context, miShadeController)
    windowManager.addView(slideBackView, layoutParams)
    //end add code
}
Kotlin 复制代码
override fun onMotionEvent(event: MotionEvent) {
    //start add code
    if (slideBackView?.onTouchEventList(event) == true) return
    //end add code

   。。。。
}

二、实现手势动画效果

SlideBackView.java 手势动画效果

java 复制代码
package com.android.systemui.navigationbar.gestural;


import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.Arrays;
import java.util.List;

public class SlideBackView extends View {

    private static final int UN = -1;
    private static final int LEFT = 0;
    private static final int RIGHT = 1;

    private static final int MAX_WIDTH = 60;

    private static final int THRESHOLD = 50;
    private float startX = 0f;
    private float downX = 0f;
    private float moveX = 0f;
    private float moveY = 0f;
    private float upX = 0f;

    private float distanceX = 0f;

    private float speed = 0.5f;

    private int showType = UN;
    Path cubicPath;
    Paint wavePaint;
    private ValueAnimator valueAnimator;
    private Path arrowPath;
    private Paint arrowPaint;
    private static final int ARROW_SIZE = 8;
    private static final int SLIDE_HEIGHT = 400;
    private  MiShadeController controller;

    public SlideBackView(Context context, MiShadeController  controller) {
        this(context, null,controller);
    }

    public SlideBackView(Context context, AttributeSet attrs, MiShadeController  controller) {
        super(context, attrs);
        this.controller=controller;
        init();
    }

    private void init() {
        cubicPath = new Path();
        arrowPath = new Path();
        wavePaint = new Paint();
        wavePaint.setColor(0x11000000);
        wavePaint.setAntiAlias(true); // 启用抗锯齿

        arrowPaint = new Paint();
        arrowPaint.setColor(Color.WHITE);
        arrowPaint.setStyle(Paint.Style.STROKE);
        arrowPaint.setAntiAlias(true); // 启用抗锯齿
        arrowPaint.setStrokeWidth(2);

        valueAnimator = ObjectAnimator.ofFloat(1, 0);
        valueAnimator.setDuration(500);
        valueAnimator.addUpdateListener(animation -> {
            distanceX = distanceX * (Float) animation.getAnimatedValue();
            postInvalidate();
        });
    }


    private boolean isReachThreshold() {
        return startX < THRESHOLD || startX > getMeasuredWidth() - THRESHOLD;
    }

    private void initSlideDirection() {
        if (startX < THRESHOLD) {
            showType = LEFT;
        } else if (startX > getMeasuredWidth() - THRESHOLD) {
            showType = RIGHT;
        } else {
            showType = UN;
        }
    }
    private boolean isHideBackView = false;

    public  boolean onTouchEventList(MotionEvent event){
        if (valueAnimator.isRunning()) return false;
        int action = event.getAction();
        if (action == MotionEvent.ACTION_DOWN) {
            startX = downX = event.getX();
            if (!isReachThreshold()) {
                showType = UN;
                return false;
            }
            initSlideDirection();
        } else if (action == MotionEvent.ACTION_MOVE) {
            if (!isReachThreshold()) {
                showType = UN;
                return false;
            }
            moveX = event.getX();
            moveY = event.getY();
            distanceX = moveX - downX;
            postInvalidate();
        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
            if (!isReachThreshold()) {
                showType = UN;
                return false;
            }
            upX = event.getX();
            distanceX = upX - downX;
            handUpEvent();
        }
        return false;
    }

    private void handUpEvent() {
        if (valueAnimator.isRunning()) {
            valueAnimator.cancel();
        }
        valueAnimator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (showType == UN) return;

        // draw wave
        cubicPath.reset();

        int currentY = (int) Math.min(Math.max(SLIDE_HEIGHT/2f,moveY),getHeight()-SLIDE_HEIGHT/2f);

        // 凸起上部Y
        int topY = (int) (currentY - SLIDE_HEIGHT/2F);
        // 凸起下部Y
        int bottomY = (int) (currentY + SLIDE_HEIGHT/2F);
        // 凸起底部X
        int footX = showType == LEFT ? 0 : getWidth();
        // 凸起顶部X
        int peekX;
        if (showType == LEFT) {
            peekX = (int) (footX + Math.min(distanceX * speed, MAX_WIDTH));
        } else {
            peekX = (int) (footX - Math.min(Math.abs(distanceX) * speed, MAX_WIDTH));
        }

        int x1 = footX;
        int y1 = (int) (topY + SLIDE_HEIGHT*0.2F);

        int x2 = peekX;
        int y2 = (int) (topY + SLIDE_HEIGHT*0.3F);

        int x4 = peekX;
        int y4 = (int) (bottomY - SLIDE_HEIGHT*0.3F);

        int x5 = footX;
        int y5 = (int) (bottomY - SLIDE_HEIGHT*0.2F);

        cubicPath.moveTo(footX, topY);
        cubicPath.cubicTo(x1, y1, x2, y2, peekX, currentY);
        cubicPath.cubicTo(x4, y4, x5, y5, footX, bottomY);
        cubicPath.close();
        wavePaint.setAlpha((int) (Math.abs(distanceX) / MAX_WIDTH * 64));
        canvas.drawPath(cubicPath, wavePaint);

        arrowPath.reset();
        if (showType == LEFT) {
            float centerX = Math.min(distanceX * speed, MAX_WIDTH)/2F - 10;
            arrowPath.moveTo(centerX+ARROW_SIZE , currentY - ARROW_SIZE);
            arrowPath.lineTo(centerX, currentY);
            arrowPath.lineTo(centerX+ ARROW_SIZE , currentY + ARROW_SIZE);
        } else {
            float centerX = peekX+Math.min(Math.abs(distanceX) * speed, MAX_WIDTH)/2F + 6;
            arrowPath.moveTo(centerX + ARROW_SIZE, currentY - ARROW_SIZE);
            arrowPath.lineTo(centerX, currentY);
            arrowPath.lineTo(centerX + ARROW_SIZE, currentY + ARROW_SIZE);
        }
        canvas.drawPath(arrowPath, arrowPaint);
    }

 
 
}

是不是很简单,但是很多兄弟看了很多文章 找了很多资料却始终找不到具体的修改位置,看我的一篇就够了 觉得我写的好的兄弟帮忙点个赞!!谢谢

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui