服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android 侧边滑动关闭Activity的示例代码

Android 侧边滑动关闭Activity的示例代码

2022-12-15 15:02裕谷 Android

这篇文章主要介绍了Android 侧边滑动关闭Activity的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

0.效果图

Android 侧边滑动关闭Activity的示例代码

1.设置Activity样式属性

?
1
2
3
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
</style>

2.自定义侧边阴影视图

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class SlideBackView extends View {
 
    private Paint mBgPaint, mShadowPaint;
    private RectF mBgRectF, mShadowRectF;
    private float mRatio;
    private float mShadowSize;
 
    public SlideBackView(Context context) {
      super(context);
      mBgPaint = new Paint();
      mBgPaint.setAntiAlias(true);
      mBgPaint.setColor(0xff000000);
      mShadowPaint = new Paint();
      mShadowPaint.setAntiAlias(true);
      mShadowPaint.setStyle(Paint.Style.FILL);
      mShadowSize = dp2px(15);
    }
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      mBgRectF = new RectF();
      mBgRectF.top = 0;
      mBgRectF.left = 0;
      mBgRectF.bottom = MeasureSpec.getSize(heightMeasureSpec);
 
      mShadowRectF = new RectF();
      mShadowRectF.top = 0;
      mShadowRectF.bottom = MeasureSpec.getSize(heightMeasureSpec);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      int width = getMeasuredWidth();
      float right = mRatio * width;
      mBgRectF.right = right;
      mBgPaint.setAlpha((int) (128 * (1 - mRatio)));
      canvas.drawRect(mBgRectF, mBgPaint);
      mShadowRectF.left = right - mShadowSize;
      mShadowRectF.right = right;
      mShadowPaint.setShader(new LinearGradient(mShadowRectF.left, 0, mShadowRectF.right, 0, 0x00000000, 0x26000000, Shader.TileMode.CLAMP));
      canvas.drawRect(mShadowRectF, mShadowPaint);
    }
 
    public void setDistance(float ratio) {
      mRatio = ratio;
      invalidate();
    }
 
    private float dp2px(float dpValue) {
      float density = getResources().getDisplayMetrics().density;
      return dpValue * density + 0.5F;
    }
  }

3.定义可滑动的Activity父类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
public class SlideBaseActivity extends AppCompatActivity implements ValueAnimator.AnimatorUpdateListener {
 
  private boolean isAnimate, isSlide, isHandle;
  private float moveNum;
  private float lastX, lastY;
  private int lastPointerCount;
  private float mAnimatedValue;
  private ValueAnimator mValueAnimator;
  private SlideBackView mSlideBackView;
  private float mTouchSlop;
  private List<ShieldView> shieldViews = new ArrayList<>();
 
  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    super.onCreate(savedInstanceState);
    initAnimator();
    initSlideBackView();
    mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
  }
 
  @Override
  public void onAnimationUpdate(ValueAnimator animation) {
    mAnimatedValue = (float) animation.getAnimatedValue();
    moveView(mAnimatedValue);
  }
 
  @Override
  public boolean dispatchTouchEvent(MotionEvent event) {
    if (!isAnimate) {
      float x = event.getRawX();
      float y = event.getRawY();
      if (event.getPointerCount() != lastPointerCount) {
        lastPointerCount = event.getPointerCount();
        lastX = x;
        lastY = y;
      }
      float offsetX, offsetY;
      switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
          offsetX = x - lastX;
          offsetY = y - lastY;
          if (!isHandle) {
            float absX = Math.abs(offsetX);
            float absY = Math.abs(offsetY);
            if (absX > mTouchSlop) {
              if (absX * 0.5f > absY) {
                isSlide = true;
                checkSlide((int) x, (int) y);
              } else {
                isSlide = false;
              }
              isHandle = true;
            }
          } else if (isSlide) {
            moveNum += offsetX;
            if (moveNum < 0) {
              moveNum = 0;
            }
            moveView(moveNum);
            lastX = event.getX();
          }
          break;
        case MotionEvent.ACTION_UP:
          if (isHandle) {
            isSlide = false;
            isHandle = false;
            isAnimate = true;
            int width = getWindow().getDecorView().getMeasuredWidth();
            if (moveNum < width / 3f) {
              mValueAnimator.setFloatValues(moveNum, 0);
            } else {
              mValueAnimator.setFloatValues(moveNum, width);
            }
            mValueAnimator.start();
            moveNum = 0;
            lastPointerCount = 0;
          }
      }
    }
    return isSlide || super.dispatchTouchEvent(event);
  }
 
  /**
   * 添加禁用滑动的子布局
   */
  public void addShieldView(View view) {
    shieldViews.add(new ShieldView(false, view));
  }
 
  /**
   * 添加水平禁用滑动的子布局
   */
  public void addHorizontalShieldView(View view) {
    shieldViews.add(new ShieldView(true, view));
  }
 
  /**
   * 移除禁用滑动的子布局
   */
  public void removeShieldView(View view) {
    for (ShieldView v : shieldViews) {
      if (v.view != null && v.view.equals(view)) {
        shieldViews.remove(v);
        break;
      }
    }
  }
 
  /**
   * 清空禁用滑动的子布局
   */
  public void clearShieldView() {
    shieldViews.clear();
  }
 
  private void initAnimator() {
    mValueAnimator = new ValueAnimator();
    mValueAnimator.setDuration(300);
    mValueAnimator.addUpdateListener(this);
    mValueAnimator.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {
        isAnimate = false;
        if (mAnimatedValue == getWindow().getDecorView().getMeasuredWidth()) {
          SlideBaseActivity.super.finish();
          overridePendingTransition(0, 0);
        }
      }
    });
  }
 
  private void initSlideBackView() {
    mSlideBackView = new SlideBackView(this);
    ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    decorView.addView(mSlideBackView);
  }
 
  private void moveView(float moveX) {
    ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    mSlideBackView.setDistance(moveX / decorView.getMeasuredWidth());
    int count = decorView.getChildCount();
    for (int i = 0; i < count; i++) {
      View view = decorView.getChildAt(i);
      if (view != mSlideBackView) {
        view.setX(moveX);
      }
    }
  }
 
  private void checkSlide(int x, int y) {
    for (ShieldView v : shieldViews) {
      Rect rect = new Rect();
      v.view.getGlobalVisibleRect(rect);
      if (rect.contains(x, y) && (!(lastX < x && !v.view.canScrollHorizontally(-1)) || (!v.isHorizontal))) {
        isSlide = false;
      }
    }
  }
  
  class ShieldView {
    boolean isHorizontal;
    View view;
 
    public ShieldView(boolean isHorizontal, View view) {
      this.isHorizontal = isHorizontal;
      this.view = view;
    }
  }
}

4.使用

继承SlideBaseActivity类,可调用addShieldViewaddHorizontalShieldView方法解决事件冲突。

5.项目源码

https://gitee.com/yugu/slide-demo

总结

到此这篇关于Android 侧边滑动关闭Activity的文章就介绍到这了,更多相关Android 侧边滑动关闭Activity内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://segmentfault.com/a/1190000022678714

延伸 · 阅读

精彩推荐
  • AndroidAndroid自定义View验证码输入框

    Android自定义View验证码输入框

    这篇文章主要为大家详细介绍了自定义View验证码输入框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    LDH_1234572022-12-12
  • AndroidFlutter持久化存储之数据库存储(sqflite)详解

    Flutter持久化存储之数据库存储(sqflite)详解

    这篇文章主要给大家介绍了关于Flutter持久化存储之数据库存储的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Flutter具有一定的参...

    Flutter编程指南11472022-09-28
  • Android2022 Android 进阶学习RoadMap!

    2022 Android 进阶学习RoadMap!

    最近几年国内的初级Android程序员已经很多了,但是中高级的Android技术人才仍然稀缺;这的确不假,今年已经是2022年了,距离Android巅峰时期那会已经过去七...

    程序员巴士7322022-01-12
  • Androidandroid桌面悬浮窗显示录屏时间控制效果

    android桌面悬浮窗显示录屏时间控制效果

    这篇文章主要为大家详细介绍了android桌面悬浮窗,显示录屏时间控制效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    zhuxingchong4262022-03-03
  • AndroidAndroid Visualizer 可视化器的自定义实现

    Android Visualizer 可视化器的自定义实现

    若想在Android应用中展示类似的可视化效果,你可以使用Android原生的Visualizer类,它是Android框架中的一部分,且能够附加到你的AudioTrack。...

    掘金10902021-09-16
  • Android使用SignalR推送服务在Android的实现 SignalA

    使用SignalR推送服务在Android的实现 SignalA

    SignalA是老外写的用于实现.net端推送消息至安卓端的实现,支持版本为android 2.3或以上...

    Android开发网12192021-03-04
  • Androidandroid自定义加减按钮

    android自定义加减按钮

    这篇文章主要为大家详细介绍了android自定义加减按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    望风的懒蜗牛4982022-12-06
  • AndroidAndroid 中使用 dlib+opencv 实现动态人脸检测功能

    Android 中使用 dlib+opencv 实现动态人脸检测功能

    完成 Android 相机预览功能以后,在此基础上我使用 dlib 与 opencv 库做了一个关于人脸检测的 demo。接下来通过本文给大家介绍Android 中使用 dlib+opencv 实现动态...

    Lightweh10672022-08-29