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);
    }

 
 
}

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

相关推荐
阿巴斯甜18 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker19 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952720 小时前
Andorid Google 登录接入文档
android
黄林晴21 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android