直接上代码:
新建三个类:MainActivity、SecondActivity和ThirdActivity
另外在新建个BaseActivity,使SecondActivity和ThirdActivity继承BaseActivity
最后修改下theme为透明即可
activity_main.xml:
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MainActivity"
android:textSize="18sp"
android:textColor="@android:color/white" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳转" />
</LinearLayout>
MainActivity:
[Java] 纯文本查看 复制代码 import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
}
activity_second.xml:
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/colorAccent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SecondActivity"
android:textSize="18sp"
android:textColor="@android:color/white" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳转" />
</LinearLayout>
SecondActivity:
[Java] 纯文本查看 复制代码 import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class SecondActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this, ThirdActivity.class);
startActivity(intent);
}
});
}
}
activity_third.xml:
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ThirdActivity"
android:textSize="18sp"
android:textColor="@android:color/white" />
</LinearLayout>
ThirdActivity:
[Java] 纯文本查看 复制代码 import android.os.Bundle;
public class ThirdActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
}
}
BaseActivity:
[Java] 纯文本查看 复制代码 import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
/**
* Created by Administrator on 2019/1/4.
*/
public class BaseActivity extends Activity {
private SwipeLayout swipeLayout;
private boolean swipeFinished = false;
/**
* 是否可以滑动关闭页面
*/
protected boolean swipeEnabled = true;
/**
* 是否可以在页面任意位置右滑关闭页面,如果是false则从左边滑才可以关闭。
*/
protected boolean swipeAnyWhere = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
swipeLayout = new SwipeLayout(this);
}
public void setSwipeAnyWhere(boolean swipeAnyWhere) {
this.swipeAnyWhere = swipeAnyWhere;
}
public boolean isSwipeAnyWhere() {
return swipeAnyWhere;
}
public void setSwipeEnabled(boolean swipeEnabled) {
this.swipeEnabled = swipeEnabled;
}
public boolean isSwipeEnabled() {
return swipeEnabled;
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
swipeLayout.replaceLayer(this);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (swipeFinished) {
super.finish();
overridePendingTransition(0, 0);
} else {
swipeLayout.cancelPotentialAnimation();
super.finish();
overridePendingTransition(0, R.anim.slide_out_right);
}
}
class SwipeLayout extends FrameLayout {
//private View backgroundLayer;用来设置滑动时的背景色
private Drawable leftShadow;
public SwipeLayout(Context context) {
super(context);
}
public SwipeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public int getScreenWidth(Context context) {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager manager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
manager.getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels;
}
public void replaceLayer(Activity activity) {
leftShadow = activity.getResources().getDrawable(R.drawable.left_shadow);
touchSlop = (int) (touchSlopDP * activity.getResources().getDisplayMetrics().density);
sideWidth = (int) (sideWidthInDP * activity.getResources().getDisplayMetrics().density);
mActivity = activity;
screenWidth = getScreenWidth(activity);
setClickable(true);
final ViewGroup root = (ViewGroup) activity.getWindow().getDecorView();
content = root.getChildAt(0);
ViewGroup.LayoutParams params = content.getLayoutParams();
ViewGroup.LayoutParams params2 = new ViewGroup.LayoutParams(-1, -1);
root.removeView(content);
this.addView(content, params2);
root.addView(this, params);
}
@Override
protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) {
boolean result = super.drawChild(canvas, child, drawingTime);
final int shadowWidth = leftShadow.getIntrinsicWidth();
int left = (int) (getContentX()) - shadowWidth;
leftShadow.setBounds(left, child.getTop(), left + shadowWidth, child.getBottom());
leftShadow.draw(canvas);
return result;
}
boolean canSwipe = false;
/**
* 超过了touchslop仍然没有达到没有条件,则忽略以后的动作
*/
boolean ignoreSwipe = false;
View content;
Activity mActivity;
int sideWidthInDP = 16;
int sideWidth = 72;
int screenWidth = 1080;
VelocityTracker tracker;
float downX;
float downY;
float lastX;
float currentX;
float currentY;
int touchSlopDP = 20;
int touchSlop = 60;
@Override
public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
if (swipeEnabled && !canSwipe && !ignoreSwipe) {
if (swipeAnyWhere) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = ev.getX();
downY = ev.getY();
currentX = downX;
currentY = downY;
lastX = downX;
break;
case MotionEvent.ACTION_MOVE:
float dx = ev.getX() - downX;
float dy = ev.getY() - downY;
if (dx * dx + dy * dy > touchSlop * touchSlop) {
if (dy == 0f || Math.abs(dx / dy) > 1) {
downX = ev.getX();
downY = ev.getY();
currentX = downX;
currentY = downY;
lastX = downX;
canSwipe = true;
tracker = VelocityTracker.obtain();
return true;
} else {
ignoreSwipe = true;
}
}
break;
}
} else if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getX() < sideWidth) {
canSwipe = true;
tracker = VelocityTracker.obtain();
return true;
}
}
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
ignoreSwipe = false;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return canSwipe || super.onInterceptTouchEvent(ev);
}
boolean hasIgnoreFirstMove;
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
if (canSwipe) {
tracker.addMovement(event);
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
currentX = downX;
currentY = downY;
lastX = downX;
break;
case MotionEvent.ACTION_MOVE:
currentX = event.getX();
currentY = event.getY();
float dx = currentX - lastX;
if (dx != 0f && !hasIgnoreFirstMove) {
hasIgnoreFirstMove = true;
dx = dx / dx;
}
if (getContentX() + dx < 0) {
setContentX(0);
} else {
setContentX(getContentX() + dx);
}
lastX = currentX;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
tracker.computeCurrentVelocity(10000);
tracker.computeCurrentVelocity(1000, 20000);
canSwipe = false;
hasIgnoreFirstMove = false;
int mv = screenWidth * 3;
if (Math.abs(tracker.getXVelocity()) > mv) {
animateFromVelocity(tracker.getXVelocity());
} else {
if (getContentX() > screenWidth / 3) {
animateFinish(false);
} else {
animateBack(false);
}
}
tracker.recycle();
break;
default:
break;
}
}
return super.onTouchEvent(event);
}
ObjectAnimator animator;
public void cancelPotentialAnimation() {
if (animator != null) {
animator.removeAllListeners();
animator.cancel();
}
}
public void setContentX(float x) {
int ix = (int) x;
content.setX(ix);
invalidate();
}
public float getContentX() {
return content.getX();
}
/**
* 弹回,不关闭,因为left是0,所以setX和setTranslationX效果是一样的
*
* @param withVel 使用计算出来的时间
*/
private void animateBack(boolean withVel) {
cancelPotentialAnimation();
animator = ObjectAnimator.ofFloat(this, "contentX", getContentX(), 0);
int tmpDuration = withVel ? ((int) (duration * getContentX() / screenWidth)) : duration;
if (tmpDuration < 100) {
tmpDuration = 100;
}
animator.setDuration(tmpDuration);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
}
private void animateFinish(boolean withVel) {
cancelPotentialAnimation();
animator = ObjectAnimator.ofFloat(this, "contentX", getContentX(), screenWidth);
int tmpDuration = withVel ? ((int) (duration * (screenWidth - getContentX()) / screenWidth)) : duration;
if (tmpDuration < 100) {
tmpDuration = 100;
}
animator.setDuration(tmpDuration);
animator.setInterpolator(new DecelerateInterpolator());
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mActivity.isFinishing()) {
swipeFinished = true;
mActivity.finish();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
animator.start();
}
private final int duration = 200;
private void animateFromVelocity(float v) {
if (v > 0) {
if (getContentX() < screenWidth / 3 && v * duration / 1000 + getContentX() < screenWidth / 3) {
animateBack(false);
} else {
animateFinish(true);
}
} else {
if (getContentX() > screenWidth / 3 && v * duration / 1000 + getContentX() > screenWidth / 3) {
animateFinish(false);
} else {
animateBack(true);
}
}
}
}
}
slide_out_right.xml:
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:toXDelta="100%p" />
</set>
res/styles.xml:
[XML] 纯文本查看 复制代码 <style name="Transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowIsTranslucent">true</item>
</style>
在AndroidManifest.xml中进行修改:
看下效果:
|