NavigationView SetCheckedItem does not trigger OnNavigationItemSelected - c#

I want to select a specific item in nav drawer when application starts.
I added navigationView.SetCheckedItem(Resource.Id.nav_gallery); in visual studio default template.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;
DrawerLayout drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, Resource.String.navigation_drawer_open, Resource.String.navigation_drawer_close);
drawer.AddDrawerListener(toggle);
toggle.SyncState();
var navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
navigationView.SetNavigationItemSelectedListener(this);
navigationView.SetCheckedItem(Resource.Id.nav_gallery);
}
But OnNavigationItemSelected is not called
public bool OnNavigationItemSelected(IMenuItem item)
{
int id = item.ItemId;
if (id == Resource.Id.nav_camera)
{
// Handle the camera action
}
else if (id == Resource.Id.nav_gallery)
{
}
If I click the nav items OnNavigationItemSelected is called and everything works right.
What is the proper way to select a default item?
UPDATE
I solved it adding this line. The specific item gets clicked.
navigationView.Menu.PerformIdentifierAction(Resource.Id.nav_gallery, 0);

navigationView.getMenu().getItem(position).setChecked(true);
you can create a function
public void selectDrawerItem(int position, String tag) {
switch (position) {
case 0:
fragment = new DashboardFragment();
tvToolbarTitleLand.setText("Dashboard");
break;
//code.................
}
if (fragment != null) {
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right);
transaction.replace(R.id.flMainContainer, fragment);
transaction.addToBackStack(tag);
transaction.commit();
}
navigationView.getMenu().getItem(position).setChecked(true);
}
let me know if you have any queries about this.

select that item programmatically
public class BaseApp extends AppCompatActivity {
//define variables
protected String LOGTAG = "LOGDEBUG";
protected Toolbar toolbar;
protected NavigationView navigationView;
protected DrawerLayout drawerLayout;
private DateManager db = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
// set the dashboard at startup
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, new DashboardFragment());
fragmentTransaction.commit();
setNavDrawer();
}
//CREATE A NavDrawer() void
private void set NavDrawer(){
toolbar = (toolbar) findViewById(r.i.d.toolbar);
setsupportactionbar(toolbar);
navigationView.setNavigationItemSelected(memuItem)
{
if (menuItems.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
drawerlayout.closeDrawers();
//now checlk which items are being clicked
//and performing appropriate action
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
switch (menuItem.getItemId()) {
case R.id.home:
DashboardFragment dashboardFragment = new DashboardFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, dashboardFragment,"DASHBOARD_FRAGMENT");
fragmentTransaction.commit();
return true;

Related

Can I use MvvmCross to programmatically bind to indivdual records

I have an application where I have two vertical Linear Layouts in which I want to place editable rows. I am trying to use MvvmCross Fluent Binding to bind each record to the proper view.
public class SurveyView : MvxActivity
{
SurveyViewModel vm;
LinearLayout ItemsView;
LinearLayout CategoryView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
}
protected override void OnViewModelSet()
{
base.OnViewModelSet();
this.SetContentView(Resource.Layout.SurveyView);
vm = (SurveyViewModel)this.ViewModel;
ItemsView = FindViewById<LinearLayout>(Resource.Id.lvItems);
CategoryView = FindViewById<LinearLayout>(Resource.Id.lvCategories);
vm.PropertyChanged += vm_PropertyChanged;
this.ActionBar.Title = "Survey - " + vm.ShipperName;
vm.LoadData();
}
private void vm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Items":
LoadItems();
break;
case "Categories":
LoadCategories();
break;
}
}
private void LoadCategories()
{
CategoryView.RemoveAllViews();
foreach (ShipmentSurveyCategory Item in vm.Categories)
{
var view = LayoutInflater.Inflate(Resource.Layout.SurveyCategoryItem, null);
var set = this.CreateBindingSet<View, ShipmentSurveyCategory>();
TextView tv = view.FindViewById<TextView>(Resource.Id.txtName);
set.Bind(tv).For(v => v.Text).To(i => i.Name);
EditText et = view.FindViewById<EditText>(Resource.Id.txtWeight);
set.Bind(et).For(v => v.Text).To(i => i.Cubes).WithConversion("FloatToStringConverter");
set.Apply();
}
}
}
I get an error on the
var set = this.CreateBindingSet();
Which is
Error CS1929 'SurveyView' does not contain a definition for 'CreateBindingSet' and the best extension method overload 'MvxBindingContextOwnerExtensions.CreateBindingSet(View)' requires a receiver of type 'View'
It doesn't like the "this.". The ShipmentSurveyCategory object does implement INotifyPropertyChanged.
Can I do what I am trying to do?

How to validate a spinner in Xamarin Android

I'm trying to validate a spinner in C# in xamarin in visual studio if the user didn't select an option. similar to setError in TextView, I have seen examples in SO but all of them are for java if I'm not wrong.
This is my spinner
Spinner spinnerJobTypes = FindViewById<Spinner>(Resource.Id.spinnerJobTypes);
and this does not work for me
TextView errorText = (TextView)mySpinner.getSelectedView();
I would like to display this, if the user hasn't selected anything
else if (spinnerJobTypes.SelectedItem.ToString() == "-Select-")
{
//Display validation error
}
Any help is appreciated,
Spinner spinnerJobTypes = FindViewById<Spinner>(Resource.Id.spinnerJobTypes);
spinnerJobTypes.ItemSelected += new EventHandler<AdapterView.ItemSelectedEventArgs> (spinner_ItemSelected);
private void spinner_ItemSelected (object sender, AdapterView.ItemSelectedEventArgs e)
{
Spinner spinner = (Spinner)sender;
string toast = string.Format ("The planet is {0}", spinner.GetItemAtPosition (e.Position));
Toast.MakeText (this, toast, ToastLength.Long).Show ();
}
for reference https://developer.xamarin.com/guides/android/user_interface/spinner/
Edited:
Use this and check
errorText.SetCompoundDrawablesWithIntrinsicBounds(0, 0, Resource.Drawable.errorIcon, 0);
My Suggestion is, add an "None selected" view to the Spinner and use a bool parameter to identify whether user has selected certain item or not:
SpinnerAdapter.cs
public class SpinnerAdapter : BaseAdapter<String>
{
Context context;
List<String> list;
public SpinnerAdapter(Context c, List<String> list)
{
context = c;
this.list = list;
}
public override string this[int position] => list[position-1];
public override int Count => this.list.Count+1;
public override long GetItemId(int position)
{
return 0;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view;
if (position == 0)
{
view = LayoutInflater.From(context).Inflate(Resource.Layout.spinner_error,null);
var txtView = view.FindViewById<TextView>(Resource.Id.tvErr);
view.FindViewById<TextView>(Resource.Id.tvErr).Text = "None Selected";
//uncomment the following line if you want to show the error icon inside of spinner
//view.FindViewById<TextView>(Resource.Id.tvErr).Error = "";
}
else
{
view = convertView;
if (view == null|| view.FindViewById<TextView>(Resource.Id.tvItem)==null)
{
view = LayoutInflater.From(context).Inflate(Resource.Layout.spinner_item, null);
}
view.FindViewById<TextView>(Resource.Id.tvItem).Text = list[position-1];
}
return view;
}
}
MainActivity:
public class MainActivity : Activity
{
Spinner mSpinner;
bool validatePass=false;
TextView tvResult;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
mSpinner = FindViewById<Spinner>(Resource.Id.mSpinner);
var list = InitList();
SpinnerAdapter adapter = new SpinnerAdapter(this, list);
tvResult = FindViewById<TextView>(Resource.Id.tvResult);
mSpinner.Adapter = adapter;
mSpinner.ItemSelected += MSpinner_ItemSelected;
}
private void MSpinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
{
//use validatePass to indicate if user has selected something.
if (e.Position != 0)
{
validatePass = true;
}
else
{
validatePass = false;
}
tvResult.Text ="Validate Result: "+ validatePass.ToString();
}
private List<string> InitList()
{
List<string> list = new List<string>();
for (int i = 0; i < 15; i++)
{
list.Add("Item: " + i);
}
return list;
}
}
But if you really want to show the error icon inside the spinner, you can set the TextView.Error inside of GetView.
Here is my complete Demo:HelloSpinner.

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

From itemclick method in adapter how to change textview in the activity

I have a simple activity which textview and listview. My list view use custom adapter to display data also in the adapter i have itemClick method. I would like to change textview after clicking the list item. My problem is I don't know how to find the text view from list adapter? I'll try something like this:
TextView TeamSelect = (TextView)activity.FindViewById(Resource.Id.tvSelectPlayers);
TeamSelect.SetText("Players", TextView.BufferType.Normal);
but this give me an error:
System.NullReferenceException: Object reference not set to an instance of an object
Here is my adapter:
public HomePlayersAdapter(Activity context)
{
mInflater = LayoutInflater.From(context);
mSelectedItemsIds = new SparseBooleanArray();
this.context = context;
public override int Count //return number of items in the list
{
get { return homePlayers.Count; }
}
public override Java.Lang.Object GetItem(int position)
{
return position;
}
public Player GetObject(int position)
{
return this.homePlayers.ElementAt(position);
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
var y = (itemPos.IndexOf(position) + 1);
var item = homePlayers[position];
if (convertView == null || holder == null)
{
convertView = mInflater.Inflate(Resource.Layout.RowPlayers, null);
holder = new ViewHolder();
holder.playerName = convertView.FindViewById<TextView>(Resource.Id.tvRow); //set holder label with label list id in the view
convertView.Tag = (holder);
}
else
{
holder = (ViewHolder)convertView.Tag;
}
holder.playerName.SetText(item.firstName + " " + item.lastName, TextView.BufferType.Normal);//set data label
holder.playerName.TextSize = 30;
if (clickCount >= 15)
{
subs = 1;
Android.Widget.Toast.MakeText(context, "ok", Android.Widget.ToastLength.Short).Show();
}
else
{
subs = 0;
}
y = (itemPos.IndexOf(position) + 1);
if (itemPos.Contains(position))
{
holder.playerName.SetTextColor(mInflater.Context.Resources.GetColor(Resource.Drawable.green));
holder.playerName.SetText(y + ". " + item.firstName + " " + item.lastName, TextView.BufferType.Normal);//set data label
}
else
{ holder.playerName.SetTextColor(mInflater.Context.Resources.GetColor(Resource.Drawable.white));
}
return convertView;
}
public void itemClick(int position)
{
if (!itemPos.Contains(position))
{
clickCount++;
var selectFixtureActivity = new Intent(context, typeof(SelectPlayers));
selectFixtureActivity.PutExtra("clickCount", clickCount);
holder.playerName.SetTextColor(mInflater.Context.Resources.GetColor(Resource.Drawable.green));
itemPos.Add(position);
NotifyDataSetChanged();
insertPlayer(position);
}
else
{
clickCount--;
var selectFixtureActivity = new Intent(context, typeof(SelectPlayers));
selectFixtureActivity.PutExtra("clickCount", clickCount);
holder.playerName.SetTextColor(mInflater.Context.Resources.GetColor(Resource.Drawable.white));
deletePlayer(position);
int po = itemPos.IndexOf(position);
itemPos.RemoveAt(po);
NotifyDataSetChanged();
class ViewHolder : Java.Lang.Object
{
public TextView playerName;
}
And my activity:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.SelectPlayer);
homeListAdapter = new HomePlayersAdapter(this);
listView = FindViewById<ListView>(Resource.Id.lvSelectPlayers);
TextView TeamSelect = FindViewById<TextView>(Resource.Id.tvSelectPlayer);
listView.Adapter = homeListAdapter;
listView.ChoiceMode = ChoiceMode.Multiple;
this.listView.ChoiceMode = ChoiceMode.Multiple;
var nameHome = Intent.GetStringExtra("nameHome");
var clickCount = Intent.GetStringExtra("clickCount");
TextView homeTeam = (TextView)FindViewById(Resource.Id.tvHomeTeam);
homeTeam.SetText(nameHome, Button.BufferType.Normal);
this.listView.ItemClick += (sender, e) =>
{
homeListAdapter.itemClick(e.Position);
}
I tried do that in different way: I send clickCount variable to the activity and there in ItemClick method i tried change the text view, but clickCount var on the begining is send to the acticity but when ItemClick method finish clickCount change value to null.How can i solve this problem?
You should not access the Activity directly from the Adapter. You should set a listener on the adapter (the listener can be the Activity). This is based on the Observer pattern. It decouples the components and promotes re-usability. Then the Activity, when called, can modify its own Text View.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
ListView myListView = (ListView)findViewById(R.id.your_list);
final TextView myTextView = (TextView)findViewById(R.id.your_text);
YourAdapter adapter = new YourAdapter();
adapter.setListener(new CustomListener() { // You write this method in your adapter
#Override
public void onItemClicked(Item clickedItem) {
myListView.setText( clickedItem.toString() );
}
});
}
Or if you aren't doing anything special in the custom adapter, you can always use the built in list view listener.
myListView.setOnItemClickListener( new OnItemClick() { // This is not onClick, but onItemClick
#Override
public void onItemClicked(AdapterView<?> parent, View view, int position, long id) {
Object clickedItem = parent.getItemAtPosition(position);
myTextView.setText( clickedItem.toString() );
}
});

Load url from Activity1 to Activity2 which contains a webview

How do I load a url from firstActivity to the webpageActivity?
I would like to be able to click a button with the url from firstActivity then pass it to the webpage activity and load the url.
Here is my code: FirstActivity
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
var scisnews = FindViewById<Button> (Resource.Id.scisnewsbtn);
string scisnewsurl = "http://cis.ulster.ac.uk/news-a-events-mainmenu-70";
//labinduction.Click += (sender, e) => {
// var LabInductionI = new Intent (this, typeof(LabInduction));
// StartActivity (LabInductionI);
//};
scisnews.Click += delegate {
var ScisNewsI = new Intent (this, typeof(WebPage));
ScisNewsI.PutExtra ("scisnews", scisnewsurl);
this.StartActivity (ScisNewsI);
};
}
public class HelloWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading (WebView view, string url)
{
view.LoadUrl ("http://cis.ulster.ac.uk/news-a-events-mainmenu-70");
return true;
}
}
}
Code: WebPageActivity
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Create your application here
SetContentView (Resource.Layout.WebPageLO);
web_view = FindViewById<WebView> (Resource.Id.webview);
web_view.Settings.JavaScriptEnabled = true;
web_view.Settings.BuiltInZoomControls = true;
web_view.SetWebViewClient (new HelloWebViewClient ());
}
}
public class HelloWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading (WebView view, string url)
{
view.LoadUrl ("http://cis.ulster.ac.uk/news-a-events-mainmenu-70");
return true;
}
}
public override bool OnKeyDown (Android.Views.Keycode keyCode, Android.Views.KeyEvent e)
{
if (keyCode == Keycode.Back && web_view.CanGoBack ())
{
web_view.GoBack ();
return true;
}
return base.OnKeyDown (keyCode, e);
}
}
You generally pass information from one activity to another by using the Intent class. It looks like you are trying to, but don't have the code pulling the value out.
Here is an example:
//In your first activity
var intent = new Intent(this, typeof(WebPage));
intent.PutExtra("url", "http://cis.ulster.ac.uk/news-a-events-mainmenu-70");
StartActivity(intent);
//Then in the second activity
string url = Intent.GetStringExtra("url");
//Then you can load the page like this
web_view.LoadUrl(url);
Does this help?

Categories

Resources