Background
When I fill a spinner using a resource array, things work just fine:
Spinner countryCodeSpinner = (Spinner) findViewById(R.id.country_code_spinner);
countryCodeSpinner.setOnItemSelectedListener(this);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.country_codes_array, android.R.layout.simple_spinner_item);
where country codes are read from a resource:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array
name="country_codes_array">
<item>971</item>
<item>961</item>
<item>628</item>
<item>193</item>
<item>477</item>
</string-array>
</resources>
output:
Question
but when I fill up the spinner contents from an api call like so:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
..
Spinner currencySpinner = (Spinner) findViewById(R.id.currency_spinner);
populateCurrency(currencySpinner);
private void populateCurrency(final Spinner spinner) {
_currencies = new HashMap<String, String>();
final Context context = this;
// getting the contents of spinner from api call
new SyncHelper().get(CreateOrderActivity.this,
Connections.CURRENCIES(CreateOrderActivity.this),
null, null, new SyncListener() {
#Override
public void onSuccess(String data, int requestCode) {
try {
JSONObject object = new JSONObject(data);
if (object.getString("errors") == "false") {
JSONArray currenciesArray = object.getJSONObject("data")
.getJSONArray("currencies");
for (int i=0; i< currenciesArray.length(); i++) {
String currencyRef = currenciesArray.getJSONObject(i).getString("ref");
String currencyId = currenciesArray.getJSONObject(i).getString("id");
_currencies.put(currencyRef, currencyId);
}
String[] currencyrefs = Arrays.copyOf(_currencies.keySet().toArray(),
_currencies.keySet().toArray().length, String[].class);
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item,currencyrefs);
spinner.setAdapter(adapter);
then the spinner rendered view is all shrunk like so:
even though in both cases, we're using android.R.layout.simple_spinner_item.. any idea how to fix this?
I wasn't able to reproduce the issue, for me the first example gives an output similar to the second example and second example gives the same output (No margins, height is set to wrap_content, also for the second example, I only used the same adapter constructor to simulate). The difference in behavior might be because of the different APIs (I used an emulator with API 26).
However, to me your first and desired output looks like simple_spinner_dropdown_item instead of simple_spinner_item and I was able to produce a similar spinner with simple_spinner_dropdown_item, so you might want to check it out.
Related
I am facing a problem that when I try to dynamically add items to my spinner the app crashes. So first I add an array from Strings.xml my R.array.restrictions contains 16 items therefore I am inserting each key into 16 and then adding it onto the next position. and after that I load each item from firebase and add it to the adapter, then I set the adapter, so in my mind it should work. Any ideas why it causes a crash? Says:
UnsupportedOperationException at
java.util.AbstractList.add(AbstractList.java:148)
Thanks.
public void startSpinner(){
//built in Profiles
spinner = (Spinner) findViewById(R.id.spinnerProfiles);
adapter = ArrayAdapter.createFromResource(this, R.array.restrictions, android.R.layout.simple_spinner_item);
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
map = (Map<String, Object>) dataSnapshot.child("users").child(userID).getValue();
ArrayList<String> array = new ArrayList<>();
int x = 16;
for (Map.Entry<String,Object> entry : map.entrySet()) {
// key contains Profile Name
String key = entry.getKey();
adapter.insert(key, x);
x++;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//Auto Generated Method
}
});
adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
}
Perhaps the problem is that you are changing an array that is coming from resources. This can happen as the list you are using is not created by you.
You can try the following:
ArrayList<CharSequence> array = new ArrayList<CharSequence>(Arrays.asList(context.getResources().getTextArray(R.array.restrictions)));
adapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, array);
I want to add the content from an EditText to a ListView here is my code that dosen't work:
mass = userInput.getText().toString();
//fruits is a String[]
final List<String> fruits_list = new ArrayList<String(Arrays.asList(fruits));
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(context.getApplicationContext(), android.R.layout.simple_list_item_1, fruits_list);
fruits_list.add(mass);
lv.setAdapter(arrayAdapter);
The code adds the item to the listview but when the process is repeated it replaces the previously added string from the EditText.
Your code appears to create a new fruits_list array every time you read the user's entry from the EditText. This will result in only the latest entry being added to your list, replacing any previously added entries.
You need to create the array once (probably as a class member) and then update it each time you read the user input, e.g. something like:
private ArrayList<String> fruits_list;
private ArrayAdapter<String> arrayAdapter;
...
public void initialise(Context context) {
fruits_list = new ArrayList<>(Arrays.asList(fruits));
arrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, fruits_list);
lv.setAdapter(arrayAdapter);
}
....
public void getInput(
mass = userInput.getText().toString();
fruits_list.add(mass);
arrayAdapter.notifyDataSetChanged();
}
Note the use of arrayAdapter.notifyDataSetChanged() to signal that new data has been added to the underlying data set.
As #Aaron says, you should also look at RecyclerView as a possible replacement, although that's a little bit more complicated to set up.
Currently I'm using an ArrayAdapter which I just import. As the question states I want to get images into my listviews. I'm loading information into my list using JSONObjects and storing them into my ArrayLists. I know my current method removes html tages from the JSONObjects.
public class Home extends Activity {
ListView lView;
TextView tView;
ArrayAdapter lAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_layout);
lView = (ListView) findViewById(android.R.id.list);
//tView = (TextView) findViewById(android.R.id.);
loadList(lView);
}
public void loadList(ListView lView){
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall("URL", ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
ArrayList<String> titles = new ArrayList<String>();
ArrayList<String> body = new ArrayList<String>();
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray entries = jsonObj.getJSONArray("entries");
for (int i = 0; i < entries.length(); i++) {
JSONObject c = entries.getJSONObject(i);
String text = c.getString("introtext");
if(text == "null"){
text = "No text here" + "\n" + "\n";
}
else {
text = android.text.Html.fromHtml(text).toString();
}
String title= c.getString("title");
String full = title + "\n" + "\n" + text;
titles.add(full);
//body.add(text);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
lAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, titles);
lView.setAdapter(lAdapter);
}
}
Any suggestions would be great help
Thanks
First create a layout same what you want to show in a row, now create a class for a custom adapter like:
public class MyAdapter extends ArrayAdapter<T>{
}
Where T represents the entity class, which represents your data model.
Now under override method:
public View getView(final int position, View convertView, ViewGroup parent) {}
Inflate your layout created for the row, and set each view as you want to show.
Don't forgot to use lazy loading for the image to load over the imageview.
Hope it will help you.
You will need to create a custom adapter that has your own Layout defined. In this layout, you can include whatever you want (including an ImageView, that you can place your image).
There are many examples, but the important thing to know in your code, is you will supply your own adapter here, and set it up a bit differently:
lAdapter = new ArrayAdapter<String>(this, R.layout.my_custom_adapter, titles);
Try to use a Base Adapter
Inflate a custom Xml having a imageview using the base adapter
You can put any views(Image,textview etc ) depending on your
requirement
Finally use picasso or imageloader to populate images using the JSON
response to your base adapter
Hope it helps, Revert back to me if you need any more help, Happy coding
You'll have to create a custom adapter instead of ArrayAdapter, so that you can use your own layout for every row, and perform any 'image loading' there. Try creating a class that extends the BaseAdapter abstract class from the framework. Also, search the web or here (in stackoverflow) you'll find tons of tutorials on how to create a custom adapter.
Since downloading and loading images can be a bit of a pain if you aren't experienced with ListViews and custom adapters, I would suggest looking up two 3rd party libraries for this job:
Picasso or Universal-Image-Loader, each one having examples on how to use them alongside with custom adapters
I looked at the following site: ListView Example
Which describes how to implement a search function in a listview which uses the default adapter and it works fine.
How can I modify it so I can use the same for a Custom Adapter for my listview?
Partial code is:
dataList = (ListView) findViewById(R.id.lvFiles);
tvQuote = (TextView) findViewById(R.id.tvDisplay);
tvQuote.setTypeface(Typeface.createFromAsset(MainActivity.this.getAssets(), "fonts/roboto.ttf"));
for (int y=0; y<strNamesOfAllah.length;y++) {
name = strNamesOfAllah[y];
meaning = strMeaning[y];
rowsArray.add(new SetRows(R.drawable.icon, name, meaning));
}
adapter = new SetRowsCustomAdapter(MainActivity.this, R.layout.customlist, rowsArray);
dataList.setAdapter(adapter);
dataList.setClickable(true);
You need to override getFilter inside of your adapter and return a new customFilter object that you create. See this answer: No results with custom ArrayAdapter Filter
Edit:
#Override
public Filter getFilter() {
if(customFilter == null){
customFilter = new CustomFilter();
}
return customFilter;
}
Wondering if i can get some help with a problem i'm having? I have searched for the answer on here, and although i found a few relevant topics i'm still really struggling...
Below you can see that i'm using a Spinner asking the user to select either Large, Med or Small.
The selection is then issued to a TextView.
What i now want to do is assign a value to the 3 selections, Large = 6, Med = 4, Small =2.
Next there will be a EditText box for the user to add their own value.
Then i want to put the two values into a calculation (say * them in this example) putting the answer into a TextView.
Any help here would be great.
Many Thanks
Will
String[] items = { "Large", "Med", "Small" };
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.plugfan);
Factor = (TextView) findViewById(R.id.Factor);
Spinner spin = (Spinner) findViewById(R.id.spinner);
spin.setOnItemSelectedListener(this);
ArrayAdapter aa = new ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
items);
aa.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(aa);
}
public void onItemSelected(AdapterView<?> parent, View v, int position,
long id) {
Factor.setText(items[position]);
}
public void onNothingSelected(AdapterView<?> parent) {
Factor.setText("");
}
A quick way to solve this (not the smartest one) is to have a paralell array:
int[] itemValues = { 6, 4, 2 };
In the method onItmeSelected you can setText using the itemValue, instead of items.
If you want a more OO-solution a new class that returns a list of Strings to use as a model for your spinner might be a beter solution (an enumeration might solve it too).