What's the difference between array adapter & android.entries in spinner? - android

What difference does it make, if I assign some items using an ArrayAdapter or using android:entries?
Which drawbacks will I face, related to a Spinner functionality?
Adding elements using android:entries
<Spinner
android:id="#+id/edu"
android:layout_width="211dp"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:entries="#array/education"
android:drawSelectorOnTop="true" />"
Adding the items using an ArrayAdapter:
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.edu));
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
education_2.setAdapter(arrayAdapter);

android:entries is a static string XML list. You cannot update the Spinner content via Java code. Similarly, (maybe I forget the property, but) in the Java code you are able to use a different layout than android.R.layout.simple_list_item_1
If that's not required for your application, there's no drawback as the XML you have gets roughly translated into the same Java code.

If you're curious how an XML attribute is used, the Android source code is your friend. You can see that Spinner extends AbsSpinner and that has a constructor defined like this:
public AbsSpinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initAbsSpinner();
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.AbsSpinner, defStyleAttr, defStyleRes);
final CharSequence[] entries = a.getTextArray(R.styleable.AbsSpinner_entries);
if (entries != null) {
final ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
context, R.layout.simple_spinner_item, entries);
adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
setAdapter(adapter);
}
a.recycle();
}
As you can see, the code checks if the entries attribute is set and, if it is, creates a default ArrayAdapter<CharSequence>to display the given set of strings.
So, to answer your questions:
What difference it makes if I assign items using array adapter or using in build android:entries ?
If you just need to show a list of strings, there's really no difference. The entries attribute is a convenience if you simply need to display a list of strings in a default spinner view without additional customization.
What drawback I will face related to functionality of spinner?
There's no difference in functionality - it's still a spinner of strings. But you cannot customize the type of item or style of the views in the spinner. So if you need a different layout or more customization in how your items are displayed, you would write the extra code to create and set your own adapter.
Hope that helps!

Related

Why do we need to pass a resource layout to a custom adapter in constructor?

I am curious to know this as I am not able to find it in internet.
I am creating a custom list adapter. In this adapter there is a getView method which I am overriding. In this method I inflate the row layout which I pick from layout folder.
In this case I should not need to pass the same row layout as a constructor to the adapter, which is not allowed.
Please answer.
Regards
Utsav.
you can safely ignore it by overriding the constructor, like this:
public class MyAdapter extends ArrayAdapter {
public MyAdapter(Context context){
super(context, 0);
}
}
edit:
That exists for cases that you're not creating a custom adapter, e.g. new ArrayAdapter(context, R.layout.item);
This adapter would write the value of to string() of its data items to TextView with ID android.R.id.text1 inside that layout.

"ArrayAdapter requires the resource ID to be a TextView"

I basically know where this exception comes from and what causes it. It's because my textview is wrapped in an RelativeLayout.
But can you tell me why this works
playerAdapter = new PlayerAdapter(this,R.layout.item_lv_player,playerList);
lvPlayer.setAdapter(playerAdapter);
While this doesn't
PlayerAdapter playerAdapter1 = new PlayerAdapter(this,R.layout.item_lv_player,playerAdapterSource[0]);
spinnerPlayer1.setAdapter(playerAdapter1);
Shouldn't both of this throw an exception?
PlayerAdapater is a class that extends ArrayAdapter.
Is it because in the first example I'm using a ListView, and in the second one it's a Spinner? That wouldn't sound logical to me at all since the problem is the creation of the Adapter.
exception is not depends upon your adapter,its depends upon widgets.Every widgets has some properties,based on that only it will raise a exception,
Listview always depends upon Textview for all positions,but spinner not depending on that.If you run ListView without R.id.TextView it raise a nullpointer exception because of you have not initialized the textview in the adapter.But spinner doesnot because it not depending on the textview.
You have ArrayAdapter with 3 parameters passed to it.
The 3 parameter ArrayAdapter constructor can take any of the following parameters -
1) ArrayAdapter(Context context, int resource, int textViewResourceId)
2) ArrayAdapter(Context context, int resource, T[] objects)
The first one Explanation -
public ArrayAdapter (Context context, int resource, int
textViewResourceId)
Added in API level 1 Constructor
Parameters
context The current context.
resource The resource ID for a layout file containing a layout to
use when instantiating views.
textViewResourceId The id of the TextView within the layout
resource to be populated
The second one Explanation -
public ArrayAdapter (Context context, int resource, T[] objects)
Added in API level 1 Constructor
Parameters
context The current context.
resource The resource ID for a layout file containing a TextView to use when instantiating views.
objects The objects to represent in the ListView.
Having explained that for -
PlayerAdapter playerAdapter1 = new PlayerAdapter(this,
R.layout.item_lv_player,playerAdapterSource[0]);
spinnerPlayer1.setAdapter(playerAdapter1);
Is the last parameter a textViewResourceId ? > NO
Is the last parameter a ListView ? > NO
From developer docs android ArrayAdapter.

WORKS: Android Custom Component - access Array in strings.xml, supplied via layout.xml

I have class, which extends LinearLayout, in it there are Buttons and a Spinner.
This Object gets included via my layout XML file:
<com.ics.spinn.ComboBox android:id="#+id/myautocombo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:entries="#array/suppliers" />
/>
The array suppliers is defined in strings.xml.
If this component now wouldn't be com.ics.spinn.ComboBox, but a Spinner, Android would
auto-populate the "android:entries" to the Spinner adapter.
I'd like my component com.ics.spinn.ComboBox to behave the same way:
to be able to access the array defined via the xml file, so I can
supply it to the Spinner inside my component, via:
ArrayAdapter<String> a = new ArrayAdapter<String>(this.getContext(),android.R.layout.simple_spinner_dropdown_item, ARRAYINSIDEMYXML);
s.setAdapter(a);
I now I could access the array defined in strings.xml DIRECTLY via getResources().getStringArray(R.array.suppliers)
but my code shouldn't know of the name "suppliers", since it shall be supplied via android:entries...
This + the entries in xml in João Melo solution WORK:
public ComboBox(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray b = context.obtainStyledAttributes(attrs,
R.styleable.ComboBox, 0, 0);
CharSequence[] entries = b.getTextArray(R.styleable.ComboBox_myEntries);
if (entries != null) {
ArrayAdapter<CharSequence> adapter =
new ArrayAdapter<CharSequence>(context,
android.R.layout.simple_spinner_item, entries);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
}
}
I don't know if it's possible to do that with android:entries attribute unless your component extends Spinner, but I'm only guessing.
You can achieve that creating your own custom attribute in attrs.xml
<declare-styleable name="ComboBox">
<attr name="myEntries" format="reference"></attr>
</declare-styleable>
Then you can access this reference (int) inside your component and set the ArrayAdapter into your spinner.
TypedArray customAttrs = context.obtainStyledAttributes(attrs, R.styleable.ComboBox);
for (int i = 0; i < customAttrs.length(); i++) {
int attrValue = customAttrs.getIndex(i);
switch (attrValue) {
case R.styleable.ComboBox_myEntries:
mArrayId = customAttrs.getResourceId(attrValue, 0);
ArrayAdapter<String> a = new ArrayAdapter<String>(this.getContext(),android.R.layout.simple_spinner_dropdown_item, mArrayId);
s.setAdapter(a);
break;
}
}
On your layout, add this line xmlns:app="http://schemas.android.com/apk/res/yourPackageName" below xmlns:android="http://schemas.android.com/apk/res/android" in the root view:
Then you can instantiate your component and custom attrs via xml:
<com.ics.spinn.ComboBox android:id="#+id/myautocombo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
app:myEntries="#array/suppliers" />
/>
Don't know if this answer is exactly what you're looking for but it would behave just like android:entries. Hope it helps.
Try to load your array like this:
String[] array = getResources().getStringArray(R.array.recipes_string_array);
ArrayAdapter spinnerAdapter = new ArrayAdapter<String>(getActivity(), R.layout.simple_spinner_dropdown_item) {
#Override
public int getCount() {
return array.length;
}
#Override
public String getItem(int position) {
return array[position];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Create your item for the spinner and return it
return spinnerItemview;
}
}
spinner.setAdapter(spinnerAdapter);
Joala's answer above is technically correct, but there is a much simpler way of expressing it.
Instead of iterating over the StyledAttributes you can just ask for the resourceId of the StringArray directly.
// Get the DisplayValues from the XML config.
final TypedArray customAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.ComboBox);
final int resourceId = customAttrs.getResourceId(R.styleable.ComboBox_myEntries, -1);
if (resourceId == -1) {
throw new IllegalArgumentException("ComboBox requires a myEntries attribute that points to a string-array resource");
}
final ArrayAdapter<String> a = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_dropdown_item, resourceId);
s.setAdapter(a);

Limit AutoCompleteTextView to only one result

I'm using AutoCompleteTextView with a custom layout for the adapter. The problem is I don't know how to limit the results for only one at time, like in the default Layout.
I read that It's possible limiting the height, but doesn't work in all screens. Thanks for your attention.
I've this on my activity_main layout.
<AutoCompleteTextView android:id="#+id/autotext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:minWidth="480dp"
android:layout_weight="1"
android:maxLength="23"
android:maxLines="1"
android:textColor="#000000" />
And this is the adapter's layout.
<TextView android:id="#+id/textpop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="17sp"/>
Have a look at this code. It's basically the code for the SDK ArrayAdapter class with a small modification(which doesn't count). If you want to show only one suggestion in the AutoCompleteTextView then you could make a small modification to the class from the link, to the performFiltering() method like this:
// ... the rest of that method
if (newValues.size() > 1) { // if we have more than an item in the list
// get the first suggestion
T oneItem = newValues.get(0);
// empty the suggestion list
newValues.clear();
// add the only suggestion.
newValues.add(oneItem);
}
results.values = newValues;
results.count = newValues.size();
I found the above answer unsatisfactory, and the link is dead.
For the simplest way to do this, create a custom adapter and simply force the count to 1
class SingleArrayAdapter extends ArrayAdapter<String> {
public SingleArrayAdapter(Context context, int resource, String[] objects) {
super(context, resource, objects);
}
#Override
public int getCount() {
return 1;
}
}
You can create your own AutoCompleteTextView adapter which implement Filterable interface, or extend existing adapter, but override getFilter() method, create your own filter implementation, then you can customize filter logic and return any number of results you like.
You can refer to the ArrayFilter implementation in ArrayAdpater for reference.

Error: The type of the expression must be an array type but it resolved to ArrayList<String>

hi I created one simple xml based spinner application.i got all value in my xml file using sax parser. I have two spinner and one grid view, the 1st spinner display one array list value 2nd spinner display one array list. The same time grid view display some images in bottom. this process working fine. now i wish to create text with images spinner so i used row.xml file in my resource folder and i change my code also but i am getting error. what mistake i made in my code.....
error line:
label.setText(hltag_List[position]);
If it is a Arraylist , use hltag_List.get(position) .
label.setText(hltag_List.get(position));
please see you are using arraylist in constructor
public MyAdapter(Context context, int textViewResourceId, ArrayList<String> hltagList) {
super(context, textViewResourceId, hltagList);
}
whereas accessing its elements via array. just change your line to
label.setText(hltag_List.get(position));
Change your adapter code to following if, you have an array in datasource:
public MyAdapter(Context context, int textViewResourceId, String[] hltagList) {
super(context, textViewResourceId, hltagList);
}
and keep the line:
label.setText(hltag_List[position]);
I think you should use ArrayList.get(int index) to obtain the i-th object in the list.

Categories

Resources