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
Related
I am using Xamarin and C# but I suspect the problem is equally valid in a Java environment.
I have an ActionBar Activity that hosts three tabs each of which hosts a fragment. It uses a ViewPager to allow the user to swipe between the tabs.
The requirement is to programmatically screenshot each tab and then email these as attachments.
The problem is that whilst the ActionBar/ViewPager works well it also optimises the tabs - effectively it isn't creating a fragment's view until it is next in line to be shown. So, if you're on tab 0 - the first tab - then the fragment view for tab 2 is null. So it can't be screenshot.
To overcome this I have tried to set any tab/fragment that has a null view to be selected. This generates the view but because setting it to be selected does not actually render it on screen the view does not have a width or a height value so again it cannot be screenshot (this is the reason for the defensive check at the start of the code taking the screenshot).
So, I guess my question is how can I force the tab to be rendered on screen so that it is correctly filled out and can be screenshot?
My main code extracts are as follows:
private void EmailReport()
{
List <Bitmap> bitmaps = new List<Bitmap>();
List <string> summaryFiles = new List<string>();
// remember the tab we're on
var selectedTab = this.ActionBar.SelectedNavigationIndex;
// take the screenshots
for (int fragmentNumber = 0; fragmentNumber < projectFragmentPagerAdapter.Count; fragmentNumber++)
{
Android.Support.V4.App.Fragment fragment = projectFragmentPagerAdapter.GetItem(fragmentNumber);
if (fragment.View == null)
{
this.ActionBar.GetTabAt(fragmentNumber).Select();
fragment = projectFragmentPagerAdapter.GetItem(fragmentNumber);
}
bitmaps.Add(ScreenShot(fragment.View));
}
// set the active tab back
this.ActionBar.GetTabAt(selectedTab).Select();
//write the screenshots into file
int i = 0;
foreach(Bitmap bitmap in bitmaps)
{
if (bitmap != null)
summaryFiles.Add(BitmapToFile(bitmap, this.ActionBar.GetTabAt(i).Text));
i++;
}
// now send the file
EmailSupport.SendAttachments(this, summaryFiles);
}
private Bitmap ScreenShot(View fragmentRootView)
{
if (fragmentRootView == null || fragmentRootView.Width == 0 || fragmentRootView.Height == 0)
return null;
fragmentRootView.DrawingCacheEnabled = true;
//create a bitmap for the layout and then draw the view into it
Bitmap bitmap = Bitmap.CreateBitmap(fragmentRootView.Width, fragmentRootView.Height,Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
//Get the view's background
Drawable bgDrawable = fragmentRootView.Background;
if (bgDrawable!=null) // has background drawable, then draw it on the canvas
bgDrawable.Draw(canvas);
else // does not have background drawable, then draw white background on the canvas
canvas.DrawColor(Color.White);
// draw the view on the canvas
fragmentRootView.Draw(canvas);
fragmentRootView.DrawingCacheEnabled = false;
return bitmap;
}
Any help would be gratefully received.
The solution in the end was very simple. The ViewPager has a setting controlling the number of pages (fragments) that it will hold "activated". This defaults to 1. As I had 3 tabs this meant there was always one tab (fragment) out of reach.
So, whilst setting up the ViewPager do the following before the tabs are added:
reportViewPager.OffscreenPageLimit = pageCount - 1;
Or in Java
reportViewPager.setOffscreenPageLimit(pageCount - 1);
I hope this helps someone else avoid wasting hours.
I have succeeded to reestablish the link between two activities after another one ( which existed before between them) was deleted.
if (containerAsFlowchart != null)
{
for (int i = 0; i < containerAsFlowchart.Nodes.Count; i++)
{
if (containerAsFlowchart.Nodes[i] is FlowStep)
{
FlowStep fs = containerAsFlowchart.Nodes[i] as FlowStep;
if (fs.Next == null)
{
if (i < containerAsFlowchart.Nodes.Count - 1)
{
fs.Next = (FlowNode)((containerAsFlowchart.Nodes[i + 1] as FlowStep));
}
}
}
}
}
Al works fine till now, but even if the connection is made back, I am not able to visualize it in the workflow designer. If I extend or collapse an activity, or any other operation which refreshes the workflow, that pretty arrow is back there but.. is there any way to do this programmatically, and trigger this repainting straight after I delete one activity ?
For the changes to be visible on the designer you've to directly edit its ModelItem.
var modelItem = Designer.Context.Services.GetService<ModelService>().Root;
// Do changes through modelItem ...
For example, to change the DisplayName of the root activity:
modelItem.Properties["DisplayName"].Value = "New Name";
What ModelItem does is to keep every part of the workflow in an agnostic model structure, from complex types down to a simple integer. That model is use by the designer itself to print the workflow to the screen among other things (read arguments, variables, etc.).
Use the debugger and watch the model to learn more.
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.
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)
I am developing a C# application to communicate with a MUD/MOO server. Basically it takes text and displays it on the screen. At the moment i'm using a RichTextBox to display the text and I have coloured text working fine and I only have to implement URLs, however while doing this I discovered that to add URLs with custom text (e.g. NOT http://, like: Click here) I need to use a Win32 API, I can't do this... at all. This needs to work in mono on linux (and possibly mac). Is there anyway to make this work? or what alternative avenues should i pursue? (I was considering switching to HTML, but is there a good cross-platform HTML control?) (All of this HAS to be free).
Thanks in advanced.
I managed to do it in the end using:
Stack<Link> Links = new Stack<Link>();
internal class Link
{
public int starts = 0;
public int ends = 0;
public string url = "";
}
private string GetLink(RichTextBox rtb, Point point)
{
int index = rtb.GetCharIndexFromPosition(point);
foreach (Link link in Links.ToArray())
if (link.starts <= index && link.ends >= index)
return link.url;
return "";
}
just append all links to the Links stack, and use GetLink inside the MouseDown event :)
as an alternative you can use GtkTextView, it should be cross platform. You can add a hyper link styled text using code below:
TextTag tag = new TextTag("link");
tag.Foreground = "blue";
tag.Underline = Pango.Underline.Single;
textview1.Buffer.TagTable.Add(tag);
Gtk.TextIter iter = textview1.Buffer.GetIterAtOffset(0);
textview1.Buffer.InsertWithTagsByName(ref iter, "link text", "link");
where textview1 is Gtk.TextView.
you should be able to change the cursor and react on mouse clicks using "motion-notify-event" and "event-after" events.
hope this helps, regards