i am trying to make an E-Leaning app.
I have a submit button, that when pressed, sends the user's answer to a server to be evaluated.
During that evaluation, I want to display a loading indicator (I am simply using Android Studio's progress bar).
During the onViewCreated of my fragment, I set the onClickListener as follows:
submit_button.setOnClickListener {
submit_button.isClickable = false
loadingIndicator.visibility = View.VISIBLE
inputFragment.passDataToActivityAndEvaluate()
}
On press, a coroutine is launched that makes an html request. After that, I want to hide the loading spinner before navigating the child fragment
loadingIndicator.visibility = View.INVISIBLE
submit_button.isClickable = true
The idea sounded simple enough, however, I discovered that when trying to make any form of UI change in the OnClickListener, it only gets applied when the evaulation is already done and the app has navigated to the next fragment.
Related
My app previous was made using Fragments as pages. Now i'm integrating Jetpack Compose into my app. The pages are like this:
HomePageFragment -> the home page made with traditional XML
ItemListPageFragment -> a fragment wraps ComposeView that everything is done by Compose
ItemDetailPageFragment -> item detail page made with traditional XML
Here are the effects I want to achieve:
When entering ItemListPage, show loading then a list of items. then user scroll down a bit, select an item, jump to ItemDetailPage
When go back from ItemDetailPage to ItemListPage, UI shouldn't reload, but stays at where it was left with.
My ItemListPage is like this:
#Composable
fun Content(){
// third party lib that kind of like useSWR for React
val states = useRequest(fetcher = {....})
if(states.error) {...}
if(states.loading) {....}
// render list of items
....
}
right now it triggers fetch and loading UI when I go back from ItemDetailPage to ItemListPage.
I think the issue is Fragment destroy views when "page-out". Then when it is "back-to" page, it creates new ComposeView and triggered onLoad event.
Use ViewModel
OR
Use rememberSavable so that there won't be change even if there are any configuration changes
I recently upgraded my app to use ViewPager2.
When the user taps the finish-early button I call this code.
setCurrentItem(myLastPageIndex, false)
doSomeWork()
The doSomeWork() function enables the circular progress bar on the last page.
The thing is that when I call doSomeWork() the page isn't displayed yet and I get an exception because I'm trying to update a View that doesn't exist yet, createFragment() is called after doSomeWork()
This used to work perfectly with the old ViewPager, is there any way to know when the setCurrentItem(myLastPageIndex, false) transition finishes?
I thought about using OnPageChangeCallback, however, I don't want doSomeWork() to be called when the last page is selected by the user, but only when I change the position page dynamically.
I want to integrate an android back button functionality in appcelerator for a parent window and its subsequent child views. I have just a single window in the entire project. Other screens are the children of this parent window. Any suggestions?
There are 2 cases you might be interested in:
Over-ride the default behaviour of the back button press.
$.window.onBack = function () {
// run your code like change views or whatever you like
};
Use Window's onBack property to attach back button callback.
It will have you take control of what should happen when back button is pressed on that window.
If you just want to listen to back button press along with default behaviour of back button press, use Window's androidback event.
$.window.addEventListener('androidback', function (e){});
Note that this method will still close the window you are on, but will allow you to run some code on back button press.
I believe you are looking for method 1.
Note: Method 1 is only available after or > SDK 5.5.1.GA. It was a breaking change in 6.0.0.GA. So do read docs properly & put some tests on their functionality.
Added Code sample to simulate back button feature.
Alloy.Globals.trackingArray = [];
function addNewView(_controllerName, _args) {
var newView = Alloy.createController(_controllerName, _args).getView();
$.window.add(newView);
// add new view in tracking array.
Alloy.Globals.trackingArray.push(_controllerName);
}
// now use something like this whenever you remove any view using backpress
function onBackPress() {
// remove lastly added view
Alloy.Globals.trackingArray.pop(_controllerName);
// add last opened view to simulate back button feature
var lastAddedView = Alloy.Globals.trackingArray[Alloy.Globals.trackingArray.length - 1];
var tempView = Alloy.createController(lastAddedView).getView();
$.window.add(tempView);
}
This is the basis of how you can manage this feature. But do note a point here that you will need to take care of managing arguments passed to while creating a new view or controller. There are multiple ways to do it & it depends on your coding style. :)
I have a fragment, inside which there is a TextView and some Buttons.
I show the fragment, user clicks on a button, I hide the fragment and show a loading icon, contact server, get a new text and:
loading.setVisibility(View.VISIBLE);
mainContent.setVisibility(View.GONE);
http.post("https://domain/service?parameters",
new ParameterizedRunnable() {
text.setText(newTextFromServer)
loading.setVisibility(View.GONE);
mainContent.setVisibility(View.VISIBLE);
});
However, when the the main content view becomes visible after service call, I still see the previous text for a very short time, and then the new text is shown.
Why is it so? It seems that the text.setText line gets called, but maybe the device is slow and UI is not updated properly before mainContent.setVisibility line.
Am I missing some concept about android views and how they get rendered?
I am trying to work out how to show the "up" arrow in Xamarin.Forms without a pushing a page onto the stack. I.E. I just want to perform an action when the back button is pressed. I am completely stuck on this so any help would be appreciated.
I have tried creating a custom renderer which handles a view property called DisplayHomeAsBack. Which in the renderer calls the following:
FormsAppCompatActivity context = ((FormsAppCompatActivity)Forms.Context);
Android.Support.V7.App.ActionBar actionBar = context.SupportActionBar;
if (actionBar != null)
{
actionBar.SetDisplayHomeAsUpEnabled(element.DisplayHomeAsBack);
}
Unfortunately it seems this does absolutely nothing, even though all online tutorials and stackoverflow question for android suggest this method.
The plan is that I can then use the "OnBackButtonPressed" override in MasterDetailPage, which should allow me to perform this action. Unfortunately displaying the back button has been the larger hurdle so far!
Any idea of a better way to do this or how I can get the current mechanism to work?
EDIT
I have created a project and uploaded it to this question on the Xamarin support forums, if it helps.
http://forums.xamarin.com/discussion/comment/186330#Comment_186330
Sorry to keep you waiting so long!
Warning that I did not actually run this code and changed it from my own so I would be surprised if it worked perfectly without some changes.
So below should add a back button where there was not one before (so like when there is not really a page to go back to) and then we will add a custom action to perform when it gets pressed.
I would suggest you push a new page onto the stack without using animation so it is transparent to the user and also makes all of this much simpler, but if you absolutely do not want to do that, the below method should work.
MainActivity:
//Use this to subscribe to the event which will create the back button
public override bool OnCreateOptionsMenu(IMenu menu) {
if(menu != null && App.AppMasterPage != null) { //You will need this to make sure you are on your MasterDetailPage, just store a global reference to it in the App class or where ever
Xamarin.Forms.MessagingCenter.Unsubscribe<string>(this, "CreateBackButton");
Xamarin.Forms.MessagingCenter.Subscribe<string>(this, "CreateBackButton", stringWeWillNotUse => { //Use this to subscribe to the event that creates the back button, then when you want the back button to show you just run Xamarin.Forms.MessagingCenter.Send<string>(this, "CreateBackButton")
ActionBar.DisplayOptions = ActionBarDisplayOptions.ShowTitle | ActionBarDisplayOptions.ShowHome | ActionBarDisplayOptions.UseLogo | ActionBarDisplayOptions.HomeAsUp; //You may need to play with these options to get it working but the important one is 'HomeAsUp' which should add the back button
});
} else {
Xamarin.Forms.MessagingCenter.Unsubscribe<string>(this, "CreateBackButton");
}
return base.OnCreateOptionsMenu(menu);
}
Now the next step is do do a custom action when it is pressed. I think you can either override OnBackPressed() or OnOptionsItemSelected() in MainActivity or maybe you can override the MasterDetailPage method. I am not sure.
Which ever one works for you, inside of that override, I would simply check to see if you are on your App.AppMasterPage like we did above, and if so, send a MessagingCenter message which your App.AppMasterPage has already subscribed to in order for it to handle the custom action.
If you get stuck let me know!
I know it sounds like a bit of a hack, but the best "solution" I have found so far is to add a page behind the current page (behind the root) so it is not visible. Then when the user presses the back button, handle it by removing that page.