android防止左向右滑出程序,Android向右滑动关闭Activity(高仿知乎微信)

本文介绍了在Android中实现Activity滑动关闭的功能。通过配置透明主题,重写FrameLayout的SlideLayout处理滑动逻辑,以及继承AppCompatActivity的SlideActivity作为基类进行绑定操作。当Activity向右滑动超过屏幕一半时关闭,否则恢复原状,还添加了阴影和滑动动画。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上一个效果图,不是很清晰,凑合看下。

42a6a216f30bc12908a744b358d4ca00.gif

大概效果就是,Activity向右滑动,滑动超过屏幕的一半,就关闭,否则,恢复原来的状态。

下面让我们来看下实现原理吧。

1.配置透明主题

要想Activity滑出屏幕后不遮挡下层Activity,需设置透明主题

@color/colorPrimary

@color/colorPrimaryDark

@color/colorAccent

@android:color/transparent

true

@android:style/Animation

添加后3条即可,当然直接用Android自带透明主题也是可以的。

2.SlideLayout

重写了FrameLayout,主要是处理滑动时的逻辑。

package me.wcy.slideanim;

import android.app.Activity;

import android.graphics.Canvas;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.widget.FrameLayout;

import android.widget.Scroller;

/**

* Created by chenyan.wang on 2015/10/29.

*/

public class SlideLayout extends FrameLayout {

private Activity mActivity;

private Scroller mScroller;

/**

* 上次ACTION_MOVE时的X坐标

*/

private int mLastMotionX;

/**

* 屏幕宽度

*/

private int mWidth;

/**

* 可滑动的最小X坐标,小于该坐标的滑动不处理

*/

private int mMinX;

/**

* 页面边缘的阴影图

*/

private Drawable mLeftShadow;

/**

* 页面边缘阴影的宽度默认值

*/

private static final int SHADOW_WIDTH = 16;

/**

* 页面边缘阴影的宽度

*/

private int mShadowWidth;

/**

* Activity finish标识符

*/

private boolean mIsFinish;

public SlideLayout(Activity activity) {

this(activity, null);

}

public SlideLayout(Activity activity, AttributeSet attrs) {

this(activity, attrs, 0);

}

public SlideLayout(Activity activity, AttributeSet attrs, int defStyleAttr) {

super(activity, attrs, defStyleAttr);

initView(activity);

}

private void initView(Activity activity) {

mActivity = activity;

mScroller = new Scroller(mActivity);

mLeftShadow = getResources().getDrawable(R.drawable.left_shadow);

int density = (int) activity.getResources().getDisplayMetrics().density;

mShadowWidth = SHADOW_WIDTH * density;

}

/**

* 绑定Activity

*/

public void bindActivity(Activity activity) {

ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();

View child = decorView.getChildAt(0);

decorView.removeView(child);

addView(child);

decorView.addView(this);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

mLastMotionX = (int) event.getX();

mWidth = getWidth();

mMinX = mWidth / 10;

break;

case MotionEvent.ACTION_MOVE:

int rightMovedX = mLastMotionX - (int) event.getX();

if (getScrollX() + rightMovedX >= 0) {// 左侧即将滑出屏幕

scrollTo(0, 0);

} else if ((int) event.getX() > mMinX) {// 手指处于屏幕边缘时不处理滑动

scrollBy(rightMovedX, 0);

}

mLastMotionX = (int) event.getX();

break;

case MotionEvent.ACTION_UP:

if (-getScrollX() < mWidth / 2) {

scrollBack();

mIsFinish = false;

} else {

scrollClose();

mIsFinish = true;

}

break;

}

return true;

}

/**

* 滑动返回

*/

private void scrollBack() {

int startX = getScrollX();

int dx = -getScrollX();

mScroller.startScroll(startX, 0, dx, 0, 300);

invalidate();

}

/**

* 滑动关闭

*/

private void scrollClose() {

int startX = getScrollX();

int dx = -getScrollX() - mWidth;

mScroller.startScroll(startX, 0, dx, 0, 300);

invalidate();

}

@Override

public void computeScroll() {

if (mScroller.computeScrollOffset()) {

scrollTo(mScroller.getCurrX(), 0);

postInvalidate();

} else if (mIsFinish) {

mActivity.finish();

}

super.computeScroll();

}

@Override

protected void dispatchDraw(Canvas canvas) {

super.dispatchDraw(canvas);

drawShadow(canvas);

}

/**

* 绘制边缘的阴影

*/

private void drawShadow(Canvas canvas) {

//保存画布当前的状态

canvas.save();

//设置drawable的大小范围

mLeftShadow.setBounds(0, 0, mShadowWidth, getHeight());

//让画布平移一定距离

canvas.translate(-mShadowWidth, 0);

//绘制Drawable

mLeftShadow.draw(canvas);

//恢复画布的状态

canvas.restore();

}

}(1)bindActivity:绑定Activity的界面,这段代码很简单。

(2)通过重写onTouchEvent处理滑动逻辑。(注意,为什么不是重写dispatchTouchEvent或interceptTouchEvnet?)

ACTION_DOWN:主要是记录了屏幕的宽度

ACTION_MOVE:分两种情况,①view的x坐标为0,即初始状态,这时只能向右滑动,禁止向左滑动。②view的坐标大于0,即view的一部分已经划出屏幕(当然是向右滑)。这时,如果继续向右滑则不用多考虑;如果向左滑,就要假设view向左滑动了x后,如果view左边缘还在屏幕内,则可以继续滑动,否则,view左边缘可能已经滑出屏幕,这是我们不想看到的,因此我们直接把view滑动到(0,0)位置。

ACTION_UP:手指释放后,如果滑动距离超过屏幕的一半,就关闭Activity,否则,恢复原来状态。

(3)这里用Scroller来处理手指释放后的滑动操作,本文中Scroller不是重点,因此不过多介绍。

(4)出于交互友好考虑,这里保留了屏幕最左边的一块区域不能滑动,即mMinX = mWidth / 10;

(5)drawShadow:页面滑出屏幕后左侧添加阴影区域,增加层次感。在dispatchDraw中调用。

3.SlideActivity

继承自AppCompatActivity,作为滑动关闭Activity的基类,主要是做了绑定操作。

package me.wcy.slideanim;

import android.content.Intent;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

public class SlideActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

SlideLayout rootView = new SlideLayout(this);

rootView.bindActivity(this);

}

@Override

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {

super.startActivityForResult(intent, requestCode, options);

overridePendingTransition(R.anim.anim_open, R.anim.anim_close);

}

@Override

public void finish() {

super.finish();

overridePendingTransition(R.anim.anim_open, R.anim.anim_close);

}

}startActivity和finish添加了滑动动画。

我在这里遇到一个问题,设置透明主题后,在style中设置Activity切换动画无效,因此这里只好在代码中添加动画。知道原因的朋友还请赐教。

主要代码就这么多,这里考虑到了扩展性,因此使用是非常简单的。如果想要滑动关闭Activity,就设置透明主题,继承SlideActivity就可以了。

如有问题可以在下面评论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值