Creating an auto-scroll in Xamarin - xamarin

I am creating an application in Xamarin.I want to use Auto-Scroll feature and i am not able to do that in a proper way. I am able to scroll manually. BUt i want to display the next picture automatically without scrolling.
Kindly share your views and codes.
I have used sliders for now. But i would like to know if i can do something better.
Grid SliderGrid = new Grid ();
//SliderGrid.BackgroundColor = Color.Black;
//SliderGrid.Padding = 10;
int SlidercolumnCount = Slider.Count;
RowDefinition Sliderrow = new RowDefinition ();
SliderGrid.RowDefinitions.Add (Sliderrow);
for (int j = 0; j < SlidercolumnCount; j++) {
ColumnDefinition col = new ColumnDefinition ();
SliderGrid.ColumnDefinitions.Add (col);
}
for (int i = 0; i < SlidercolumnCount; i++) {
var vetImageCol = new Image {
HeightRequest=260,
WidthRequest=360,
BindingContext = Slider [i],
Source = Slider [i].CategoryImage,
Aspect=Aspect.AspectFill,
};
Grid.SetColumn (vetImageCol, i);
SliderGrid.Children.Add (vetImageCol);
}
var SliderContent = new ScrollView {
Orientation=ScrollOrientation.Horizontal,
HorizontalOptions=LayoutOptions.FillAndExpand,
//HeightRequest=265,
Content= SliderGrid,
};

It's ok to do it with Task commands like this one:
private async void DoSomethingAsync()
{
await Task.Delay(1000);
DoSomething();
await Task.Delay(1000);
DoSomethingelse();
}
Although it's better to do it with Task return value instead of void but you get the idea

//page view is may ui scroll view
//counter for if my image focus on last image then return on 1 img
//new PointF((float)(your image size * count),your top margin or your fram y);
int count = 0;
public async void StartTimer()
{
await Task.Delay(3000); //3 sec
count += 1;
if (count == 5)
{
count = 0;
}
var bottomOffset = new PointF((float)(UIScreen.MainScreen.Bounds.Width * count),0);
pageview.SetContentOffset(bottomOffset, animated: true);
StartTimer();
}
public override void ViewDidLoad(){
StartTimer();
}

Related

How can i change of button background color on another form in xamarin

hello
for (int i = 1; i < terasmasasayisi; i++)
{
var buttonteras = new Button
{
Text = i.ToString(),
HeightRequest = 45,
WidthRequest = 45,
Margin = 5,
CornerRadius = 100,
};
buttonteras.Clicked += butonteras;
teras.Children.Add(buttonteras);
async void butonteras(object o, EventArgs args)
{
secilenmasa = buttonteras.Text;
secilenkonum = "Teras";
await Navigation.PushModalAsync(new menu());
}
}
i create multiple buttons in that way terasmasasayisi is counts how many row i have in database
and theese buttons directs me to another page on that page after clicking to a button i have to change the first buttons background color, how can i do that?
You could check the following code
Use MessagingCenter
for (int i = 1; i < 10; i++)
{
var buttonteras = new Button
{
Text = i.ToString(),
HeightRequest = 45,
WidthRequest = 45,
Margin = 5,
CornerRadius = 100,
};
buttonteras.Clicked += butonteras;
stack.Children.Add(buttonteras);
}
MessagingCenter.Subscribe<Object,View>(this,"click",(obj,view)=>
{
var childrens = stack.Children;
for (int i = 0; i < childrens.Count; i++)
{
var element = childrens[i];
var type = element.GetType();
if (element == view)
{
element.BackgroundColor = Color.Red;
}
}
});
async void butonteras(object o, EventArgs args)
{
//...
var button = o as Button;
await Navigation.PushModalAsync(new menu(button));
}
And in menu, when click button .
View Element;
public menu(View element)
{
Element = element;
InitializeComponent();
}
MessagingCenter.Send<Object,View>(this, "click",Element);
MessagingCenter.Subscribe<siparis>(this, "click", (obj) =>
{
var childrens = bahce.Children;
for (int i = 0; i < childrens.Count; i++)
{
var element = childrens[i];
var type = element.GetType();
if (element.GetType().ToString() == "Xamarin.Forms.Button")
{
element.BackgroundColor = Color.Red;
break;
}
}
});
async void bahcebuton(object o, EventArgs args)
{
secilenmasa = buttonbahce.Text;
secilenkonum = "Bahçe";
await Navigation.PushModalAsync(new menu());
}
and other form
if (masterpage.secilenkonum == "Bahçe")
{
MessagingCenter.Send<siparis>(this, "click");
}
now it doesnt makes all buttons red but now makes only first button red

Xamarin Forms Custom Renderer iOS UICollectionView scrolling in both directions / horizontal – vertical scrolling

Xamarin Forms Custom Renderer iOS UICollectionView scrolling in both directions / horizontal – vertical scrolling
Intention: Implementation of an interactive Grid which scroll horizontally and vertically .
Problem:
The grid scrolls in both direction that much laggy. After scrolling with the finger you have to wait some seconds to see an reaction of the app.
We have implemented an UICollectionView in the same way in an native swift project, and it scrolls fluently. So I think the problem is rather the way of implementation than the rendering process.
With instruments I could find out that the CoreFoundation(RunLoops) cost the most of time(11s). So I guess its a threading problem.
Why I need to customize the UICollectionViewLayout to achieve horizontal scrolling? Because I need the ability to modify the width of single cells and other customizations too.
So the only way for scrolling in both direction I see, is to customize the UICollectionViewLayout.
Implementation:
Xamarin.Forms Project:
Create Custom Control (MyGrid) in Xamarin Forms, which extends from View Class:
public class MyGrid : View
{
public MyGrid() : base()
{
}
}
Use Custom Control ( MyGrid) in Xamarin Forms ContentPage):
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:GridDemo"
x:Class="GridDemo.GridDemoPage">
<ContentPage.Content>
<local:MyGrid
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
BackgroundColor="White"/>
</ContentPage.Content>
</ContentPage>
Xamarin.iOS Project:
Implement Custom Renderer for MyGrid Class in iOS project:
[assembly: ExportRenderer(typeof(MyGrid), typeof(MyGridRenderer))]
namespace GridDemo.iOS
{
public class MyGridRenderer : ViewRenderer<MyGrid, IOSGrid>
{
public MyGridRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<MyGrid> e)
{
base.OnElementChanged(e);
if (Control == null)
{
MyGrid myGrid = (MyGrid)e.NewElement;
List<List<string>> values = myGrid.Source;
var list = new List<CustomIOSGridCell>();
var column = 0;
var row = 0;
var maxColumnLength = new int[myGrid.ColumnCount];
for (int i = 0; i < myGrid.RowCount; i++)
{
for (int j = 0; j < myGrid.ColumnCount; j++)
{
var array = values[i];
var stringLength = array.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur);
if (stringLength.Length > maxColumnLength[j])
{
maxColumnLength[j] = stringLength.Length;
}
list.Add(new CustomIOSGridCell(values[i][j));
}
}
var grid = new IOSGrid(this.Bounds, new IOSGridLayout(myGrid.ColumnCount, myGrid.RowCount, maxColumnLength));
grid.AddValues(list, myGrid.ColumnCount, myGrid.RowCount);
SetNativeControl(grid);
}
if (e.OldElement != null)
{
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null)
{
// Configure the control and subscribe to event handlers
}
}
}
}
Implement native control(iOSGrid), the corresponding Control to Custom Xamarin Forms Control (MyGrid):
public class IOSGrid : UICollectionView
{
List<CustomIOSGridCell> values = new List<CustomIOSGridCell>();
public IOSGrid(CGRect frame, IOSGridLayout collectionViewLayout) : base(frame, collectionViewLayout)
{
this.RegisterClassForCell(typeof(CustomCollectionViewCell), CustomCollectionViewCell.CellID);
BackgroundColor = UIColor.Blue;
}
public void AddValues(List<CustomIOSGridCell> values, int columncount, int rowCount)
{
this.values.AddRange(values);
this.Source = new CustomCollectionSource(this.values, rowCount, columncount);
this.ReloadData();
}
}
Implement Custom UICollectionViewLayout for IOSGrid(UICollectionView) to provide horizontal AND vertical scrolling
public class IOSGridLayout : UICollectionViewLayout
{
private Timer timer;
enum Direction { up, down ,leftRight, none }
int columnsCount = 0;
int rowCount = 0;
CoreGraphics.CGSize[] itemsSize = null;
CoreGraphics.CGSize contentSize = CoreGraphics.CGSize.Empty;
int[] maxLength;
public CGRect currentRect = CGRect.Empty;
CGPoint currentCorner = new CGPoint(-1, -1);
UICollectionViewLayoutAttributes[,] itemAttributes;
public IOSGridLayout(int columnsCount, int rowCount, int[] maxLength)
{
this.columnsCount = columnsCount;
this.rowCount = rowCount;
this.maxLength = maxLength;
itemAttributes = new UICollectionViewLayoutAttributes[rowCount, columnsCount];
}
public override void PrepareLayout()
{
if (CollectionView == null) return;
var collectionView = CollectionView;
if (collectionView.NumberOfSections() == 0) return;
if (itemAttributes.Length != collectionView.NumberOfSections())
{
generateItemAttributes(collectionView);
return;
}
for (int section = 0; section < collectionView.NumberOfSections(); section++)
{
for (int item = 0; item < collectionView.NumberOfItemsInSection(section); item++)
{
if (section != 0 && item != 0)
{
continue;
}
var attributes = LayoutAttributesForItem(NSIndexPath.FromItemSection(item, section)); }
}
}
public override CGSize CollectionViewContentSize
{
get { return contentSize; }
}
public override UICollectionViewLayoutAttributes LayoutAttributesForItem(NSIndexPath indexPath)
{
return itemAttributes[indexPath.Section, indexPath.Row];
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(CGRect rect)
{
var attributes = new List<UICollectionViewLayoutAttributes>();
// calculate actual shown attributes
return attributes.ToArray();
}
public override bool ShouldInvalidateLayoutForBoundsChange(CGRect newBounds)
{
return true;
}
private void generateItemAttributes(UICollectionView collectionView)
{
if (itemsSize?.Length != columnsCount)
{
CalculateItemSizes();
}
var column = 0;
nfloat xOffset = 0;
nfloat yOffset = 0;
nfloat contentWidth = 0;
itemAttributes = new UICollectionViewLayoutAttributes[rowCount, columnsCount];
var se = collectionView.NumberOfSections();
for (int section = 0; section < rowCount; section++)
{
var sectionAttributes = new UICollectionViewLayoutAttributes[columnsCount];
for (int index = 0; index < columnsCount; index++)
{
var itemSize = itemsSize[index];
var indexPath = NSIndexPath.FromItemSection(index, section);
var attributes = UIKit.UICollectionViewLayoutAttributes.CreateForCell(indexPath);
attributes.Frame = new CGRect(xOffset, yOffset, itemSize.Width, itemSize.Height).Integral();
if (section == 0)
{
var frame = attributes.Frame;
frame.Y = collectionView.ContentOffset.Y;
attributes.Frame = frame;
}
if (index == 0)
{
var frame = attributes.Frame;
frame.X = collectionView.ContentOffset.X;
attributes.Frame = frame;
}
sectionAttributes[index]=attributes;
xOffset += itemSize.Width;
column += 1;
if (column == columnsCount)
{
if (xOffset > contentWidth)
{
contentWidth = xOffset;
}
column = 0;
xOffset = 0;
yOffset += itemSize.Height;
}
}
for (int i = 0; i < sectionAttributes.Length; i++)
{
itemAttributes[section, i] = sectionAttributes[i];
}
}
var attr = itemAttributes[rowCount-1,columnsCount-1];
if (attr != null)
{
contentSize = new CGSize(contentWidth, attr.Frame.GetMaxY());
}
}
private void CalculateItemSizes()
{
itemsSize = new CGSize[columnsCount];
for (int index = 0; index < columnsCount; index++)
{
itemsSize[index] = SizeForItemWithColumnIndex(index);
}
}
private CGSize SizeForItemWithColumnIndex(int index)
{
// CollectionView.CellForItem()
string text = "";
for (int i = 0; i < maxLength[index]; i++)
{
text += "M";
}
NSString ma = new NSString(text);
var size = ma.StringSize(UIFont.SystemFontOfSize(14));
size.Height = 35;
return size;
}
}
Implement Custom UICollectionViewSource for IOSGrid(UICollectionView):
public class CustomCollectionSource : UICollectionViewSource
{
private readonly List<CustomIOSGridCell> values = new List<CustomIOSGridCell>();
private readonly int rowCount = 0;
private readonly int columnCount = 0;
public CustomCollectionSource(List<CustomIOSGridCell> values, int rowCount, int columnCount)
{
this.values = values;
this.rowCount = rowCount;
this.columnCount = columnCount;
}
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return rowCount;
}
public override nint NumberOfSections(UICollectionView collectionView)
{
return columnCount;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = (CustomCollectionViewCell)collectionView.DequeueReusableCell(CustomCollectionViewCell.CellID, indexPath);
cell.UpdateCell(values[indexPath.Row].Text);
return cell;
}
}
Implement Custom UICollectionViewCell for IOSGrid(UICollectionView):
public class CustomCollectionViewCell : UICollectionViewCell
{
public UILabel mainLabel;
public static NSString CellID = new NSString("customCollectionCell");
[Export("initWithFrame:")]
public CustomCollectionViewCell(CGRect frame) : base(frame)
{
// Default
ContentView.Layer.BorderColor = UIColor.Blue.CGColor;
ContentView.Layer.BorderWidth = 1.0f;
ContentView.Layer.BackgroundColor = UIColor.White.CGColor;
mainLabel = new UILabel();
ContentView.AddSubview( mainLabel );
}
public void UpdateCell(string text)
{
mainLabel.Text = text;
mainLabel.Frame = new CGRect(5, 5, ContentView.Bounds.Width, 26);
}
}

Why do I get an IndexOutOfBoundsException?

Here is my for loop, is my for loop wrong? I have not been doing loops for a very long time so I am still a beginner and I would really appreciate if someone could take a look at my problem.
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
if (tab != null) {
tab.setCustomView(mSectionsPagerAdapter.getTabView(i));
}else{
System.out.println("ERROR---TAB IS NULL---ERROR");
}
}
and here is my Count Method and Char
#Override
public int getCount() {
// Show 3 total pages.
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
// return tabTitles[position];
// getDrawable(int i) is deprecated, use getDrawable(int i, Theme theme) for min SDK >=21
// or ContextCompat.getDrawable(Context context, int id) if you want support for older versions.
// Drawable image = context.getResources().getDrawable(iconIds[position], context.getTheme());
// Drawable image = context.getResources().getDrawable(imageResId[position]);
Drawable image = ContextCompat.getDrawable(MainActivity.this, imageResId[position]);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
SpannableString sb = new SpannableString(" ");
ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}

android - how to catch touch event like game: World Search

I have a game like WorldSearch on Store, I tried using this solution:
I created matrix by array of TextView and added TouchEvent on each TextView. Then I caught event by MOTION.UP, MOTION.DOWN. When I touched on a TextView and dragged it, although it went thought other TextViews but I just could get event of first TextView.
Here is code:
private void createMetrix(){
// amound of item in a row and column
int itemNum = 10;
// calculate size of item
ScreenDimension screenDimension = Utilities.getFinalScreenDimension(this);
int itemSize = screenDimension.screenWidth / 10;
// mContentLinear has VERTICAL orientation
// then adding children linear layouts, these layout has HORIZONTAL orientation
for(int i = 0; i < itemNum; i++) {
LinearLayout theItemLayout = createHorizontalLayout(itemNum, itemSize, i);
mContentLinear.addView(theItemLayout);
}
}
private LinearLayout createHorizontalLayout(int itemNum, int itemSize, int row) {
LinearLayout theLinear = new LinearLayout(this);
theLinear.setOrientation(LinearLayout.HORIZONTAL);
theLinear.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemSize));
for(int i = 0; i < itemNum; i++){
// add item metrix into linear layout having HORIZONTAL orientation
TextView itemTxt = createItemMatrix(itemSize, row, i);
theLinear.addView(itemTxt);
}
return theLinear;
}
private TextView createItemMatrix(int itemSize, int row, int column) {
TextView theItemTxt = new TextView(this);
theItemTxt.setWidth(itemSize);
theItemTxt.setHeight(itemSize);
theItemTxt.setTextSize(13);
theItemTxt.setGravity(Gravity.CENTER);
theItemTxt.setText("A" + row + "" + column);
String tag = row + "|" + column;
theItemTxt.setTag(tag);
theItemTxt.setOnTouchListener(mOnTouchListener);
return theItemTxt;
}
// Listener
private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
private Rect rect;
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v == null) return true;
TextView itemTxt = (TextView)v;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
Log.d("TEXT", "MOVE DOWN: " + itemTxt.getText().toString());
return true;
case MotionEvent.ACTION_UP:
if (rect != null
&& !rect.contains(v.getLeft() + (int) event.getX(),
v.getTop() + (int) event.getY())) {
// The motion event was outside of the view, handle this as a non-click event
return true;
}
// The view was clicked.
Log.d("TEXT", "MOVE ON: " + itemTxt.getText().toString());
// TODO: do stuff
return true;
case MotionEvent.ACTION_MOVE:
Log.d("TEXT", "MOVE OUT: " + itemTxt.getText().toString());
return true;
default:
return true;
}
}
};
Does someone have any ideas on this case?
Thanks,
Ryan

How to handle list picker in Wp7

I have a list picker which is displayed in my phone application page.I have created list picker in starting of class,and i am adding the list picker in the phoneApplicationPage_loaded() method.When the page is launched the first time, ,the scenario works perfectly and its navigates further to second page.When i navigate back to previous page(containing list picker),it shows Invalid Operation Exception occured stating "Element is already the child of another element."
I want to know how to handle these scenarios?
Code is below
namespace My.Design
{
public partial class myclass : PhoneApplicationPage
{
String[] values = null;
ListPicker picker = new ListPicker();
StackPanel sp;
StackPanel mainFrame;
String statementInfo = "";
public myclass()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Phone Application Page Loaded_>>>>>>");
List<String> source = new List<String>();
displayUI();
}
public void displayUI()
{
Debug.WriteLine("About to display UI in miniStatement");
Debug.WriteLine("<-------------Data--------->");
Debug.WriteLine(statementInfo);
Debug.WriteLine("<-------------Data--------->");
int count = VisualTreeHelper.GetChildrenCount(this);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
UIElement child = (UIElement)VisualTreeHelper.GetChild(this, i);
string childTypeName = child.GetType().ToString();
Debug.WriteLine("Elements in this Child" + childTypeName);
}
}
List<String> source = new List<String>();
String[] allParams = ItemString.Split('#');
source.Add("PleaseSelect");
for (int i = 0; i < allParams.Length; i++)
{
Debug.WriteLine("All Params Length" + allParams[i]);
if (!(allParams[i].Equals("") && (!allParams[i].Equals(null))))
{
if (values != null)
{
Debug.WriteLine("Values length" + values.Length);
values[values.Length] = allParams[i];
}
else
{
Debug.WriteLine("Allparams Length" + allParams[i]);
source.Add(allParams[i]);
}
}
}
//picker = new ListPicker();
this.picker.ItemsSource = source;
mainFrame = new StackPanel();
TextBlock box = new TextBlock();
box.Text = "> DEmoClass";
box.FontSize = 40;
mainFrame.Children.Add(box);
Canvas canvas = new Canvas();
StackPanel sp = new StackPanel();
TextBlock box1 = new TextBlock();
box1.Text = "Number";
box1.HorizontalAlignment = HorizontalAlignment.Center;
box1.FontSize = 40;
SolidColorBrush scb1 = new SolidColorBrush(Colors.Black);
box1.Foreground = scb1;
sp.Children.Add(box1);
picker.Width = 400;
picker.Height = 150;
sp.Children.Add(picker);
Canvas.SetTop(sp, 150);
canvas.Children.Add(sp);
mainFrame.Children.Add(canvas);
this.ContentPanel1.Children.Add(mainFrame);
}
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
/*
Debug.WriteLine("OnNavigatingFrom>>>.>>MainPage");
if (sp != null)
{
sp.Children.Remove(picker);
}*/
base.OnNavigatingFrom(e);
}
}
}
If you are not intending to update the listpicker after navigating back from the second page add the following line in your Loaded event handler
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
this.Loaded -= PhoneApplicationPage_Loaded;
Debug.WriteLine("Phone Application Page Loaded_>>>>>>");
List<String> source = new List<String>();
displayUI();
}
i don't know why you can not use that case when app resume from tombstoned.
error happened because when you back to your page , loaded event runs again.
by the way,
Application_Activated 's argument can tell you app resumes from tombstoned or not--.
if (e.IsApplicationInstancePreserved)
{
IsTombstoning = false;
}
else
{
IsTombstoning = true;
}
I'm curious why you're creating it in code and not leaving it in XAML? Also the error is coming from the fact that you're attempting to add it twice into a location that can probably only have a single content element. What's the higher level problem you're trying to solve?

Resources