I have a motion layout that moves back and forth between covering the element below it, and showing it when it is swiped up, this element (the dashboard) has a swipe up image on it that lets the user know it’s swipable. The problem here is that I want the "swipe up arrow" to disappear after getting swiped.
But I’m faced with several problems: the motion layout doesn’t recognize elements other than the one below it, so it seems that a motion layout can’t do transitions for more than one element.
-
So I can’t use the dashboard motion layout to hide the swipe up image after the swipe, I tried and I it didn’t work and never gave me an error
-
I can’t turn the swipe up image into a motion layout either because it won’t recognize the dashboard
So I thought I would do it programmatically. Whenever the dashboard (the one in black) element is swiped up, the swipe up image is set to invisible, but having started to set that up, the dashboard element now ignores the swipe up listener from the motion layout and acknowledges the kotlin listener.
I can only think of several solutions, being a new android dev. One of which is adding a swipe up listener to the dashboard programmatically and using that to transition it upwards and get the arrow to disappear OR find a way to get the motion layout to transition the dashboard upward and remove the swipe up image once its been swiped
Neither of which is something I know how to do, I’m also open to more efficient alternatives
How it looks before its been swiped
main activity:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="500dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<androidx.cardview.widget.CardView
android:id="@+id/dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="@color/green"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/constraintLayout12"
android:layout_width="match_parent"
android:layout_height="100dp"
android:elevation="20dp"
app:layoutDescription="@xml/activity_main_light_copy_2_xml_constraintlayout12_scene"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/swipeUpPic"
android:layout_width="match_parent"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="@id/dashboard"
app:layout_constraintEnd_toEndOf="@id/dashboard"
app:layout_constraintStart_toStartOf="@id/dashboard"
app:srcCompat="@drawable/scroll_image" />
</androidx.constraintlayout.motion.widget.MotionLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Motion layout:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<OnSwipe
motion:touchAnchorId="@id/dashboard"
motion:dragDirection="dragUp"
motion:touchAnchorSide="top" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@id/dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" >
</Constraint>
<Constraint
android:id="@id/swipeUpPic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" >
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/dashboard"
android:layout_width="match_parent"
android:layout_height="400dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" >
</Constraint>
<Constraint
android:id="@id/swipeUpPic"
android:layout_width="match_parent"
android:layout_height="match_parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
android:visibility="invisible">
</Constraint>
</ConstraintSet>
</MotionScene>
2
Answers
There a few ways to achieve this.
The easiest is to simply design it flat. It is a little tricky to figure out how to make a virtual panel. The order of views in a MotionLayout is the z order(Bottom first). Playing around with it you can work it out.
You may not want to do that for team/architecture reasons. e.g. One panel is being recused across several screens.
2 and 3 are just variants of each other.
The idea is the ViewGroup subclass listens to setProgress(float x) and the controlling motionLayout calls setProgress at the correct point.
MotionLayout already listens to setProgress so some of it is done for you.
The key is the outer MotionLayout panel is in Control of the Swipe.
I would also recommend looking at a few examples:
https://developer.android.com/training/constraint-layout/motionlayout/examples
Let me start by saying, I totally agree with @hoford.
The best approach would be to flatten your
MotionLayout
, however you can show/hide your swipe up button by adding a TransitionListener to yourMotionLayout
. Use addTransitionListener()You can either use: