如何使用手势和动画向前滑动以前的活动,就像在Telegram和Tinder应用程序中一样?
在Github上有一个很好的库,我做出了贡献:它可以使用活动和片段来处理此功能。
getWindow().getDecorView().setBackgroundResource(android.R.color.transparent);
MIN_DISTANCE = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, this.getResources().getDisplayMetrics());
rootView = (ViewGroup) ((ViewGroup) this .findViewById(android.R.id.content)).getChildAt(0);
rootView.post(new Runnable() { @Override public void run() {
rootWidth = rootView.getWidth();
} });
}
// Custom Variables
ViewGroup rootView ;
int rootWidth;
boolean enableSwipe= false;
boolean lockSwipe = false;
float downX;
float downY;
float MIN_DISTANCE ;
// Detect touch Events
@Override public boolean dispatchTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getRawX();
downY =event.getRawY();
enableSwipe = false;
lockSwipe = false;
//convert activity to transparent
try { java.lang.reflect.Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions"); getActivityOptions.setAccessible(true); Object options = getActivityOptions.invoke(this); Class<?>[] classes = Activity.class.getDeclaredClasses(); Class<?> translucentConversionListenerClazz = null; for (Class clazz : classes) { if (clazz.getSimpleName().contains("TranslucentConversionListener")) { translucentConversionListenerClazz = clazz; } }
java.lang.reflect.Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent", translucentConversionListenerClazz, ActivityOptions.class); convertToTranslucent.setAccessible(true); convertToTranslucent.invoke(this, null, options); } catch (Throwable t) {
}
break;
case MotionEvent.ACTION_MOVE:
if (!lockSwipe){
if(enableSwipe){
float translation = event.getRawX() -downX - MIN_DISTANCE;
if (translation >= rootWidth || translation<= 0){
rootView.setTranslationX(0);
}else{
rootView.setTranslationX(translation);
}
}else{
float translation = event.getRawX() -downX;
if(Math.abs(event.getRawY() - downY) >= MIN_DISTANCE){
enableSwipe = false;
lockSwipe = true;
}else{
enableSwipe = event.getRawX() -downX >= MIN_DISTANCE;
}
}
}
break;
case MotionEvent.ACTION_UP:
if(rootView.getTranslationX() > rootWidth / 5){
rootView.animate()
.translationX(rootWidth)
.setListener(
new AnimatorListenerAdapter() {
@Override public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
finish();
overridePendingTransition(0, 0);
} });
}else{
rootView.animate()
.translationX(0)
.setListener(
new AnimatorListenerAdapter() {
@Override public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// convert activity back to normal
try {
java.lang.reflect.Method method = Activity.class.getDeclaredMethod("convertFromTranslucent");
method.setAccessible(true);
method.invoke(this);
} catch (Throwable t) {
}
} });
enableSwipe =false;
lockSwipe = false;
}
break;
default:
enableSwipe =false;
lockSwipe = false;
break;
}
if (enableSwipe){
// Event will not be passed to next views
return true;
}
else{
// Event will be passed to next views
return super.dispatchTouchEvent(event);
}
}
{
这是一个非常简单的库,与NavComponent完全集成。
我仍在开发中,但它已经很稳定,您可以在生产中使用它。
https://github.com/massivemadness/Fragula
(注意:它只适用于片段)
首先,您需要在布局中用FragulaNavHostFragment
替换NavHostFragment
:
<!-- activity_main.xml -->
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.fragula2.FragulaNavHostFragment"
android:id="@+id/nav_host"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true" />
第二步, 你需要将图表中的<fragment>
目标替换为如下所示的<swipeable>
:
<!-- nav_graph.xml -->
<navigation 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:id="@+id/nav_graph"
app:startDestination="@id/detailFragment">
<swipeable
android:id="@+id/detailFragment"
android:name="com.example.fragula.DetailFragment"
android:label="DetailFragment"
tools:layout="@layout/fragment_detail" />
...
</navigation>
最后,您需要将不透明背景设置为片段的根布局,以避免滑动动画出现任何问题。
<!-- fragment_detail.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:colorBackground">
...
</androidx.constraintlayout.widget.ConstraintLayout>
基本上就是这样