I'm currently working on a small game for android using Xamarin in Visual Studio, I have activities for the gameplay, and the game over screen. On the game over screen I want the users score to be displayed, which I get from an intent. This works perfectly the first time, but if the user chooses to restart the game, no matter what they score, the game over screen defaults their score to zero. How can I fix this so that the correct score is displayed everytime? Also I'm still fairly new to this so any help at all would be great!
Code in Game class the calls the game over screen
this.intent = new Intent(Android.App.Application.Context, typeof(GameOverAct));
this.intent.PutExtra("ThePoint", buttons.score);
this.intent.SetFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
Game Over Activity
public class GameOverAct : Microsoft.Xna.Framework.AndroidGameActivity
{
TextView score;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.layout1);
score = FindViewById<TextView>(Resource.Id.scoretext);
score.Text = "Score: " + getGameScore();
removescore();
Button restart = FindViewById<Button>(Resource.Id.restart);
restart.Click += (sender, e) =>
{
var intent = new Intent(this, typeof(Activity1));
StartActivity(intent);
};
Button mm = FindViewById<Button>(Resource.Id.mainmenu);
mm.Click += (sender, e) =>
{
var intent3 = new Intent(this, typeof(MainMenuAct));
StartActivity(intent3);
};
}
protected override void OnRestart()
{
base.OnRestart();
SetContentView(Resource.Layout.layout1);
score = FindViewById<TextView>(Resource.Id.scoretext);
score.Text = "Score: " + getGameScore();
removescore();
Button restart = FindViewById<Button>(Resource.Id.restart);
restart.Click += (sender, e) =>
{
var intent = new Intent(this, typeof(Activity1));
StartActivity(intent);
};
Button mm = FindViewById<Button>(Resource.Id.mainmenu);
mm.Click += (sender, e) =>
{
var intent3 = new Intent(this, typeof(MainMenuAct));
StartActivity(intent3);
};
}
public int getGameScore()
{
int a = Intent.GetIntExtra("ThePoint", 0);
return a;
}
public void removescore()
{
Intent.RemoveExtra("ThePoint");
}
}
Activity that runs the Game class
public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity
{
Game1 g;
//When the Game is played for the first time after launching the app, this method is called
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//Gets a Game1 object, which is the class that builds the game
this.g = new Game1();
//sets it to view
SetContentView((View)g.Services.GetService(typeof(View)));
g.Run();
}
//If the player chooses to restart, this method is called
protected override void OnRestart()
{
base.OnRestart();
this.g = new Game1();
SetContentView((View)g.Services.GetService(typeof(View)));
g.Run();
}
}
Related
For my new game button, the Game code has an error saying it doesn't take a constructor that takes 3 arguments. I have no idea how to fix it and I really need to. Anyone got any ideas please, I'm really far behind. If i can get this to work then i can actually move on at developing my game.
namespace Game1.State
{
public class menu : States
{
private List<Component> _components;
public menu(Game1 game, GraphicsDevice graphicsdevice, ContentManager content)
{
var buttonTexture = _content.Load<Texture2D>("Controls/Button");
var buttonFont = _content.Load<SpriteFont>("Fonts/font");
var newGameButton = new Button(buttonTexture, buttonFont)
{
Position = new Vector2(300, 200),
Text = "New Game",
};
newGameButton.Click += NewGameButton_Click;
var loadGameButton = new Button(buttonTexture, buttonFont)
{
Position = new Vector2(300, 250),
Text = "load Game"
};
loadGameButton.Click += LoadGameButton_Click;
var quitGameButton = new Button(buttonTexture, buttonFont)
{
Position = new Vector2(300, 300),
Text = "quit Game"
};
quitGameButton.Click += QuitGameButton_Click;
_components = new List<Component>()
{
newGameButton,
loadGameButton,
quitGameButton,
};
}
private void QuitGameButton_Click(object sender, EventArgs e)
{
_game.Exit();
}
private void LoadGameButton_Click(object sender, EventArgs e)
{
Console.WriteLine("Load Game");
}
private void NewGameButton_Click(object sender, EventArgs e)
{
_game.ChangeState(new **Game**(_game, _graphicsDevice, _content));
}
public override void Draw(GameTime gametime, SpriteBatch spritebatch)
{
spritebatch.Begin();
foreach (var Components in _components)
Draw(gametime, spritebatch);
spritebatch.End();
}
public override void PostUpdate(GameTime gametime)
{
// Remove sprites when they are no longer needed in game
}
public override void Update(GameTime gametime)
{
foreach (var Component in _components)
Update(gametime);
}
}
}
I got an issue with my Android program when updating user data on Fragment_profile. Fragment_Profile loads User profile data and contains an update button in which the button navigates to an activity called EditProfileActivity. Users can technically update the data but, after they save the updated data, the data still can't be updated. The old data still appear. I try to refresh the fragment by using OnResume() and add OnRestart on my EditProfileActivity.cs and OnPause both in fragment and activity but, still nothing. I am using Xamarin Android and develop it with C#. For more info, you can see what happened in the GIF
My issue
So far, I've tried to code, and here's my code.
Fragment_profile.cs
public class Fragment_Profile : Android.Support.V4.App.Fragment
{
public HomePageActivity m_currentActivity;
public TextView m_tv_loginname, m_tv_username, m_tv_fullname , m_tv_dob;
public Boolean isRefreshing = false;
public override void OnCreate(Bundle aSavedInstanceState)
{
base.OnCreate(aSavedInstanceState);
}
//public static Fragment_Profile NewInstance(Model.User aCurrentUser)
public static Fragment_Profile NewInstance()
{
var _frag4 = new Fragment_Profile { Arguments = new Bundle() };
return _frag4;
}
public override View OnCreateView(LayoutInflater aInflater, ViewGroup aContainer, Bundle aSavedInstanceState)
{
var _ignored = base.OnCreateView(aInflater, aContainer, aSavedInstanceState);
var view= aInflater.Inflate(Resource.Layout.FragmentProfile, null);
m_tv_loginname = view.FindViewById<TextView>(Resource.Id.tv_loginname);
m_tv_username = view.FindViewById<TextView>(Resource.Id.tv_userEmail);
m_tv_fullname = view.FindViewById<TextView>(Resource.Id.tv_fullname);
m_tv_dob = view.FindViewById<TextView>(Resource.Id.tv_dob);
Button _updateProfile = view.FindViewById<Button>(Resource.Id.btnUpdateProfile);
_updateProfile.Click += _updateProfile_Click;
m_currentActivity = (HomePageActivity)this.Activity;
if (m_currentActivity.CurrentUser != null)
{
//string = "Welcome, " + m_currentActivity.CurrentUser.UserName;
m_tv_loginname.Text = m_currentActivity.CurrentUser.LoginName;
m_tv_fullname.Text = m_currentActivity.CurrentUser.UserName;
m_tv_username.Text = m_currentActivity.CurrentUser.UserEmail;
m_tv_dob.Text = m_currentActivity.CurrentUser.DateOfBirth;
}
else
{
Toast.MakeText(Activity, "The data is not found!", ToastLength.Short).Show();
Intent i = new Intent(Context, typeof(MainActivity));
StartActivity(i);
this.Activity.Finish();
}
return view;
}
private void _updateProfile_Click(object sender, EventArgs e)
{
Intent i = new Intent(Context, typeof(EditProfileActivity));
i.PutExtra("loginname", m_currentActivity.CurrentUser.LoginName);
i.PutExtra("fullname", m_currentActivity.CurrentUser.UserName);
i.PutExtra("useremail", m_currentActivity.CurrentUser.UserEmail);
i.PutExtra("dob", m_currentActivity.CurrentUser.DateOfBirth);
StartActivity(i);
}
public override void OnResume()
{
base.OnResume();
if (isRefreshing)
{
Fragment fragment = new Fragment_Profile();
Android.Support.V4.App.FragmentManager fragmentMg = Activity.SupportFragmentManager;
FragmentTransaction fragmentTrans = fragmentMg.BeginTransaction();
fragmentTrans.Replace(Resource.Id.content_frame, fragment);
fragmentTrans.Detach(fragment);
fragmentTrans.Attach(fragment);
fragmentTrans.Commit();
//adapter.notifyDataSetChanged();
}
}
public override void OnPause()
{
base.OnPause();
isRefreshing = true;
}
}
When user click the _updateProfile button It will reference to next activity which is EditProfileActivity. Here's my EditProfileActivity.cs
public class EditProfileActivity : Activity, IOnDateSetListener
{
public EditText m_editFullName, m_editUsername, m_dob;
public TextView m_tvEmail;
public Button m_btnUpdate;
public Boolean isRefreshing = false;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.EditProfile);
m_editFullName = FindViewById<EditText>(Resource.Id.et_editfullName);
m_editUsername = FindViewById<EditText>(Resource.Id.et_editUserName);
m_tvEmail = FindViewById<TextView>(Resource.Id.tv_Email);
m_dob = FindViewById<EditText>(Resource.Id.et_editDob);
m_btnUpdate = FindViewById<Button>(Resource.Id.btn_updateprofile);
m_btnUpdate.Click += _btnUpdate_Click;
m_dob.Click += _dob_Click;
Bundle extras = Intent.Extras;
m_editFullName.Text = extras.GetString("loginname");
m_editUsername.Text = extras.GetString("fullname");
m_tvEmail.Text = extras.GetString("useremail");
m_dob.Text = extras.GetString("dob");
}
private void _btnUpdate_Click(object sender, EventArgs e)
{
try
{
Model.User _currentUser = Model.User.CheckEmailUser(m_tvEmail.Text);
_currentUser.UserName = m_editUsername.Text;
_currentUser.LoginName = m_editFullName.Text;
_currentUser.UserEmail = m_tvEmail.Text;
_currentUser.DateOfBirth = m_dob.Text;
var _updated = DBManager.Instance.Update(_currentUser);
if (_updated > 0)
{
Toast.MakeText(this, "Your account has been succesfully updated!", ToastLength.Long).Show();
Finish();
OnResume();
}
else
{
Toast.MakeText(this, "Failed to update!", ToastLength.Long).Show();
}
}
catch(Exception ex)
{
Toast.MakeText(this, ex.ToString(), ToastLength.Short).Show();
}
}
private void _dob_Click(object sender, EventArgs e)
{
var _dateTimeNow = DateTime.Now;
DatePickerDialog _datepicker = new DatePickerDialog(this, this
, _dateTimeNow.Year, _dateTimeNow.Month, _dateTimeNow.Day);
_datepicker.Show();
}
public void OnDateSet(DatePicker view, int year, int month, int dayOfMonth)
{
m_dob.Text = new DateTime(year, month + 1, dayOfMonth).ToShortDateString();
}
protected override void OnRestart()
{
base.OnRestart();
if (isRefreshing)
{
isRefreshing = false;
Finish();
}
}
protected override void OnPause()
{
base.OnPause();
if (!isRefreshing)
isRefreshing = true;
}
}
I also have read some articles that have the same problems as me but, It still confusing me and still same. I know it's a simple thing but, It took a few days for me because I am a newby and I still don't get the solution.
Do you guys have any ideas? Would you like to help me? If you don't mind please check my source code so, I know what I am missing. Thank in advance for your help!
In you Fragment, you can override the OnResume method. If you back to the fragment from Acitivty. you should query the new data from DB, then set the new value to the controls in Fragment.
public override void OnResume()
{
base.OnResume();
PHName.Text = photoDAO.GetFirstPhotos(Id).PhotoName;
}
Here is running GIF.
You can see this lifecycle about Fragment. Every time you display the Fragment,OnResume method will be executed. You get the newest data from DB, then set it to the Fragment page.
Here is my demo.
https://drive.google.com/file/d/11dROKS7TtqAaVYkG8w6ZKpqnQJRBD87E/view
I know that Android OS need paramterles constructor to recreate Activity and i could use bundle to pass some arguments if required as follows:
private void OpenOtherActivityWindow_Click(object sender, EventArgs e)
{
Intent nextActivity = new Intent(this, typeof(ThirdActivity));
Dog mydog = new Dog("mydogName");
Bundle bundle = new Bundle();
bundle.PutSerializable("mydoggy", mydog);
nextActivity.PutExtra("RowID", Convert.ToString(10));
nextActivity.PutExtras(bundle);
StartActivity(nextActivity);
}
[Activity(Label = "ThirdActivity")]
public class ThirdActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.third);
//Receive values if any from previous activity
if (!Intent.HasExtra("mydoggy")) return;
Dog tryme = (Dog)Intent.GetSerializableExtra("mydoggy");
if (!Intent.HasExtra("RowID")) return;
string text = Intent.GetStringExtra("RowID") ?? "0";
}
}
Nevertheless is it possible to create static method which would return intent for me from given parameters like?:
static Intent CreateIntent(Dog dog, int rowID)
If so could someone show me then how it could look like as opposite to whati show in my code please.
I don't know the details of your ThirdActivity, but I could achieve the similar function by creating a simple demo.
You can check the code here.
[Activity(Label = "MovieDetailActivity")]
public class MovieDetailActivity : Activity
{
public TextView textView;
public static MovieModel mMoviemodel;// define your model here
public static int mRowID; // define a int variable mRowID
public static Intent createIntent(Context context, MovieModel movie, int rowID)
{
Intent intent = new Intent(context, typeof(MovieDetailActivity));
//Pass parameters here
mMoviemodel = movie;
mRowID = rowID;
return intent;
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.detaillayout);
textView = FindViewById<TextView>(Resource.Id.info_textview);
textView.Text = "movie name:" + mMoviemodel.mMovieName + " text = " + mRowID;
}
}
Usage:
// pass your Object model
StartActivity( MovieDetailActivity.createIntent(this, movie,10));
I'm trying to create an activity with two tabs, one holding FragmentA and one holding FragmentB. Here is how I add the fragments to the Activity:
[Activity(Label = "My App")]
public class MyActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ConnectionMenu);
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab("A", new FragmentA());
AddTab("B", new FragmentB());
}
private void AddTab(string tabText, Fragment fragment)
{
var tab = ActionBar.NewTab();
tab.SetText(tabText);
tab.TabSelected += (sender, e) =>
{
e.FragmentTransaction.Replace(
Resource.Id.fragmentContainer,
fragment);
};
ActionBar.AddTab(tab);
}
}
When I rotate the orientation I want to keep fields filled out in the fragments the same. I save my data in OnSaveInstanceState and restore the data in OnActivityCreated. However, I'm noticing that the OnCreateView and OnActivityCreated methods are being called twice per rotate. The first time containing my filled in Bundle and the second time with bundle being null.
I assume that my error is in the MyActivity class but if you need more information let me know!
Given you create the fragment in your Activity.OnCreate(), you will always have 2 calls due to creating new ones in the method, and maintaining the old ones in the base.OnCreate(). What you should probably do is instead of always creating these fragments, you can search via a tag or ID for an existing fragment and use those in the Tabs instead.
i.e.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ConnectionMenu);
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
if(savedInstanceState == null)
{
AddTab("A", new FragmentA());
AddTab("B", new FragmentB());
}
else
{
Fragment a = (FragmentA)SupportFragmentManager.FindFragmentByTag("my_tag_a");
Fragment b = (FragmentB)SupportFragmentManager.FindFragmentByTag("my_tag_b");
AddTab("A", a);
AddTab("B", b);
}
}
I ended up solving the issue. as #JonDouglas said you need to make sure the tab wasn't already loaded before creating a new fragment. To do this the fragment can be loaded from the FragmentManager class using a tag. During the TabSelected event if the fragment was not previously create, a new fragment is created and added to the event FragmentTransaction using the tag. During the TabUnselected event, if the fragment was created then it is detached.
I also added in a Bundle value to hold onto the last active tab.
Here is the code I used to solve the issue.
[Activity(Label = "My App")]
public class MyActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ConnectionMenu);
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab("A", "a_fragment", () => new FragmentA());
AddTab("B", "b_fragment", () => new FragmentB());
if (savedInstanceState != null)
{
var selectedTab = savedInstanceState.GetInt(
"ActionBar.SelectedNavigationIndex", 0);
ActionBar.SetSelectedNavigationItem(selectedTab);
}
}
protected override void OnSaveInstanceState(Bundle savedInstanceState)
{
base.OnSaveInstanceState(savedInstanceState);
savedInstanceState.PutInt(
"ActionBar.SelectedNavigationIndex",
ActionBar.SelectedNavigationIndex);
}
private void AddTab<TFragment>(
string tabText,
string tag,
Func<TFragment> ctor) where TFragment : Fragment
{
var tab = ActionBar.NewTab();
tab.SetText(tabText);
tab.SetTag(tag);
var fragment = FragmentManager.FindFragmentByTag<TFragment>(tag);
tab.TabSelected += (sender, e) =>
{
if (fragment == null)
{
fragment = ctor.Invoke();
e.FragmentTransaction.Add(
Resource.Id.fragmentContainer,
fragment,
tag);
}
else
{
e.FragmentTransaction.Attach(fragment);
}
};
tab.TabUnselected += (sender, e) =>
{
if (fragment != null)
{
e.FragmentTransaction.Detach(fragment);
}
};
ActionBar.AddTab(tab);
}
}
I have basket activity when I add products from list of products.
Code of adding attributes
add.Click += delegate {
var intent = new Intent (this, typeof(CartActivity));
intent.PutExtra ("title", (string)(firstitem ["post_title"]));
intent.PutExtra ("price", (string)(firstitem ["price"] + " грн"));
intent.PutExtra ("weight", (string)(firstitem ["weight"] + "г"));
StartActivity (intent);
};
Code of receiving attributes
productname.Text = Intent.GetStringExtra("title");
price.Text = Intent.GetStringExtra("price");
weight.Text = Intent.GetStringExtra("weight");
I tried OnPause
namespace MurakamiKiev
{
[Activity(Label = "Murakami", Icon = "#drawable/logo", Theme = "#android:style/Theme.Black.NoTitleBar", ScreenOrientation = ScreenOrientation.Portrait)]
public class CartActivity : Activity
{
protected override void OnPause()
{
base.OnPause();
But when I run activity I have black screen
Did you call SetContentView() in OnCreate()?
like this
namespace MurakamiKiev
{
[Activity(Label = "Murakami", Icon = "#drawable/logo", Theme = "#android:style/Theme.Black.NoTitleBar", ScreenOrientation = ScreenOrientation.Portrait)]
public class CartActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.YourLayout);
}
}
}