1

J'ai une application avec deux activities, où la seconde fonctionne comme un «sélecteur» d'image et fournit des informations à la première, de sorte qu'un ImageView peut être mis à jour en conséquence.Elément partagé lors de l'utilisation de startActivityForResult

Pour cela, je vous appelle la deuxième activity par startActivityForResult() et mise à jour du ImageView selon les informations reçues sur onActivityResult().

Le problème se pose lorsque je tente d'animer un élément partagé entre le sélecteur et le principal Activity: il semble que la transition « instantanés » la première Activity, et même si le ImageView est mis à jour dès que les Activity CV, la animation de transition va "scintiller" une ancienne version du View avant d'afficher la version actuelle.

Voici un exemple d'application que j'ai fait pour illustrer ce dont je parle:

Visual description of the bug

Quelle serait la meilleure façon de mettre en œuvre cette animation en toute transparence? Une autre approche devrait-elle être utilisée?

Voici le code utilisé pour l'exemple:

Activité principale

public class MainActivity extends AppCompatActivity { 

    ImageView mainImageView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     getSupportActionBar().setTitle("Main Activity"); 

     mainImageView = (ImageView) findViewById(R.id.imageView); 
     findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Intent intent = new Intent(MainActivity.this, PickerActivity.class); 
       ActivityOptionsCompat options = ActivityOptionsCompat. 
         makeSceneTransitionAnimation(MainActivity.this, mainImageView, "shape_transition"); 
       startActivityForResult(intent, 1, options.toBundle()); 
      } 
     }); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) { 
     super.onActivityResult(requestCode, resultCode, intent); 
     int shapeNumber = intent.getIntExtra("shape_number", -1); 

     switch (shapeNumber) { 
      case 1: 
       mainImageView.setImageResource(R.drawable.blue); 
       break; 
      case 2: 
       mainImageView.setImageResource(R.drawable.green); 
       break; 
      default: 
       //something else 
       break; 
     } 


    } 
} 

Picker Activité:

public class PickerActivity extends AppCompatActivity { 

    ImageView blueImageView; 
    ImageView greenImageView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_picker); 
     getSupportActionBar().setTitle("Picker Activity"); 

     blueImageView = (ImageView) findViewById(R.id.imageView2); 

     blueImageView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       blueImageView.setTransitionName("shape_transition"); 
       Intent intent = new Intent(PickerActivity.this, MainActivity.class); 
       intent.putExtra("shape_number", 1); 
       setResult(RESULT_OK, intent); 
       finishAfterTransition(); 
      } 
     }); 

     greenImageView = (ImageView) findViewById(R.id.imageView3); 

     greenImageView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       greenImageView.setTransitionName("shape_transition"); 
       Intent intent = new Intent(PickerActivity.this, MainActivity.class); 
       intent.putExtra("shape_number", 2); 
       setResult(RESULT_OK, intent); 
       finishAfterTransition(); 
      } 
     }); 
    } 
} 

xml Activité principale:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="demonstration.sharedelementproblemexample.MainActivity"> 

    <ImageView 
     android:layout_width="128dp" 
     android:layout_height="128dp" 
     android:id="@+id/imageView" 
     android:transitionName="shape_transition" 
     android:layout_alignParentTop="true" 
     android:layout_alignParentStart="true" 
     android:src="@drawable/red" /> 

    <Button 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Pick" 
     android:id="@+id/button" 
     android:layout_below="@+id/imageView" 
     android:layout_alignParentStart="true" /> 
</RelativeLayout> 

Picker Activité xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="demonstration.sharedelementproblemexample.PickerActivity"> 

    <ImageView 
     android:layout_width="128dp" 
     android:layout_height="128dp" 
     android:id="@+id/imageView2" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentEnd="true" 
     android:src="@drawable/blue" /> 

    <ImageView 
     android:layout_width="128dp" 
     android:layout_height="128dp" 
     android:id="@+id/imageView3" 
     android:src="@drawable/green" 
     android:layout_alignParentStart="true" 
     android:layout_alignTop="@+id/imageView2" /> 
</RelativeLayout> 

Répondre

0

En travaillant sur un autre projet, j'ai trouvé un moyen d'éviter ce scintillement.

Dans la première activité (celle qui a envoyé la demande), au lieu de mettre à jour la vue initialement passée par la méthode onActivityResult(int requestCode, int resultCode, Intent intent), vous devez remplacer onActivityReenter(int resultCode, Intent data) et mettre à jour la vue à partir de là.

Cette méthode est appelée avant le début de l'animation de transition et vous avez toujours accès aux informations de l'autre Activity via le paramètre .

est ici le même exemple application utilisant cette solution:

picture showing the fix

Et voici la méthode surchargée:

@Override 
public void onActivityReenter(int resultCode, Intent data) { 
    int shapeNumber = data.getIntExtra("shape_number", -1); 

    switch (shapeNumber) { 
     case 1: 
      mainImageView.setImageResource(R.drawable.blue); 
      break; 
     case 2: 
      mainImageView.setImageResource(R.drawable.green); 
      break; 
     default: 
      //something else 
      break; 
    } 
    super.onActivityReenter(resultCode, data); 
} 
0

Le principal problème est que cela devrait fonctionner parfaitement même lorsque l'utilisateur ne sélectionne pas non plus des images (presses simplement en arrière). Je ne pouvais pas vraiment trouver une manière élégante d'accomplir ceci (puisque, nous utilisions déjà onActivityResult()). Cependant, j'ai un bidouillage [assez sale] qui devrait fonctionner.

Ce que nous pouvons faire est d'avoir une très petite AlphaAnimation (10 ms environ) et à la décoloration de la racine ViewGroup du Activity et sur onResume() et onPause() respectivement. Pour que cela fonctionne parfaitement (lire sans flickr) la visibilité initiale du ViewGroup devrait être View.INVISIBLE. Cela doit également être défini lorsque l'animation de fondu disparaît (via AnimationListener). Avec cette configuration, nous achetons du temps pour nous-mêmes afin que nous puissions configurer notre instance ImageView de façon appropriée. C'est bien sûr un hack à la fin de la journée et j'aimerais entendre d'autres réponses valables. Bonne question!