I'm trying to implement a loading screen since GoogleMaps sometimes takes ~2 seconds to load. I tried using a RelativeLayout and putting the ImageView above the map fragment and making it ViewStates.Gone once the map loads. However, I noticed that the loading is happening on base.OnCreateBundle and not on SetUpMap() and now I'm clueless how to implement it.
private GoogleMap mMap;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Map);
mSplash = FindViewById<ImageView>(Resource.Id.splash);
SetUpMap();
}
private void SetUpMap()
{
if (mMap == null)
{
FragmentManager.FindFragmentById<MapFragment(Resource.Id.map).GetMapAsync(this);
}
}
public void OnMapReady(GoogleMap googleMap)
{
mSplash.Visibility = ViewStates.Gone;
mMap = googleMap;
mMap.MapType = GoogleMap.MapTypeSatellite;
(...)
}
If I'm not mistaken, OnMapReady is meant to be used to verify that Google Play Services is installed and active on the device. As the documentation puts it:
If Google Play services is not installed on the device, the user will
be prompted to install it, and the onMapReady(GoogleMap) method will
only be triggered when the user has installed it and returned to the
app.
OnMapReady Documentation
Alternatively, the OnMapLoaded function is meant to be called after the map has finished loading its tiles.
Called when the map has finished rendering. This will only be called
once. You must request another callback if you want to be notified
again.
OnMapLoaded Documentation
You can implement the OnMapLoaded function by first setting the callback once you have a reference to the map
mMap.setOnMapLoadedCallback(this);
Finish by simply overriding the OnMapLoaded function and handling it accordingly
#Override
public void onMapLoaded() {
if (mMap != null) {
mSplash.Visibility = ViewStates.Gone;
}
}
Remember that if you need to load the map again and need to display another splash screen, you will first need to set the callback again, as onMapLoaded is only called once per callback.
Related
Working with Xamarin Android and C# -
I want to have a download function, that just download the next item (url) from the list if the first with index 0 is finished. While Downloading, the user should be able to extend the list (add new urls for download).
My idea was to have one void OnButtonClick() (for user input) and one custom aysnc void Download() function, as well the possibility to use the "share function" (intent) to send the link directly. It is working BUT only if the user does not uses the "share function" in another app (see here: Intent.GetStringExtra). If the App gets open via this intent, the download loop gets overwritten completely. Is there a way to avoid this "bug" or another solution for a download que?
protected override void OnCreate() //gets called if activity starts
{
string catchedLink = Intent.GetStringExtra(Intent.ExtraText);
if (!String.IsNullOrEmpty(catchedLink))
{
button.Text = catchedLink;
}
}
public OnButtonClick()
{
urlList.Add(Button.Text);
}
private aysnc void Download()
{
if(IsDownloading) return;
IsDownloading = true;
do
{
await DownloadSomethingFromTheInternet(); //Let's say these two function need 2 mins to complete -
await SafeItToStorage(); //But after one minute the user adds a secound url for download
//so this loop needs to run again (see below)
urlList.Remove(urlList[0]);
} while (urlList.Count >= 1) //see here
IsDownloading = false;
}
Please leave a comment if more details are needed.
Okay it's working now:
What I did:
Save the links on the device with Preferences.Set(); not only just with a List
Added LaunchMode = Android.Content.PM.LaunchMode.SingleTask to AndroidMainfest.xml (in <activity [...] />)
Used for intent-input following code:
protected override void OnNewIntent(Intent myIntent)
{
base.OnNewIntent(myIntent);
string catchedLink = myIntent.GetStringExtra(Intent.ExtraText);
if (!String.IsNullOrEmpty(catchedLink))
{
AddVideoToQue(catchedLink);
}
}```
Thanks #Leo Zhu - MSFT for his comments and help!
So im trying to disable the back button in my app and it seems like the code im using doesnt want to respond, its hard to explain in words so I made a gif so you can see it more clearly and understand because im not sure I will be able to explain in words.
I want to disable the back button in "Activity2" but the codes I've been trying doesnt want to respond to the back button
Ive tried these codes, dont know any more solutions since im new to android development.
First attempt
public override void OnBackPressed ()
{
base.OnBackPressed ();
}
Second attempt (Both did the same thing)
public override void OnBackPressed ()
{
// base.OnBackPressed (); /* Comment this base call to avoid calling Finish() */
// Do nothing
}
What could the possible issue be here?
Try this
protected override bool OnBackButtonPressed()
{
return true;
}
Returning true means that nothing will happen.. if you return false it should still do the default operation (going back)
This is the way to do it on a contentpage atleast... Unsure about activity.
Maybe try this:
OnBackPressed in Xamarin Android
protected override void OnBackPressed()
and
[Activity ( NoHistory = true )]
did you check that pressing the back button actually enters your function?
Set a breakpoint like this :
http://imgur.com/maQCdBg
And start the application in debug mode (F5)
This code will get it to work, make sure you build the program and restart your emulator before you run it (I think thats what made it work for me)
public override void OnBackPressed()
{
// base.OnBackPressed (); /* Comment this base call to avoid calling Finish() */
// Do nothing
}
I did this and it worked perfectly
public override void OnBackPressed()
{
// This prevents a user from being able to hit the back button and leave the login page.
return;
//base.OnBackPressed();
}
Do Just Like This
public override void OnBackPressed()
{
return;
}
You can Try like this
Step 1 Add [Activity(NoHistory =true)
Step 2 Add protected override bool OnBackButtonPressed()
{
return true;
}
to your content page that you want to disable Back Button Pressed.
Although this has been posted before on StackOverflow but i think none of those reflect my issue and none of those solutions work for me either. So i'm developing a Windows Phone app and my workflow is a bit like this:
App starts
ContactPicker opens up
User selects one or multiple contacts
Based on how many contacts he selected, that many PivotItems are added into the Pivot.
My code is as follows:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
SelectContacts();
}
private async Task SelectContacts()
{
var picker = new ContactPicker();
picker.DesiredFieldsWithContactFieldType.Add(ContactFieldType.PhoneNumber);
ContactsList = (List<Contact>)await picker.PickContactsAsync();
DisplayContacts();
}
private void DisplayContacts()
{
if (ContactsList != null)
{
foreach (var item in ContactsList)
{
PivotItem pivotItem = new PivotItem();
pivotItem.Header = item.FirstName.ToString();
ContentRoot.Items.Add(pivotItem);
}
}
}
According to me, in SelectContacts() method, the app should wait at the await call and once it gets back the list of contacts, than it should execute the DisplayContacts() method but its not working. I've tried multiple other variations of this code and they aren't working either.
await the SelectContacts() method and add the DisplayContacts() method beneath it. Remove the DisplayContacts() method from SelectContacts()
await SelectContacts();
DisplayContacts();
I don't know the complete reason why but i figured it out that since i was making the PickContactsAsync() call in the OnNavigatedTo() event, that is why it wasn't working as expected. Once i moved the PickContactsAsync() call into the PageLoaded() event handler, it started working as usual.
I am trying to capture the PanGesture event, so when the user swipe with his/her finger anywhere in the view to the right, for example, the RightView shows up and when to left, the LeftView shows up.
I am using the code below. It is from Xamarin docs. I modified it a bit. My 'currView' is my outlet for the current View. When I swipe at the simulator with my mouse, the event gets captured correctly, but when stepping through (after break pointing) at the curly bracket of
if (recognizer.State != (UIGestureRecognizerState.Cancelled | UIGestureRecognizerState.Failed
{
The code loops between it and this one.
HandleDrag(gesture))
once for every pixel (I think).
I am trying to trigger the load of another view, but didn't find a spot to place it at. I tried at the
Console.WriteLine ("Here")
and at:
currView.AddGestureRecognizer (gesture);
but every time the code finishes the loop, it just ignores it and execution ends. How can I make the loading of next view work?
The line of the comment:
// NEED TO LOAD ANOTHER VIEW HERE
shows my desires spot to load another View.
Here is my code
namespace Example_Touch.Screens.iPhone.GestureRecognizers
{
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
public partial class GestureRecognizers_iPhone : UIViewController
{
private RectangleF originalImageFrame = RectangleF.Empty;
// The IntPtr and initWithCoder constructors are required for items that need
// to be able to be created from a xib rather than from managed code
public GestureRecognizers_iPhone(IntPtr handle)
: base(handle)
{
Initialize();
}
[Export("initWithCoder:")]
public GestureRecognizers_iPhone(NSCoder coder)
: base(coder)
{
Initialize();
}
public GestureRecognizers_iPhone()
: base("GestureRecognizers_iPhone", null)
{
Initialize();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
WireUpDragGestureRecognizer();
}
protected void WireUpDragGestureRecognizer()
{
// create a new tap gesture
UIPanGestureRecognizer gesture = new UIPanGestureRecognizer();
// wire up the event handler (have to use a selector)
gesture.AddTarget(() => HandleDrag(gesture));
currView.AddGestureRecognizer (gesture);
}
protected void HandleDrag(UIPanGestureRecognizer recognizer)
{
PointF offset2 = recognizer.TranslationInView(currView);
// if it's just began, cache the location of the image
if (recognizer.State != (UIGestureRecognizerState.Cancelled | UIGestureRecognizerState.Failed
| UIGestureRecognizerState.Possible))
{
Console.WriteLine ("Here");
// NEED TO LOAD ANOTHER VIEW HERE
}
}
private void Initialize()
{
}
}
}
From Apple documentation:
A panning gesture is continuous. It begins (UIGestureRecognizerStateBegan) when the minimum number of fingers allowed (minimumNumberOfTouches) has moved enough to be considered a pan. It changes (UIGestureRecognizerStateChanged) when a finger moves while at least the minimum number of fingers are pressed down. It ends (UIGestureRecognizerStateEnded) when all fingers are lifted.
Check for UIGestureRecognizerState.Ended state and if it occurs, you can load another view.
From your description it seems that you could use UISwipeGestureRecognizer instead of UIPanGestureRecognizer. The UISwipeGestureRecognizer is a discrete gesture, so you don't have to check for states, you just implement it this way:
Somewhere in your code implement the handler:
private void HandleSwipeRight()
{
// load another view
Console.WriteLine("Swipe right.");
}
And initialize the gesture recognzier in ViewDidLoad():
UISwipeGestureRecognizer swipeGestureRecognizerRight = new UISwipeGestureRecognizer(HandleSwipeRight);
swipeGestureRecognizerRight.Direction = UISwipeGestureRecognizerDirection.Right;
this.View.AddGestureRecognizer(swipeGestureRecognizerRight);
You can add another swipe gesture recognizer for a different direction.
I am working in a windows mobile application and I want to show my current location with google maps. I used the Location dll from the samples. As you see below in my code, I call the proper method for updating the map in the gps_Locationchanged event where I use the Invoke method to update the pictureboxe's image. The problem is that I can't use the main menu and the context menu of the application whenever i want. It's like they freeze until the new map finish downloading. Is there another way to do that in different thread so they can be used anytime?
void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
if (args.Position.LatitudeValid && args.Position.LongitudeValid)
{
pictureBox1.Invoke((UpdateMap)delegate()
{
center.Latitude = args.Position.Latitude;
center.Longitude = args.Position.Longitude;
LatLongToPixel(center);
image_request2(args.Position.Latitude, args.Position.Longitude);
});
}
}
Maybe something along these lines?
bool m_fetching;
void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
if (m_fetching) return;
if (args.Position.LatitudeValid && args.Position.LongitudeValid)
{
ThreadPool.QueueUserWorkItem(UpdateProc, args);
}
}
private void UpdateProc(object state)
{
m_fetching = true;
LocationChangedEventArgs args = (LocationChangedEventArgs)state;
try
{
// do this async
var image = image_request2(args.Position.Latitude, args.Position.Longitude);
// now that we have the image, do a synchronous call in the UI
pictureBox1.Invoke((UpdateMap)delegate()
{
center.Latitude = args.Position.Latitude;
center.Longitude = args.Position.Longitude;
LatLongToPixel(center);
image;
});
}
finally
{
m_fetching = false;
}
}
It's hard to say for sure, but it looks like the image_request2() method that (I assume) gets the actual image from the server is the problem. If you were to run this method on a worker thread, and provide a simple callback method that would paint the image on the screen once it's completely downloaded, this would leave your UI thread open to receive events from the user.