如何在Xamarin表单按钮中的图像上叠加文本?

时间:2017-08-29 04:32:04

标签: c# button xamarin.forms

我无法找到一种简单的方法来创建Xamarin表单按钮作为顶部带有叠加文本的图像。奇怪的是,Button的Image属性只允许图像旁边的文本。

所以我将在这里分享我的代码实现。它包括一个在点击按钮时隐藏键盘的工具,它支持文本属性,图像大小调整和启用。感谢@F。 Badili,@ Sharada Gururaj和其他人寻求帮助。

2 个答案:

答案 0 :(得分:0)

我的实施:

public class ImageButton : Grid
// A clickable visual element overlaying a label on an image, serving as a button
{
    public event EventHandler Clicked;

    public Image TheImage { get; set; }
    public Label TheLabel { get; set; }
    public bool HideKeyboard { get; set; }
    public string Text
    { 
        get
        {
            if ( TheLabel == null )
                return null;
            return TheLabel.Text;
        }

        set
        {
            if ( TheLabel == null )
                return;
            TheLabel.Text = value;
        }
    }

    public Color TextColor 
    {
        set
        {
            if ( TheLabel != null )
                TheLabel.TextColor = value;
        }
    }
    public string FontFamily 
    {
        set 
        {
            if ( TheLabel != null )
                TheLabel.FontFamily = value;
        }
    }

    public FontAttributes FontAttributes 
    {
        set 
        {
            if ( TheLabel != null )
                TheLabel.FontAttributes = value;
        }
    }

    public double FontSize 
    {
        set 
        {
            if ( TheLabel != null )
                TheLabel.FontSize = value;
        }
    }

    public double ImageHeightRequest
    {
        set
        {
            if ( TheImage != null )
                TheImage.HeightRequest = value;
        }
    }

    public double ImageWidthRequest
    {
        set
        {
            if ( TheImage != null )
                TheImage.WidthRequest = value;    
        }
    }

    public ImageButton ( Image image, Label label, bool hideKeyboard = true )
    {
        TheImage = image;
        TheLabel = label;
        HideKeyboard = hideKeyboard;
        Text = label.Text;

        // Construct the control
        ConstructControl ();
    }

    // Invoke the Clicked event; called when ImageButton is tapped
    protected virtual void OnClicked ( EventArgs e )
    {
        if ( Clicked != null )
            Clicked ( this, e );
    }

    private void ConstructControl ()
    // Construct the control using a grid with a single cell
    {
        // Add action performed upon tap
        this.AddTap ( () => 
        {
            // Hide keyboard
            if ( HideKeyboard )
                DependencyService.Get<IKeyboard> ().HideKeyboard ();

            // Fire the event 
            OnClicked ( EventArgs.Empty );
        });

        // Bind opacity of image and label to IsEnabled via a converter
        TheLabel.SetBinding ( OpacityProperty, new Binding ( "IsEnabled", converter: new BooleanToOpacityConverter (), source: this ) );
        TheImage.SetBinding ( OpacityProperty, new Binding ( "IsEnabled", converter: new BooleanToOpacityConverter (), source: this ) );

        // Stack image and label on top of each other in a grid with a single cell
        this.RowDefinitions.Add ( new RowDefinition { Height = new GridLength ( 1, GridUnitType.Auto ) } );
        this.ColumnDefinitions.Add ( new ColumnDefinition { Width = new GridLength ( 1, GridUnitType.Auto ) } );
        this.Children.Add ( TheImage, 0, 0 );   // Add image first, so overlaid label will be visible
        this.Children.Add ( TheLabel, 0, 0 );
    }

    public class BooleanToOpacityConverter : IValueConverter
    {
        public object Convert ( object value, Type targetType, object parameter, CultureInfo culture )
        {
            var isEnabled = ( value != null ) && (bool)value;
            return isEnabled ? 1 : 0.5;
        }

        public object ConvertBack ( object value, Type targetType, object parameter, CultureInfo culture )
        {
            throw new NotImplementedException ();
        }
    }
}

public static class GridExtensions
{
    // Grid extension methods

    private static void AddTap ( this Grid grid, Action action )
    // Allows Grid to be tappable
    // action = method to call when Grid is tapped
    // Example:
    //          Grid grid = new Grid ();
    //          grid.AddTap ( () => MyMethod () );
    {
        grid.GestureRecognizers.Add ( new TapGestureRecognizer 
        {
            Command = new Command (action)
        });
    }
}

public interface IKeyboard
{
    void HideKeyboard ();       // Hide the keyboard
}

iOS:

[assembly: Xamarin.Forms.Dependency (typeof(Keyboard))]
namespace MyApp.iOS
{
    public class Keyboard : MyApp.IKeyboard
    {
        public Keyboard () {}

        public void HideKeyboard ()
        // Hides the keyboard
        {
            UIApplication.SharedApplication.KeyWindow.EndEditing ( true );
        }
    }
}

Android (not tested yet):

[assembly: Xamarin.Forms.Dependency (typeof (Keyboard))]
namespace MyApp.Droid
{
    public class Keyboard : MyApp.IKeyboard
    {
        public Keyboard () {}

        public void HideKeyboard ()
        // Hides the keyboard
        {
            var context = Forms.Context;
            var inputMethodManager = context.GetSystemService ( Context.InputMethodService ) as InputMethodManager;
            if ( inputMethodManager != null && context is Activity ) 
            {
                var activity = context as Activity;
                var token = activity.CurrentFocus?.WindowToken;
                inputMethodManager.HideSoftInputFromWindow ( token, HideSoftInputFlags.None );

                activity.Window.DecorView.ClearFocus ();
            }
        }
    }
}    

用法示例:

public static ImageButton StandardImageButton ( string buttonText, EventHandler onClickedEventHandler = null, string imageResourceID = "MyApp.standardbutton.png", string imageSource = null, 
                                              Color textColour = default(Color), string fontFamily = null, double fontSize = 15D, FontAttributes fontAttributes = FontAttributes.Bold, 
                                              double heightRequest = 44D, double widthRequest = 200D, bool hideKeyboard = true )
    // Returns tappable image serving as a button
    // buttonText = text overlaid onbutton
    // Image is sourced from embedded PCL file (Build Action = Embedded Resource) OR, if imageSourceID is non-null, from local platform file in platform-specific location
    {
        // Background image
        Image image = new Image 
        { 
            Aspect = Aspect.Fill,           // Stretch to fill
            HeightRequest = heightRequest,
            WidthRequest = widthRequest,
            HorizontalOptions = LayoutOptions.CenterAndExpand,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };

        if ( imageResourceID == null )
            image.Source = ImageSource.FromFile ( imageSource );
        else
            image.Source = ImageSource.FromResource ( imageResourceID );

        // Foreground label
        Color colour;
        if ( textColour == default(Color) )
            colour = Color.Black;
        else
            colour = textColour;

        Label label = new Label 
        {
            Text = buttonText,
            TextColor = colour,
            FontFamily = fontFamily,
            FontSize = fontSize,
            FontAttributes = fontAttributes,
            HorizontalTextAlignment = TextAlignment.Center,
            VerticalTextAlignment = TextAlignment.Center
        };

        ImageButton ret = new ImageButton ( image, label, hideKeyboard );
        ret.Clicked += onClickedEventHandler;
        return ret;
    }

答案 1 :(得分:0)

如果在代码或xaml中指定btn1.Image,则可以执行此操作

btn1.ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Bottom, 10);

这会给你一个按钮,底部是图片,顶部是文字