0

I am using motionlayout to handle animations since it's seems like a good choice. One of the animation i should implement required to alter the src of the image and i couldnt animate that.(seems like we cant change src attribute of an image in constraintsets of motionlayour scene file) Then i found its posssible to crossfade two images with ImageFilterView. I finish the job and switch to another activity, there i need same resource and as you expect i used it but it didn't appeared. I thought this is related with something else, i try many different ways to find out but after some time I found its because motion layout. when i use the image as altsrc with imagefilterview and if its somehow ended up faded state this image will not be visible even if you use it in another activity. it keeping its state across the whole app. What i am wondering is this a bug or some "supposed to be" way logic?

Edit: upon @hoford request I create a new project just to test it. and it happened again. Basically what i am try to do is move an image from right side of the screen to left side when clicked. meanwhile its should fading to another image. and doing the opposite on second click Here is what i do:

MainActivity.java:

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.motion.widget.MotionLayout;
import androidx.constraintlayout.utils.widget.ImageFilterView;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {
MotionLayout _motionlayout;
boolean isForward = true;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    _motionlayout = findViewById(R.id.rootlayout_motionlayout);

    ImageFilterView imageFilterView = findViewById(R.id.about_imagefilterview);
    isForward = true;
    imageFilterView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (isForward) {
                Log.d("TAG", "onClick: inside if");
                _motionlayout.setTransition(R.id.mainactivity_transition_about_icon_1);
                _motionlayout.transitionToEnd();
                isForward = false;
            } else {
                Log.d("TAG", "onClick: inside else");
                _motionlayout.setTransition(R.id.mainactivity_transition_about_icon_2);
                _motionlayout.transitionToEnd();
                isForward = true;
            }
        }
    });

    findViewById(R.id.open_second_activity_button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, SecondActivity.class);
            startActivity(intent);
        }
    });
}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 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/rootlayout_motionlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#d80"
    app:layoutDescription="@xml/activity_main_scene"
    tools:context=".MainActivity">

    <!--
    damn overlay!
    https://stackoverflow.com/questions/52996035/motionlayout-using-crossfade-altsrc-appears-on-top-of-src-original-image-does
    -->
    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:id="@+id/about_imagefilterview"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@drawable/ic_about_icon_normal_filled"
        app:altSrc="@drawable/ic_about_icon_normal_empty"
        app:layout_constraintBottom_toTopOf="@id/mainactivity_guidline_about_icon_bottom"
        app:layout_constraintDimensionRatio="1"
        app:layout_constraintEnd_toStartOf="@id/mainactivity_guidline_about_icon_right_end"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toEndOf="@id/mainactivity_guidline_about_icon_left_end"
        app:layout_constraintTop_toBottomOf="@id/mainactivity_guidline_about_icon_top"
        app:overlay="false" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/mainactivity_guidline_about_icon_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.038" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/mainactivity_guidline_about_icon_bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.079" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/mainactivity_guidline_about_icon_right_end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.95" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/mainactivity_guidline_about_icon_left_end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.05" />

    <Button
        android:id="@+id/open_second_activity_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go to Second"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>

activity_main_scene.xml

   <?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
        android:id="@+id/mainactivity_transition_about_icon_1"
        motion:constraintSetEnd="@+id/mainactivity_constraintset_state2"
        motion:constraintSetStart="@id/mainactivity_constraintset_state1"
        motion:duration="500" />

    <Transition
        android:id="@+id/mainactivity_transition_about_icon_2"
        motion:constraintSetEnd="@+id/mainactivity_constraintset_state1"
        motion:constraintSetStart="@id/mainactivity_constraintset_state2"
        motion:duration="500" />

    <!-- ===================================== CONSTRAINTSETS ===================================== -->
    <ConstraintSet android:id="@+id/mainactivity_constraintset_state1">
        <Constraint
            android:id="@+id/about_imagefilterview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toTopOf="@id/mainactivity_guidline_about_icon_bottom"
            motion:layout_constraintDimensionRatio="1"
            motion:layout_constraintEnd_toStartOf="@id/mainactivity_guidline_about_icon_right_end"
            motion:layout_constraintHorizontal_bias="1"
            motion:layout_constraintStart_toEndOf="@id/mainactivity_guidline_about_icon_left_end"
            motion:layout_constraintTop_toBottomOf="@id/mainactivity_guidline_about_icon_top">
            <CustomAttribute
                motion:attributeName="crossfade"
                motion:customFloatValue="0" />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/mainactivity_constraintset_state2">
        <Constraint
            android:id="@+id/about_imagefilterview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toTopOf="@id/mainactivity_guidline_about_icon_bottom"
            motion:layout_constraintDimensionRatio="1"
            motion:layout_constraintEnd_toStartOf="@id/mainactivity_guidline_about_icon_right_end"
            motion:layout_constraintHorizontal_bias="0"
            motion:layout_constraintStart_toEndOf="@id/mainactivity_guidline_about_icon_left_end"
            motion:layout_constraintTop_toBottomOf="@id/mainactivity_guidline_about_icon_top">
            <CustomAttribute
                motion:attributeName="crossfade"
                motion:customFloatValue="1" />
        </Constraint>
    </ConstraintSet>
</MotionScene>

SecondActivity.Java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }
}

activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="#b40"
    tools:context=".SecondActivity">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@drawable/ic_about_icon_normal_empty"
        app:layout_constraintBottom_toTopOf="@id/secondactivity_imageview_bottom"
        app:layout_constraintDimensionRatio="1"
        app:layout_constraintEnd_toStartOf="@id/secondactivity_imageview_right_end"
        app:layout_constraintStart_toEndOf="@id/secondactivity_imageview_left_end"
        app:layout_constraintTop_toBottomOf="@id/secondactivity_imageview_top" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/secondactivity_imageview_left_end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.40" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/secondactivity_imageview_right_end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.60" />


    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/secondactivity_imageview_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.40" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/secondactivity_imageview_bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.60" />
</androidx.constraintlayout.widget.ConstraintLayout>
eddym
  • 648
  • 7
  • 11
  • What you are describing is simply not possible. So I assume your description is wrong. An image in one activity cannot end up faded in another activity with out some activity transition work. Create a new simple project with a MotionLayout containing an ImageFilterVew and the images you are trying to cross fade. Try and create the effect you do not like. Post the XML, what it did, and what you would like it to do. – hoford Feb 12 '21 at 18:05
  • I update the post @hoford. And I also thought it should not be possible but seems like it is. Maybe I am doing something extreme I don't know. – eddym Feb 14 '21 at 00:26
  • 1
    Yes are correct this is a strange bug/feature. Android is cashing drawables across the process so if you use the same drawable across process it affects all instances. It was done for efficiency. There is no go fix on your side. (Just have 2 drawables) We are not sure what to do now if we copy it. It impacts performance across the system. You can file a bug to track it. – hoford Feb 27 '21 at 01:27

0 Answers0