i'm looking for this problem for hours.
I have autocompletetextview which is shows the all inputs in dropdownlist.
I keep values in Sharedpreference.
AutoCompleteTextView texttutar;
ArrayAdapter<String> adapter;
SharedPreferences.Editor editor;
SharedPreferences pref;
Set<String> hs;
ONCREATE ----
pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
editor = pref.edit();
hs = pref.getStringSet("set", new HashSet<String>());
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line);
texttutar.setAdapter(adapter);
if(!texttutar.getText().toString().isEmpty()){
hs.add(texttutar.getText().toString());
editor.clear();
editor.putStringSet("set",hs);
editor.commit();
}
// SortedSet<String> sortedSet = new TreeSet<String>(hs);
// Toast.makeText(getApplicationContext(), "" + sortedSet.first(), Toast.LENGTH_LONG).show();
// if(hs.size()>=5)
// hs.remove(hs.iterator().next()); Removing last value of hs
adapter.clear();
adapter.addAll(hs);
texttutar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
adapter.getFilter().filter(null);
texttutar.setThreshold(1);
}
return false;
}
});
texttutar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
texttutar.showDropDown();
}
});
Now, this code works perfectly.
But i need two more things to do.
First problem : When i add values like
100 - 101 - 102 - 103 -104 - 105
its showing me the values like that :
102 - 100 - 105 - 103 - 101 - 104
I dont know why. It must sort by time.
Second problem : As you can see i can remove the last value but i didnt find any solution for first item.
I tried something like Treeset but its not important. Important is i should delete the value of Set (Sharedpreference).
After autotextview shows 5 value, it must delete the first item.
Like that : I'm adding this values. 110-200-300-400-690 and then 900
When i add 900 the code must remove the first value (110 ) then first value will be 200 . Its work like that.
Sets are unsorted. THe definition of a Set is that it keeps track of a group of items and that you can test quickly whether an item is in it or not (typically in O(log n) or O(1) time). There is no promise of order, and in fact a set usually uses balanced binary trees or a hash internally, purposely losing order for speed.
For what you want, a Set is not the appropriate data structure. You want a queue. A queue is an ordered group of items where you add them to one side and remove from the other. Particularly it seems like you want a fixed size queue. I suggest you use one, rather than trying to make a data structure that's inappropriate work.
Related
This is driving me a little mad since I know this should be very simple but I am not getting the desired affect.
I have the following arraylist
private List<String> tagStringArray = new ArrayList<>();
Then later I have a method that creates dynamic buttons, based on ID values pulled across from my Retrofit instance.
In my method, I have a count to help me set the title of the button but I also add the values of count to an ArrayList for use in another method.
I have taken a snip of relevant information from the method mentioned.
count = 1;
if (!questionNumber.equals("") && !questionNumber.equals(null)) {
for (final Object value : list) {
try {
/*Dynamically create new Button which includes the question number
*/
final AppCompatButton btn_question = new AppCompatButton(getActivity());
/*LayoutParams (int width, int height,float weight)
As LayoutParams is defaulted in px, I have called a method called dpToPX to make sure
the dynamically added EditText is the same size on all devices.
*/
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(280), dpToPx(45), 1);
btn_question.setBackgroundColor(Color.parseColor("#3B5998"));
btn_question.setTextColor(Color.WHITE);
btn_question.setText("Question "+count);
//set the Tag based on its position in the XML
tagStringArray.add(String.valueOf((count)));
count++;
If a user clicks on say Question 1 Button, I want my fragment to say Question 1, so to try and achieve that, I have tried doing the following:
String tags = String.valueOf(tagStringArray);
tags = tags.substring(1, tags.length() -1);
String[] currentTag = tags.split(",");
if (currentTag[0].contains("1")) {
tv_setQuestions_edit.setText("Question 1");
}else if(currentTag[1].contains("2")) {
tv_setQuestions_edit.setText("Question 2");
}
But this will always set the title to Question 1 and I am not sure what is going wrong.......
If I use the following toast Toast.makeText(getActivity(), Arrays.toString(currentTag), Toast.LENGTH_LONG).show(); it shows [1,2] so I know they are being added ok.
I did look into using tags by doing:
public static int KEY_COUNT=0; public static int KEY_VALUE=1;
btn_question.setTag(KEY_VALUE,value);
btn_question.setTag(KEY_COUNT,count);
But for some reason, when I add more than one tag (as I need a minimum of 2), my dynamic button is missing from the layout. But for some reason when only 1 tag - like this btn_question.setTag(value); is used, it shows up fine (I have a feeling its some issue with my fragment). Therefore I am trying to think of a workaround in the meantime.
Any help or guidance would be really appreciated.
It's because
currentTag[0].contains("1")
is always true. The first item of currentTag always contains "1".
Instead of doing this, why don't you just do String titleForFragment = myButton.getText() in the onClick method for the button? That way, you can set the same onClickListener on all the buttons, and it will reduce the amount of code you need to write.
I have a string array :
private String [] arrFilePaths=new String[4];
and I have a funtion which returns strings and im adding that to array:
#Override
public void accept(List<File> files) throws Exception {
int size = files.size();
while (size-- > 0) {
arrFilePaths[size]=files.get(size).toString();
}
}
Now i have a button and I am accessing array inside of it:
#Override
public void onClick(View v) {
if(arrFilePaths[0]==null){
//some code
}else {
//some code
}
Now the problem is arrFilePaths only return strings in button click sometime. most of time its returning null.The data always getting inserted to array before button click. so i dont know whats going on.
Yes i have tested in debug mode and arrFilePathsis getting data inserted, but somehow after the button click it saying null(even though I am using same variable).
Can anyone explain about this weird output? Thanks!
As far as I can see, you will be getting null every time when your List<File> files has fewer elements than arrFilePaths array.
Imagine this is files list [L1 , L2 , L3]
And your array is [A1 , A2 , A3 , A4 , A5 , A6]
As you're writing from end, the last element from the end of files will appear at last position of arrFilePaths so on so force.
Finally, array will look like [null, null, null, L1 , L2 , L3].
Obviously, the 1st element of this array will be null.
I am not sure how you are seeing the values sometimes because to me it seems like a logical problem in below code
while (size-- > 0) {
arrFilePaths[size]=files.get(size).toString();
}
Lets assume your size is 3 so you travel here in the reverse order. So you fill the position 3 and 2 and 1 but as soon as size becomes 0, your condition fails and it never sets the value for 0th element.
then your if condition checks -
if(arrFilePaths[0]==null)
So its checking if 0th element is null which is obviously the case because your while loop didn't let it enter there. hence no data.
so if your size is more than 4 in that case your 0th element will get filled as your arrFilePaths can only take 4 elements
In my opinion you should Modify this line
while (size-- > 0)
like this
while (size-- >= 0) {
Just replace that while with a fori, I don't see any reason at all why you would want to populate that array from the end to the front.
I want to change dinamically the list entries and entryvalues of a listpreference. Well, finally it works, the list changes, but the problem is that I can see the new values only when I click the second time or more in the listpreference in the preference screen.
The first time, the list is always the original list, from 1 to 10.
numeroIntentosLP.setOnPreferenceClickListener(new OnPreferenceClickListener()
{
#Override
public boolean onPreferenceClick(Preference preference)
{
CharSequence[] NuevosValores = new String[10 - LineaActual];
int Indice = 0;
for(int i = LineaActual + 1; i <= 10; i++)
{
NuevosValores[Indice++] = String.valueOf(i);
}
numeroIntentosLP.setEntries(NuevosValores);
numeroIntentosLP.setEntryValues(NuevosValores);
return true;
}
});
I have tried with numeroIntentosLP.setOnPreferenceChangeListener, but the same result.
LineaActual is an integer value that I passed from MainActivity to PreferenceActivity. This is useful to me to know the new start value for the list.
So, everytime I open the preference screen and I click for the first time in the listpreference, I always get numbers 1 to 10, but when I click again, no matter how many times, I get what I want, I mean the list from LineaActual to 10.
Thanks in advance.
Ok, I found the solution. It was as easy as put the code directly in the onCreate, not in the listeners.
Thank you samgak, I saw your answer a little bit late and you're right, thank you anyway.
I've created a dialog containing two NumberPicker views. The first contains a list of groups, the second contains the items from the selected group:
Group Group Items
1 2: Group 2 Item 2
[2] [3: Group 2 Item 3]
3 4: Group 2 Item 4
I'm hooking in to the setOnValueChangedListener in the first NumberPicker to populate the second NumberPicker.
mNumberPickerGroup.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker numberPicker, int from, int to) {
int size = mData.getItemsForGroup(to).size();
String[] strings = mData.getItemTitlesForGroup(to);
mNumberPickerItems.setMinValue(1);
mNumberPickerItems.setValue(1);
mNumberPickerItems.setMaxValue(size);
mNumberPickerItems.setDisplayedValues(strings);
}
});
This basically works - until, in certain circumstances, changing the group a few times can cause a crash in the NumberPicker class, when setting the setDisplayedValues strings.
The error is an array index out of bounds exception in the numberpicker for items, a line to do with the string array I passed in. I've set a break point in the update code above, and verified that the String array is always the correct size for the number of items set between min and max value on the number picker, so this has stumped me.
java.lang.ArrayIndexOutOfBoundsException: length=22; index=22
at android.widget.NumberPicker.ensureCachedScrollSelectorValue(NumberPicker.java:1768)
at android.widget.NumberPicker.initializeSelectorWheelIndices(NumberPicker.java:1583)
at android.widget.NumberPicker.setMaxValue(NumberPicker.java:1390)
at uk.co.my.app.fragments.GroupMarkUptoDialog.updateItemPicker(MarkUptoDialog.java:99)
I'm about to start reading through what happens in the NumberPicker to figure out if I'm using it wrong, but any suggestions would be welcome. "ensureCachedScrollSelectorValue" makes me think I need to reset the numberpicker somehow before updating it with new data but I'm not sure.
Can anyone see what I'm doing wrong here?
I realise the NumberPicker is not really a String picker, so if anyone has a better suggestion for how to achieve this sort of UI I'm all ears. Otherwise, I'm heading down the route of trying to implement some kind of debouncer, to update the items picker once all activity on the group picker is complete.
It happens when you setDisplayedValue(String[]) many times.
If the string[]'s length is larger than the current getMaxValue(), Exception happens!
My solution
use
picker.setMaxValue(0);
before
picker.setDisplayedValues(stringArr);
My code
cityPicker.setMaxValue(0);
try {
cityPicker.setDisplayedValues(citySet.toArray(new String[citySet.size()]));
} catch (Exception e) {
Log.e("Ninja", "cityPicker.setDisplayedValues(citys) occurs Error. province is " + province);
}
cityPicker.setMaxValue(citySet.size() - 1);
If you use indexes started from 1 then use:
int size = mData.getItemsForGroup(to-1).size();
Use this to change second picker (if current value is above maximum it will set it to new maximum):
int i = mNumberPickerItems.getValue();
int max = strings.length;
if (i > max)
i = max;
mNumberPickerItems.setMinValue(1);
mNumberPickerItems.setMaxValue(1);
mNumberPickerItems.setDisplayedValues(strings);
mNumberPickerItems.setMaxValue(max);
mNumberPickerItems.setValue(i);
And try to use values as indexes, i.e.
minValue=0
maxValue=strings.length-1
I have a spinner with a few values and I fill it from my webservice.
Filling the spinner
int i = 0;
var dropItems = new List<SpinItem2>();
DataRow[] result = myOPTvalues.Tables[0].Select("FieldValue=" + item.FieldValue);
foreach (DataRow row in result)
{
var optItem = new PrevzemSpin();
optItem.FieldValue = row["FieldValue"].ToString();
if (optItem.FieldValue.Equals(""))
optItem.FieldValue = null;
optItem.FieldTextValue = row["FieldTextValue"].ToString();
if (optItem.FieldTextValue.Equals(""))
optItem.FieldTextValue = null;
dropItems.Add(new SpinItem2(i, optItem.FieldValue.ToString(), optItem.FieldTextValue.ToString()));
}
i = 1;
foreach (DataRow row in myOPTvalues.Tables[0].Rows)
{
var optItem = new PrevzemSpin();
optItem.FieldValue = row["FieldValue"].ToString();
if (optItem.FieldValue.Equals(""))
optItem.FieldValue = null;
optItem.FieldTextValue = row["FieldTextValue"].ToString();
if (optItem.FieldTextValue.Equals(""))
optItem.FieldTextValue = null;
if (optItem.FieldValue != item.FieldValue)
{
dropItems.Add(new SpinItem2(i, optItem.FieldValue.ToString(), optItem.FieldTextValue.ToString()));
}
++i;
}
For some reason it acts like the item that was inserted first is "selected" on default and then triggers the ItemSelected event which I use to send the selected but I don't want that.
Since there's quite a number of these spinners on my screen it really slows down the activity plus it also sends the incorrect values to the field and since I use the ItemSelect to detect if everything went OK (let's say the service fell or the values themselves changed on server (someone added a new field on the server application) while the user is completing the form etc.)
Is there someway to tell the app not to trigger that on activity load but on actual user interaction?
I can't speak for Android specifically, but I have encountered this many times with Windows.
The solution I usually use is to simply add a boolean loading variable. Set it to true at the beginning of your initialisation and then clear it at the end.
In your event handlers like ItemSelected you can simply check if this is being triggered as the result of the initial load.
private void onItemSelected(....)
{
if(loading)
{
return; //Ignore as form is still loading
}
//Normal event handling logic goes here
....
}
Before I declared GetView:
int LastSpinnerSelectedPosition;
Inside my spinner definition:
LastSpinnerSelectedPosition = 0;
My spinner ItemSelected event:
var CurrentSelectedIndex = SpinnerValue.SelectedItemPosition;
if (CurrentSelectedIndex != LastSpinnerSelectedPosition)
{
// WHATEVER I WANTED TO DO ON ITEM SELECT ANYWAY
// Fix the LastSpinnerSelectedPosition ;)
LastSpinnerSelectedPosition = CurrentSelectedIndex;
}
Simple ;D
Just for clarification, the event fires when an item is selected. The semantics are obviously flawed, but technically the item IS selected when it initially loads since you can then immediately ask the spinner for which item is selected, so as the other answers say, just ignore the first time it is selected since it's guaranteed to be the loading select, and then proceed as normal after that.