我试图通过Mvx在我的Xamarin Android应用程序中使用animation/transition。
我有卡片的回收查看。点击卡片时,我现在打电话:
private void TimeLineAdapterOnItemClick(object sender, int position)
{
TimeLineAdapter ta = (TimeLineAdapter) sender;
var item = ta.Items[position];
int photoNum = position + 1;
Toast.MakeText(Activity, "This is photo number " + photoNum, ToastLength.Short).Show();
ViewModel.ShowDetails(item.Id);
}
我试图找出如何通过Mvvmcross过渡到Xamarin来翻译这个java导航:
ActivityOptionsCompat options =
ActivityOptionsCompat.MakeSceneTransitionAnimation(this, imageView, getString(R.string.activity_image_trans));
startActivity(intent, options.toBundle());
我知道在Mvx中您可以使用自定义演示者,但是我如何抓住RecyclerView中的轻触卡的ImageView,我希望将其转换为'新活动的新ImageView?
谢谢!
答案 0 :(得分:9)
是否有Xamarin Mvvmcross Android共享元素导航 示例
我不相信。
我知道在Mvx中您可以使用自定义演示者,但是如何使用 例如,我是否掌握了Tapped Card的ImageView 我希望“转换”为新的RecyclerView ImageView上的新活动?
我可以想到实现共享您想要转换的控件元素的最简单方法是在使用ShowViewModel
时使用view tags和演示文稿包。
我建议您对适配器点击处理程序进行一些更改,以包含所选ViewHolder
的视图(例如,使用EventArgs查看GitHub repo )。这样,您就可以与ImageView
进行交互,并设置一个可以在以后用于标识它的标记。
private void TimeLineAdapterOnItemClick(object sender, View e)
{
var imageView = e.FindViewById<ImageView>(Resource.Id.imageView);
imageView.Tag = "anim_image";
ViewModel.ShowDetails(imageView.Tag.ToString());
}
然后在您的ViewModel中,通过presentationBundle发送该标记。
public void ShowDetails(string animationTag)
{
var presentationBundle = new MvxBundle(new Dictionary<string, string>
{
["Animate_Tag"] = animationTag
});
ShowViewModel<DetailsViewModel>(presentationBundle: presentationBundle);
}
然后创建一个自定义演示者来拾取presentationBundle
并通过转换处理新活动的创建。自定义演示者,它使用标记来查找要转换的元素,并在新活动的开头包含ActivityOptionsCompat
。此示例使用的是MvxFragmentsPresenter
,但如果您没有使用片段并使用MvxAndroidViewPresenter
,则解决方案几乎相同(替代显示而不需要构造函数)。
public class SharedElementFragmentsPresenter : MvxFragmentsPresenter
{
public SharedElementFragmentsPresenter(IEnumerable<Assembly> AndroidViewAssemblies)
: base(AndroidViewAssemblies)
{
}
protected override void ShowActivity(MvxViewModelRequest request, MvxViewModelRequest fragmentRequest = null)
{
if (InterceptPresenter(request))
return;
Show(request, fragmentRequest);
}
private bool InterceptPresenter(MvxViewModelRequest request)
{
if ((request.PresentationValues?.ContainsKey("Animate_Tag") ?? false)
&& request.PresentationValues.TryGetValue("Animate_Tag", out var controlTag))
{
var intent = CreateIntentForRequest(request);
var control = Activity.FindViewById(Android.Resource.Id.Content).FindViewWithTag(controlTag);
control.Tag = null;
var transitionName = control.GetTransitionNameSupport();
if (string.IsNullOrEmpty(transitionName))
{
Mvx.Warning($"A {nameof(transitionName)} is required in order to animate a control.");
return false;
}
var activityOptions = ActivityOptionsCompat.MakeSceneTransitionAnimation(Activity, control, transitionName);
Activity.StartActivity(intent, activityOptions.ToBundle());
return true;
}
return false;
}
}
GetTransitionNameSupport
是一种扩展方法,只需在获取TransitionName
时执行平台API检查。
public static string GetTransitionNameSupport(this ImageView imageView)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
return imageView.TransitionName;
return string.Empty;
}
最后一步是在您Setup.cs
protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var mvxPresenter = new SharedElementFragmentsPresenter(AndroidViewAssemblies);
Mvx.RegisterSingleton<IMvxAndroidViewPresenter>(mvxPresenter);
return mvxPresenter;
}
您可以查看演示此示例的repo on GitHub。解决方案的设计使得演示者不必关心正在转换的控件的类型。控件仅需要用于标识它的标记。 repo中的示例还允许指定要转换的多个控件元素(我不希望在上面的示例中包含更多复杂性)。