I am trying to make a custom style for android spinner, however there are several problems.
I have noticed in many examples, they pass array to getCustomView method. I am wondering whether I can pass a list instead of an array.
Second problem is why they have declared variable and initialized in class variable scope?
They have declared arrays like this.
String []data1={"Brainbitz:java","Brainbitz:Android","Brainbitz:Embedded Systems","Brainbitz:PHP"};
in class variable scope. But when I try to do for the list I get an error. why?
Third is,
If we can pass list to getCustomView how do I do that? Here is the link to the tutorial tutorial
I am considering this source code.
public View getCustomView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.spinner, parent, false);
TextView label=(TextView)row.findViewById(R.id.textView1);
label.setText(list3.get(position));
// TextView sub=(TextView)row.findViewById(R.id.textView2);
// sub.setText(data2[position]);
//
// ImageView icon=(ImageView)row.findViewById(R.id.imageView1);
// icon.setImageResource(images[position]);
return row;
}
In above code I don't know the syntax to pass position to list3 list type reference.
Please be kind enough to explain this.
First of All,
You are using default ArrayAdapter Class..
new ArrayAdapter<String>();
Which Uses String class for data bind. If you want to make an ArrayAdapter with a ArrayList or List you have to make a Custom Adapter by extending ArrayAdapter<Custom_Class> or BaseAdapter.
The ArrayAdapter class can handle any Java object as input. It maps the data of this input to a TextView in the layout.
ArrayAdapter uses the toString() method of the data input object to determine the String which should be displayed.
Look at How to use ArrayAdapter<myClass> and this Tutorial
Update:
public class MyAdapter extends ArrayAdapter<String>
{
private List<String> listString = new ArrayList<String>();
public MyAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
listString = objects;
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.spinner, parent, false);
TextView label=(TextView)row.findViewById(R.id.textView1);
label.setText(listString.get(position)); // How to use listString
.
.
.
Here is the corrected solution,
public class MyAdapter extends ArrayAdapter<String>
{
public MyAdapter(Context context, int textViewResourceId,List<String> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
}
#Override
public View getDropDownView(int position, View convertView,ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.spinner, parent, false);
TextView label=(TextView)row.findViewById(R.id.textView1);
label.setText(list3.get(position));
// TextView sub=(TextView)row.findViewById(R.id.textView2);
// sub.setText(data2[position]);
//
// ImageView icon=(ImageView)row.findViewById(R.id.imageView1);
// icon.setImageResource(images[position]);
return row;
}
}
Basiclly, I had done 1 mistake, one is I hadnt initalised constructor correctly.
Related
I'm creating an app for a bus station, to give the schedule. For that i'm using a custom listview. Here it is:
class custom_adapter extends ArrayAdapter<String>{
public custom_adapter(Context context, ArrayList<String> horarios) {
super(context, R.layout.costum_listview ,horarios);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater horarioInflater = LayoutInflater.from(getContext());
View costumView = horarioInflater.inflate(R.layout.costum_listview, parent, false);
String singleHorario = getItem(position);
TextView hora = (TextView) costumView.findViewById(R.id.Hora);
TextView nota = (TextView) costumView.findViewById(R.id.Nota);
hora.setText(singleHorario);
nota.setText(" ");
return costumView;
}
}
Now as you can see I have just 2 texViews yet, the "hora" is to show the timers of the bus, the "nota" is for some notes, like someday the bus don't go or something like that. And my problem is exactly on that "nota" textview. I have dozens of arrayList's passing to this custom ListView, and so dozens and dozens of timers, and there are some timers that I need to put a note and other that I don't. So, can I had another argument to this custom ListView, like a boolean or something, so I can do a if / else in that code to put a note on each one. What do I need to change in order to do that ? I've been trying, but didn't quite managed to do that.
Instead of using a String as the argument for your ArrayAdapter, create a custom class and use that instead.
That way you can pass all the information you want into the adapter and show it however you like.
public class custom_adapter extends ArrayAdapter<MyClass>{
public custom_adapter(Context context, ArrayList<MyClass> horarios) {
super(context, R.layout.costum_listview ,horarios);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater horarioInflater = LayoutInflater.from(getContext());
View costumView = horarioInflater.inflate(R.layout.costum_listview, parent, false);
MyClass singleHorario = getItem(position);
TextView hora = (TextView) costumView.findViewById(R.id.Hora);
TextView nota = (TextView) costumView.findViewById(R.id.Nota);
hora.setText(singleHorario.hora);
nota.setText(singleHorario.nota);
return costumView;
}
And the new class
public class MyClass {
public String hora;
public String nota;
}
How about making a class for holding two values 'hora' and 'nota', and with, lets say, boolean isNotaAvailable() method. Then in getView() you just make something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater horarioInflater = LayoutInflater.from(getContext());
View costumView = horarioInflater.inflate(R.layout.costum_listview, parent, false);
YourClassName singleHorario = getItem(position);
TextView hora = (TextView) costumView.findViewById(R.id.Hora);
TextView nota = (TextView) costumView.findViewById(R.id.Nota);
// set hora text
hora.setText(singleHorario);
// check if nota is available, if true - set nota text
if(singleHorario.isNotaAvailable()) {
nota.setText(singleHorario.getNota())}
else nota.setVisibility(View.GONE);
return costumView;
}
It's just an idea, tell me if it helps :)
Just extend BaseAdapter, so you can define the data structure.
class custom_adapter extends BaseAdapter
change ArrayList<String> horarios to ArrayList<Data> horarios
And the Data can be
public class Data{
private String hora;
private String nota;
private boolean shouldShowNota;
//write getter and setter here
}
at last, read the data in getView
Data data = getItem(position);
if (data.getShouldShowNota) {
nota.setText(data.getNote);
}
hora.setText(data.getHora);
I need to customize this listview, I wonder how I could do to put the buttons and an identifier of different colors to distinguish them.
Anyone know how it could be the xml? and how it could change colors ?? is there any component in android? or I could use an imageview to the colors?
I appreciate your help.
You should use a custom class, to create the Adapter for the List, and that class has to extend the BaseAdapter class. In this class, you have to implement the following methods:
public int getCount()
public Object getItem(int position)
public long getItemId(int position)
public View getView(int position, View convertView, ViewGroup parent)
In the last one, you can get a LayoutInflater, and load a view from .xml. In that .xml, you can define the layout of one row. Here's an example from one of my projects:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// menuItems is an ArrayList of Strings
final String menu = menuItems.get(position);
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.list_mainmenu_row, null);
TextView menuText = (TextView) view.findViewById(R.id.menuListRow_menuItem);
menuText.setText(menu);
return view;
}
I have a listView of custom views. Each view contains an editText. I'm trying to add listeners to the editText variables which I create in the getView(). The problem is that when I create the listeners it doesn't let me use the editText variable unless I make it final, but if I make it final, I guess I'm going to have problems when the row gets reused. This is a simple example of what my problem is:
private class MyAdapter extends ArrayAdapter<Date>{
public MyAdapter(Context context, int resource, int textViewResourceId,
List<Date> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.listview_cell_single, parent, false);
}else{
row = convertView;
}
EditText et = (EditText) row.findViewById(R.id.editText_single);
et.setText("" + position);
et.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
et.setText("You edited row: " + position);
//Error: et must be final, position must be final
}
}
});
You should declare this EditText et as a class variable in MyAdapter. As
private class MyAdapter extends ArrayAdapter<Date>{
EditText et;
}
And then initiate it in getView(); method.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//do your stuff
........
et=(EditText) row.findViewById(R.id.editText_single);
}
This is a contract between scopes, i.e. the stack versus the heap. The reference created on the stack must be final to declare that the reference will not (and cannot) be changed since the reference is basically bound by the anonymous class (OnFocusChangeListener) using it.
The reference will not be reused since each stack will get its own copy of the reference to the EditText object.
I have a spinner and I have added a custom style to spinner. Problem is when I select an item it doesnt show up on the spinner but when I use android spinner style it shows what I selected on the spinner. Is there any more coding to add to make it work? Otherwise everthing of the spinner works. I have written the app when an item is selected in spinner to show a text. These things work. But it doesnt show what I selected.
Here is my code
MyAdapter dataAdapter3 = new MyAdapter(this, R.layout.spinner, list3);
spinner1.setAdapter(dataAdapter3);
list 3 referes a list
List<String> list3 = new ArrayList<String>();
Here is the class for custom spinner style
public class MyAdapter extends ArrayAdapter<String>
{
private List<String> listString = new ArrayList<String>();
public MyAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
this.listString = objects;
}
#Override
public View getDropDownView(int position, View convertView,ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.spinner, parent, false);
TextView label=(TextView)row.findViewById(R.id.textView1);
label.setText(listString.get(position));
return row;
}
}
please can anybody tell whether I have done any mistake here?
This is how spinner is shows when I selected item
I tried several days on this problem. Actually code is pretty ok. problem was in the spinner.xml file. I had added a large padding to textview. Therefore, though spinner works it is not visible the selected item on spinner. Point is I forget xml file. :D
Modify the padding in the layout spinner.xml file to a lower value,
for ex:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="#000000"
android:textSize="14sp" />
I want to have an access to another XML file in an inner class but I can't get a reference to the other XML components, this an inner class code:
class ItemsClass extends ArrayAdapter<String>
{
public ItemsClass ()
{
super(ListActivity.this, R.layout.itemslist);
}
public View getView (final int position, View convertview, ViewGroup parent)
{
//setContentView(R.layout.itemslist);
final String s = this.getItem(position);
LayoutInflater inflater= getLayoutInflater();
View row= inflater.inflate(R.layout.itemslist, parent, false);
// get ref to each component in itemList.xml
TextView itemName= (TextView) row.findViewById(R.id.textView1);// here i can't access to the TextView in itemslist.xml
}
}
View row= inflator.inflate(R.layout.itemslist, null);
read this
http://www.vogella.de/articles/AndroidListView/article.html
I am not sure why you are trying to using the same xml for both the main activity & the row component.I think you need to reiterate your code,check about the neccesity of the usage of the constructor here.Cheers.