Xamarin how to open another layout by clicking on new resource layout - c#

I am new with Xamarin, but I am training by creating parking application. Now I got issue by trying to access to another layout.
This is my MainActivity.cs
[Activity(Label = "CustomActionBarParking", MainLauncher = true, Icon = "#drawable/icon", Theme ="#style/CustomActionBarTheme")]
public class MainActivity : Activity
{
private LinearLayout mBarZone;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
ActionBar.SetDisplayShowCustomEnabled(true);
SetContentView(Resource.Layout.action_bar);
mBarZone = FindViewById<LinearLayout>(Resource.Id.linearLayout2);
mBarZone.Click += (object sender, EventArgs args) =>
{
SetContentView(Resource.Layout.zones_list);
};
}}}
Here I am accessing from my menu, by clicking on "Zones" action bar. And open "zones list" layout.
From here I want to access to another Layout: vehicle_not_parked by clicking on blue zone action bar button. But I don't know where I have to initialize it, because when I initialized that in MainAcitivy class on OnCreate method, then I got error, that my object is nullable. Then I create ZonesActivity.cs which looks like this:
[Activity(Label = "CustomActionBarParking")]
public class ZonesActivity : Activity
{
private LinearLayout mBlueZone;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.zones_list);
mBlueZone = FindViewById<LinearLayout>(Resource.Id.linearLayout2);
mBlueZone.Click += (object sender, EventArgs args) =>
{
SetContentView(Resource.Layout.vehicle_not_parked);
};
}}}
But when I tryed to call this class in Main Activity class I have to deal with Bundle savedInstanceState property. I am not really know how I can from one view -> 2nd view and then -> 3rd view.

If I understand you correctly, your swapping out the layouts in the button click event? I think it would be best to start a new activity
mBarZone.Click += delegate {
StartActivity(typeof(ZonesActivity));
};
Docs on starting a new activity

Related

How to get view from main Activity

There is a class inheritor from the handler through which I control the graphic button.
To search for this button, I pass in the designer a link to the activation. But I want to pass the view there. How can I get a view from activity?
public class FlActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_fl);
toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
tabLayout = FindViewById<TabLayout>(Resource.Id.tabLayout);
viewPager = FindViewById<ViewPager>(Resource.Id.viewPager);
fpAdapter = new FpAdapter(SupportFragmentManager, null);
uiHandler = new UiHandler(this, MainLooper);
}
}
public class UiHandler : Handler
{
private Activity activity { get; }
public UiHandler(Activity a, Looper loader) : base(loader)
{
activity = a;
}
public override void HandleMessage(Message msg)
{
activity.FindViewById<ImageButton>(Resource.Id.imageButton1).SetImageResource(msg.Data.GetInt("ID", Resource.Drawable.bt_off));
}
}
If I change private Activity activity { get; } to private View view { get; }, how can I transfer the view from the main activity when creating a handler instance. What to replace this in creating a nadler object?
There are quite several ways to do this :
this.Window.DecorView.RootView;
or
this.Window.DecorView.FindViewById(Android.Resource.Id.Content);
or
this.FindViewById(Android.Resource.Id.Content);
or
this.FindViewById(Android.Resource.Id.Content).RootView;
or
((ViewGroup) this.FindViewById(Android.Resource.Id.Content)).GetChildAt(0);
Although, since it's probably a layout, not a single view, I recommend using ViewGroup instead of View (these methods returns View so you have to cast them to ViewGroup if you want)
=================
Credit to this answer

how to change navigation bar title icon on xamarin.forms ios?

i want to change navigation bar title icon on my xamarin.forms ios application.You can find requested point at the attached image.app_screenshot
You can achieve this by using Custom Renderers on Xamarin.Forms. Since each UIViewController has its own NavigationItem, you should do this in your particular page which you want to modify its LeftBarButtonItem. Here is my Renderer for you referring to:
[assembly: ExportRenderer(typeof(CustomPage), typeof(CustomPageRenderer))]
namespace UIBarButtomItemsForms.iOS
{
public class CustomPageRenderer : PageRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var navigationItem = NavigationController.TopViewController.NavigationItem;
UIBarButtonItem leftItem = new UIBarButtonItem(UIImage.FromBundle("Image.png"), UIBarButtonItemStyle.Plain, (sender, args) =>
{
});
navigationItem.SetLeftBarButtonItem(leftItem, false);
}
}
}
Then on Forms you can use this CustomPage, please notice that you should make your MainPage wrapped in a NavigationPage: MainPage = new NavigationPage(new MainPage());
Take a look at Change the Back Button: https://developer.xamarin.com/recipes/ios/content_controls/navigation_controller/change_the_back_button/

Click events for multiple pages

How do I assign click events to buttons in an app with multiple pages?
I can do it fine with a single page app, as follows:
namespace Welf
{
[Activity(Label = "Welf", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Assign click event to direct to next page (page1)
Button cmdFirst = FindViewById<Button>(Resource.Id.cmdFirst);
cmdFirst.Click += delegate
{
SetContentView(Resource.Layout.page1);
};
}
}
}
But at what point to I assign click events for buttons on other pages?
If I do the following it doesn't work, I'm guessing because the pages aren't instantiated yet so FindByView returns a null:
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Assign click event to direct to next page (page1)
Button cmdFirst = FindViewById<Button>(Resource.Id.cmdFirst);
cmdFirst.Click += delegate
{
SetContentView(Resource.Layout.page1);
};
// This assignment doesn't work
Button cmdSecond = FindViewById<Button>(Resource.Id.cmdSecond);
cmdSecond.Click += delegate
{
SetContentView(Resource.Layout.page3);
}
}
}
...and the following does work, but then I get into trouble with repeat visits to the same page because I'm adding the event a second time:
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Assign click event to direct to next page (page1)
Button cmdFirst = FindViewById<Button>(Resource.Id.cmdFirst);
cmdFirst.Click += delegate
{
SetContentView(Resource.Layout.page1);
// This click works the first time only, for obvious reasons
Button cmdSecond = FindViewById<Button>(Resource.Id.cmdSecond);
cmdSecond.Click += delegate
{
SetContentView(Resource.Layout.page3);
}
};
}
}
So how should I do it?
You should only call SetContentView() once in any activity. What you need to do here is make a new activity.
1: Right click on your project and click new item.
2: Create a new activity and a new Android layout.
3: Then in your new Activity.cs call SetContentView for your new layout you just created.
4: Then use this code to call your new activity: Intent intent = new Intent(this,typeof(mynewactivityname));
StartActivity(intent);

OnCreateView Called twice

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);
}
}

Create instance of ActionBar Xamarin Android

Iam using A ActionBar in my app. I have done something like so:-
ActionBar.SetDisplayHomeAsUpEnabled(true);
ActionBar.SetHomeButtonEnabled(true);
But I get a compilation error like:-
A object reference is required for the non-static field, method, or property 'Android.Support.V7.App.ActionBar.SetDisplayHomeAsUpEnabled(bool)'
How can I create a instance of ActionBar as it is a Abstract class?
EDIT:-
With waquaslam's solution I did this:-
public class Homescreen : ActionBarActivity
{
private DrawerLayout _drawer;
private MyActionBarDrawerToggle _drawerToggle;
private ListView _drawerList;
private static ActionBar ActionBar ;
private string _drawerTitle;
private string _title;
private string[] _planetTitles;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SupportRequestWindowFeature(WindowCompat.FeatureActionBar);
SetContentView(Resource.Layout.homescreen);
_title = _drawerTitle = Title;
_planetTitles = Resources.GetStringArray(Resource.Array.TitlesArray);
_drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
_drawerList = FindViewById<ListView>(Resource.Id.left_drawer);
_drawer.SetDrawerShadow(Resource.Drawable.drawer_shadow_dark, (int)GravityFlags.Left);
_drawerList.Adapter = new ArrayAdapter<string>(this,
Resource.Layout.drawerlistitem, _planetTitles);
_drawerList.ItemClick += (sender, args) => SelectItem(args.Position);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetHomeButtonEnabled(true);
//DrawerToggle is the animation that happens with the indicator next to the
//ActionBar icon.
_drawerToggle = new MyActionBarDrawerToggle(this, _drawer,
Resource.Drawable.ic_drawer_light,
Resource.String.DrawerOpen,
Resource.String.DrawerClose);
//You can alternatively use _drawer.DrawerClosed here
_drawerToggle.DrawerClosed += delegate
{
ActionBar.Title = _title;
//InvalidateOptionsMenu();
};
//You can alternatively use _drawer.DrawerOpened here
_drawerToggle.DrawerOpened += delegate
{
ActionBar.Title = _drawerTitle;
// InvalidateOptionsMenu();
};
_drawer.SetDrawerListener(_drawerToggle);
if (null == savedInstanceState)
SelectItem(0);
}
Now I get a NoClassDefinitionFoundError.
If you are using support.V7 then make sure your activity inherits from ActionBarActivity.
In order to get reference of ActionBar in compatibility library, you must need to use the following:
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetHomeButtonEnabled(true);
For more info, read this in which the example is based on Tabs in actionbar but using support library.

Categories

Resources