Toggleable save button in Xamarin Android

2019-08-23 07:06发布

问题:

I've create a layout that lists a List of objects in a RecyclerView. I would like to add the option for the user to save a certain object, but I have no idea how to achieve something like the layout bellow. I need a button that can be toggled, and that if the user clicks it, it will fill the heart button with red, otherwise, it will be empty. Thank you.

Layout

回答1:

If you want that heart to fill from nothing to full using some kind of animation, I'd suggest looking into SkiaSharp (https://blog.xamarin.com/deep-dive-skiasharp-xamarin-forms/) and then using the Animation Class (https://xamarinhelp.com/custom-animations-in-xamarin-forms/) to animate the fill height.

In a nutshell, you have to create a custom view in which you add a SKCanvasView:

<skia:SKCanvasView x:Name="PrimaryCanvas" PaintSurface="OnPaintSurface" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>

In your view.xaml.cs you add a new function

OnPaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e) { ... }

Inside of this function you'll need to write some code to draw your heart. I'd suggest you draw an outline first and then the inside, which is supposed to fill up. You probably want to add a bindable property which holds the value of the amount to fill up, maybe as a percentage. Use this property to calculate the height of your inner part within your OnPaintSurface code.

Finally when you want your icon to fill up, you create an Animation, which then alters the property created earlier:

new Animation((value) =>
{
    FillHeightProperty = value;
    PrimaryCanvas.InvalidateSurface();
}).Commit(this, "fillAnimation", length: 350, repeat: () => false);

Notice that you need to invalidate the PrimaryCanvas surface. This will result in calling OnPaintSurface again, which will use your changed property and therefore increase the height of your filling while redrawing the canvas.



回答2:

You can define a heart background with vector and path:

<?xml version="1.0" encoding="utf-8" ?>
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="250dp"
    android:width="250dp"
    android:viewportHeight="32"
    android:viewportWidth="32" >
    <path
        android:name="heart"
        android:fillColor="#f9f7f7"
        android:strokeColor="#090808"
        android:strokeWidth="1"
        android:pathData="M20.5,9.5
                        c-1.955,0,-3.83,1.268,-4.5,3
                        c-0.67,-1.732,-2.547,-3,-4.5,-3
                        C8.957,9.5,7,11.432,7,14
                        c0,3.53,3.793,6.257,9,11.5
                        c5.207,-5.242,9,-7.97,9,-11.5
                        C25,11.432,23.043,9.5,20.5,9.5z"/>
</vector> 

Here, I have posted my demo on github, you can see a button with selector background which allow you change the button's background with the button's state, and another button with the SVG background.

Update:

I have add animation on the button.

    private void Mbt_Click(object sender, System.EventArgs e)
    {
        if (isClick)
        {
            mbt.SetBackgroundResource(Resource.Drawable.heart);
            isClick = false;
        }else {
            mbt.SetBackgroundResource(Resource.Drawable.heart_press);
            ObjectAnimator animator = ObjectAnimator.OfFloat(mbt, "scaleY", 1f, 1.2f, 1f);
            animator.SetDuration(1000);
            animator.Start();

            ObjectAnimator animator1 = ObjectAnimator.OfFloat(mbt, "scaleX", 1f, 1.2f, 1f);
            animator1.SetDuration(1000);
            animator1.Start();
            isClick = true;
        }
    }