I try to use Conductor library but have a problem with backstack.
I have an activity with 4 buttons in bottom navigation panel.
Each of the buttons in ACTIVITY opens 1 of the 4 controllers:
- today news (root controller)
- trending news
- market news
- regulatory news
I need to add all controlers to backstack, and when i tap on the back button i must return to previous controller.
For example:
Today -> Market -> Trending
If i tap on the back button in Trending controller, i must to return to Market e.t.c.
But now activity is closing when i tap on the back in any controller.
How can i implement this behavior?
This is the code in my activity:
#Override
public void navigateToMarketHighlights() {
MarketHighlightsController marketHighlightsController = new MarketHighlightsController();
router.pushController(RouterTransaction.with(marketHighlightsController)
.popChangeHandler(new FadeChangeHandler())
.pushChangeHandler(new FadeChangeHandler()));
}
#Override
public void navigateToTrendingNow() {
TrendingNowController trendingNowController = new TrendingNowController();
router.pushController(RouterTransaction.with(trendingNowController)
.popChangeHandler(new FadeChangeHandler())
.pushChangeHandler(new FadeChangeHandler()));
}
#Override
public void navigateToTodayView() {
TodayController todayController = new TodayController();
router.pushController(RouterTransaction.with(todayController)
.popChangeHandler(new FadeChangeHandler())
.pushChangeHandler(new FadeChangeHandler()));
}
#Override
public void navigateToRegulatoryUpdatesView() {
RegulatoryUpdatesController regulatoryUpdatesController = new RegulatoryUpdatesController();
router.pushController(RouterTransaction.with(regulatoryUpdatesController)
.popChangeHandler(new FadeChangeHandler())
.pushChangeHandler(new FadeChangeHandler()));
}
I guess you just forget to handle onBackPressed() in your Activity
router.handleBack() dealing with backstack navigation, so router pops backstack if this method called and returns true, othervise (e.g backstack is empty) it returns false
#Override
public void onBackPressed() {
if (!router.handleBack()) {
super.onBackPressed();
}
}
Related
I'm using the Prism- dialog-service to show a dialog with a yes- and a no-button. This works fine. The user makes the choice and the calling page gets the dialogresult.
But it is also possible for the user to press the back-button if the dialog is present and the dialog disappears without any result to the calling page.
I know that I can override the OnBackButtonPressed-event in the MainActivity but this affects everywhere in my app.
It's important for me, that I can handle this behavior (suspend Back-Button or not) individually for each Dialog.
Therefore I'm looking for an event which will be fired if the back-button is pressed while the dialog is shown.
Similary with the OnBackButtonPressed-Event on a ContentPage.
forms project - pages:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
.
.
IsBusy="{Binding IsBusy}">
android project - MainActivity:
public override void OnBackPressed()
{
var allNotBusy = true;
foreach (var fragment in this.GetFragmentManager().Fragments)
{
var contentPage = fragment.GetType().GetProperty("Page")?.GetValue(fragment) as ContentPage;
if (contentPage.IsBusy)
{
allNotBusy = false;
}
}
if (allNotBusy)
{
base.OnBackPressed();
}
}
Consider a tabbar with "home" and "profile" buttons, when i click on either i switch between two pages, on the "home" page the user can navigate multiple times up in the navigationstack still having the focus on the "home" tab indicating that this is where the user came from.
Now, on iOS whenever the user clicks on "home" from high up in the navigationstack the user is popped to root and all is well, this is not the case on android however, on android the user has to pop one page at a time by clicking on the backbutton to get to the root.
Is this intended behavior, am i doing something wrong, does someone have a clue as to what i can do to get the desired behavior?
This is the intended behavior between iOS and Android .
If you need to make the Android has the same effect with iOS, you need to custom TabbedPageRenderer to achieve that. And the bottom tab bar effect can custom a FreshTabbedNavigationContainer . Last, we will use MessagingCenter to send message to Forms to pop to Root Page.
For example, CustomFreshTabbedNavigationContainer class:
public class CustomFreshTabbedNavigationContainer : FreshTabbedNavigationContainer
{
public CustomFreshTabbedNavigationContainer()
{
On<Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
MessagingCenter.Subscribe<object>(this, "Hi", (sender) =>
{
// Do something whenever the "Hi" message is received
PopToRoot(true);
});
}
}
Used in App.xaml.cs:
public App()
{
InitializeComponent();
var container = new CustomFreshTabbedNavigationContainer();
container.AddTab<FirstPageModel>("Home", default);
container.AddTab<ProfilePageModel>("Profile", default);
MainPage = container;
}
Now we will create a CustomTabbedPageRenderer in Android:
public class CustomTabbedPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener
{
public CustomTabbedPageRenderer(Context context) : base(context)
{
}
int previousItemId = 0;
bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
base.OnNavigationItemSelected(item);
if (item.IsChecked)
{
if (previousItemId != item.ItemId)
{
previousItemId = item.ItemId;
}
else
{
Console.WriteLine("ok");
MessagingCenter.Send<object>(this, "Hi");
}
}
return true;
}
}
The effect:
Note: If need to have the same effect with the top Tabbar in Android, there is different code in CustomTabbedPageRenderer. You can have a look at this discussion.
I came across an issue in my android app which i have developed using ionic 4.
My scenario is if i navigate through pages and came back using toolbar back button and again navigate to another pages and came back using android hardware back button then the pages i navigated back using toolbar back button shows in middle while using hardware back button.
Page A->B->C and then on toolbar back button C->B->A
Again page navigate A->D->E and then using hardware back button page navigate E->D->B->C->B->A
Unable to maintain state.
My Code
In app.component.ts constructor
this.router.events.subscribe(event => {
const url = this.router.url //current url
if (event instanceof NavigationEnd) {
const isCurrentUrlSaved = this.navLinksArray.find((item) => { return item === url });
if (!isCurrentUrlSaved) this.navLinksArray.push(url);
}
});
ngAfterViewInit() {
this.backButtonSubscription = this.platform.backButton.subscribe(() => {
if (this.router.url === '/tabs/home') {
navigator['app'].exitApp();
} else {
if (this.navLinksArray.length > 1) {
this.navLinksArray.pop();
const index = this.navLinksArray.length - 1;
const url = this.navLinksArray[index];
this.navCtrl.navigateBack(url);
}
}
});
}
}
Thanks in advance.
I think, this.navCtrl.navigateBack(url); is pushing pages again like behavior is asynchronous just assuming.
Why dont you just pop the navigated page, lets say you have a generic function
ngAfterViewInit() {
static BackButton(platform:Platform,navCtrl:NavController){
platform.registerBackButtonAction(() => {
navCtrl.pop();
}, 0)
}
}
and from the navigated page component just call, which must have
constructor(public navCtrl: NavController,public platform:Platform){}, defined and then call generic method BackButton(this.platform,this.navCtrl) in same navigated page component.
I'm writing a mobile application using cordova 3.6, this app just open an external url corresponding to the mobile version of my website
var ref = window.open('http://www.stackoverflow.com', '_self', 'location=no');
If a use _self as the target, the back button behavior is fine forme as it works correctly within browesed pages but the problem is that the last back in the history stack done go back on my index page and then open once again my url ! Also the events on the window doesn't work. How to exit?
var ref = window.open('http://www.stackoverflow.com', '_blank', 'location=no');
If a use _self as the target, the back button behavior is not the same. There is no back possible within browsed pages, just a back on the index page whatever we are. How can I modify the behavior to have the same as the _self?
I am stuck with these 2 solutions :(
Note: I saw this similar question but the suggested code
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
closeDialog();
}
});
no more exists in cordova InAppBrowser.java no more exist
I found a working solution for the "_blank" option target using cordova 3.6 thanks to the answer of Kris Erikson on this post
With those modifications the hardware back button works within pages in an InAppBrowser.
I copy hereafter his working solution
Go to src/com/org/apache/corodova/inappbrowser directory and edit the InAppBrowserDialog.java:
Change
public void onBackPressed () {
if (this.inAppBrowser == null) {
this.dismiss();
} else {
// better to go through the in inAppBrowser
// because it does a clean up
this.inAppBrowser.closeDialog();
}
}
to
public void onBackPressed () {
if (this.inAppBrowser == null) {
this.dismiss();
} else {
if (this.inAppBrowser.canGoBack()) {
this.inAppBrowser.goBack();
} else {
this.inAppBrowser.closeDialog();
}
}
}
Then go to InAppBrowser and find the goBack function, change:
/**
* Checks to see if it is possible to go back one page in history, then does so.
*/
private void goBack() {
if (this.inAppWebView.canGoBack()) {
this.inAppWebView.goBack();
}
}
to
/**
* Checks to see if it is possible to go back one page in history, then does so.
*/
public void goBack() {
if (this.inAppWebView.canGoBack()) {
this.inAppWebView.goBack();
}
}
public boolean canGoBack() {
return this.inAppWebView.canGoBack();
}
Please post if you find a better solution avoiding to modify the java code
I'm trying to implement PlayHaven's SDK in my Android application and while I do get Interstital ads, I cannot seem to capture the event of content dismissed.
I do get a log when the content is loaded.
This is what I've tried:
PlayHaven.configure(this, R.string.token, R.string.secret);
OpenRequest open = new OpenRequest();
open.send(this);
placement = new Placement("some_placement");
placement.setListener(pl); //PlacementListener
placement.preload(this);
The PlacementListener(pl) implementation:
private PlacementListener pl = new PlacementListener() {
#Override
public void contentLoaded(Placement placement) {
Log.i(TAG_PH, "PlayHaven contentLoaded");//this log is displayed
startActivity(FullScreen.createIntent(Splash.this,placement));
}
#Override
public void contentFailed(Placement placement, PlayHavenException e) {
Log.i(TAG_PH, "PlayHaven contentFailed");
}
#Override
public void contentDismissed(Placement placement, DismissType dismissType,
Bundle data) {
Log.i(TAG_PH, "PlayHaven content Dismissed");//this log is **NOT** displayed
}
};
In your onActivityResult method, you can use the following code:
String placementTag = data.getStringExtra(PlayHavenView.BUNDLE_PLACEMENT_TAG);
PlayHavenView.DismissType dismissType = (PlayHavenView.DismissType) data.getSerializableExtra(PlayHavenView.BUNDLE_DISMISS_TYPE);
You will get back dismissType. The values you are looking for are EmergencyClose (triggered when a user clicks on the X button to close a content unit), NoThanks (user declines the content unit offer), SelfClose (the Content Unit dismisses itself which happens when the SDK has to intelligently close a content unit), and BackButton (when the user presses back).