Avatar image clickable and display on screen Xamarin.Forms - xamarin.forms

I want to make my avatar image which is in a circle clickable. After click it has to be displayed on screen like in FB. So how I can implement this in my code?
listView.Header = "";
listView.HeaderTemplate = new DataTemplate(() =>
{
var avatarLayout = new StackLayout()
{
HeightRequest = 350,
};
var grid = new Grid();
grid.HeightRequest = 400;
grid.BackgroundColor = Color.White;
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
var bgrImg = new Image();
bgrImg.Aspect = Aspect.Fill;
bgrImg.Source = ImageSource.FromFile("abstract_background.jpg");
var avImg = new CircleImage();
avImg.VerticalOptions = new LayoutOptions(LayoutAlignment.Center, false);
avImg.Source = ImageSource.FromFile("about_background.png");
grid.Children.Add(bgrImg, 0, 0);
grid.Children.Add(avImg);
Grid.SetRowSpan(avImg, 2);
avatarLayout.Children.Add(grid);
Example of my
avatar

You can make an element tappable by using a GestureRecognizer
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) => {
// handle the tap
};
image.GestureRecognizers.Add(tapGestureRecognizer);

Related

How do I write this in code behind: <Button Command="{prism:NavigateTo 'path/to/navigate'}" />

I have a common Page class which the rest of my app pages inherit from.
I'm writing the buttons in code but I'd like to replicate the way prims does it as it more predictable/readable for a beginner. e.g.
This is current method. How do I change the Command property below to do what the button code does i.e
var im_Logo = new ImageButton
{
Margin = new Thickness(0),
Padding = new Thickness(0),
Source = "blalogo",
BackgroundColor = Color.Transparent,
HorizontalOptions = LayoutOptions.Start,
Command = new Command(GoHome)// This works but other pages are not so easy.
};
void GoHome(object obj)
{
Navigation.PopToRootAsync();
}
Plus I'm just curious how you write Command="{prism:NavigateTo 'path/to/navigate'}" in code.
If I could attach a Viewmodel to this 'code' page, it would also solve the problem as the Viewmodels I have have all the Prism stuff built in.(Supplied by infragistics)
Edit Update: I'm adding full class of page I'm creating in code. I thought writing a common class for multiple pages to use would be simple but I'm stumped.
My error on these fails are when clicking on the Search button which I'll concentrate on for now is.
11-06 16:28:54.988 D/Mono (30123): Loading reference 0 of System.Drawing.Common.dll asmctx DEFAULT, looking for mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
11-06 16:28:54.988 D/Mono (30123): Assembly Ref addref System.Drawing.Common[0xc7e18f60] -> mscorlib[0xe5c08580]: 70
Loaded assembly: System.Drawing.Common.dll [External]
11-06 16:28:55.040 D/EGL_emulation(30123): eglMakeCurrent: 0xc9270ce0: ver 2 0 (tinfo 0xc8d25b10)
**System.NullReferenceException:** 'Object reference not set to an instance of an object.'
using iBasisAppV1.ViewModels;
using Prism.Navigation;
using Prism.Navigation.Xaml;
using Syncfusion.XForms.BadgeView;
using Syncfusion.XForms.Buttons;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Xamarin.Forms;
namespace iBasisAppV1.Views.Templates
{
public class CommonToolbarPage : ContentPage
{
public CommonToolbarPage()
{
NavigationPage.SetHasBackButton(this, false);
ShowDefaultTitle();
//this.BindingContext= new CommonToolbarPageViewModel(navigationService);
}
private void ShowDefaultTitle()
{
var im_Logo = new ImageButton
{
Margin = new Thickness(0),
Padding = new Thickness(0),
Source = "boilerparts",
BackgroundColor = Color.Transparent,
HorizontalOptions = LayoutOptions.Start,
Command = new NavigateToExtension { Name = $"/Home" }
//Command = new Command(GoHome)
};
var b_search = new SfButton
{
HorizontalTextAlignment = TextAlignment.End,
HorizontalOptions = LayoutOptions.FillAndExpand,
FontSize = 26,
TextColor = Color.White,
BackgroundColor = Color.Transparent,
Margin = new Thickness(0),
Padding = new Thickness(0),
FontFamily = "UIFontIcons",
Text = (String)Application.Current.Resources["Search"],
//Command = new NavigateToExtension { Name = "../Search" } //Not Work
//Command = new NavigateToExtension { Name = "Search" } //Not Work
//Command = new NavigateToExtension { Name = $"{nameof(Search)}" } //Not Work
// Command = new NavigateToExtension { Name = $"../{nameof(Search)}" } //Not Work
//Command = new Command(ShowSearch)// Works
};
var boxView = new BoxView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Red,
Margin = new Thickness(0,0,0,0),
};
SfButton sfButton = new SfButton
{
CornerRadius = 4,
HorizontalOptions = LayoutOptions.End,
VerticalOptions= LayoutOptions.Center,
Style = (Style)Application.Current.Resources["IconButtonStyle"],
Text = (String)Application.Current.Resources["Cart"],
FontFamily = "UIFontIcons",
TextColor = Color.White,
// Command = new Command(GoCart)
};
var imSfBadgeView = new SfBadgeView
{
BadgeText = "4",
Margin = new Thickness(0, 0, 10, 0),
Padding = new Thickness(0),
WidthRequest = 40,
Content = sfButton,
HorizontalOptions = LayoutOptions.EndAndExpand,
VerticalOptions = LayoutOptions.Center,
BackgroundColor = Color.Transparent,
BadgeSettings = new BadgeSetting
{
BackgroundColor= (Color)Application.Current.Resources["PrimaryColor"],
BadgeType = BadgeType.None,
FontSize = 10,
Stroke = (Color)Application.Current.Resources["Gray-White"],
StrokeWidth = 1,
Offset = new Point(-10, 10)
}
};
var layout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions=LayoutOptions.FillAndExpand,
BackgroundColor = (Color)Application.Current.Resources["HeaderColor"]
};
var Endlayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.EndAndExpand,
};
if (this.GetType().Name.ToLower() != "search")
Endlayout.Children.Add(b_search);
Endlayout.Children.Add(imSfBadgeView);
layout.Children.Add(im_Logo);
layout.Children.Add(Endlayout);
NavigationPage.SetTitleView(this, layout);
}
private void ShowSearch(object obj)
{
Navigation.PushAsync(new Search());
}
private void cancel(object obj)
{
ShowDefaultTitle();
}
void GoCart(object obj)
{
Navigation.PushAsync(new Home());
}
void GoHome(object obj)
{
Navigation.PopToRootAsync();
// Navigation.PushAsync(new NavigationPage(new Home()));
//NavigationService.NavigateAsync("/MainPage/NavigationPage/ViewA");
}
}
}
If you want the exact match, here we go...
var im_Logo = new ImageButton
{
Margin = new Thickness(0),
Padding = new Thickness(0),
Source = "blalogo",
BackgroundColor = Color.Transparent,
HorizontalOptions = LayoutOptions.Start,
Command = new NavigateToExtension {Name = "/path/to/navigate"}
};
void GoHome(object obj)
{
Navigation.PopToRootAsync();
}
And you will need the following import:
using Prism.Navigation.Xaml;
Long story short, Prism use this class to create a command which can use INavigationService accessing the container in Application.Current. If you check the source code in Github you will see how all the magic happens.
https://github.com/PrismLibrary/Prism/blob/master/src/Forms/Prism.Forms/Navigation/Xaml/NavigateToExtension.cs
If you want to do it in ViewModel, then you need a INavigationService.
Then you can use it like:
await NavigationService.NavigateAsync(nameof(YourView));
So like
Command = new Command(async () => await NavigationService.NavigateAsync("YourView"));
NavigateAsync uses URI parameters, you can use ../ and ../YourView.
I like the nameof() method eg. await NavigationService.NavigateAsync($"../{nameof(YourView)}"));

I am trying to programmatically add images to a list/array and access them in a for each loop to change their source image

I have been trying to add images to an array and then access their properties to change their source image in a loop.
Detailed: I create a grid with a layout for each for each grid element, in that layout there is a GridImage, who's source folder is set to "ClosedFolder.png", when I click one of the layouts it should change the clicked layouts folder to "OpenFolder.png".
for (int eachCount = 0; eachCount <= MaxRows / MaxCols; eachCount++)
{
Selectedrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(80, GridUnitType.Absolute) });
for (int newCol = 0; newCol <= MaxCols; newCol++)
{
for (int newRow = 0; newRow <= MaxRows / MaxCols; newRow++)
{
if (folderIndex >= DirectoryArrayList.Count) { break; }
var folder = DirectoryArrayList[folderIndex];
var label = new Label()
{
Text = folder.Name,
FontSize = 12,
VerticalTextAlignment = TextAlignment.Center,
HorizontalTextAlignment = TextAlignment.Center
};
var GridImage = new Image() { Source = "ClosedFolder.png", StyleId = "Image" };
var GridTap = new TapGestureRecognizer();
var Layout = new StackLayout() { StyleId = "StackContent" };
var folderSelection = _mainFolder + "/" + folder.Name;
GridTap.Tapped += async(object sender, EventArgs e) =>
{
FileHandler.CreateTextFiles(folderSelection, "File_" + FileID + ".txt");
files = FolderOptions.AddFilesToList(folderSelection);
lst.ItemsSource = files;
//foreach (Image img in ImageList) I know this i incorrect, just an example of what I think!
//{
// img.Source = "ClosedFolder.png";
//}
GridImage.Source = "OpenFolder.png"; // clicked layout gets its openfolder.png
};
Layout.Children.Add(label);
Layout.Children.Add(GridImage);
Layout.GestureRecognizers.Add(GridTap);
Selectedrid.Children.Add(Layout, newCol, newRow);
folderIndex += 1;
FileID += 1;
}
}
}
Not sure on the declaration of the array and how to implement it.
I added the following into my BasicGrid method ...
var GridImage = new Image() { Source = "ClosedFolder.png", StyleId = "Image" };
var ImageList = new List<Image>{};
ImageList.Add( GridImage );
for (var i = 0; i < ImageList.Count; i++)
{
var img = ImageList[i];
img.Source = "ClosedFolder.png";
} GridImage.Source = "OpenFolder.png"
Just adding to say that Jason's information is the most likely direction I will go in, but as I am still learning it will take me time and I dint want to keep this open while I do that :-)

Line Separator in iOS ImageCell not always showing

I have an ImageCell which binds to an iOS Asset. When it renders, the line separator doesn't always show.
Seems to be a drawing issue because if I scroll up and down some of the rows get the separator line redrawn as can be seen in the screenshot.
Any ideas?
I've coded up my UI like this:
public class Contact{
public Contact(string name, string email) {
Name = name;
Email = email;
Initial = "Avatar";
}
public string Name { get; }
public string Email { get; }
public string Initial { get; }
}
public class ContactCell: ImageCell {
public ContactCell() {
this.SetBinding(TextProperty, "Name");
this.SetBinding(DetailProperty, "Email");
this.SetBinding(ImageSourceProperty, "Initial");
}
}
public class ContactListPage : ContentPage {
public ContactListPage() {
Title = "List";
Content = new ListView {
RowHeight = 60,
ItemTemplate = new DataTemplate(typeof(ContactCell)),
Margin = new Thickness(10, 0, 0, 0),
ItemsSource = new List<Contact> {
new Contact("Isa Tusa", "isa.tusa#me.com"),
.
.
};
}
}
I think that's the behavior when using the default viewcell templates like Image cell, etc. I would suggest you go for custom implementation like using grid for the item template. We have more control over it and can be easily modified to any required design. I've modified your code and pasted below. Check if it is useful for you...
public ContactListPage()
{
Title = "List";
Content = new ListView
{
RowHeight = 71,
SeparatorVisibility = SeparatorVisibility.None,
// ItemTemplate = new DataTemplate(typeof(ContactCell)),
ItemTemplate = new DataTemplate(() =>
{
return new ViewCell { View = ContactCellGrid() };
}),
ItemsSource = new List<Contact> {
new Contact("Isa Tusa", "isa.tusa#me.com"),
new Contact("Racquel Ricciardi", "racquel.ricciardi#me.com"),
new Contact("Teresita Mccubbin", "teresita.mccubbin#me.com"),
new Contact("Rhoda Hassinger", "rhoda.hassinger#me.com"),
new Contact("Carson Cupps", "carson.cupps#me.com"),
new Contact("Devora Nantz", "devora.nantz#me.com"),
new Contact("Tyisha Primus", "tyisha.primus#me.com"),
new Contact("Muriel Lewellyn", "muriel.lewellyn#me.com"),
new Contact("Hunter Giraud", "hunter.giraud#me.com"),
}
};
}
private Grid ContactCellGrid()
{
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(5, GridUnitType.Absolute) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(2, GridUnitType.Star) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(5, GridUnitType.Absolute) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Absolute) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5, GridUnitType.Absolute) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5, GridUnitType.Absolute) });
var nameLabel = new Label { FontAttributes = FontAttributes.Bold, VerticalTextAlignment = TextAlignment.Center };
var ageLabel = new Label { VerticalTextAlignment = TextAlignment.Start }; ;
var locationLabel = new Image { HorizontalOptions = LayoutOptions.Center };
var boxView = new BoxView { Color = Color.Gray, HeightRequest = 1 };
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Email");
locationLabel.SetBinding(Image.SourceProperty, "Initial");
grid.Children.Add(nameLabel, 2, 1);
grid.Children.Add(ageLabel, 2, 2);
grid.Children.Add(locationLabel, 1, 1);
Grid.SetRowSpan(locationLabel, 2);
grid.Children.Add(boxView, 1, 4);
Grid.SetColumnSpan(boxView, 2);
return grid;
}
below is the screenshot of it..

Xamarin.Forms/UWP: issue with Iconize and MasterDetailPage

I use the Iconize plugin for my project, and there is an issue that occurs in case of the IconToolbarItem is used in a IconNavigationPage, that is itself used in the Detail of a MasterDetailPage.
If we launch the UWP project from IconizeSample, the IconToolbarItems are well displayed in the TabbedPage:
var tabbedPage = new IconTabbedPage { Title = "Iconize" };
foreach (var module in Plugin.Iconize.Iconize.Modules)
{
tabbedPage.Children.Add(new Page1
{
BindingContext = new ModuleWrapper(module),
Icon = module.Keys.FirstOrDefault()
});
}
MainPage = new IconNavigationPage(tabbedPage);
If we replace the TabbedPage by a MasterDetailPage, this also works if the Detail is not a IconNavigationPage:
var mdPage = new MasterDetailPage();
mdPage.Master = new ContentPage
{
Title = "Iconize"
};
var module = Plugin.Iconize.Iconize.Modules.First();
mdPage.Detail = new Page1
{
BindingContext = new ModuleWrapper(module),
Icon = module.Keys.FirstOrDefault()
};
MainPage = new IconNavigationPage(mdPage);
But if we put the Detail in an IconNavigationPage, the icons of the IconToolbarItem are no longer visible:
var mdPage = new MasterDetailPage();
mdPage.Master = new ContentPage
{
Title = "Iconize"
};
var module = Plugin.Iconize.Iconize.Modules.First();
mdPage.Detail = new IconNavigationPage(new Page1
{
BindingContext = new ModuleWrapper(module),
Icon = module.Keys.FirstOrDefault()
});
MainPage = mdPage;
Would you have an explanation? Is there a way to fix this awaiting a new package version?
But if we put the Detail in an IconNavigationPage, the icons of the IconToolbarItem are no longer visible:
The problem is that you have not inserted the mdPage into IconNavigationPage. I have modified your code and it works.
var mdPage = new MasterDetailPage();
mdPage.Master = new ContentPage
{
Title = "Iconize"
};
var module = Plugin.Iconize.Iconize.Modules.First();
var page = new Page1
{
BindingContext = new ModuleWrapper(module),
Icon = module.Keys.FirstOrDefault()
};
mdPage.Detail = page;
MainPage = new IconNavigationPage(mdPage);

Flex, Problem when jpegencoding two bitmaps in sequence

I am creating this "drawing application", where the user can click "preview" and it will take what they made, draw a bitmap, and then I want to split that bitmap into left and right images. I create the first bitmap, encode it as a jpeg, and then use that to cut the left and right out using copypixels. I then reform the images together with a space inbetween in one canvas, and draw that canvas. Everything works fine up there.
When I go to encode the new bitmap, and then offer it to save out, the saved image is blank. I have tested everything up to that point and it all works fine. I see the images on screen, I can save out the first bitmap fine.. but the second one is always blank. Here is some sample code, possibly someone can help me out.
_mainBmd = new BitmapData(_jacketWidth, _jacketHeight);
_mainBmd.draw(_imageHolder);
startEncode(_mainBmd);
private function startEncode(imageBitmapData:BitmapData):void
{
var encoder:JPEGAsyncEncoder = new JPEGAsyncEncoder(100);
encoder.PixelsPerIteration = 150;
encoder.addEventListener(JPEGAsyncCompleteEvent.JPEGASYNC_COMPLETE, encodeDone);
encoder.encode(imageBitmapData);
}
private function encodeDone(event:JPEGAsyncCompleteEvent):void
{
_leftBmd = new BitmapData(sideWidth, sideHeight);
var lRect:Rectangle = new Rectangle(0,0, sideWidth, sideHeight);
var lPoint:Point = new Point(0,0);
_leftBmd.copyPixels(_mainBmd, lRect, lPoint);
_rightBmd = new BitmapData(sideWidth, sideHeight);
var bWidth:Number = 200;
var sWidth:Number = 111;
var rRectWidth:Number = (bWidth/2 + sWidth) * Constants.print_dpi;
var rRect:Rectangle = new Rectangle(rRectWidth, 0, sideWidth, sideHeight);
var rPoint:Point = new Point(0, 0);
_rightBmd.copyPixels(_mainBmd, rRect, rPoint);
var lbm:Bitmap = new Bitmap(_leftBmd);
var rbm:Bitmap = new Bitmap(_rightBmd);
//now combine the two images into one holder with a space in the middle
//left Image
var l_Image:Image = new Image();
l_Image.source = lbm;
//right image
var r_Image:Image = new Image();
r_Image.source = rbm;
var newRender:Canvas = new Canvas();
newRender.clipContent = false;
newRender.minHeight = 0;
newRender.minWidth = 0;
newRender.addChild(l_Image);
r_Image.x = 500;
newRender.addChild(r_Image);
fcBMD = new BitmapData(renderW, renderH);
fcBMD.draw(newRender);
startEncode2(fcBMD);
}
private function startEncode2(imageBitmapData:BitmapData):void
{
var encoder:JPEGAsyncEncoder = new JPEGAsyncEncoder(100);
encoder.PixelsPerIteration = 150;
encoder.addEventListener(JPEGAsyncCompleteEvent.JPEGASYNC_COMPLETE, encode2Done);
encoder.encode(imageBitmapData);
}
private function encode2Done(event:JPEGAsyncCompleteEvent):void
{
_data = event.ImageData;
}
private function onSaveRenderClick(e:MouseEvent):void //save button listener
{
var fileRef:FileReference = new FileReference();
fileRef.addEventListener(Event.SELECT, onSaveComplete);
fileRef.save(_data, 'testImage.jpg');
}
Is there a special reason why you go trough all the loops of creating a Canvas holder and adding Images?
Why not use copyPixels directly on the final BitmapData that you want to encode:
var backgroundColor:uint = 0xffffff;
fcBMD = new BitmapData(renderW, renderH, false, backgroundColor);
var lPoint:Point = new Point(0,0);
var lRect:Rectangle = new Rectangle(0,0, sideWidth, sideHeight);
fcBMD.copyPixels(_mainBmd, lRect, lPoint);
var rRect:Rectangle = new Rectangle(rRectWidth, 0, sideWidth, sideHeight);
var rPoint:Point = new Point(renderW - sideWidth, 0);
fcBMD.copyPixels(_mainBmd, rRect, rPoint);
startEncode2(fcBMD);

Resources