How to fill a button with an image in Xamarin Forms? - xaml

I am trying to fill a Button with an Image. The button resides within a Grid. The problem is that the image is not fully filling the button. I have also tried to use the ImageButton control.
Here is how I am building my U.I:
<Grid Grid.Row="1" Grid.Column="1" x:Name="VotingGrid" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="45*" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Image="yay.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<Button Grid.Row="0" Grid.Column="2" Image="meh.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</Grid>
It currently looks like the image attached below, but I'd like to image to fill my button.
Any help will be appreciated!

Try to place an image instead of button.
You can make use of Tap Gesture Gesture Recognizer to take click events.
Try something like this :
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped" />
</Image.GestureRecognizers>
</Image>
The code for the event handler
void OnTapGestureRecognizerTapped(object sender, EventArgs args) {
var imageSender = (Image)sender;
// Do something
DisplayAlert ("Alert", "Tap gesture recoganised", "OK");
}
Refer : Adding a Tap Gesture Gesture Recognizer

I have not used it myself but maybe you can use this one from XLab
https://github.com/XLabs/Xamarin-Forms-Labs/wiki/ImageButton

Related

Hoe to make an ImageButton with a label ontop clickable

So I've run into a problem with Imagebuttons in XAML.
I usually render a background image from photoshop and then use this button everywhere and just add a label ontop that says what it does:
enter image description here
This here for isntance comes from this code (partially):
<!--Grid for button-->
<Grid Grid.Row="1" >
<ImageButton
x:Name="btn_register_mainpage"
Source="btn_emptydummy.png" BackgroundColor="#00000000"/>
<Label
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
Now, this works just fine, unless you want to click on it.
As you can see I gave the button a name, I can now catch that name in code and delegate a click to it:
btn_register_mainpage.Clicked += async delegate
{
await Navigation.PushAsync(new Screen_EditInformation());
};
However, this only works when the user clicks on the button - but NOT on the label since this is on top and has no click assigned to it.
So, what I could do is just assign the same click event to both objects (the label and the image button) but that seems rather unusual.
What is the best way to have a custom image as a button with a label ontop that is clickable?
You can add GestureRecognizers to any control in Xamarin.Forms. In your case you could add one to the Grid layout
YourView.xaml
<Grid Grid.Row="1" >
<Grid.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<ImageButton
x:Name="btn_register_mainpage"
InputTransparent="True"
Source="btn_emptydummy.png" BackgroundColor="#00000000"/>
<Label
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
YourView.xaml.cs
private void OnTapGestureRecognizerTapped(object sender, EventArgs e)
{
Navigation.PushAsync(new Screen_EditInformation());
}
You could add a TapGestureRecognizer on the label .
<Grid Grid.Row="1" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<ImageButton
Clicked="Button_Clicked"
Grid.Row="0"
x:Name="btn_register_mainpage"
BackgroundColor="LightBlue"/>
<Label
Grid.Row="0"
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer
Tapped="Button_Clicked"
NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
</Grid>

Editor goes behind the keyboard when it resized using Wordwrap in Xamarin.Forms (iOS)?

I am proceeding further and generating new ticket as it is quite different from this issue How to prevent Editor to go behind the keyboard in Xamarin.Forms?
I have chat page and autosize editor. When user type more than 1-2 lines, Editor expand correctly but it goes behind the keyboard.
However, if user add multiple lines using "return" it works correctly. I think I am missing something in Xaml page to play with Editor and StackLayout.
Please suggest
Please note that I don't use Xam.Plugins.Forms.KeyboardOverlap. To manage layout on keyboard visibility, I use custom stacklayout WrapperStackLayoutRenderer which set bottom padding on appear and disappear of keyboard.
Page Xaml
<ContentPage.Content>
<local1:WrapperStackLayout>
<Grid Margin="0" Padding="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ListView x:Name="MessagesListView"
ItemTemplate="{StaticResource MessageTemplateSelector}"
ItemsSource="{Binding Conversations}"
HasUnevenRows="True"
Margin="0"
Grid.Row="0"
SeparatorVisibility="None"/>
<Grid RowSpacing="1" ColumnSpacing="2" Padding="5" Grid.Row="1" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<local1:EditorWithAutoSize x:Name="txtMessage" Text="{Binding SendingText}" TextChanged="EnableSend"/>
<Frame x:Name="SendButton" Grid.Column="1" Margin= "0" Padding="0" HasShadow="false" HeightRequest="25"
BackgroundColor="Transparent" HorizontalOptions="FillAndExpand">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="SendMessage_Click" NumberOfTapsRequired="1" />
</Frame.GestureRecognizers>
<Label Text="Send" x:Name="sendButton" HeightRequest="20"
HorizontalOptions="Center" VerticalOptions="Center"/>
</Frame>
</Grid>
</Grid>
</local1:WrapperStackLayout>
</ContentPage.Content>
EditorWithAutoSize
public class EditorWithAutoSize : Editor
{
public EditorWithAutoSize()
{
this.TextChanged += (sender, e) => {
this.InvalidateMeasure();
};
}
}
WrapperStackLayout
public class WrapperStackLayout : StackLayout
{
}
WrapperStackLayoutRenderer
public class WrapperStackLayoutRenderer : VisualElementRenderer<StackLayout>
{
public WrapperStackLayoutRenderer()
{
UIKeyboard.Notifications.ObserveWillShow((sender, args) =>
{
if (Element != null)
{
Element.Margin = new Thickness(0, 0, 0, (args.FrameEnd.Height));
}
});
UIKeyboard.Notifications.ObserveWillHide((sender, args) =>
{
if (Element != null)
{
Element.Margin = new Thickness(0); //set the margins to zero when keyboard is dismissed
}
});
}
}
You have to add RowDefinition Height="auto" in your second Grid, then the editor will auto group with the text you entered:
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
The complete code should be:
<Grid RowSpacing="1" ColumnSpacing="2" Padding="5" Grid.Row="1" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<local:EditorWithAutoSize x:Name="txtMessage" Text="Binding SendingText" />
<Frame x:Name="SendButton" Grid.Column="1" Margin= "0" Padding="0" HasShadow="false" HeightRequest="25"
BackgroundColor="Transparent" HorizontalOptions="FillAndExpand">
<Label Text="Send" x:Name="sendButton" HeightRequest="20"
HorizontalOptions="Center" VerticalOptions="Center"/>
</Frame>
</Grid>
I uploaded my test sample here and you can check it: editor-xamarin.forms
BTW, there is a sample in github that you can refer: ChatUIXForms, you can use the editor and custom renderer code in his project. There are also blogs the author wrote you can read.

Textbox not losing focus when tapping anywhere inside Popup control

I have a Popup with a Textbox and a Button control in it.
When I click/tap anywhere inside the Popup, the Textbox doesn't lose focus.
The only way to make the Textbox lose focus is to set focus on the Button.
I want to be able to remove focus from the Textbox without having to close the Popup or clicking the button.
This issue only occurs in a Popup.
I used to have the controls in a Flyout, and the behavior there is when a user clicks outside the Textbox and anywhere inside the Flyout, the Textbox loses focus. Also when the Flyout opens, the Textbox would automatically get focus on Flyout opening.
I tested the different behaviors for how Textboxes losing focus in a new blank UWP project, and it's the same. Also tested behavior of Textbox directly in root-grid. This is the XAML from MainPage:
<Page x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:App1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Margin="0,40"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button Margin="20,0"
Content="Popup button"
Tapped="Button_Tapped" />
<Button Margin="20,0" Content="Flyout button">
<Button.Flyout>
<Flyout>
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" />
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
<Popup x:Name="MyPopup"
Width="320"
Height="60"
IsLightDismissEnabled="True">
<Grid Width="320"
Height="60"
Background="WhiteSmoke"
Padding="12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" />
</Grid>
</Popup>
<TextBox Grid.Row="1"
MinWidth="64"
MaxWidth="300"
Margin="0,40"
VerticalAlignment="Center" />
</Grid>
</Page>
And the event to open the Popup:
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
MyPopup.IsOpen = true;
}
The problem is that Grid is not "focusable" because it does not derive from Control. One way is that you place your Grid inside a ContentControl or ContentPresenter.
The other way is a bit of a hack but you can set the focus programatically on the button when the Grid inside the Popup is tapped:
<Popup
x:Name="MyPopup"
Width="320"
Height="60"
IsLightDismissEnabled="True">
<Grid
x:Name="Grid"
Width="320"
Height="60"
Background="WhiteSmoke"
Tapped="Grid_OnTapped"
Padding="12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button
Grid.Column="1"
Content="Test" />
</Grid>
</Popup>
And the Tapped handler in which you generally search for any focusable control that is not a TextBox. If you don't have any you can place an invisible ContentControl with Opacity=0.01 for example and this will then be the focus element:
private void Grid_OnTapped(object sender, TappedRoutedEventArgs e)
{
var grid = sender as Grid;
if(grid == null) return;
var controlToFocus = FindChild<Button>(grid);
controlToFocus.Focus(FocusState.Programmatic);
}
private static T FindChild<T>(DependencyObject parent) where T : DependencyObject
{
var childCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childCount; i++)
{
var elt = VisualTreeHelper.GetChild(parent, i);
if (elt is T) return (T)elt;
var result = FindChild<T>(elt);
if (result != null) return result;
}
return null;
}

Capture Element not using room from parent control

I am trying to create a page with a capture element and a button overlaid on top to take the picture.
The problem I've got is, the capture element won't use up the whole screen. There are bars above and below.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<CaptureElement
Grid.Row="0"
x:Name="capPreview"
Stretch="Uniform"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Tapped="capPreview_Tapped"
/>
<Button Content="Submit"
HorizontalAlignment="Center"
Grid.Row="1"
x:Name="btnTakePicture"
Click="btnTakePicture_Click">
<Button.Background>
<SolidColorBrush Color="Black" Opacity="100"/>
</Button.Background>
<Button.BorderBrush>
<SolidColorBrush Color="White"/>
</Button.BorderBrush>
</Button>
</Grid>
Edit: I have since used the code behind to rotate the capture element, however; upon doing so, the element now just has a box all around it instead of top and bottom.
<CaptureElement
Grid.Row="0"
x:Name="capPreview"
Tapped="capPreview_Tapped"
/>
Short of hard coding the height and width values, I am out of ideas.
It deos use the whole screen, the issue is the orientation of the preview is different than the orientation of the screen.
MediaCapture has a method SetPreviewRotation to handle this issue.
It works for me :) Just grid and Strech, If you want to have focus just make transparent grid outside CaptureElement
<Grid>
<Grid Tapped="SetFocus">
<CaptureElement x:Name="CaptureElement" Stretch="UniformToFill"/>
</Grid>
<Grid VerticalAlignment="Bottom">
<Button x:Name="SaveButton" Foreground="Transparent" IsDoubleTapEnabled="False" Width="48" Height="48" Background="Transparent" BorderBrush="Transparent"
Click="OnSaveButtonClicked" HorizontalAlignment="Stretch" Margin="12,0">
</Button>
</Grid>
</Grid>
Try this one it will capture directly with the button click
private async void Button_Click_3(object sender, RoutedEventArgs e)
{
Uri u = new Uri("ms-data:///local");
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("Photo.jpg");
IRandomAccessStream st = await file.OpenAsync(FileAccessMode.Read);
BitmapImage image = new BitmapImage();
image.SetSource(st);
img.Source = image;
}
<CaptureElement Name="element" Height="600"/>
<StackPanel>
<Button Content="Capture Image" Click="Button_Click_3"/>
</StackPanel>
<Image Name="img" Margin="0,0,0,0"/>

Automatically resize elements when changing orientation in Windows Phone

My app layout doesn't have any issues when in portrait mode, but when I change the orientation to landscape, there are some issues:
The app bar, which is minimized by default, is larger in landscape mode and overlaps the first button and the browser window
The URL text box and the Go button disappear when in landscape orientation.
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="ButtonOne" Content="ButtonOne" IsEnabled="False" Click="ButtonOne_Click" Grid.Column="0"/>
<Button x:Name="ButtonTwo" Content="ButtonTwo" Click="ButtonTwo_Click" IsEnabled="False" Grid.Column="1"/>
</Grid>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBox x:Name="URL" Margin="0,545,69,-41" TextWrapping="NoWrap" Text="http://www.xbox.com" VerticalAlignment="Top" Height="75"/>
<Button x:Name="Go" Content="Go" HorizontalAlignment="Right" Margin="0,545,0,-41" VerticalAlignment="Top" Click="Go_Click" Height="75"/>
<phone:WebBrowser x:Name="MiniBrowser" Margin="10,-25,10,79"/>
</Grid>
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" Mode="Minimized">
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Click="Item1_Click" Text="Item 1"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
So what I would like to have is:
An app bar that doesn't overlap with the page content
If possible, I would like to hide the URL bar and the Go button when in landscape mode, and have the browser windows fill all available space
The overlap probably occurs because you try to position the controls hard coded by setting the margins. You better put your controls in a grid like this and remove Mode=Minimized from the application bar:
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" >
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="Item 1"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<phone:WebBrowser Grid.ColumnSpan="2" x:Name="MiniBrowser"/>
<TextBox Grid.Row="1" Grid.Column="0" x:Name="URL" TextWrapping="NoWrap" Text="http://www.xbox.com" VerticalAlignment="Top" Height="75"/>
<Button Grid.Row="1" Grid.Column="1" x:Name="Go" Content="Go" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Go_Click" Height="75"/>
</Grid>
</Grid>
Hiding the textbox and the button can be done in the OrientationChanged event of the page:
private void MainPage_OnOrientationChanged(object sender, OrientationChangedEventArgs e)
{
// Switch the visibility of the controls based on an orientation change.
if ((e.Orientation & PageOrientation.Portrait) == (PageOrientation.Portrait))
{
ApplicationBar.Mode = ApplicationBarMode.Minimized;
URL.Visibility = Visibility.Visible;
Go.Visibility = Visibility.Visible;
}
// If not in portrait, hide controls.
else
{
ApplicationBar.Mode = ApplicationBarMode.Default;
URL.Visibility = System.Windows.Visibility.Collapsed;
Go.Visibility = System.Windows.Visibility.Collapsed;
}
}
In order for this eventhandler to work you need to add OrientationChanged="MainPage_OnOrientationChanged" to your MainPage.xaml (as an attribute of the phone:PhoneApplicationPage element.
Source: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207002(v=vs.105).aspx