Carousel Page Indicator - c#

I have a Xamarin.Forms (1.4.2.6359) Project using Visual Studio 2013 and have created the carousel page below. I want to add page indicators, i.e. dots over top of the carousel page. Is this able to be done with the Xamarin Forms CarouselPage?
public class SplashPage : CarouselPage
{
public SplashPage ()
{
this.Children.Add(new CarouselChild("Logo.png", "Welcome"));
this.Children.Add(new CarouselChild("Settings.png", "Settings"));
}
}
class CarouselChild : ContentPage
{
public CarouselChild(string image, string text)
{
StackLayout layout = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
};
layout.Children.Add(new Image
{
Source = image,
});
layout.Children.Add(new Label
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.EndAndExpand,
Text = text,
Scale = 2,
});
this.Content = layout;
}
}

Trying to keep things simple, what I did was:
MyCarouselPage:
class MyCarouselPage : CarouselPage
{
private int totalPages;
private int currentPage;
public MyCarouselPage()
{
var pages = GetPages();
totalPages = pages.Length;
this.ChildAdded += MyCarouselPage_ChildAdded;
for (int i = 0; i < totalPages; i++)
{
currentPage = i;
this.Children.Add(pages[i]);
}
}
void MyCarouselPage_ChildAdded(object sender, ElementEventArgs e)
{
var contentPage = e.Element as MyPageBase;
if (contentPage != null)
{
contentPage.FinalStack.Children.Add(new CarouselPageIndicator(currentPage, totalPages, "indicator.png", "indicator_emtpy.png"));
}
}
private MyPageBase[] GetPages()
{
var pages = new MyPageBase[] { new Page1(), new Page2() };
return pages;
}
}
The Base class for the Pages
class MyPageBase:ContentPage
{
public StackLayout FinalStack { get; set; }
}
CarouselPageIndicator
public class CarouselPageIndicator : StackLayout
{
public CarouselPageIndicator(int currentIndex, int totalItems, string sourceIndicator, string souceEmptyIndicator)
{
this.Orientation = StackOrientation.Horizontal;
this.HorizontalOptions = LayoutOptions.CenterAndExpand;
for (int i = 0; i < totalItems; i++)
{
var image = new Image();
if (i == currentIndex)
image.Source = sourceIndicator;
else
image.Source = souceEmptyIndicator;
this.Children.Add(image);
}
this.Padding = new Thickness(10);
}
}
And for the n-Pages
class Page1:MyPageBase
{
public Page1()
{
var layout = new StackLayout
{
Children = {
new Label{Text="Page 1"}
}
};
this.FinalStack = layout;
this.Content = FinalStack;
}
}

I was able to make a work around for the problem by hard coding the page indicators by changing CarouselChild method below:
public CarouselChild(string image, string text, int pageNumber, int pageCount)
{
var width = this.Width;
StackLayout layout = new StackLayout
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Padding = new Thickness( 40, 40, 40, 40),
BackgroundColor = Color.Black,
};
layout.Children.Add(new Image
{
Source = image,
VerticalOptions = LayoutOptions.Start,
HorizontalOptions = LayoutOptions.Center,
});
layout.Children.Add(new Label
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
Text = text,
FontSize = 36,
LineBreakMode = LineBreakMode.WordWrap,
});
layout.Children.Add(CarouselPageIndicator(pageNumber, pageCount));
this.Content = layout;
}
internal StackLayout CarouselPageIndicator(int pageNumber, int pageCount)
{
StackLayout layout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.EndAndExpand,
};
if (pageCount >= pageNumber)
{
for (int i = 1; i < pageCount + 1; i++)
{
if (i == pageNumber)
{
layout.Children.Add(new Image
{
Source = "Light.png",
});
}
else
{
layout.Children.Add(new Image
{
Source = "Dark.png",
});
}
}
}
return layout;
}

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;
}
}

StackLayout inside StackLayout creates overflow

I'm creating a menu and this is the scene:
(I'm just hiding the items names)
So this is the code:
public Menu(List<Document> documents, MenuItem parent) {
ParentItem = parent;
Orientation = StackOrientation.Vertical;
HorizontalOptions = LayoutOptions.FillAndExpand;
VerticalOptions = LayoutOptions.FillAndExpand;
Spacing = 0;
Margin = new Thickness(0);
Padding = new Thickness(0);
if (documents.Count > 0)
foreach (Document doc in documents)
AddItem(new MenuItem(doc, this));
}
public MenuItem(Document doc, Menu parent) {
Orientation = StackOrientation.Vertical;
HorizontalOptions = LayoutOptions.FillAndExpand;
VerticalOptions = LayoutOptions.Start;
BackgroundColor = Color.Transparent;
Spacing = 0;
Margin = new Thickness(0);
Padding = new Thickness(0);
Document = doc;
Parent = parent;
Head = new MenuItemHead(doc);
var bdy = new StackLayout() {
Orientation = StackOrientation.Vertical,
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Transparent,
Spacing = 0,
Margin = new Thickness(0),
Padding = new Thickness(15, 0, 0, 0)
};
bdy.Children.Add(new Menu(doc.Documents, this));
Body = bdy;
Active = false;
if (!doc.IsFolderOpen) {
var tapped = new TapGestureRecognizer();
tapped.Tapped += (s, e) => {
bool wasActive = Active;
parent.CollapseItems();
if (!wasActive) Show();
};
Head.GestureRecognizers.Add(tapped);
} else {
if (doc.Documents.Count > 0) {
var tapped = new TapGestureRecognizer();
tapped.Tapped += async (s, e) => {
await MenuView.Push(new Menu(doc.Documents, this));
};
Head.GestureRecognizers.Add(tapped);
}
}
}
Why the menu item body is overflowing? I don't get it, maybe I'm missing something.
If you check the Microsoft Docs for a StackLayout
You will find out that your StackLayout has a default spacing of 6.
Setting the Spacing to 0 should do the trick for you.

programatically binding a listview in xamarin c#

I want to create a listview in Xamarin portable,
the item source of the listview is List<String> and my datatemplate of the listview is prepared by this function,
private DataTemplate createItemtemplate()
{
try
{
Label lbl_binding = new Label()
{
TextColor = Color.Red,
FontSize = 16,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
lbl_binding.SetBinding(Label.TextProperty, ".");
StackLayout stkBottom = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.Center,
Padding = new Thickness(0),
};
stkBottom.Children.Add(lbl_binding);
ViewCell vc = new ViewCell() {
View = stkBottom
};
DataTemplate Dp = new DataTemplate(() =>
{
return vc;
});
return Dp;
}
catch (Exception ex)
{
return null;
}
}
Now, my list view is populated, but all the labels are filled with last item, I mean the no of items are rightly populated, but all the items are filled with the last item only.
what i am doing wrong here?
lstAdmin = new ListView()
{
ItemTemplate = createItemtemplate(),
};
lstadmin.Itemsource = source;
Change your listview from List to ObservableCollection. This should do the work.
Below code useful for you as reference
Take Class members:
public class Dummy
{
public string Id { get; set; }
public string Img { get; set; }
public string Title { get; set; }
public string SubTitle { get; set; }
public string Count { get; set; }
public string Status { get; set; }
}
Create One ObservableCollectionList:
ObservableCollection<Dummy> productItems = new
ObservableCollection<Dummy>();
Add Items to the ObservableCollectionList:
productItems.Add(new Dummy() { Name = "0", Img = "Avatar.png",
Title = "Total Books", SubTitle = "Desc", Count = "50", Status =
"Total" });
productItems.Add(new Dummy() { Id = "1", Img = "Avatar.png", Title
= "Out of Stock Books", SubTitle = "Desc", Count = "40", Status =
"OutStock" });
Declare ListView:
ListView listview = new ListView()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
SeparatorVisibility = SeparatorVisibility.None,
RowHeight = 30,
};
listview.ItemTemplate = new DataTemplate(typeof(cell));
listview.ItemSelected += listviewItemSelected;
Take ViewCell and design your UI in ViewCell and assign binding
public class cell : ViewCell
{
public cell()
{
Image img = new Image()
{
VerticalOptions = LayoutOptions.StartAndExpand,
};
img.SetBinding(Image.SourceProperty, new Binding("Img"));
Label lbltitle = new Label()
{
VerticalOptions = LayoutOptions.Start,
TextColor = Color.Black
};
lbltitle.SetBinding(Label.TextProperty, new
Binding("Title"));
Label lbldesc = new Label()
{
VerticalOptions = LayoutOptions.Start,
TextColor = Color.Black
};
lbldesc.SetBinding(Label.TextProperty, new
Binding("SubTitle"));
StackLayout lblstack = new StackLayout()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Children = { lbltitle, lbldesc },
};
BoxView boxEdit = new BoxView()
{
VerticalOptions = LayoutOptions.Start,
HorizontalOptions = LayoutOptions.End,
Color = Color.Black,
HeightRequest = 20,
WidthRequest = 10
};
tapGestureEdit.Tapped += tapGestureEditTapped;
Label lblCount = new Label()
{
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
TextColor = Color.Black
};
lblCount.SetBinding(Label.TextProperty, new
Binding("Count"));
StackLayout stackCount = new StackLayout()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.EndAndExpand,
Children = { boxEdit, lblCount },
};
StackLayout stackMain = new StackLayout()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Children = { img, lblstack, stackCount },
Orientation = StackOrientation.Horizontal,
Margin = new Thickness(10, 10, 10, 10)
};
View = stackMain;
}
}
public class AdminCell : ViewCell
{
public AdminCell()
{
Label lbl_binding = new Label()
{
TextColor = Color.FromRgb(30, 144, 255),
FontSize = 16,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
lbl_binding.SetBinding(Label.TextProperty, ".");
StackLayout stkBottom = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.Center,
Padding = new Thickness(0),
};
stkBottom.Children.Add(lbl_binding);
View = stkBottom;
}
}
this code is working for me removed the template and use this cell, i still don't understand why the data template is not working
I had the same issue and after some tests I've figured out how to not get always the last item.
You should put the Label creation ,and all the other elements you want put as ItemTemplate, inside the lambda of the DataTemplate like this (example code) :
DataTemplate itemTemplate = new DataTemplate(() =>
{
Label label = new Label()
{
Margin = new Thickness(45, 0, 0, 0),
HorizontalOptions = LayoutOptions.Start,
FontSize = (double)Xamarin.Forms.Application.Current.Resources["BodyFontSize"],
HeightRequest = 20
};
label.SetBinding(Label.TextProperty, "Name");
ViewCell templateCell = new ViewCell()
{
View = label
};
return templateCell;
});
Hope that helps (helped in my case).

Xamarin bind a dynamic list of images to a grid

first of all sorry for the mess, I'm kicking my head in this for a while already, I'm kind new in xamarin and starting with difficult problems. I'm trying to add dynamically a list of random images in a grid.
currently i have the grid printing like
Name1 Detail1
filename1 filename2 filename3
Name2 Detail2
Filename1 filename2
var cell = new DataTemplate(() => {
var grid = new Grid() { Padding = 8, RowSpacing = 5, ColumnSpacing = 5 };
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Star) });
Subtitle.SetBinding(Label.TextProperty, "Images");
grid.Children.Add(labelName, 0, 0);
grid.Children.Add(labelDetail, 1, 0);
grid.Children.Add(Subtitle, 1, 1);
the cell in the end is attached to a listview
listdata.ItemTemplate = cell;
in the Object I have defined images as a string, I already tried to create another bind to a list, and create a listview of a custom call and add it to the grid, but throws an error and I can't see any description, it's something like sigsegv-without-stack trace
Also tried to instead of a grid, create a stack layout. again nothing.
CustomCell
public class CustomNocCell : ViewCell
{
public CustomCell()
{
//instantiate each of our views
var image = new Image();
var nameLabel = new Label();
var typeLabel = new Label();
var verticaLayout = new StackLayout();
var horizontalLayout = new StackLayout() { BackgroundColor = Color.Transparent };
//set bindings
nameLabel.SetBinding(Label.TextProperty, new Binding("Name"));
image.SetBinding(Image.SourceProperty, new Binding("Image"));
//Set properties for desired design
horizontalLayout.Orientation = StackOrientation.Horizontal;
horizontalLayout.HorizontalOptions = LayoutOptions.Center;
image.HorizontalOptions = LayoutOptions.End;
nameLabel.FontSize = 24;
//add views to the view hierarchy
verticaLayout.Children.Add(nameLabel);
horizontalLayout.Children.Add(verticaLayout);
horizontalLayout.Children.Add(image);
// add to parent view
View = horizontalLayout;
}
}
what I tried already that gave the error
//ListView listView = new ListView();
//listView.RowHeight = 60;
//listView.ItemTemplate = new DataTemplate(typeof(CustomNocCell));
////listView.ItemsSource = "ImagesNoc";
//listView.SetBinding(ListView.ItemsSourceProperty, "ImagesList");
ImagesList class
[Ignore]
public ListView ImagesList
{
get
{
ListView listView = new ListView();
listView.RowHeight = 60;
listView.ItemTemplate = new DataTemplate(typeof(CustomNocCell));
List<string> list = new List<string>();
if (!string.IsNullOrEmpty(Detail))
{
foreach (string str in Detail.Split(';'))
{
list.Add(str);
}
}
listView.ItemsSource = list.Select(s => new { Name = s, Image = s.ToLower() + ".png" }).ToList();
return listView;
}
}
I had the class also returning a simple List of type Name and Image that the CustomCell is waiting and nothing.
EDIT
public class TestObject
{
public string title { get; set; }
public string countries { get; set; }
}
void load()
{
List<TestObject> list = new List<TestObject>();
list.Add(new TestObject { title = "test1", countries = "esp,ita,prt" });
list.Add(new TestObject { title = "test2", countries = "esp,ita" });
list.Add(new TestObject { title = "test3", countries = "rus" });
var labelTitle = new Label()
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
VerticalOptions = LayoutOptions.StartAndExpand,
};
listdata = new ListView();
listdata.ItemsSource = list;
var cell = new DataTemplate(() => {
var grid = new Grid() { Padding = 8, RowSpacing = 5, ColumnSpacing = 5 };
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
labelTitle.SetBinding(Label.TextProperty, "title");
countriesLabel.SetBinding(Label.TextProperty, "countries"); //here i want to make a customcell to show the images, like be able to "bind" and calc the countries split the string by "," and add (name + ".png") then show the image.
// i was able to do it in a listview when i have the source in my side.. in this one i have to bind and then calc..
grid.Children.Add(labelTitle, 0, 0);
grid.Children.Add(countriesLabel, 1, 0);
});
listdata.ItemTemplate = cell;
}

Xamarin.Forms - StackLayout labels going outside device width

Can set percentage widths for elements?
The problem ive got is the 2nd label pushes the button off screen, how can you force a label to only take up the space available. I've tried setting minimum width of the elements.
new StackLayout
{
Orientation = StackOrientation.Horizontal,
Spacing = 0,
Children = {
new Label() { Text = "TITLE", HorizontalOptions = LayoutOptions.Start},
new Label() { Text = "fsdf dsfsd fsdfsdfs ewtrey vjdgyu jhy jgh tyjht rhyrt rgtu gtr ujtrey gt yu tgrt uh tyui y5r rtuyfgtj yrjhrytjtyjy jty t ruy ujh i rt", HorizontalOptions = LayoutOptions.Center, LineBreakMode = LineBreakMode.WordWrap},
new Button() { Text = "wee", HorizontalOptions = LayoutOptions.EndAndExpand}
}
},
Try Using OnSizeAllocated(double width, double height),
Code In your Xamarin.Forms Page
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
Metrics.Instance.Width=width;
Metrics.Instance.Height=height;
}
Singleton Class to Save the width and Height and Check orientation change
public class Metrics
{
private static Metrics _instance;
protected SessionData ()
{
}
public double Width{ get; set; } //Width
public double Height{ get; set; } //Height
}
Creating Stacklayout
var StackchildSize = Metrics.Width/3;
new StackLayout
{
Orientation = StackOrientation.Horizontal,
Spacing = 0,
Children = {
new Label() { Text = "TITLE", HorizontalOptions = LayoutOptions.Start
WidthRequest=stackChildSize},
new Label() { Text = "<Your Text>", WidthRequest=stackChildSize,},
new Button() { Text = "wee", HorizontalOptions = LayoutOptions.EndAndExpand,
WidthRequest=stackChildSize,}
}
},

Categories

Resources