C# Xamarin avoiding code repetition - c#

I am making a basic note taking app using C# in Xamarin Studio and have been following along with a course online.
Problem is that the code examples provided contain a lot of repetitive code which is making updating the app increasingly hard.
I labelled the relevant code below which is pertinent to two very similar classes, EditNoteViewController.cs and AddNoteViewController.cs, how can I extract the code out so that I can call it just once?
Alternatively I am looking at extracting it all into one class and having a conditional flow rendering different attributes based on whether the user is creating or updating a note.
EditNoteController.cs
using System;
using UIKit;
namespace NoteTaker.iOS
{
public class EditNoteViewController : UIViewController
{
Note note;
public EditNoteViewController (Note _note)
{
note = _note;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (255, 0, 255); // Repeated code. Also used in MainViewController.cs
this.Title = "Edit Note";
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes () { ForegroundColor = UIColor.White };
this.NavigationController.NavigationBar.TintColor = UIColor.White;
this.View.BackgroundColor = UIColor.White;
var titleEntryBox = new UITextField () {
Frame = new CoreGraphics.CGRect (0, 100, View.Bounds.Width, 45), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note.title
};
var descriptionLabel = new UILabel () {
Frame = new CoreGraphics.CGRect (10, 180, 250, 35),
Text = "Description",
};
var descriptionEntryBox = new UITextView () {
Frame = new CoreGraphics.CGRect (0, 220, View.Bounds.Width, 100), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note.description
};
var updateButton = new UIButton () {
Frame = new CoreGraphics.CGRect (10, 340, 120, 45)
}; // Repeated code
updateButton.SetTitle ("Update", UIControlState.Normal);
updateButton.BackgroundColor = UIColor.FromRGB (255, 0, 255);
updateButton.SetTitleColor (UIColor.White, UIControlState.Normal);
this.View.Add (titleEntryBox);
this.View.Add (descriptionLabel);
this.View.Add (descriptionEntryBox);
this.View.Add (updateButton);
updateButton.TouchUpInside += (sender, e) => {
if (titleEntryBox.Text.Length < 4)
return;
var noteToUpdate = new Note () {
ID = note.ID,
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.updateNote (noteToUpdate);
this.NavigationController.PopViewController (true);
};
}
}
}
AddNoteViewController.cs
using System;
using UIKit;
namespace NoteTaker.iOS
{
public class AddNoteViewController : UIViewController
{
public AddNoteViewController ()
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (255, 0, 255);
this.Title = "New Note";
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes () { ForegroundColor = UIColor.White };
this.NavigationController.NavigationBar.TintColor = UIColor.White;
this.View.BackgroundColor = UIColor.White;
var titleEntryBox = new UITextField () {
Frame = new CoreGraphics.CGRect (0, 100, View.Bounds.Width, 45),
BackgroundColor = UIColor.LightGray,
Placeholder = "Enter title...",
TextColor = UIColor.Black
};
var descriptionLabel = new UILabel () {
Frame = new CoreGraphics.CGRect (10, 180, 250, 35),
Text = "Enter description below"
};
var descriptionEntryBox = new UITextView () {
Frame = new CoreGraphics.CGRect (0, 220, View.Bounds.Width, 100),
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black
};
var saveButton = new UIButton () {
Frame = new CoreGraphics.CGRect (10, 340, 120, 45)
};
saveButton.SetTitle ("Save Note", UIControlState.Normal);
saveButton.BackgroundColor = UIColor.FromRGB (255, 0, 255);
saveButton.SetTitleColor (UIColor.White, UIControlState.Normal);
this.View.Add (titleEntryBox);
this.View.Add (descriptionLabel);
this.View.Add (descriptionEntryBox);
this.View.Add (saveButton);
saveButton.TouchUpInside += (sender, e) => {
if (titleEntryBox.Text.Length < 4)
return;
var noteToSave = new Note () {
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.InsertNote (noteToSave);
titleEntryBox.Text = "";
descriptionEntryBox.Text = "";
};
}
}
}

There are lots of different ways to approach a problem like this; this is just a simple example - passing a null into the controller will cause it to "Add", otherwise it will act as an "Edit" page
public class NoteViewController : UIViewController
{
Note note;
public NoteViewController (Note _note)
{
note = _note;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (255, 0, 255); // Repeated code. Also used in MainViewController.cs
this.Title = note == null ? "Add Note" : "Edit Note";
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes () { ForegroundColor = UIColor.White };
this.NavigationController.NavigationBar.TintColor = UIColor.White;
this.View.BackgroundColor = UIColor.White;
var titleEntryBox = new UITextField () {
Frame = new CoreGraphics.CGRect (0, 100, View.Bounds.Width, 45), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note == null ? string.Empty : note.title
};
var descriptionLabel = new UILabel () {
Frame = new CoreGraphics.CGRect (10, 180, 250, 35),
Text = "Description",
};
var descriptionEntryBox = new UITextView () {
Frame = new CoreGraphics.CGRect (0, 220, View.Bounds.Width, 100), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note == null ? string.Empty : note.description
};
var button = new UIButton () {
Frame = new CoreGraphics.CGRect (10, 340, 120, 45)
}; // Repeated code
if (note == null) {
button.SetTitle ("Add", UIControlState.Normal);
} else {
button.SetTitle ("Update", UIControlState.Normal);
}
button.BackgroundColor = UIColor.FromRGB (255, 0, 255);
button.SetTitleColor (UIColor.White, UIControlState.Normal);
this.View.Add (titleEntryBox);
this.View.Add (descriptionLabel);
this.View.Add (descriptionEntryBox);
this.View.Add (button);
button.TouchUpInside += (sender, e) => {
if (note == null) {
var noteToSave = new Note () {
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.InsertNote (noteToSave);
titleEntryBox.Text = "";
descriptionEntryBox.Text = "";
} else {
if (titleEntryBox.Text.Length < 4)
return;
var noteToUpdate = new Note () {
ID = note.ID,
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.updateNote (noteToUpdate);
this.NavigationController.PopViewController (true);
}
};
}
}

Related

How to show image over whole screen when clicked on?

I want to show image on whole screen if someone clicks on it. Image is loaded from database, just url of that image. How can i do that, code looks like this.
public void GetAllPlanes()
{
string _dbPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "myDB.db3");
var db = new SQLiteConnection(_dbPath);
for (int a = 1; a <= DatabaseNmbr(); a++)
{
var rowData = db.Table<Airplane>().FirstOrDefault(i => i.Id == a);
if (rowData.Plane != null && rowData.Airline != null && rowData.Registration != null && rowData.Registration != null && rowData.Airport != null && rowData.Url != null)
{
//vzhled
Frame cardFrame = new Frame
{
BackgroundColor = Color.FromHex("#00d2ff"),
CornerRadius = 30,
Margin = new Thickness(0, 60, 0, -20),
Content = new StackLayout
{
Children =
{
new Label {Text = "Plane " + a, TextColor = Color.White, HorizontalOptions = LayoutOptions.Center, FontSize = 30 },
new Image { Source = rowData.Url },
new Label {Text = "Plane:" + rowData.Plane, TextColor = Color.White, FontSize = 20 },
new Label {Text = "Airline:" + rowData.Airline, TextColor = Color.White, FontSize = 15 },
new Label {Text = "Livery:" + rowData.Livery, TextColor = Color.White, FontSize = 15 },
new Label {Text = "Registration:" + rowData.Registration, TextColor = Color.White, FontSize = 15 },
new Label {Text = "Airport:" + rowData.Airport, TextColor = Color.White, FontSize = 15 },
new Label {Text = "Date:" + rowData.Date, TextColor = Color.White, FontSize = 15 },
new Label {Text = "Comment:" + rowData.Comment, TextColor = Color.White, FontSize = 15}
}
}
};
Contenttest.Children.Add(cardFrame);
}
}
}
I want to show image on whole screen if someone clicks on it.
You can add TapGestureRecognizer to Image, when you Tap in Image, navigating to another to display entire image.
ContentPage1:
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
for (int i=0;i<4;i++)
{
Image image = new Image { Source = "https://aka.ms/campus.jpg", HeightRequest = 100, WidthRequest = 100 };
var tapGestureRecognizer = new TapGestureRecognizer();
// tapGestureRecognizer.NumberOfTapsRequired = 2; // double-tap
tapGestureRecognizer.Tapped += OnTapGestureRecognizerTapped;
image.GestureRecognizers.Add(tapGestureRecognizer);
Frame cardFrame = new Frame
{
CornerRadius = 30,
Content = new StackLayout
{
Children =
{
new Label {Text="Panel "+i, HorizontalOptions = LayoutOptions.Center, FontSize = 30 },
image
}
}
};
Contenttest.Children.Add(cardFrame);
}
}
private async void OnTapGestureRecognizerTapped(object sender, EventArgs e)
{
var imageSender = (Image)sender;
await Navigation.PushAsync(new Page2(imageSender.Source));
}
}
ContentPage2:
<StackLayout>
<Image
x:Name="image1"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</StackLayout>
public partial class Page2 : ContentPage
{
public Page2(ImageSource source)
{
InitializeComponent();
image1.Source = source;
}
}

WPF Bar Chart how to add space between bars?

I am using Telerik (RadPieChart) with WPF. What I want to do is add a small space between the bars. I am not asking about the space between the series, as that is already available, but about a smaller space between the bars just as shown in the image examples below.
Here is what I have now:
And this is how I would like my Bar Chart to look like with a small space between them:
This is my source code:
private BarSeries CreateBarSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings, int colorPaletteIndex)
{
var isStackMode = chartSeries.Key.CombineMode == SeriesCombineMode.Stack;
var barSerie = new BarSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
LegendSettings = legendSettings,
StackGroupKey = chartSeries.Key.Group,
Opacity = 0.8,
ZIndex = 120,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group)
? ChartSeriesCombineMode.Cluster
: (isStackMode ? ChartSeriesCombineMode.Stack : ChartSeriesCombineMode.Stack100),
// start animations
//PointAnimation = new ChartMoveAnimation()
//{
// MoveAnimationType = MoveAnimationType.Bottom,
// Duration = new TimeSpan(0, 0, 0, 0, 600),
// Delay = new TimeSpan(0, 0, 0, 0, 155),
// //Easing = new ElasticEase()
// //{
// // EasingMode = EasingMode.EaseOut,
// //},
//},
LabelDefinitions =
{
// set the clarion format for the labels
new ChartSeriesLabelDefinition()
{
Template = new DataTemplate()
{
VisualTree = GetSeriesFormat(chartSeries),
}
}
}
};
// this is the color of bar series
if (chartSeries.Key.ColorHex != null)
{
Style style = new Style(typeof(Border));
style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
barSerie.DefaultVisualStyle = style;
}
foreach (ChartDataPoint serie in chartSeries.Value)
{
barSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return barSerie;
}
The answer:
For some reason adding the BorderThickness to the Style as suggested in one of the answers did not do the trick, although BorderThicknes should be the solution. So I added a PointTemplate with a VisualTree and there I defined the BorderThickness. Now it is working perfectly.
private BarSeries CreateBarSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings, int colorPaletteIndex)
{
var seriesPredefinedColor = this.ChartBase.Palette.GlobalEntries[colorPaletteIndex].Fill;
FrameworkElementFactory borderFramework = new FrameworkElementFactory(typeof(Border));
borderFramework.SetValue(Border.BackgroundProperty, ColorService.BrushFromHex(chartSeries.Key.ColorHex) ?? seriesPredefinedColor);
borderFramework.SetValue(Border.OpacityProperty, 0.8D);
borderFramework.SetValue(Border.BorderThicknessProperty, new Thickness(2));
borderFramework.AddHandler(Border.MouseEnterEvent, new MouseEventHandler((sender, args) =>
{
var seriesBorder = (Border)sender;
//seriesBorder.BorderBrush = new SolidColorBrush(Colors.Black);
//seriesBorder.BorderThickness = new Thickness(1);
seriesBorder.Opacity = 1;
}));
borderFramework.AddHandler(Border.MouseLeaveEvent, new MouseEventHandler((sender, args) =>
{
var seriesBorder = (Border)sender;
//seriesBorder.BorderBrush = new SolidColorBrush(Colors.Black);
//seriesBorder.BorderThickness= new Thickness(1);
seriesBorder.Opacity = 0.8;
}));
var isStackMode = chartSeries.Key.CombineMode == SeriesCombineMode.Stack;
var barSerie = new BarSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
LegendSettings = legendSettings,
StackGroupKey = chartSeries.Key.Group,
ZIndex = 120,
IsHitTestVisible = true,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group)
? ChartSeriesCombineMode.Cluster
: (isStackMode ? ChartSeriesCombineMode.Stack : ChartSeriesCombineMode.Stack100),
// start animations
//PointAnimation = new ChartMoveAnimation()
//{
// MoveAnimationType = MoveAnimationType.Bottom,
// Duration = new TimeSpan(0, 0, 0, 0, 600),
// Delay = new TimeSpan(0, 0, 0, 0, 155),
// //Easing = new ElasticEase()
// //{
// // EasingMode = EasingMode.EaseOut,
// //},
//},
LabelDefinitions =
{
// set the clarion format for the labels
new ChartSeriesLabelDefinition()
{
Template = new DataTemplate()
{
VisualTree = GetSeriesFormat(chartSeries),
}
}
},
PointTemplate = new DataTemplate()
{
VisualTree = borderFramework,
}
};
// this is the color of bar series
//if (chartSeries.Key.ColorHex != null)
//{
// Style style = new Style(typeof(Border));
// style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
// barSerie.DefaultVisualStyle = style;
//}
foreach (ChartDataPoint serie in chartSeries.Value)
{
barSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return barSerie;
}
Set the BorderThickness property of the DefaultVisualStyle of the BarSeries:
// this is the color of bar series
if (chartSeries.Key.ColorHex != null)
{
Style style = new Style(typeof(Border));
style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
style.Setters.Add(new Setter(Border.BorderThicknessProperty, new Thickness(2.0)));
barSerie.DefaultVisualStyle = style;
}
have you look into this ? seem default is 0 mean bar take all the space
Scale.SpacingSlotCount Property
Determines the number of space slots that will be left around the DataPoints per category slot, measured relatively to the DataPoint
slot's width: Empty Space = SpacingSlotCount * DataPoint_SlotWidth
Namespace: Telerik.Reporting
Assembly: Telerik.Reporting (in Telerik.Reporting.dll) Version: 12.1.18.816 (12.1.18.816)

How to add and remove rows in a UITableview dynamically in xamarin.ios

I am new in xamarin.ios ,I want to add rows into the UITableView in a button click, and remove the row when clicking the particular button also.
Please help me...
my viewcontroller.cs
public partial class ViewController : UIViewController
{
public static UITableView table;
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
table = new UITableView(new CGRect(0, 0, 500, 500));
View.AddSubview(table);
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("Cell"), OnChange, this);
contentdata _cnt = new contentdata();
table.AddSubview(_cnt);
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
private void Addmore_TouchUpInside(object sender,
EventArgs e)
{
NSNotificationCenter.DefaultCenter.PostNotificationName("Cell", new NSString("Add"));
}
public class contentdata : UIView
{
public contentdata()
{
this.Frame = new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, 50);
nfloat width = UIScreen.MainScreen.Bounds.Width / 3;
UITextField title = new UITextField();
title.Placeholder = " Enter title";
title.TextColor = UIColor.Black;
title.TextAlignment = UITextAlignment.Left;
title.Font = UIFont.SystemFontOfSize(20);
title.Layer.BorderColor = UIColor.Black.CGColor;
title.Layer.BorderWidth = 1;
title.Frame = new CGRect(10, 0, width, 75);
this.Add(title);
UIView _view2 = new UIView(new CGRect(0,5,10,10));
_view2.BackgroundColor = UIColor.White;
_view2.Layer.BorderColor = UIColor.Black.CGColor;
_view2.Layer.BorderWidth = 1;
_view2.Frame = new CGRect(width, 0, UIScreen.MainScreen.Bounds.Width / 3, 75);
this.Add(_view2);
nfloat _view2Width = _view2.Frame.Width;
nfloat _view2Height = _view2.Frame.Height;
UIButton _browse = new UIButton(new CGRect(15, 10,100, 30));
_browse.SetTitle("Browse", UIControlState.Normal);
// _browse.SizeToFit();
_browse.SetTitleColor(UIColor.Black, UIControlState.Normal);
_browse.Layer.CornerRadius = 13;
_browse.Layer.BorderWidth = 2;
_browse.Layer.BorderColor = UIColor.FromRGB(25, 106, 155).CGColor;
// _browse.TouchUpInside += _browse_TouchUpInside;
_view2.AddSubview(_browse);
UILabel _text = new UILabel(new CGRect(5, (_view2Height/2)+5, 150, 30));
_text.Text = "No file selected";
_text.TextAlignment = UITextAlignment.Justified;
_text.TextColor = UIColor.Black;
_text.Font = _text.Font.WithSize(15);
_text.LineBreakMode = UILineBreakMode.WordWrap;
_view2.AddSubview(_text);
UIView _view3 = new UIView();
_view3.BackgroundColor = UIColor.White;
_view3.Layer.BorderColor = UIColor.Black.CGColor;
_view3.Layer.BorderWidth = 1;
_view3.Frame = new CGRect(width * 2, 0, UIScreen.MainScreen.Bounds.Width / 3-10, 75);
this.Add(_view3);
UIButton _addmore = new UIButton(new CGRect(10, 15, 40, 40));
_addmore.SetTitle("+", UIControlState.Normal);
_addmore.BackgroundColor = UIColor.FromRGB(25, 106, 155);
_addmore.SetTitleColor(UIColor.White, UIControlState.Normal);
_addmore.TouchUpInside += Addmore_TouchUpInside;
_view3.AddSubview(_addmore);
UIButton _remove = new UIButton(new CGRect(65, 15, 40, 40));
_remove.BackgroundColor = UIColor.Red;
_remove.SetTitle("-", UIControlState.Normal);
_remove.SetTitleColor(UIColor.White, UIControlState.Normal);
_view3.AddSubview(_remove);
}
void OnChange(NSNotification notification)
{
string s = notification.Object as NSString;
if (s == "Add")
{
contentdata _cd = new AddMore.ViewController.contentdata();
table.AddSubview(_cd);
}
else
{
int index = (notification.Object as NSIndexPath).Row;
//tableItems.RemoveAt(index);
}
table.ReloadData();
}
}
}
I want to add rows in to the table when clicking the plus button, and remove the selected row when clicking the minus button.And after browsing a file, the filename is displayed in the label also.How can I do this
You can use NSNotification to operate the datasource , and then reload the TableView.
When click add button , datasource + 1, when click remove button, datasource will remove the specified one.
ViewController
void OnChange(NSNotification notification)
{
string s = notification.Object as NSString;
if(s is "Add")
{
tableItems.Add(new TableItem("Vegetables") { SubHeading = "65 items", ImageName = "Vegetables.jpg" });
}
else
{
int index = (notification.Object as NSIndexPath).Row;
tableItems.RemoveAt(index);
}
table.ReloadData();
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("Cell"), OnChange,this);
//xxx
}
UITableViewCell
private void _addmore_TouchUpInside(object sender, EventArgs e)
{
NSNotificationCenter.DefaultCenter.PostNotificationName("Cell", new NSString("Add"));
}
private void _remove_TouchUpInside(object sender, EventArgs e)
{
NSNotificationCenter.DefaultCenter.PostNotificationName("Cell", Cellindex);
}

XamarinForms RelativeLayout: Can't get relative layout to resize correctly in a row

Here is my issue:
The red block is meant to be the avatar for the person sometime, and the blue balloon a chat message. The chat message object is a RelativeLayout with a Label and an Image positioned one of top of each other, but not matter what I do, I can't get it to be centered. I only have one View:
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace TestChat
{
public partial class ChatPage : ContentPage
{
public ChatPage ()
{
this.Title = "Chat page";
InitializeComponent ();
}
void OnChatClick (object sender, EventArgs args) {
Image pic = new Image {
Source = "bubble.png",
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Aspect = Aspect.Fill
};
Label textLabel = new Label {
Text = "Hello",
TextColor = Color.White,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.EndAndExpand
};
Frame picFrame = new Frame {
HasShadow = false,
BackgroundColor = Color.Red,
Padding = new Thickness (0),
Content = pic
};
Frame textFrame = new Frame {
HasShadow = false,
BackgroundColor = Color.Transparent,
Padding = new Thickness (0,0,15,0),
Content = textLabel
};
RelativeLayout overlayLayout = new RelativeLayout { BackgroundColor = Color.Blue, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
overlayLayout.Children.Add (picFrame,
xConstraint: Constraint.RelativeToParent((parent) => parent.X),
yConstraint: Constraint.RelativeToParent((parent) => parent.Y),
widthConstraint: Constraint.RelativeToParent((parent) => parent.Width-2),
heightConstraint: Constraint.RelativeToParent((parent) => parent.Height-2)
);
overlayLayout.Children.Add (textFrame,
xConstraint: Constraint.RelativeToParent((parent) => parent.X),
yConstraint: Constraint.RelativeToParent((parent) => parent.Y),
widthConstraint: Constraint.RelativeToParent((parent) => parent.Width-2),
heightConstraint: Constraint.RelativeToParent((parent) => parent.Height-2)
);
Frame overlayContainerFrame = new Frame {
HasShadow = false,
BackgroundColor = Color.Red,
Padding = new Thickness(1),
HeightRequest = 100,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Content = overlayLayout
};
StackLayout horizontalLayout = new StackLayout {
Orientation = StackOrientation.Horizontal
};
BoxView avatarImage = new BoxView {
Color = Color.Red,
HeightRequest = 50,
WidthRequest = 50
};
horizontalLayout.Children.Add (avatarImage);
horizontalLayout.Children.Add (overlayContainerFrame);
ChatScrollViewStackLayout.Children.Add (horizontalLayout);
//ChatStackLayout.Children.Add (pic);
}
void CreateChatBubble() {
}
}
}
Does anyone have any ideas why I can't get the relative layout to resize accordingly so it doesn't go out of range of the screen? I tried setting its WidthConstraint to parent.With-52 to make up for the avatar taking up 50 units horizontally, but instead I get this:
I've been stuck at this for at least 8 hours now, and I'm pretty much out of ideas. Any tips would be greatly appreciated. Here is the project's git repo so you can clone it if you would like to test anything:
https://github.com/sgarcia-dev/xamarin-chat.git
Any help would be greatly appreciated, and feel free to completely ignore my code if it looks messy if you can replicate what I want. (One image on the left, and a message bubble on the right with an underlying image background)
Check out this implementation
void OnChatClick (object sender, EventArgs args) {
var pic = new Image {
Source = "bubble.png",
Aspect = Aspect.Fill
};
var textLabel = new Label {
Text = "Hello",
TextColor = Color.White,
VerticalOptions = LayoutOptions.Center,
LineBreakMode = LineBreakMode.WordWrap
};
var relativeLayout = new RelativeLayout {
BackgroundColor = Color.Navy,
// HeightRequest = 1000
};
var absoluteLayout = new AbsoluteLayout {
VerticalOptions = LayoutOptions.Center,
BackgroundColor = Color.Blue
};
var frame = new Frame {
BackgroundColor = Color.Red
};
absoluteLayout.Children.Add (pic,
new Rectangle (0, 0, 1, 1),
AbsoluteLayoutFlags.All);
absoluteLayout.Children.Add (textLabel,
new Rectangle (0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize),
AbsoluteLayoutFlags.PositionProportional);
// textLabel.SizeChanged += (object label, EventArgs e) => {
// relativeLayout.HeightRequest = textLabel.Height + 30;
// absoluteLayout.HeightRequest = textLabel.Height + 30;
// };
relativeLayout.Children.Add (frame,
heightConstraint: Constraint.RelativeToParent (parent => parent.Height),
widthConstraint: Constraint.RelativeToParent (parent => parent.Width * 0.3));
relativeLayout.Children.Add (absoluteLayout,
xConstraint: Constraint.RelativeToParent (parent => parent.Width * 0.3),
widthConstraint: Constraint.RelativeToParent (parent => parent.Width * 0.7));
ChatScrollViewStackLayout.Children.Add (relativeLayout);
}
If you need to auto-adjust height of the chat message for long text uncomment all five commented lines.

UIScrollView Scroll Not working Xamarin IOS

Create the scroll view added to UIViewController View
UIScroll scroll_View;
scroll_View = new UIScrollView {
BackgroundColor = UIColor.Black,
Frame = View.Frame,
ContentSize = new SizeF(320,720),
};
View.addSubView(scroll_View);// Added to Regisration ViewController
// Created text Fields
firstName = new UITextField {
Placeholder = "Enter firstName",
BorderStyle = UITextBorderStyle.None,
VerticalAlignment = UIControlContentVerticalAlignment.Center,
AutocorrectionType = UITextAutocorrectionType.No,
AutocapitalizationType = UITextAutocapitalizationType.None,
ClearButtonMode = UITextFieldViewMode.WhileEditing,
Background = TextFieldBackground,
LeftView = new UIView (new RectangleF (0, 0,8, 8)),
LeftViewMode = UITextFieldViewMode.Always,
ReturnKeyType = UIReturnKeyType.Next,
ShouldReturn = delegate {
lastName.BecomeFirstResponder ();
return true;
}
};
// Like this created 9 textfields and one submit button. added to ScrollView
Frame TextField.
firstName.Frame = new RectangleF(80, 20, 200, 41);
lastName.Frame = new RectangleF(80, 70, 200, 41);
middle.Frame = new RectangleF(80, 120, 200, 41);
email.Frame = new RectangleF(80, 127, 200, 41);
password.Frame = new RectangleF(80, 220, 200, 41);
conformPassword.Frame = new RectangleF(80, 270, 200, 41);
phoneNumber.Frame = new RectangleF(80, 320, 200, 41);
description.Frame = new RectangleF(80, 370, 200, 41);
other.Frame = new RectangleF(80, 420, 200, 41);
buttonSubmit.Frame = new RectangleF(80, 470, 420, 41);
Adding textfield to ScrollView
scroll_View.addSubView(firstName);
scroll_View.addSubView(lastName);
scroll_View.addSubView(middleName);
scroll_View.addSubView(email);
scroll_View.addSubView(Password);
scroll_View.addSubView(conformaPassword);
scroll_View.addSubView(phoneNumber);
scroll_View.addSubView(description);
scroll_View.addSubView(other);
scroll_View.addSubView(buttonSubmit);
Added Scroll View UIViewController View.
View.AddSubview (scroll_View);
When scrolling scrolling effect is not working. Xamarin IOS.
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
float h = 50.0f;
float w = 50.0f;
float padding = 10.0f;
int n = 25;
_scrollView = new UIScrollView {
Frame = new RectangleF (0, 0, View.Frame.Width, h + 2 * padding),
ContentSize = new SizeF ((w + padding) * n, h),
BackgroundColor = UIColor.DarkGray,
AutoresizingMask = UIViewAutoresizing.FlexibleWidth
};
for (int i=0; i<n; i++) {
var button = UIButton.FromType (UIButtonType.RoundedRect);
button.SetTitle (i.ToString (), UIControlState.Normal);
button.Frame = new RectangleF (padding * (i + 1) + (i * w), padding, w, h);
_scrollView.AddSubview (button);
_buttons.Add (button);
}
View.AddSubview (_scrollView);
}
Try to use "ContentSize " property in UIScrollView.
If you want to enable "Horizontal Scroll on UIScrollView" , need to increase the width of contentsize.
If you want to enable "Vertical Scroll on UIScrollView" , need to increase the height of contentsize.
UIScrollView *scrollView =[[UIScrollView
alloc]initWithFrame:CGRectMake(0, 40, 500, 300)];
scrollView.contentSize=CGSizeMake(1500, 200); //Horizontal scrolling
UIScrollView *scrollView =[[UIScrollView
alloc]initWithFrame:CGRectMake(0, 40, 500, 300)];
scrollView.contentSize=CGSizeMake(200, 1500); //vertical scrolling
Not a real answer yet it seems on this old question, but for future references: The problem in these cases is mostly that the ContentSize is equal to or smaller then the frame of the ScrollView. Therefore the ScrollView is unaware of the need to scroll.
In your case you should verify that the ContentSize of 320x720 is larger than the View.Frame you assign to the ScrollView Frame...
public class FirstTab : UIViewController
{
private UIView content1;
private UIView content2;
private UIView content3;
private UIView containerView;
private UIScrollView scrollView;
CoreGraphics.CGSize contentViewSize;
public FirstTab()
{
content1 = new UIView();
content2 = new UIView();
content3 = new UIView();
containerView = new UIView();
scrollView = new UIScrollView();
contentViewSize = new CoreGraphics.CGSize(View.Frame.Width, View.Frame.Height + 800);
}
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
scrollView.ContentSize = contentViewSize;
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
content1.BackgroundColor = UIColor.Red;
content2.BackgroundColor = UIColor.Black;
content3.BackgroundColor = UIColor.Brown;
Constraint();
}
private void Constraint()
{
containerView.AddSubviews(content1, content2, content3);
containerView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
containerView.AddConstraints(
content1.Width().EqualTo(300),
content1.Height().EqualTo(300),
content1.AtTopOf(containerView).Plus(20),
content1.WithSameCenterX(containerView),
content2.Width().EqualTo(300),
content2.Height().EqualTo(300),
content2.Below(content1).Plus(20),
content2.WithSameCenterX(containerView),
content3.Width().EqualTo(300),
content3.Height().EqualTo(300),
content3.Below(content2).Plus(20),
content3.WithSameCenterX(containerView)
);
scrollView.AddSubviews(containerView);
scrollView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
scrollView.AddConstraints(
containerView.WithSameHeight(scrollView).Plus(300),
containerView.WithSameWidth(scrollView)
);
View.AddSubviews(scrollView);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
scrollView.WithSameWidth(View),
scrollView.WithSameHeight(View).Plus(400)
);
}
}
UIScrollView will work when You put the ScrollView.ContentSize into ViewWillLayoutSubview() method.
It took me very long time to find this simple trick for a working UIScrollView. I have used Cirrious.FluentLayout for autolayout.
In this case u need better work with UITableView not UIScrollView.

Categories

Resources