How to align two buttons in a stack panel without any spacing - c#

I have been using UmaStackPanel to align two views in Xamarin iOS. Somehow, even when I don't specifically define the space, there's a huge gap between the two views. One on one corner and the other in the other corner. I have been trying to remove the gap between, and I have failed. How to go about this?
The first button looks like this:
UIButton test= new UIButton(UIButtonType.System)
{
HorizontalAlignment = UIControlContentHorizontalAlignment.Left,
TranslatesAutoresizingMaskIntoConstraints = false,
TitleEdgeInsets = new UIEdgeInsets(0, 10, 0, 0),
Font = UmaFont.GetDefaultAppFont(17f)
};
test.SetImage(IconUtils.arrow.ToUIImage(new CoreGraphics.CGSize(24, 24)), UIControlState.Normal);
test.SetTitle(My Test, UIControlState.Normal);
test.SetTitleColor(UIColor.Black, UIControlState.Normal);
test.TintColor = iconColor;
UIImageView testView = new UIImageView()
{
ClipsToBounds = true,
TranslatesAutoresizingMaskIntoConstraints = false,
};
testView.Layer.MasksToBounds = true;
testView.Layer.CornerRadius = 12;
testView.ContentMode = UIViewContentMode.ScaleAspectFit;
testView.Image = IconUtils.arrow.ToUIImage(new CoreGraphics.CGSize(24, 24));
testView.Layer.BorderWidth = 2;
And I created a horizontal UmaStackPanel and added the views.

Related

How to programmatically add a Vertical or Horizontal StackView to a view

I'm able to add a Vertical and Horizontal StackView programmatically to my main view but the view is not performing any stacking type layout.
Here is what I have so far:
// create vertical stack
var viewSize = new CGSize(200, 150);
var viewLocation = new CGPoint(0, 0);
var viewRectangle = new CGRect(viewLocation, viewSize);
var frame = new CGRect(0, 0, 200, 20);
var stackView = new NSStackView(viewRectangle);
var button1 = new NSButton(frame) {
Title = "Button 1"
};
var frame2 = new CGRect(0, 10, 200, 20);
var button2 = new NSButton(frame2) {
Title = "Button 2"
};
// show background to help see size and position
stackView.WantsLayer = true;
stackView.Layer.BackgroundColor = new CGColor(150, 0, 150, 1);
stackView.Orientation = NSUserInterfaceLayoutOrientation.Vertical;
stackView.Alignment = NSLayoutAttribute.Top;
stackView.Distribution = NSStackViewDistribution.Fill;
stackView.Spacing = 10;
stackView.AddSubview(button1);
stackView.AddSubview(button2);
stackView.NeedsLayout = true;
frame1.AddSubview(stackView);
Screenshot below.
The top view is a manually created Vertical Stack in Interface Builder. The bottom is the programmatic one created from the code above:
Update:
I found some example code in the Xamarin iOS documentation:
https://learn.microsoft.com/en-us/xamarin/ios/user-interface/controls/uistackview
There are some properties I can't find but some of it is working.
The main enabling difference is that you need to use the addArrangedSubViews() method instead of addSubviews() method.
stackView.AddArrangedSubview(button);
Visual Studio for Mac using Xamarin and C#

iTextSharp Duplicating Acrofields

I have an acroform on page 1 of my document. I am creating a blank second page and i would like to show one of the fields on this page as well. If the user changes the value of this field on either of the pages, i want them both to show the new value. I found a few posts that are showing this type of solution but it doesn't work as expected:
PdfFormField fNotes = PdfFormField.CreateTextField(writer, false, false, 500);
string fieldNotes = "tfNotes";
fNotes.FieldName = fieldNotes;
PdfFormField widgetNotes = PdfFormField.CreateEmpty(writer);
PdfPCell notesCell = new PdfPCell(new Paragraph("test", helv8))
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(0, 0, 100, 100), fieldNotes);
writer.AddAnnotation(fNotes);
writer.AddAnnotation(widgetNotes);
In this example, the field on page 1 is named tfNotes. If i understand correctly, i need to create a second widget reference to the acrofield. I think the above code would be for a field that doesn't already exist, in my case it does. Is there an easier way to grab a field by name on page 1 and create a duplicate reference to it on page 2?
Thank you for your time!
EDIT:
This works as expected when i take the table out of the equation, but once i try to put the duplicated field into the PdfPCell it shows up on the page at 0,0 with a width and height of 0. For some reason the rectangle of the cell is returning as 0,0,0,0.
PdfPCell notesCell = new PdfPCell()
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
//Notes Cell Rectangle
float llxNotes = notesCell.GetLeft(0);
float llyNotes = notesCell.GetBottom(0);
float urxNotes = notesCell.GetRight(0);
float uryNotes = notesCell.GetTop(0);
//Notes Duplicate
string fieldNotesName = "tfQuoteNotes";
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(llxNotes, llyNotes, urxNotes, uryNotes), fieldNotesName)
{
FieldName = fieldNotesName
};
tField.SetRotationFromPage(doc.PageSize);
writer.AddAnnotation(tField.GetTextField());
I think all i need to do now is find the correct rectangle coords for the cell.
So the part i was missing was a CellEvent, which i don't completely understand why, but here is the final working snippet for anyone who needs it:
PdfPCell notesCell = new PdfPCell()
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
//Notes Cell Rectangle
float llxNotes = notesCell.GetLeft(0);
float llyNotes = notesCell.GetBottom(0);
float urxNotes = notesCell.GetRight(0);
float uryNotes = notesCell.GetTop(0);
//Notes Duplicate
string fieldNotesName = "tfQuoteNotes";
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(llxNotes, llyNotes, urxNotes, uryNotes), fieldNotesName)
{
FieldName = fieldNotesName
};
tField.SetRotationFromPage(doc.PageSize); //Needed since this page is rotated 90 from the first page
iTextSharp.text.pdf.events.FieldPositioningEvents events = new iTextSharp.text.pdf.events.FieldPositioningEvents(writer, tField.GetTextField());
writer.AddAnnotation(tField.GetTextField());
notesCell.CellEvent = events; //This somehow ignores the original rectangle (0,0,0,0) in the TextField definition above and changes it to the cell's rectangle

Button on top of the Scrollview does not show up

I have something like this so far for my view:
public StackLayout OffersSlideViewCarouselChild(Offer offer)
{
Image productImage = new Image
{
Source = ImageSource.FromUri(new Uri(offer.Image.Replace("https://", "http://"))),
HeightRequest = 270,
WidthRequest = 270,
Aspect = Aspect.AspectFit
};
var topStackLayout = new StackLayout
{
Spacing = 0
};
topStackLayout.Children.Add(productImage);
StackLayout contentStackLayout = new StackLayout
{
Spacing = 0,
Padding = new Thickness(5, 10, 5, 10),
Orientation = StackOrientation.Vertical
};
var savedBtn = SavedButtonLayout(offer.IsSelected, offer.Id);
var redeemBtn = RedeemBtnLayout(offer.Id);
var timeRemainingLabel = TimeRemainingLayout(offer, offer.Id);
contentStackLayout.Children.Add(new UILabel(16) {
Text = offer.ProductName,
TextColor = ColorHelper.FromHex(CoreTheme.COLOR_OFFERCELL_PRODUCT_TEXT),
FontFamily = CoreTheme.FONT_FAMILY_DEFAULT_BOLD,
WidthRequest = DeviceDisplaySettings.defaultwidth,
VerticalTextAlignment = TextAlignment.Center
});
contentStackLayout.Children.Add(new UILabel(14)
{
Text = offer.Headline,
TextColor = ColorHelper.FromHex(CoreTheme.COLOR_OFFERCELL_PRODUCT_TEXT),
FontFamily = CoreTheme.FONT_FAMILY_DEFAULT_BOLD,
WidthRequest = DeviceDisplaySettings.defaultwidth,
VerticalTextAlignment = TextAlignment.Center
});
contentStackLayout.Children.Add(new UILabel(14) {
Text = offer.LongRewardsMessage,
TextColor = ColorHelper.FromHex(CoreTheme.COLOR_DEAL_PAGE_LONG_REWARD_MESSAGE_RED),
FontFamily = CoreTheme.FONT_FAMILY_DEFAULT_BOLD,
WidthRequest = DeviceDisplaySettings.defaultwidth,
VerticalTextAlignment = TextAlignment.Center
});
if (!string.IsNullOrEmpty(offer.PowerMessage)) {
var htmlText = string.Format("<html><body style='color:#9b9b9b'>{0}</body></html>", offer.PowerMessage.Replace(#"\", string.Empty));
var browser = new WebView() {
//HeightRequest = (DeviceDisplaySettings.defaultheight > 600) ? 500 : 400,
HeightRequest = 800,
Source = new HtmlWebViewSource() { Html = htmlText },
};
browser.Navigating += OnNavigating;
contentStackLayout.Children.Add(browser);
}
var nestedStackLayout = new StackLayout()
{
VerticalOptions = LayoutOptions.FillAndExpand
};
nestedStackLayout.Children.Add(topStackLayout);
nestedStackLayout.Children.Add(timeRemainingLabel);
nestedStackLayout.Children.Add(contentStackLayout);
var mainScrollView = new ScrollView()
{
Padding = new Thickness(0, 0, 0, 10),
VerticalOptions = LayoutOptions.FillAndExpand,
Orientation = ScrollOrientation.Vertical,
Content = nestedStackLayout
};
var mainStackLayout = new StackLayout()
{
Spacing = 5,
Padding = new Thickness(0, 0, 0, 0),
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.Fill,
Orientation = StackOrientation.Vertical,
Children = { savedBtn, mainScrollView, redeemBtn }
};
return mainStackLayout;
}
private StackLayout SavedButtonLayout(bool isSelected, int offerid)
{
int buttonsToShow = 2;
bool displaySaveButton = true;
if (IsPremisesOffer (offerid)) {
buttonsToShow = 3;
displaySaveButton = false;
}
btnShare = new UIFieldDefinition(_pageFieldDefinition.ShareButtonDefinition);
btnShare.Text = "SHARE";
btnShare.ClassId = offerid.ToString();
btnShare.WidthRequest = (DeviceDisplaySettings.defaultwidth / buttonsToShow) - 40;
btnShare.BackgroundColor = Color.FromRgb(167, 188, 33);
btnShare.VerticalContentAlignment = TextAlignment.Center;
btnShare.HandleClick(btnShare_Clicked);
btnSave = new UIFieldDefinition(_pageFieldDefinition.SaveButtonDefinition);
btnSave.Text = isSelected ? "UNSAVE" : "SAVE";
btnSave.ClassId = offerid.ToString();
btnSave.WidthRequest = (DeviceDisplaySettings.defaultwidth / buttonsToShow) - 40;
btnSave.BackgroundColor = Color.FromRgb(167, 188, 33);
btnSave.VerticalContentAlignment = TextAlignment.Center;
btnSave.HandleClick(btnSave_Clicked);
rl = new StackLayout {
Spacing = 10,
Orientation = StackOrientation.Horizontal,
BackgroundColor = Color.FromRgb(196, 221, 57),
Padding = new Thickness(40, 5, 5, 5),
WidthRequest = DeviceDisplaySettings.defaultwidth
};
rl.Children.Add(btnShare);
if (displaySaveButton) rl.Children.Add(btnSave);
return rl;
}
public UIFieldDefinition RedeemBtnLayout(int offerid)
{
int buttonsToShow = 1;
btnRedeem = new UIFieldDefinition(_pageFieldDefinition.RedeemButtonDefinition);
btnRedeem.Text = "REDEEM NOW";
btnRedeem.ClassId = offerid.ToString();
btnRedeem.WidthRequest = (DeviceDisplaySettings.defaultwidth / buttonsToShow) - 10;
// btnRedeem.HorizontalOptions = LayoutOptions.FillAndExpand;
// btnRedeem.VerticalOptions = LayoutOptions.EndAndExpand;
btnRedeem.HandleClick(btnRedeem_Clicked);
return btnRedeem;
}
However, I am noticing that the Redeem button does not even display on the view (It's supposed to be fixed on the bottom).
The scrollview works but the buttom is missing. Why?
Please let me know if you need further code details.
Moving here from comments above. There are two separate issues from what I can tell, and as far as I can tell, are unrelated:
The WebView, nested inside the ScrollView, is not big enough to fully display the content.
The button that is supposed to be at the bottom of the screen is not displaying.
For both of them, the answer is probably in how you are setting HeightRequest. There have been a lot of suggestions by myself and other commenters to change or get rid of some of the HeightRequest settings, and I'm not sure of the current state of your source code. So assuming those are still there:
For solving the WebView issue, read How can I add HTML to a Stacklayout inside a Scrollview in Xamarin forms?. This will let you figure out the right HeightRequest to use. The short answer is that depending on exactly what you want to happen, you may need a custom renderer. Note that the HeightRequest for the WebView will not affect any layout outside of the ScrollView.
For solving the issue of the button not appearing, get rid of the HeightRequest setting on the ScrollView, and the VerticalOptions on the StackLayout created in SavedButtonLayout.
I am assuming you did the experiment suggested above to make sure that the redeemBtn will render if placed before the ScrollView, and it does show up then. If not, you first need to fix that.
If you have "fixed" this by changing the HeightRequest then your real problem is the fixed pixel size of all your views and layouts, I recommend you DON'T use fixed pixel sizes for different screen resolution this will be a bigger problem later, What you can do is get the Screen size and do the math to fit all your elements of the view, one way to get the width and height of the screen is on the OnSizeChanged event of Pages (Like ContentPage), something like this:
SizeChanged += SizeChanged;
void SizeChanged (object sender, EventArgs e)
{
Layout.WidthRequest = Width * 0.3;
Layout.HeightRequest = Height * 0.35;
}
Your layout is pretty busy. A few things:
Set VerticalOptions to EndAndExpand for redeemBtn.
Set VerticalOptions to StartAndExpand for savedBtn.
Set VerticalOptions to Fill for mainScrollView.
Set VerticalOptions to FillAndExpand for mainRelLayout.
Set VerticalOptions and HorizontalOptions to Fill for
mainStackLayout.
I think that will get you to where you want to be.
The options that include "Expand" will grow the element to accommodate the desired height of its contents.

Add annotations in MS chart (e.g. (10, 20) (20, 39) etc) and horizontal Scroll Bar

I want to add text(say, annotations) in MS chart(winforms) like (10, 20) , (30, 40) where I already have a scroll bar.
I can able to draw strings(graphics.drawstring) in Chart, but on scrolling the horizontal scroll bar, the text which I have drawn remains static and immovable.
On scrolling the scrollbar, the text which I have drawn also should move along with my horizontal scrolling.
My code follows:
chart2.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart2.BorderlineColor = System.Drawing.Color.FromArgb(26, 59, 105);
chart2.BorderlineWidth = 3;
chart2.BackColor = Color.White;
chart2.ChartAreas.Add("chtArea");
chart2.ChartAreas[0].AxisX.Title = "Category Name";
chart2.ChartAreas[0].AxisX.TitleFont =
new System.Drawing.Font("Verdana", 11, System.Drawing.FontStyle.Bold);
chart2.ChartAreas[0].AxisY.Title = "UnitPrice";
chart2.ChartAreas[0].AxisY.TitleFont =
new System.Drawing.Font("Verdana", 11, System.Drawing.FontStyle.Bold);
chart2.ChartAreas[0].BorderDashStyle = ChartDashStyle.Solid;
chart2.ChartAreas[0].BorderWidth = 2;
chart2.ChartAreas["chtArea"].AxisX.ScrollBar.Enabled = true;
chart2.ChartAreas["chtArea"].CursorX.IsUserEnabled = true;
chart2.ChartAreas["chtArea"].CursorX.IsUserSelectionEnabled = true;
chart2.ChartAreas["chtArea"].AxisX.ScaleView.Zoomable = false;
chart2.ChartAreas["chtArea"].AxisX.ScrollBar.IsPositionedInside = true;
chart2.ChartAreas["chtArea"].AxisX.ScaleView.Size = 20;
chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Seconds;
chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 1;
chart2.Legends.Add("UnitPrice");
chart2.Series.Add("UnitPrice");
chart2.Series[0].ChartType = SeriesChartType.Line;
Random rand = new Random();
var valuesArray = Enumerable.Range(0, 500).Select(x => rand.Next(0, 100)).ToArray();
for (int i = 0; i < 500; i++)
{
chart2.Series["UnitPrice"].Points.AddXY(i+10, valuesArray[i]);
}
I tried TextAnnotaions, Line annotations, etc Nothing helped me.
Then I tried drawing dynamic labels inside MS chart also. Labels remain immovable while scrolling horizontal scroll bar.
This code works perfectly in your machine also.
Sounds a lot as if you want to add TextAnnotations.
If you want them to stick with your data points you should anchor them to the points they shall stay with.
Here are a few examples:
// directly anchored to a point
TextAnnotation TA1 = new TextAnnotation();
TA1.Text = "DataPoint 222";
TA1.SetAnchor(chart2.Series["UnitPrice"].Points[222]);
chart2.Annotations.Add(TA1);
// anchored to a point but shifted down
TextAnnotation TA2 = new TextAnnotation();
TA2.Text = "DataPoint 111";
TA2.AnchorDataPoint = chart2.Series["UnitPrice"].Points[111];
TA2.AnchorY = 0;
chart2.Annotations.Add(TA2);
// this one is not anchored on a point:
TextAnnotation TA3 = new TextAnnotation();
TA3.Text = "At 50% width BC";
TA3.AnchorX = 50; // 50% of chart width
TA3.AnchorY = 20; // 20% of chart height, from top!
TA3.Alignment = ContentAlignment.BottomCenter; // try a few!
chart2.Annotations.Add(TA3);
By default they either anchor to DataPoints or are positioned in % of the chart size.
It is also possible to set the positions according to pixel coordinates, but for this you need to calculate the positions each time the chart changes its view!
See here for an example how to transform chart data positions to chart control coordinates and vice versa.. (Not really recommended, though)

Making graphic object selected

Hi i want to make my graphic object "selected" after click on them.
I tryied something like that to make selected line:
else if (e.OriginalSource is Line)
{
LineFocus = true;
MojaLinia = (Line)e.OriginalSource;
Rectangle rect_1 = new Rectangle
{
Stroke = Brushes.Black,
StrokeThickness = 1,
Fill = new SolidColorBrush(Color.FromRgb(255, 255, 255))
};
rect_1.Width = 6;
rect_1.Height = 6;
Canvas.SetLeft(rect_1, MojaLinia.X1);
Canvas.SetTop(rect_1, MojaLinia.Y1);
canvas.Children.Add(rect_1);
Rectangle rect_2 = new Rectangle
{
Stroke = Brushes.Black,
StrokeThickness = 1,
Fill = new SolidColorBrush(Color.FromRgb(255, 255, 255))
};
rect_2.Width = 6;
rect_2.Height = 6;
Canvas.SetLeft(rect_2, MojaLinia.X2);
Canvas.SetTop(rect_2, MojaLinia.Y2);
canvas.Children.Add(rect_2);
}
Its a bit stupid, and its hard to make white rectangle with distance from line. Is there any good way to do this without tons of if() ?
Im using VS2012, WPF/C# .
You can use Adorners to show your shape as "selected", this way you can also make the "selected" state visual hint in XAML.
And you can use an Attached Property to "add" a IsSelected property (boolean for example) to your object and toggle the value each time there is a click event rised.

Categories

Resources