I have a kind of form with 3 Spinners. The content of 2 Spinners (minorSpinner) depends on the selection of the first one (mainSpinner). To be more precise, I set the content of those 2 minorSpinner in the mainSpinner's onItemSelected listener.
The form can be saved and load back again.
The problem is:
When I am trying to load the form, first I set the mainSpinner and then minerSpinners.
Like:
mainSpinner.setSelection(value);
minorSpinner1.setSelection(value1);
minorSpinner2.setSelection(value2);
Unfortunatelly the minorSpinners are not ready in time. Maybe because their values are set in the UI Thread?
Question:
how to wait until they are ready?
What I tried:
runOnUIThread(){
mainSpinner.setSelection(value);
minorSpinner1.setSelection(value1);
minorSpinner2.setSelection(value2);
}
but ti does not work:(
Any idea?
how to wait until they are ready?
So my first idea is to register OnItemSelectedListener() for all Spinners.
Then create two boolean variables for example isSpinnerOneSelected, isSpinnerTwoSelected and when you'll select item from Spinner, assign variable to true.
Then create some Thread (with Handler) that will control your states. If both variables are assigned to true, just make action with third Spinner.
If you don't know how to use Handler, look at:
How to run a Runnable thread in Android?
Related
I'm new to all of this and was making good progress but I have hit a brick wall with working out how to do the next thing. I am using Kotlin and have a Fragment with an associated Recyclerview Adapter. I would like to set OnClick (On or Off) against items in a row depending upon a value in the Fragment which could change at any time.
My adapter works fine to show and update the array of data and also to implement OnClick.
I have tried sending a data element via a constructor which changed in the fragment but always showed as the initial setting in the adapter. The same with trying to call a method.
Many other questions touch on the issue but only show snippets of code, and it seems that I'm not advanced enough to get them working successfully in my code.
Could anyone please provide a pointer to a working set of Kotlin code that includes parsing a variable from fragment to adapter - perhaps in Git or a tutorial. I'm sure that if I can study a working program I can move forward. Thank you.
It would have been better if you had included your Adapter and Fragment code in the question, that would have helped us in understanding how you have setup everything and what data model are you passing to adapter.
But looking at your question, one solution that comes to my mind is to add an enabled boolean in your data model that is displayed in the ViewHolder. Using this you can set view.clickable = model.enabled. Now whenever your "value in the Fragment" changes you can update this list and let the adapter rebind items.
Note that the above solution is when you want to selectively enable/disable clicks on individual items. If you want to do this for all items at once, it's better to create a variable in adapter that you can change from the Fragment, and inside the clickListener you can check the value of that adapter variable. If it's false, just return out of the click listener. Something like,
view.setOnClickListener {
if(adapterValue) {
// handle Click
}
}
If this approach doesn't help, I would ask you to add more context in your question and show what you have done so far.
I wrote a very simple FMX Adroid App, the function is:
Show Form 2 then write something to record(include title and detail text),
close Form 2 to Main Form, then make a checkbox in Main Form with the title we just recorded in Form 2.
if user check the checkbox, then press "del" buttn then delete the record file and checkbox.
the problem is:
when closed Form 2 and in MainForm::OnActivate we can add a new checkbox for the record.
if we checked checkbox then clicked delete, free the pointer of checked checkbox, the checkbox still in main form until I reopen the APP.
I tried:
Invalidate();
Application->ProcessMessages();
BeginUpdate();
EndUpdate();
Still can't work
does anyone know what's going on ? why FMX TForm member has no "Repaint()" or "Update()" "Refresh()" ? just like VCL has.
If you want your TCheckBox* (or any other control) disappear from a Form, you need to set its Parent property to nullptr before deleting it. If you created your control in runtime using new please remember to call delete.
//init
TCheckBox* checkBox = new TCheckBox(Form2);
//delete
checkBox->Parent = nullptr;
delete checkBox;
Answering the second part of your question, you can call Invalidate() function to repaint your whole Form (but first see first part of this answer). But I think it will run properly without calling this function.
Your controls have Repaint() member and it may be better to call them instead, ie. if your checkbox was placed in TPanel*, repainting only this panel is better idea than repainting whole form.
I am trying to follow what is going on with the boolean variable, hasMoreData with EndlessAdapter and why is seems to be prematurely turning false.
Let me start from beginning to run through what happens. Note: I am using a task and setRunInBackground(false);
I start off setting my list and setting the adapter:
profileList = new ArrayList<ProfileReview>();
endlessAdapter = new EndlessProfileAdapter(getActivity(), profileList);
endlessAdapter.setRunInBackground(false);
listView.setAdapter(endlessAdapter);
Sidenote: Not sure if this is correct, but it seems I am setting the list with an empty adapter.
The first thing that appears to happen after adapter is set is the method cacheInBackground(), where my profileList size is zero, so it sets 0 as int startPoint when calling my AsyncTask where hasMoreData is set to true. Meanwhile, in this (cache) method, hasMoreData returns true. Not sure why? Because the list is zero in size? Or because its still associated with the default value of true?
In the task, it grabs first 10 items.
Then as user scrolls, the thobber starts spinning. And next 10 are displayed. Log.d tells me that profileList.size() is now 10 and hasMoreData is therefore false.
public void onItemsReady(ArrayList<ProfileReview> data) {
profileList.addAll(data);
endlessAdapter.onDataReady();
hasMoreData = profileList.isEmpty(); \\ Log.'d this out
}
My questions: My list starts with 10 items, users scrolls, it grabs 10 more. Then stops after a total of 20 items (or when hasMoreData == false.) But I have many more items to pull from. How do I keep hasMoreData == true? What is the trigger for this? Obviously the trigger is list size (I think?), and why would the list size ever be 0 once it starts to grab data? (until the end of course)
Not sure if this is correct, but it seems I am setting the list with an empty adapter.
EndlessAdapter is definitely designed to start with a non-empty adapter. In fact, it is designed assuming that the user must scroll to get it to load more data. Behavior in your current approach is unspecified, and I do not recommend that approach. Please load some data, then populate the list once your first batch of data is ready.
Meanwhile, in this (cache) method, hasMoreData returns true. Not sure why? Because the list is zero in size? Or because its still associated with the default value of true?
Since EndlessAdapter does not have a hasMoreData method. A search of the source code to EndlessAdapter turns up nothing named hasMoreData. Heck, the only places the word "more" appears is in comments.
A sample app has a hasMoreData value. Since you are not using this sample app, I cannot help you with random data members of random classes in your own code.
In the sample app, in EndlessAdapterCustomTaskFragment, I use a data member named hasMoreData. This is a boolean value, designed to be returned from cacheInBackground(). The responsibility of cacheInBackground() is to return true if we should continue to load data (after the current batch just loaded), false otherwise. In the case of this sample app, hasMoreData is populated by the call to onItemsReady(), itself triggered by onPostExecute() of the AsyncTask simulating loading some data. hasMoreData is set to true or false depending upon whether the items collection is empty, so it basically does a single load of additional data, then calls it quits.
But that is the behavior of a sample app. I didn't even write most of this class -- it came as a patch adding in support for your own data-fetching task. Do not consider sample code to be anything more than a sample.
Hence, you need to set your hasMoreData value to whatever makes sense for your application logic to serve whatever role you decided to use hasMoreData for. If hasMoreData has the same role in your code as it does in the sample, leave it true until you have determined that you are out of data, then set it false.
In my application I have a list of questions stored in an ArrayList, and I want to display a dialog that shows one question, and then continues to the next one after the question is answered. The way that I'm currently doing it (iterating through a loop) hasn't been working because it just layers all of the dialogs on top of one another all at once which causes a host of other issues. What I'm looking for is a way to still iterate through the questions, but just change the layout of the dialog each time until it has finished each question in the list. Can anyone give me a good pointer for how to get this going?
You can make a function that takes title and message as parameters and shows a dialog.
showDialog(String title, String message){ // Show dialog code here}
Within that dialog's answer button's listener call another function (showQuestion(currentQuestion)) that iterates the arrayList till it is over
int currentQuestion=0;
ArrayList<QuestionObject> questionList;
showQuestion(int i){
if(i<questionList.size()){
showDialog(questionList.get(i).getTitle,questionList.get(i).getMessage);
currentQuestion++;
}else{
//quiz is over
}
}
I assume you mean that you just want to change 1 single layout(created within XML i.e main.xml). In order to do this, make sure that the class your working on is pointing to that layout. From there (assuming your using an Event listener for when the user submits an answer) you can change do as you want by the following:
TextView txt = (TextView) findViewById(R.id.textView); // references the txt XML element
and in your Event listener, if the answer is correct then change(Have i be a global variable thats initially set to 0).
if(i<arrayList.size()){
txt.setText(arrayList.get(++i));
}else{
txt.setText("You Finished");
}
From there, in the else statement, you can change arrayLists and reset i to 0;
If you are trying to use the positive, neutral, and negative buttons; then you may have problems with multiple dialogs. Try defining a customized layout with your own TextViews, ListViews, and Buttons. You can implement listeners and everything else like a regular layout. Then just pass your customized layout to the dialog through AlertDialog.Builder.setView().
PS If you include code examples of what you are currently doing we can provided answers that are less vague.
sorry for stupid question. But really interesting and incomprehensible. In this session discussed about notifyDataSetChanged() method.
From documentation for this method - "called when the data set being observed has changed, and which when read contains the new state of the data". My English bad and I do not understand all. But I right if guess that method called when I need refresh ListView with new data set?
If I'm right then I'm confused. In the past and my first program I played with contacts api of android. And run some processing in an asynctask. At this time appeared dialog with progress bar and in the background, you could see how the state of ListView changed in real time. Data for ListView row changed via BindView.
Why? So I'm in something wrong. Explain please.
As i read it, BindView is only used with cursors, which are a specific type of a data set basically. You can have alternative data sets, there is for example an ArrayListAdapter in the API which uses an ArrayList as its dataset. In case that data set changes, notifyDataSetChanged() will have to be called to notify the list view that its bounds will have to be recalculated and its views have to be redrawn (and probably some more).
If you decide to write your own and create the possibility to modify the data shown in the list view through an adapter (one could imagine adding method like addObject(SomeObject o) in your home made adapter for example), then you'd call notifyDataSetChanged() in that method.
Similarly if you have a deleteObject(SomeObject x), if the remaining data set is larger than zero you'd call notifyDataSetChanged() or when the remaining data set is empty you'd call notifyDataSetInvalidated() which in turn will to some extra stuff like setting the so called empty view in the list if you have one specified.