【发布时间】:2022-04-09 23:19:27
【问题描述】:
如何在 Telegram 和 Tinder 应用中使用手势和动画滑动到上一个活动?
【问题讨论】:
-
你怎么知道那些是活动,而不是片段?
-
好的,如何处理片段?
标签: android android-activity android-animation android-gesture
如何在 Telegram 和 Tinder 应用中使用手势和动画滑动到上一个活动?
【问题讨论】:
标签: android android-activity android-animation android-gesture
【讨论】:
在 github 上有一个很好的库,我贡献了我的贡献:它通过活动和片段处理此功能。
【讨论】:
其实你所要做的就是把这个 OnCreate:
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
(注意:它只适用于片段)
首先,您需要在布局中将 NavHostFragment 替换为 FragulaNavHostFragment:
<!-- 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>
基本上就是这样
【讨论】: