共有要素として画像を使用して、2 つのアクティビティ間にアニメーションを作成したいです。「アクティビティの遷移をカスタマイズする」を参照してください。
私の問題: ソース アクティビティでは、カスタム ビューのキャンバスに画像が描画されます :-(
この画像を共有要素として使用する方法はありますか、それとも実際の ImageView を追加する必要がありますか?
共有要素として画像を使用して、2 つのアクティビティ間にアニメーションを作成したいです。「アクティビティの遷移をカスタマイズする」を参照してください。
私の問題: ソース アクティビティでは、カスタム ビューのキャンバスに画像が描画されます :-(
この画像を共有要素として使用する方法はありますか、それとも実際の ImageView を追加する必要がありますか?
画像のみを共有することはできませんが、カスタム ビュー全体を共有できます。これは、共有要素が起動されたアクティビティに転送されると、呼び出し元のアクティビティからカスタム ビュー全体が消えることを意味します。カスタム ビューに画像しかない場合は問題ありませんが、他のものを描画する場合は悲惨です。
画像のみを共有したい場合は、View (ImageView など) を作成し、そこに画像を移動してから共有する必要があります。そうすれば、共有要素が転送されると、呼び出し元のアクティビティから適切に隠されます。
共有要素は、実際にはビューをアクティビティ間で移動しません。ビューの「スナップショット」をビットマップとして共有し、ビューの位置を共有するだけです。起動されたアクティビティでは、指定された遷移名を持つビューがその位置に配置されます。必要に応じて、スナップショットを使用することも使用しないこともできます。デフォルトでは、スナップショットは使用されません。
したがって、次のようなコードが必要になります。
public void launchActivity(final Intent intent, final CustomView view) {
final Bitmap bitmap = view.getSharedImage();
ImageView imageView = new ImageView(view.getContext());
imageView.setBitmap(bitmap);
LayoutParams layoutParams = view.createSharedImageLayoutParams();
final ViewGroup parent = (ViewGroup)view.getParent();
parent.addView(imageView, layoutParams);
parent.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
parent.getViewTreeObserver().removeOnPreDrawListener(this);
customView.hideSharedImage();
ActivityOptions activityOptions = ActivityOptions.
makeSceneTransitionAnimation(this, imageView, "destName");
startActivity(intent, activityOptions.toBundle();
}
});
setExitSharedElementCallback(new SharedElementCallback() {
@Override
public void onSharedElementsArrived(List<String> sharedElementNames,
List<View> sharedElements, OnSharedElementsReadyListener listener) {
super.onSharedElementsArrived(sharedElementNames, sharedElements,
listener);
parent.removeView(imageView);
customView.showSharedImage();
}
});
}
上記を具体的に試したことはありませんが、それが本質です。新しい onSharedElementsArrived を使用したくない場合は、onVisibilityChanged をリッスンするカスタム ImageView を作成できます。終了トランジションがある場合は、その終了もリッスンできます。ImageView が削除され、カスタム ビューが画像を再度描画するように、状態をリセットするように指示するトリガーが必要なだけです。
上記の例では、カスタム ビューと同じ親に ImageView を配置しました。DecorView に配置することで柔軟性が向上する可能性がありますが、グローバル位置が何であるかを把握する必要があり、画面上のすべてのものもオーバーレイされます。または、ImageView を親に追加したため、すべての親 (ListView、LinearLayout など) では機能しません。ビュー階層を知っているので、それを配置するのに最適な場所を選択する必要があります。
または、カスタム ビューをカスタム ViewGroup に変更し、共有可能な画像を ImageView として含めることもできます。私には簡単に聞こえます。