In a pivot based application, I have added a couple of situations where the user is navigated back to a certain pivot item. However this is done in one sudden movement. Is there a way I can do this action more smoothly, with some form of transition? Or something of the like?
The code I'm trying to use at the moment doesn't seem to work, it navigates to the selected pivot item, but not smoothly...
private void pivotTransition(int index)
{
SlideTransition slideTransition = new SlideTransition();
slideTransition.Mode = SlideTransitionMode.SlideRightFadeIn;
ITransition transition = slideTransition.GetTransition(PivotControl);
transition.Completed += delegate
{
transition.Stop();
};
PivotItem pItem = (PivotItem)PivotControl.Items[index];
PivotControl.SelectedItem = pItem;
transition.Begin();
}
I cant comment due to reputation points
but I just tried your code without the slide transistion part using a jump of 2 pivot items
private void pivotTransition(int index)
{
var pItem = (PivotItem)DisplayContainer.Items[index];
DisplayContainer.SelectedItem = pItem;
}
and the animation sequence was the same as the default sequence which seems fairly smooth to me.
If I have missed something please take a at [this question] (Windows Phone 8: How to animate page navigation?) as it looks like its using the same tool kit.
Related
In our app, we constantly reload objects from the server and then place them inside a recyclerview scrollview. Now, it does work fine but it is a big laggy. Like - it scrolls, then stops and reloads for a second, then scrolls, then reloads and so on and so forth. I have noticed that other apps do this differently. For instance, when one scrolls thorugh facebook. One can scroll all the way down and then, when the images have done loading, they get placed inside their empty layout container. So I thought this is only achievable via background threadding - so I have done that but the result is the above mentioned. It is just nowhere near as smooth as it is with facebook or any other app where you scroll throuh images. What could be the problem here:
private async Task LoadTHEBOOKAsync(PVH_TheBook_Singles vh, int position, int fkTaskId)
{
await Task.Run(() =>
{
//Loading on another Thread
int taskID = loadPhotos.pictures[position - (this.hasHeader ? 1 : 0)].taskID;
int taskIDWHenTheBook = loadPhotos.pictures[position - (this.hasHeader ? 1 : 0)].fullscreenID;
Bitmap bmp = loadImage(position);
String commentCount = KumulosHelper.Functions.Pictures.GetCountOfComments
(fkTaskId.ToString()).ToString();
String LikeCount = loadPhotos.pictures[position - (this.hasHeader ? 1 : 0)].likes.ToString();
int taskDoneId = loadPhotos.pictures[position - (this.hasHeader ? 1 : 0)].taskdoneid;
String exp = null;
if (taskID != 0)
{
exp = BookOfLife.Challenges.Libary.Instance.getTask(taskID).Experience.ToString() + "ap";
}
else
{
exp = BookOfLife.Challenges.Libary.Instance.getTask(taskIDWHenTheBook).Experience.ToString() + "ap";
}
// Setting on UI Thread
((Activity)ctx).RunOnUiThread(() =>
{
vh.Image.SetImageBitmap(bmp);
vh.txtComments.Text = commentCount;
vh.txtLikeCountBlue.Text = LikeCount;
vh.taskdoneid = taskDoneId;
vh.txtap.Text = exp;
});
});
}
As you can see, all the donwloading is done in an async task and only the placing is done on the ui thread. Is this wrong? Because I cannot seem to find any other solution to this ? I mean, I do have to set my images on the UI thread, right? So i HAVE to block it for a second until everything sits right, dont I?
Any help would be awesome.
Thanks! :)
You can check the WoWonder Android Timeline which is built in xamarin and you get more info there about the news feed system
enter image description here
I'm using iCarousel by #Nick Lookwood to load a scrollable list of "flashcards".
Each View of the iCarousel control is one flashcard. By design, I require that when a user taps the flashcard (view), the flashcard flips to reveal the behind. Before using iCarousel, I was making two separate controls, one for front and one for back, and then using UIView.Transition (with a nice Flip From Top animation) to go from front to back when a Tap was detected, or the other way round.
Adding a UITapGestureRecognizer to my View is leading to weird artifacts and not functioning as expected (overlapping controls, the next one instead of the current one flipping, no animation, etc.) and I need a different approach. I could conveniently use the Selected event in the iCarousel Delegate instead of a Tap Gesture Recognizer, but what do I do there exactly?
In essence, I would like to replace the specific view which was tapped with another but I feel this is conflicting with the whole reusable views idea. Is there nothing I can do? (Once the view is out of the screen, I am fine with it being "flipped forward" again.)
Thanks!
p
P.S. I'm using C# and Xamarin.iOS, but I can understand Obj-C and Swift code fairly well, so any help will be appreciated.
There are lots of example for iCarausal. I assume you are using this :
iCarausal
and specifically folder name "Basic iOS Example"
How about the below changes in delegate methods:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
UILabel *label = nil;
//create new view if no view is available for recycling
if (view == nil)
{
//don't do anything specific to the index within
//this `if (view == nil) {...}` statement because the view will be
//recycled and used with other index values later
view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)];
((UIImageView *)view).image = [UIImage imageNamed:#"page.png"];
view.contentMode = UIViewContentModeCenter;
//back view i have just added this apart from it there is no change made by me in this method
UIView *backView = [[UIView alloc] initWithFrame:view.bounds];
backView.tag = 2;
[backView setBackgroundColor:[UIColor redColor]];
[view addSubview:backView];
[backView setHidden:YES];
//back view
label = [[UILabel alloc] initWithFrame:view.bounds];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [label.font fontWithSize:50];
label.tag = 1;
[view addSubview:label];
}
else
{
//get a reference to the label in the recycled view
label = (UILabel *)[view viewWithTag:1];
}
//set item label
//remember to always set any properties of your carousel item
//views outside of the `if (view == nil) {...}` check otherwise
//you'll get weird issues with carousel item content appearing
//in the wrong place in the carousel
label.text = [_items[index] stringValue];
return view;
}
and implementing didSelect delegate as below:
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index{
UIView *frontview = [carousel itemViewAtIndex:index];
UIView *backView = [frontview viewWithTag:2];
BOOL isInFront = NO;
if (backView.hidden == NO) {
isInFront = YES;
}
[UIView transitionWithView: isInFront ? backView : frontview
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[backView setHidden:isInFront];
}
completion:nil];
}
You should write your code more structured, it was an example to show you that you can acheive what you want with iCarausal.
Basically, what I'm trying to do is to create a window with list of images and large image view box. If user points at one of the images in the list, imagebox should display it, otherwise it should display live feed from a webcam.
I'm trying to achieve that by using ImageGrabbed event of EmguCV.Capture, and a field that stores index of the currently viewed image. Camera feed works alright, however, when I move the mouse over listbox, image view merely stops updating. It stays stuck at the last frame it saw, and doesn't display the image I'm pointing at. I've checked that the list has images in it, that index is correct, and that image coming from the camera is different from ones saved in the list. Also, same behavior happens when I use vanila PictureBox.
See the code (stripped of extra parts) below.
Initialization:
int ViewedFrame = -1;
var Frames = new List<Image<Rgb, byte>>();
// This list will have some images added to it along the way.
// They will be displayed in a custom drawn ListBox bound to the list.
Camera = new Emgu.CV.Capture(cameraid);
Camera.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, width);
Camera.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, height);
Camera.ImageGrabbed += UpdateCamera;
Camera.Start();
Frame capture:
private void UpdateCamera(object sender, System.EventArgs ev)
{
if (ViewedFrame == -1)
Preview.Image = Camera.RetrieveBgrFrame();
else
// !!! this line has no apparent effect, image in the ImageBox is still the same
Preview.Image = Frames[ViewedFrame];
}
Mouse handling:
private void FrameList_MouseMove(object sender, MouseEventArgs e)
{
int index = FrameList.IndexFromPoint(e.Location);
if (index == ListBox.NoMatches)
ViewedFrame = -1;
else if (index != ViewedFrame)
{
ViewedFrame = index;
}
}
private void FrameList_MouseLeave(object sender, EventArgs e)
{
ViewedFrame = -1;
}
UPD: I tried adding Preview.Update() and Preview.Refresh() into the same branch as Frames[ViewedFrame], and after the conditional operator. In first case it doesn't have any effect. In second case nothing is shown at all. In case the ImageBox can't keep up updating itself, I enabled doublebuffering, but that didn't help either. Moreover, after I hover the mouse over an image in the list, the camera stream breaks too. The code above is the only one that's somewhat working.
I am making a simple class extending CheckedListBox that just adds a small textbox to the right of an item when it is checked. My issue is finding a good way to place the box at the correct location.
I had initially though I could use the Controls.Find() along with the ItemCheckEventArgs index to get the coordinates of the checkbox in question, and move to the right edge of the column from there. However, that did not work, and a brief look through the CheckedListBox class seemed to show that it does not actually contain any CheckBox controls, but merely draws images of them.
I then came up with the following method:
void CreateAmountBox(int index)
{
int itemsPerCol = Height/ItemHeight;
int x = GetColumn(index, itemsPerCol)*ColumnWidth - boxWidth;
int y = (index % itemsPerCol)*ItemHeight - offset;
System.Windows.Forms.TextBox NewAmountTextBox = new System.Windows.Forms.TextBox();
NewAmountTextBox.Location = new System.Drawing.Point(x, y);
NewAmountTextBox.Name = Items[index] + "Amount";
NewAmountTextBox.Size = new System.Drawing.Size(20, boxWidth);
Controls.Add(NewAmountTextBox);
}
where GetColumn(...) returns the column of the given index (from the CheckEventArgs). This works, but it feels like a hack and is not very readable.
Two other ideas I thought of:
1) I could just create all the TextBoxes at the start, and simply hide them until they are needed. Controls like these are all created dynamically throughout the rest of the program however, and I don't want these ones to be the odd exception. It also means that some more functionality needs to be added for cases when an item is added or removed.
2) I could use mouse position, which of course won't work if the input is via keyboard. I don't anticipate it ever being so, but best not to leave that possibility.
With some googling, the only other way I found of possibly doing this was using the ListBoxItem and TranslatePoint method, but I haven't gotten that to work, and I'm unsure as to whether it even can with a CheckedListBox instead of a ListBox.
So, is there a simple way of finding the x and y of the checked item that I don't know of? Or am I limited to simply extracting the x and y declarations above into a method and leaving it there?
You can just use the GetItemRectangle function to accomplish that:
void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
Rectangle r = checkedListBox1.GetItemRectangle(e.Index);
TextBox newAmountTextBox = new TextBox();
newAmountTextBox.Location = new Point(r.Left, r.Top);
//...
}
I am looking for an event (or another mechanism / workaround) that I can use to know when rendering of trading cards has completed in the Pivot Viewer control. I am using the SL5 version of the control and adding to its ItemSource (via an observable collection). Currently, there is quite a lag between providing the control with data and seeing something animate on the pivot viewer control. My thread that populates ItemSource exits and after 5-10 seconds of staring at a blank screen, the user eventually sees the trading cards images. The built-in events don't support any indication of when rendering of the trading card images is in a 'ready' state.
I had the same issue so I coded up my own solution by extending the pivotviewer control: http://stevenhollidge.blogspot.ch/2012/12/pivotviewer-itemsloaded-event.html
I hope someone finds this useful!
I looked into this (talking to the PivotViewer developers) and there is currently nothing you can handle to figure out when rendering has completed.
The best option open to you may be to investigating the SL rendering performance and look for the drop after loading a collection. Not pretty and might not work anyway...
Starting point: http://msdn.microsoft.com/en-us/library/bb980092.aspx
Jason R. Shaver
Previous PM for PivotViewer
The best way I've found to detect when the visuals are loaded is to find the MultiScaleImage object and detect whether the images are "Downloading" or "Idle", as well as what the viewport of an image is:
Here's how you can get at that object on the PivotViewer in SL5:
Subclass the PivotViewer object and place the following in OnApplyTemplate() override:
PartContainer = (Grid)this.GetTemplateChild("PART_Container");
cvv = (PartContainer).Children[2] as CollectionViewerView;
if (cvv != null)
{
cvvm = ViewBehaviors.GetViewModel(cvv);
Grid container = cvv.Content as Grid;
Border viewerBorder = container.Children[1] as Border;
Grid cvGrid = viewerBorder.Child as Grid;
cvc = cvGrid.Children[0] as CollectionViewContainer;
}
Then you have a reference to cvv - the CollectionViewerView.
When you set your ItemsSource on the PivotViewer object, start a timer that will check every 300 ms or so for this:
ItemViewerView ivv = ((Grid)(((UserControl)(cvc.Content)).Content)).Children[0] as ItemViewerView;
Grid g = (((Grid)ivv.Content).Children[0] as Grid);
ContentControl cc1 = (g.Children[0] as ContentControl);
if (cc1 != null)
{
Canvas cvs = cc1.Content as Canvas;
if (cvs != null && cvs.Children.Count > 0)
{
var contentControl = cvs.Children[0] as ContentControl;
if (contentControl != null)
{
MultiScaleImage x = contentControl.Content as MultiScaleImage;
bool isIdle = x.Source != null && !x.IsDownloading && x.IsIdle;
// This could be more precise, but the origin is by default set to 99999 when a new image is loaded in - we're watching for when this value changes.
bool inViewPort = x.SubImages[x.SubImages.Count - 1].ViewportOrigin.X < 999999;
// if both of these boolean values are true, then the images will be displaying on the screen.
}
}
}
Note this is SL .dll with version 5.0.61118 (future version this code will most likely break)