是否有Xamarin Mvvmcross Android共享元素导航示例?

时间:2017-05-05 12:21:26

标签: xamarin xamarin.android mvvmcross

我试图通过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?

谢谢!

1 个答案:

答案 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中的示例还允许指定要转换的多个控件元素(我不希望在上面的示例中包含更多复杂性)。

Shared Element Demo