Removing the BackStack Entry in MetroStyle Application - windows-8

How can I implement removing the backStack Entry in Metro style applications?

frame.SetNavigationState("1,0");
will clear the navigation history for you.

I found this answer useful:
How to clear Backstack of the frame and start afresh
Write your own NavigationService and store the navigationstate in the constructor.
string state;
public NavigationService(Frame mainFrame)
{
state = mainFrame.GetNavigationState();
_mainFrame = mainFrame;
_mainFrame.Navigating += _mainFrame_Navigating;
}
Then implement this method on the service and call it when needed:
public void ClearBackstack()
{
_mainFrame.SetNavigationState(state);
}

It doesn't seem to be possible. If you want to clear the back stack entirely (e.g. if you have a "home" button), you can use the code supplied in the LayoutAwarePage.cs file in the grid sample app.
if (this.Frame != null)
{
while (this.Frame.CanGoBack) this.Frame.GoBack();
}
While this doesn't actually clear the stack, it does take you back to the program's start location and there will be no further back-direction entries in the list. If you want to back out of a dead-end page by pressing a button, you could modify this behaviour to step back a number of pages and effectively remove the back entries.

Related

talkback not focusing by default on any view on start of inner fragment

I am using accessibility talkback functionality and I am facing one problem I have one bottom navigation in the parent activity and from the setting tab I am opening another fragment(inner fragment) using .add but the inner fragment view not getting focus by default
I also tried with . replace but it's not focusing by default on fragment creation.
open fragment code
val details = DetailsFragment.newInstance();
getSupportFragmentManager().setupForAccessibility()
getSupportFragmentManager().beginTransaction().add(android.R.id.content, details).commit()
and I used this extension function to not get focus on the previous fragment from this source
fun FragmentManager.setupForAccessibility() {
addOnBackStackChangedListener {
val lastFragmentWithView = fragments.lastOrNull { it.view != null }
for (fragment in fragments) {
if (fragment == lastFragmentWithView) {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_YES
} else {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
}
}
}
}
in normal I show that at the start of the first fragment it's focusing top first Textview and speaking automatic but in the inner fragment it's not focusing by default so what should I do to get focus by default on the first view by default
I already try
android:focusable="true"
android:focusableInTouchMode="true"
and request focus but it's not working
Please suggest me any help would be highly appriciated
I've had the best luck using
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
on the view you want to focus, or maybe
Handler().postDelayed({
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
}, someDelayMillis)
to let the system do whatever it does, and then jump in after a moment and force a focus change.
But this might be considered bad accessibility, if it's interfering with the usual navigation, and that might be why it's so hard to get focus working consistently! It might be better to just announce the new fragment (with something like view.announceForAccessibility("new fragment")) and let the user start navigating from the top. It depends on your app, it's your call
Also you probably want to use replace for your fragment instead of add, if you add a fragment on top of an old one, TalkBack can get stuck looking at the "invisible" views on the old fragment
this is my improved code that extends from #cactustictacs
//target to specific a view
binding.getRoot().postDelayed(new Runnable() {
#Override
public void run() {
binding.textView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
}, 300);
full: https://github.com/dotrinh-PM/AndroidTalkback

How to implement correct Back behaviour when using Frame.Navigate?

I have a Windows 10 Universal Windows Platform app with multiple pages, a main page, a list page and a details page and use the following to navigate to List page:
this.Frame.Navigate(typeof(ListPage), parameter);
When you are on the list page you can select an item which will launch a details page like so:
this.Frame.Navigate(typeof(DetailsPage), parameter);
Which works fine, the parameter is a selected Id or information then when using the Back button which on a Desktop app or Phone uses:
this.Frame.GoBack();
This always returns to the MainPage, that is when go from Main, to List to Details hitting back goes to Main, how do I get the GoBack to Go back to the previous page, it always seems to go home rather than the user expected behaviour, an ideas how to resolve this?
I’ve seen this before when you subscribe to the HardwareButtons.BackPressed event (or whatever the equivalent is in a Win10 UWP app) on a page, but then don’t unsubscribe from it. This means two event handlers get called when pressing Back, and both event handlers call Frame.GoBack().
I always subscribe to the event in the page’s NavigatedTo event, and unsubscribe in the NavigatedFrom event.
Could this be happening with your app?
If every page in your app should have the same behaviour, i.e. go back to the previous page, then subscribe to the back button event in the app class as suggested by #RoguePlanetoid in the comments:
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
The OnLaunched method would be a good place to do this. Don't forget to tell the OS to display the back button when the app is running on a desktop or tablet:
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
Then, add an event handler in the app class like this:
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
If you want different behaviour on different pages when back is pressed, i.e. ask the user to confirm losing their changes or something, then subscribe to the back button event in a pages OnNavigatedTo method (the code will be same as above), but make sure you unsubscribe in the page's OnNavigatedFrom event:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested -= this.OnBackPressed;
base.OnNavigatedFrom(e);
}

Unable to navigate backward using hardware key in a Universal App

I navigate forward using Frame.Navigate but when I press the hardware back key on my phone I end up on the start screen and not the page I just visited.
What might be wrong?
The reason behind your problem is, you are creating a Blank Page. If you're creating a blank page, you should define what the app has to do when the back button is fired.
Better, consider adding "Basic page". It will have backstack by nature. If you are navigating from the MainPage to the Basic Page and when you pressed back button at the Basic Page it will back to the MainPage.
I hope this could solve your problem!
If you want to use Blank Page in your application, you need to use like this on your page where you wanna override back button:
add this in your header:
using Windows.Phone.UI.Input;
and then in your constructor:
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
add this anywhere in your code:
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
this.Frame.Navigate(typeof(MainPage));
e.Handled = true;
}
You've probably forgotten to use the NavigationHelper included in the template of the universal app.
You should use it like this on every page:
NavigationHelper _navigationHelper;
public LoginPage()
{
this.InitializeComponent();
_navigationHelper = new NavigationHelper(this);
}

Win 8.1 Metro Hub Navigation

In a Hub view App with subItems Pages, my question is when I navigate to a sub item detail Page and then use command navigate goback, the view always returns to pageroot hub section01.
How can I return the MainHub Page to the original calling section that went to the sub page in the first place?
My research has been fruitless. I don't think snaps are my answer but hey any advice is appreciated.
I apologize if this is a very simple question but...
Thx.
Ok. Thanks for the answers. After looking at this problem for three days I have found a solution but not quite an answer.
this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
By enabling Navigation Caching the page will return to it's sender position. However I still desire to return to the Hub root page to a specific section. If anyone still has info on how to achieve this I would be grateful.
Seasons Greetings.
Well the newbie here has also discovered the MyHub.ScrollToSection(MyHub.Sections[0]);
This allows you to navigate directly to a section thereby bringing it into the current view.
I'm trying to find an answer to the same question. This is what I've found so far. I welcome any better solutions.
Option 1
Enable caching for the page. Note that this must be set in the page constructor or XAML. This will increase memory usage but will improve performance of your app when you navigate back to a cached page.
this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
More information here: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.page.navigationcachemode.aspx
Option 2
Manually save a controls state between page navigations. The example below is using the NavigationHelper class which is added to a new Windows Store project by default.
private void OnNavigationHelperSaveState(obj sender, SaveStateEventArgs e)
{
e.PageState["SelectedSection"] = this.MainHub.SectionsInView;
}
private void OnNavigationHelperLoadState(obj sender, LoadStateEventArgs e)
{
if (e.PageState != null)
{
var sections = e.PageState["SelectedSection"] as IList<HubSection>;
if (sections != null && sections.Any())
{
this.MainHub.ScrollToSection(sections[0]);
}
}
}
More information here: http://msdn.microsoft.com/en-gb/library/windows/apps/hh986968.aspx
you could get the Hub's descendant scrollviewer and register to scrollchanged events, store the scrollOffsets and restore them as soon as the user navigates back to the page by applying the values to the hub's scrollviewer.
I guess you would have to register to the hub's loaded event to get the descending scrollviewer (you can use an Extension method from WinRt XAML Toolkit that allows you to get the descendants by Type (e.g. Scrollviewer)
greetings!
you can delete un back stack with this :
if(this.Frame.CanGoBack)
{
this.Frame.BackStack.RemoveAt(0);
}
Have you tried what i suggested?
Unforunately Hub can't be extended to do this and access it's Scrollviewer so you have to do this with an attached Property or plainly in your page.cs .
First you register an handler for the Loaded event of your hub. In the handler you get the descending scrollviewer (with the help of WINRT XAML Toolkit maybe) and register for it's ViewChanged Event.
You store the paremeters you like somewhere they don't get deleted on page navigation and restore and attach them to the scrollviewer on backwards-navigation.
I can give you example code in the afternoon.
Greetings
It's not a ridiculous request. Try this:
public static class Concurrency
{
public static HubSection GotoSection { get; set; }
}
public class MainPage : Page
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (Concurrency.GotoSection != null)
MainHub.ScrollToSection(Concurrency.GotoSection);
Concurrency.GotoSection = null;
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Concurrency.GotoSection = MainHub.SectionsInView.First();
base.OnNavigatedFrom(e);
}
}
The reason this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled; may not be the correct solution is because you might want your hub to be refreshed. If the detail page resulted in an edit (or especially a delete) a back navigation would show stale data, and subject your app to un unexpected state if the user interacts with dead data.
Best of luck!
Enable cache mode on your page at initialization
public MainHubPage()
{
. .......
this.NavigationCacheMode = NavigationCacheMode.Enabled;
.......
}
You need to add Loaded method to Page constructor.
MainHub.Loaded += async (s, e) => await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//here you can scroll
MainHub.ScrollToSection(Loyaltysection);
});

Windows 8 app: How to pass a parameter on GoBack()?

There are a lot of samples showing how to pass a parameter on navigating to a page in Window 8 (WinRT). But I could not find any hint for passing parameters going back.
Situation: The user navigates to a details page of same data. The data is passed to the page by
Frame.Navigate(typeof(DedtailsPage), data);
How can I pass back the changed data on GoBack()?
Store the reference to data somewhere and retrieve it when you navigate back?
Also note that it's best not to pass objects other than simple strings or values between pages, since only simple types are supported for storing frame navigation state in case your app gets suspended.
I know, that this is a very bad idea, but usualy I use this:
To write:
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Tag = myObject1;
To read:
Frame rootFrame = Window.Current.Content as Frame;
var myObject2 = rootFrame.Tag;
I've made another choice to handle this.
Keep in mind that I'm a Xamarin developer (not Forms!) so i was looking for a solution which was similar for all platforms: iOS, Android and Windows.
I am a great fun of events, rather than passing objects or storing globals.
So the best choice to pass data from PageB (the child) to PageA (the parent) is to communicate via events.
Some notes: In iOS and Android, when you navigate from a "page" to "page" you can do this by passing an instance of the target object you want to navigate to. In iOS you create an instance of a custom UIViewController. In Android you create an instance of a custom Fragment. Doing this allow you to attach events handler to your instances.
An example:
var controller = new ExtrasViewController();
controller.ExtraSelected += ExtrasFragment_ExtraSelected;
controller.ExtrasCleared += ExtrasFragment_ExtrasCleared;
this.NavigationController.PushViewController(controller, false);
In WinRT Apps you are only allowed to pass "types" of target page to navigate to. So the only way to attach event handlers to your page instance is to use the OnNavigatedFrom method from the calling page. So suppose you are in PageA and want to attach some event handlers to your PageB, before it become active, simply write in your PageA "code behind":
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var page = e.Content as ExtraBody;
if(page != null)
{
page.ExtraSelected += ExtrasFragment_ExtraSelected;
page.ExtrasCleared += ExtrasFragment_ExtrasCleared;
}
}