Create instance of ActionBar Xamarin Android - c#

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.

Related

Call activity using intent method

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

Using Custom XAML Controls in the Xamarin.Android Project with a Keyboard Service App

I have a custom keyboard app I'm trying to write. I'd like to define the key layout as XAML control (KeyboardPage.xaml) in my shared code and then incorporate them into native code in the .Android and .iOS projects. Being primarily a desktop WPF developer, I'm comfortable with this approach.
When my MainActivity inherits from FormsAppCompatActivity or AppCompatActivity, this is pretty straight forward.
namespace MobileTestApp2.Droid
{
[Activity(Label = "MobileTestApp2", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(savedInstanceState);
Forms.Init(this, bundle);
LoadApplication(new App());
}
}
}
However, in order for the app to register as an Android keyboard service, MainActivity has to inherit from InputMethodService:
namespace TestKeyboard.Droid
{
[Service(Permission = "android.permission.BIND_INPUT_METHOD", Label = "Test Keyboard")]
[MetaData("android.view.im", Resource = "#xml/method")]
[IntentFilter(new string[] { "android.view.InputMethod" })]
public class MainActivity : InputMethodService, KeyboardView.IOnKeyboardActionListener
{
private KeyboardView keyboardView;
private Keyboard keyboard;
private bool isCaps = false;
public override View OnCreateInputView()
{
keyboardView = (KeyboardView)LayoutInflater.Inflate(Resource.Layout.Keyboard, null);
keyboard = new Keyboard(this, Resource.Xml.Qwerty);
keyboardView.Keyboard = keyboard;
keyboardView.OnKeyboardActionListener = this;
return keyboardView;
}
}
I'm not sure how to convert my XAML controls into Android controls; and how to get them to replace the Keyboard.axml and.or qwerty.xml layouts I have defined in the .Android project.
From research, I found that this is possible using the CreateSupportFragment() method and the SupportFragmentManager member. However, the SupportFragmentManager member is only available when inheriting from FormsAppCompatActivity or AppCompatActivity. I tried instantiating a local object inheriting from FormsAppCompatActivity and replacing my Keyboard.axml and qwerty.xml layouts with my converted XAML control (KeyboardPage.xaml) before I instantiated a new Keyboard object; but it didn't work. I'm not even sure if the OnCreate() method is even being called.
namespace MurrayRegisterKeys.Droid
{
public class MainActivity : InputMethodService, KeyboardView.IOnKeyboardActionListener
{
private KeyboardView keyboardView = null;
private Keyboard keyboard = null;
private bool isQwerty = false;
public override View OnCreateInputView()
{
new InnerActivity();
KeyboardView keyboardView = (KeyboardView)LayoutInflater.Inflate(Resource.Layout.Keyboard, null);
keyboard = new Keyboard(this, Resource.Xml.Keypad);
keyboardView.Keyboard = keyboard;
keyboardView.OnKeyboardActionListener = this;
return keyboardView;
}
}
public class InnerActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Forms.Init(this, bundle);
SetContentView(Resource.Layout.Keyboard);
Android.Support.V4.App.Fragment keyboardPage = new KeyboardPage().CreateSupportFragment(this);
SupportFragmentManager
.BeginTransaction()
.Replace(Resource.Xml.Qwerty, keyboardPage)
.Commit();
}
}
}
Any ideas? Is what I'm trying to do even possible? Are there alternate approaches for creating a new default keyboard service?
Thanks!

Writing to a UITextField in my storyboard but not seeing anything write to it

I am pretty new to IOS development and I am using Xamarin IOS to accomplish this.
The issue I am having is that I have a UITextField declared automatically as an outlet called 'dateInput'. What I am trying to do is write to the text property of this textfield using a string. I am trying to do this inside another method inside my ViewController class. I have instantiated a new instance of the dateInput textfield as a UITextFIeld but when I try to write to this, nothing appears in the textfield.
If I don't create an instance of the dateInput then I just get a Null exception returned. As I said, i'm pretty new so this may just be a simple fix but cannot work it out.Any help would be appreciated.
ViewController Code:
public void HandleDateChange(string dateOutput){
dateInput = new UITextField();
dateInput.Text = dateOutput;
}
And this is the code which is automatically generated for the textfield object:
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UIKit.UITextField dateInput { get; set; }
ViewDidLoad Method:
public override void ViewDidLoad()
{
base.ViewDidLoad();
testButton.TouchUpInside += (object sender, EventArgs e) =>
{
PerformSegue("dateSegue", this);
};
testLabel.Text = "ViewDidLoad";
}
The point at which the HandleDateChange method is called inside another viewcontroller:
partial void dateValueChanged(UIDatePicker sender)
{
var date = PMSimpilfied.Application.NSDateToDateTime(datePicker.Date);
var dateConversion = date.ToString("dd-MM-yyyy");
NewPmSheetViewController newPmSheetView = new NewPmSheetViewController();
newPmSheetView.HandleDateChange(dateConversion);
}
This is the crash I receive:
[https://i.imgur.com/iFCS69D.png][Crash Log]
Thanks in advance for any help!
Jamie
If you want to pass a parameter to the NewPmSheetViewController, you should not configure the UIViewController's control directly. Because before the UIViewController has been loaded, all of its controls haven't been loaded.
NewPmSheetViewController newPmSheetView = new NewPmSheetViewController(); just means you construct an instance of NewPmSheetViewController. It has not been loaded in the window, so all of its references would be null.
You should create a property in the NewPmSheetViewController, then use this property to show the dateInput's Text:
public string dateOutput { set; get; }
Moreover another error is in your dateValueChanged() when you want to pass the date string. It seems you use UIStoryboard to initialize your UIViewController, the construct method should be like this:
partial void dateValueChanged(UIDatePicker sender)
{
var date = PMSimpilfied.Application.NSDateToDateTime(datePicker.Date);
var dateConversion = date.ToString("dd-MM-yyyy");
// This identifier string can be configured in your Storyboard called "Storyboard ID"
NewPmSheetViewController newPmSheetView = Storyboard.InstantiateViewController("NewPmSheetViewController") as NewPmSheetViewController;
// Pass the parameter through this property
newPmSheetView.dateOutput = dateConversion;
// Try to show the controller on the Window
NavigationController.PushViewController(newPmSheetView, true);
}
At last in the newPmSheetView's ViewDidLoad() event show the string on the UITextField:
public override void ViewDidLoad()
{
base.ViewDidLoad();
if (dateOutput != null)
{
dateInput.Text = dateOutput;
}
}

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

Xamarin how to open another layout by clicking on new resource layout

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

Categories

Resources