Android - Custom back button (back stack) - android-activity

I have implemented my own back stack but I'm not sure what is wrong or what I could improve, my scenario: I have a project with 2 activities, the first one is the "SplashActivity" - where I load some network data - the second one, the MainActivity.
Inside of my MainActivity I have a fragment and inside of this fragment a webview.
The back button should behave like:
When the user doesn't navigate inside of my webview, close the app.
When the user navigates in webview, use the back history of the browswer.
Here is my code:
#Override
public void onBackPressed() {
Log.d("lastfragment", String.valueOf(fragmentStack.lastElement().getId()));
if (fragmentStack.size() >= 2) {
// implement normal behavior?
Fragment activeFragment=fragmentStack.lastElement();
FragmentTransaction ft = getFragmentManager().beginTransaction();
activeFragment.onPause();
ft.remove(fragmentStack.pop());
Fragment returnToFragment=fragmentStack.lastElement();
String name = returnToFragment.getClass().getName();
if(name=="SplashScreen" || name=="LoginFragment"){
// close?
}
else {
// implement normal behavior?
returnToFragment.onResume();
ft.show(returnToFragment);
ft.commit();
}
}
else {
//close ??
}
}

Try to this code i hope solved this your problem.
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(FragmentTransaction.TRANSIT_FRAGMENT_OPEN, YOUR_FRAGMENT_OBJECT);
fragmentTransaction.addToBackStack(null); // Your fragment add to back stack
fragmentTransaction.commit();

Related

open fragment from onOptionsItemSelected , in navigation drawer, fragment overlap and stay

Bonjour,
In Android Studio, I am trying to open a fragment from the onOptionsItemSelected in a navigationdrawer, it opens the frgament but the fragment will ovelap the one who was there and it remains there.
so now when I call another fragmentit will be shown at the back so I will have many occurencse of the fragment overlapping.
I hope I am clear
this is the code i use in the MainActivity to call the fragment from onOptionsItemSelected
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//Handle item selection
switch (item.getItemId()) {
case R.id.action_apropos:e:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment_content_main,
new AnnoncesFragment(),null).commit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
if I use this code:
NavController navController = Navigation.findNavController(this,
R.id.nav_host_fragment_content_main);
navController.navigate(R.id.nav_apropos);
everything works fine but I will not be abble to pass arguments
Thanks for your help

button back to my app in the background and when you resume it starts again

I am developing an app in Xamarin.Forms, before I was trying to make a master detail page to become my MainPage when I logged in to my app, this I have already achieved. Now I have the problem that when I use the button behind the phone my app is miimiza and goes to the background which is the behavior I hope, but when I return to my app does not continue showing my master detail page, but returns to my LginPage.
It is as if my app was running twice or at least there were two instances of LoginPage existing at the same time, this is because in my LoginPage I trigger some DisplayAlert according to some messages that my page is listening through the MessaginCenter and they are they shoot twice.
Can someone tell me how I can return the same to my app on the master detail page and not restart in the strange way described?
LoginView.xaml.cs:
public partial class LogonView : ContentPage
{
LogonViewModel contexto = new LogonViewModel();
public LogonView ()
{
InitializeComponent ();
BindingContext = contexto;
MessagingCenter.Subscribe<LogonViewModel>(this, "ErrorCredentials", async (sender) =>
{
await DisplayAlert("Error", "Email or password is incorrect.", "Ok");
}
);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<LogonViewModel>(this, "ErrorCredentials");
}
}
Part of my ViewModel:
if (Loged)
{
App.token = token;
Application.Current.MainPage = new RootView();
}
else
{
MessagingCenter.Send(this, "ErrorCredentials");
}
Thanks.
I hope this is in Android. All you can do is, you can override the backbuttonpressed method in MainActivity for not closing on back button pressed of the entry page. like below, you can add some conditions as well.
public override void OnBackPressed()
{
Page currentPage = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
if (currentPage != null)
{
if (currentPage.GetType().Name == "HomePage" || currentPage.GetType().Name == "LoginPage")
{
return;
}
}
base.OnBackPressed();
}
When you press the Home button, the application is paused and the
current state is saved, and finally the application is frozen in
whatever state it is. After this, when you start the app, it is
resumed from the last point it was saved with.
However, when you use the Back button, you keep traversing back in
the activity stack, closing one activity after another. in the end,
when you close the first activity that you opened, your application
exits. This is why whenever you close your application like this, it
gets restarted when you open it again.
Answer taken from this answer. The original question asks about the native Android platform, but it still applies here.
It means you have to Use Setting Plugin or save data in Application properties.
You have to add below code in App.xaml.cs file:
if (SettingClass.UserName == null)
MainPage = new LoginPage();
else
MainPage = new MasterDetailPage();
For Setting Plugin you can refer this link.

Preloader in Wicket Application

In a wicket application on search event it takes few secons and sometimes minutes to show the result as its a long data . I want to show a preloader while the data is fetched from the database to let the user know something is going on when they click search . I am very new to wicket application , dont understands the things very deeply but I find AjaxLazyPreloader but as I said I want to show the preloader when the search method is called ...I am sharing the SearchSubmit method ...
private void processSearchSubmit(AjaxRequestTarget ajaxRequestTarget) {
ajaxRequestTarget.add(tableHolder);
ajaxRequestTarget.add(productTableHolder);
if (zipcode == null) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showWarningToast','Please enter a zipcode')");
} else if (!ZipCodeValidator.isValid(zipcode)) {
useZones = true;
currentZone = zipcode;
ajaxRequestTarget.add(tableHolder);
if (searchProduct != null) {
ajaxRequestTarget.add(productTableHolder);
if (lstProduct.getList().size() == 0) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showErrorToast','Sorry! This product is not avialable .')");
}
}
} else if (lstMerchants.getList().size() == 0) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showWarningToast','Sorry! There are currently no services')");
}
if (ZipCodeValidator.isValid(zipcode)) {
ajaxRequestTarget.add(tableHolder);
if (searchProduct != null && !searchProduct.equals("")) {
ajaxRequestTarget.add(productTableHolder);
if (lstProduct.getList().size() == 0) {
ajaxRequestTarget
.appendJavaScript("$().toastmessage('showErrorToast','Sorry! This product is not avialable in this zip code or zone.')");
}
}
}
}
I want when this method is called till the times it fetch the result data , it should show a preloader or spinner . Can anybody suggest how to do that .??
If you need to call long execution method by clicking button check this answer.
You can also use AjaxLazyLoadPanel, check this demo (it's Java part and html part)
Either use an AjaxLazyLoadPanel or an IndicatingAjaxLink/-Button. Both will work fine in either normal or Ajax calls.
To use an AjaxLazyLoadPanel: create a subclass of AjaxLazyLoadPanel which loads the panel you want to display and add it to the AjaxRequest.
IndicatingAjaxLinks just display a spinner while the request is being processed and can be used straightforward in your current application. Use this instead of the button/link you use for formsubmits now.

How to get the webview's content which was clicked on the webview

I want to add the bookmark function to my app, when I clicked on the webview which display the HTML files (The file's main part is string), I want to capture the first line of the content which display on the screen. Anyone knows the answer?
Thanks very much in advance.
-Shawn
you can identify the some content of the page as It contains img tag or not
Use this API of webView click here
WebView.HitTestResult hr = ((WebView)v).getHitTestResult();
int i=hr.getType() ;
and use the int values of this class for the content
Hope it help
If there is a link into the WebView and you want to do a specific action when the user click on this link you must catch the link click using the following code:
Somewhere in your activity code (commonly in the onCreate method):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.news_details);
...
mWebView.setWebViewClient(new MyWebViewClient());
...
}
And the WebViewClient class:
class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (DEBUG) {
Log.d(TAG, "shouldOverrideUrlLoading url= " + url);
}
if ( the url is like you want) {
// TODO: add the code to do what you need to do with the url
// the webview should not do anything with this link.
return true;
} else {
// let the webview normally handle the link
return false;
}
}
}
If what you want to do is get the actual displayed content of the WebView, there is no API to do that.
Have a look on those post:
Is it possible to get the HTML code from WebView
Retrieve webview content
Both redirect on this website:
http://lexandera.com/2009/01/extracting-html-from-a-webview/

How to close a ViewPart in Eclipse?

I have a view in Eclipse (implemented by a class which extends org.eclipse.ui.part.ViewPart) which I need to close. I mean completely close, not just hide. I want a new ViewPart instance to be created when the user (or my code) asks to open the view again.
The only method I found was IWorkbenchPage.hideView which hides the view, but does not completely dispose of it. Invoking dispose on the view has no affect, either.
BTW, my view is defined as allowMultiple="false" but I tried with true and that didn't make any difference.
Any help will be appreciated.
I found the problem eventually. If the view is open on more than one perspective, hiding it on one perspective will not close it. It is possible to iterate over all the open perspective and look for the view. Hiding it on all perspectives will close it.
I think the IWorkbenchPage.hideView() method you mentioned is the only one available to programmaticaly close a view. I also think this method name should be closeView() beacause it really close the view.
I have been using this method for a while (with allowMultiple=true views) and after debugging it seems my view.dispose() method is invoked each time I invoke hideView().
Next time I open this view again (I mean from my code and not from user interface), a new one is created by Eclipse and the createPartControl() method is invoked again.
Moreover, the call hierarchy view told me than the hideView() should call the dispose method() ....
hideView() >> releaseView() >> partRemoved() >> disposePart() >> dispose() >> doDisposePart() >> doDisposePart() >> dispose()
Hope this can help ....
One last question, how did you checked that your view was not correctly disposed ??
The org.eclipse.ui.internal.ViewFactory has a method called releaseView that I think closes the view completely (though I'm not certain). It takes an IViewReference.
You can access the ViewFactory by calling Perspective.getViewFactory, and you can access the Perspective, you then pass it an IViewReference to release the view.
IWorkbenchPage page =
Workbench.getInstance().getActiveWorkbenchWindow().getActivePage()
Perspective perspective = page.getPerspective();
String viewId = "myViewId"; //defined by you
//get the reference for your viewId
IViewReference ref = page.findViewReference(viewId);
//release the view
perspective.getViewFactory.releaseView(ref);
I overridden dispose method from IWorkbenchPart and that worked.
I had something like this in my overridden dispose method:
public void dispose() {
super.dispose();
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
if (page != null) {
IViewReference[] viewReferences = page.getViewReferences();
for (IViewReference ivr : viewReferences) {
if (ivr.getId().equalsIgnoreCase("your view id")
|| ivr.getId().equalsIgnoreCase("more view id if you want to close more than one at a time")) {
page.hideView(ivr);
}
}
}
}
In order to dispose ViewPart on closing Perspective we used the next code:
IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (workbenchWindow != null) {
workbenchWindow.addPerspectiveListener(new PerspectiveAdapter() {
#Override
public void perspectiveActivated(IWorkbenchPage page,
IPerspectiveDescriptor perspectiveDescriptor) {
super.perspectiveActivated(page, perspectiveDescriptor);
}
#Override
public void perspectiveDeactivated(IWorkbenchPage page,
IPerspectiveDescriptor perspective) {
super.perspectiveDeactivated(page, perspective);
page.closePerspective(perspective, false, true);
}
});
}
In result of page.closePerspective(perspective, false, true);, ViewPart that was opened within perspective, will be disposed.
To close views, opened in different perspective, I overridden perspectiveDeactivated() of org.eclipse.ui.PerspectiveAdapter.
public void perspectiveDeactivated(IWorkbenchPage page,
IPerspectiveDescriptor perspective) {
super.perspectiveDeactivated(page, perspective);
boolean myPerspective = MyPerspective.PERSPECTIVE_ID.equals(perspective.getId());
if(!myPerspective) {
//close Error Log view if it is opened in any perspective except My perspective.
IViewPart errorView = page.findView("org.eclipse.pde.runtime.LogView");
if(errorView != null) {
page.hideView(errorView);
}
}
}
My requirement was to close "Error Log" view. Above code can be modified to close any view.