Android. Swipe to back Activity like Telegram
Asked Answered
F

4

9

How to swipe to previous activity using gesture and animation like in Telegram and Tinder app?

Frequent answered 28/5, 2015 at 19:6 Comment(2)
How do you know that those are activities, and not fragments?Terrieterrier
ok, how to do this with fragments?Eamon
H
6

Telegram is using it's own created fragments.They Created a class named ActionBarLayout which is basically a FrameLayout and is added to the main Activity and the fragment is just a view class (called TelegramFragment) that is added to the ActionBarLayout (they are kept in a list and much faster than normal fragments (with a bit less features).

To do the animation , they just animate the added view.

You can see the classes work in action HERE and HERE

Humanize answered 12/9, 2015 at 13:47 Comment(1)
Hi @snaky , I`m studiying telegram animations over 2months to apply same animations on my android application. I only need "in" and "out" animations like when we click on any chat inside DialogFragment. I wont implement all ActionBarLayout functionalities like fragmentcontainer and stackcontainer (I know this functionalities is very important ) My only question is : Only with ActionBarLayout.startLayoutAnimation and ActionBarLayout.onSlideAnimationEnd I will got the same telegram animation ? with same mellowness?Adown
V
3

there is a good library on github where I gave my contribute: it handles this feature both with activities and fragments.

https://github.com/r0adkll/Slidr

Volva answered 27/1, 2018 at 18:30 Comment(3)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.Consistent
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewConsistent
This is a library (Slidr), the link is to github, where it's located. I cannot answer by writing the entire code of the library here and moreover it's not necessary a how-to introduction about the usage because it's well explained on the readme.Volva
E
1

Actually all you have to do is put this 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); 
}
}
{
Evadnee answered 28/3, 2021 at 4:43 Comment(0)
G
0

Navigation library

Here is really simple library, fully integrated with NavComponent.
I'm still working on it, but it is already stable so you can use it in production.

https://github.com/massivemadness/Fragula
(Note: it works only with fragments)

First, you need to replace NavHostFragment with FragulaNavHostFragment in your layout:

<!-- 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" />

Second, you need to replace your <fragment> destinations in graph with <swipeable> as shown below:

<!-- 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>

Finally, you need to set opaque background to your fragment’s root layout to avoid any issues with swipe animation.

<!-- 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>

That's basically it

Granger answered 27/3, 2022 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.