Кнопка градиента форм Xamarin для Android - PullRequest
0 голосов
/ 20 февраля 2019

Я реализовал пользовательский рендерер для моего приложения Xamarin.Forms для Android, чтобы иметь кнопки с градиентным фоном.Градиент работает, но он рисуется поверх моей кнопки и ее текста, и я не могу понять, как нарисовать его за кнопкой.

Пользовательский рендерер Android:

[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace MyApp.Droid
{
public class CustomButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
    public CustomButtonRenderer(Context context) : base(context)
    {
    }

    protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
    {
        base.DispatchDraw(canvas);
        var gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,
            Color.FromRgba(255, 239, 124, 255).ToAndroid(),
            Color.FromRgba(239, 210, 0, 50).ToAndroid(),
            Android.Graphics.Shader.TileMode.Repeat);

        var paint = new Android.Graphics.Paint()
        {
            Dither = true,
        };
        paint.SetShader(gradient);

        canvas.DrawPaint(paint);

    }

}

}

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Я пишу демо, которое было достигнуто с помощью Custom Renderer

Это GIF этой демонстрации.

enter image description here

Android renderer

[assembly: ExportRenderer(typeof(MyButton), typeof(GradientButtonRenderer))]
namespace GradientButton.Droid.Renderers
{
    public class GradientButtonRenderer : ButtonRenderer
    {
    public GradientButtonRenderer(Context context) : base(context) { }
    protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged(e);

        var btn = this.Control as Android.Widget.Button;
        btn?.SetBackgroundResource(Resource.Drawable.gradient_button_style);
    }
}
}

gradient_button_style

    <?xml version="1.0" encoding="utf-8" ?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" >
    <shape>
    <solid android:color="#1E90FF" />
    <corners android:radius="20dp" />
    <padding android:left="10dp" android:top="10dp" android:right="10dp" 
      android:bottom="10dp" />
   </shape>
</item>
<item>
   <shape>
    <gradient android:startColor="#1E90FF" android:endColor="#00BFFF" 
      android:angle="0" />
    <corners android:radius="20dp" />
    <padding android:left="10dp" android:top="10dp" android:right="10dp" 
      android:bottom="10dp" />
</shape>
</item>
</selector>

Значение этих вкладок

[shape] корневой тег, объявлять форму

[градиент] объявляетсвойства формы - градиент, в дополнение к другим свойствам, таким как углы, обводка, размер и т. д.

[android: angle] Угол цвета градиента, например, 0 представляет градиент сверху вниз;45 представляет градиент слева направо;90 представляет градиент снизу вверх ...

[android: startColor & android: endColor] - хорошее понимание цвета градиента и цвета в конце градиента (от какого цвета до какого цвета)

MyButton

   public class MyButton:Button
{

}

IOS рендерер.

[assembly: ExportRenderer(typeof(MyButton), typeof(GradientButtonRenderer))]
namespace GradientButton.iOS.Renderers
{
public class GradientButtonRenderer : ButtonRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement == null)
        {
            var gradient = new CAGradientLayer()
            {
                StartPoint = new CGPoint(0, 0.5),
                EndPoint = new CGPoint(1, 0.5)
            };
            gradient.Locations = new NSNumber[] { .0f, 1f };
            gradient.CornerRadius = Element.CornerRadius;
            gradient.NeedsDisplayOnBoundsChange = true;
            gradient.MasksToBounds = true;

            gradient.Colors = new CGColor[]
            {

                UIColor.FromRGB(30 ,144, 255).CGColor,
                UIColor.FromRGB(0 ,191, 255).CGColor
            };

            var layer = Control?.Layer.Sublayers.FirstOrDefault();
            Control?.Layer.InsertSublayerBelow(gradient, layer);
        }
    }

    public override CGRect Frame
    {
        get
        {
            return base.Frame;
        }
        set
        {
            if (value.Width > 0 && value.Height > 0)
            {
                foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
                {
                    layer.Frame = new CGRect(0, 0, value.Width, value.Height);
                }
            }
            base.Frame = value;
        }
    }
}
}
0 голосов
/ 20 февраля 2019

Я не думаю, что вам нужен отдельный рендерер здесь, вы можете сделать это так:

Resources/drawable/gradient.xml

добавьте свой градиентный дизайн здесь

    <?xml version="1.0" encoding="utf-8" ?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
      <gradient
        android:angle="45"
        android:startColor="#80D776"
        android:endColor="#71D6C5"
        android:type="linear"/>
      <corners
        android:bottomLeftRadius="40dp"
        android:bottomRightRadius="40dp"
        android:topLeftRadius="40dp"
       android:topRightRadius="40dp" />
      <padding
        android:left="3dp"
        android:top="8dp"
        android:right="3dp"
        android:bottom="8dp" />
    </shape>

если это универсальная кнопка, которая вам нужна повсюду в приложении, тогда в вашем Resouces/values/styles.xml

<style name="Widget.Button" parent="Theme.AppCompat">
    <item name="android:background">@drawable/gradient</item>
    <item name="android:focusable">true</item>
    <item name="android:clickable">true</item>
    <item name="android:textColor">@color/primary</item>
    <item name="android:textAppearance">?android:attr/textAppearanceSmallInverse</item>
    <item name="android:gravity">center_vertical|center_horizontal</item>
</style>

enter image description here

...