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

 
 
}

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

相关推荐
恋猫de小郭42 分钟前
Flutter Widget IDE 预览新进展,开始推进落地发布
android·前端·flutter
百锦再2 小时前
Java与Kotlin在Android开发中的全面对比分析
android·java·google·kotlin·app·效率·趋势
Ya-Jun6 小时前
常用第三方库:flutter_boost混合开发
android·flutter·ios
_一条咸鱼_7 小时前
深度剖析:Android NestedScrollView 惯性滑动原理大揭秘
android·面试·android jetpack
_一条咸鱼_7 小时前
深度揭秘!Android NestedScrollView 绘制原理全解析
android·面试·android jetpack
_一条咸鱼_7 小时前
揭秘 Android CoordinatorLayout:从源码深度解析其协同工作原理
android·面试·android jetpack
_一条咸鱼_7 小时前
揭秘 Android View 的 TranslationY 位移原理:源码深度剖析
android·面试·android jetpack
_一条咸鱼_7 小时前
揭秘 Android NestedScrollView 滑动原理:源码深度剖析
android·面试·android jetpack
_一条咸鱼_7 小时前
深度揭秘:Android NestedScrollView 拖动原理全解析
android·面试·android jetpack
_小马快跑_7 小时前
重温基础:LayoutInflater.inflate(resource, root, attachToRoot)参数解析
android