Przykład, który tu zostanie przedstawiony można pobrać z chomika: (link)
Layouty
Na potrzeby tego przykładu przygotowałem 3 layouty - jeden główny, dla aplikacji, oraz 2 używane przez spinnera:
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:gravity="center_horizontal" android:layout_marginBottom="20dip" /> <Spinner android:id="@+id/spinner" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>
spinner_view1.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/spinner_title" android:text="EXAMPLE TEXT" android:gravity="center_horizontal"/> </LinearLayout>
spinner_view2.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:layout_weight="1" android:layout_width="0dip" android:layout_height="fill_parent" android:id="@+id/spinner_icon" android:src="@drawable/ic_launcher"/> <TextView android:layout_weight="1" android:layout_width="0dip" android:layout_height="fill_parent" android:id="@+id/spinner_title" android:text="EXAMPLE TEXT" android:gravity="center"/> </LinearLayout>Jak widać nie ma tu wielkich szaleństw, ot Spinner, TextView i ImageView :)
Activity
Po stworzeniu layoutów i generalnie wiedząc co chcemy wyświetlać czas przenieść się do aktywności, która tym wszystkim będzie zarządzać.package runaurufu.example.spinner; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; public class AndroidSpinnerActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // list of elements displayed in spinner String[] objects = new String[]{ "Object 1", "Object 2", "Object 3", "Object 4"}; Spinner spin = (Spinner)findViewById(R.id.spinner); // here we use default android simple_spinner_item so we do not need to worry about // display while in normal (not in dropdown) view spin.setAdapter(new CustomAdapter(spin, this, android.R.layout.simple_spinner_item, objects)); } public class CustomAdapter extends ArrayAdapter<String> { Spinner spinner = null; String[] headers = null; public CustomAdapter(Spinner spinner, Context context, int textViewResourceId, String[] objects) { super(context, textViewResourceId, objects); // this will allow us to use spinner view inside of our code this.spinner = spinner; // this will allow us to set proper values for views on specified positions headers = objects; } @Override public View getDropDownView(int position, View convertView,ViewGroup parent) { LayoutInflater inflater=getLayoutInflater(); View row; // here we check if currently selected position match currently rendered position if(spinner.getSelectedItemPosition() == position) { row=inflater.inflate(R.layout.spinner_view2, parent, false); // be sure to find views using inflated view and not default Activity view TextView tv = (TextView)row.findViewById(R.id.spinner_title); tv.setText(headers[position]); ImageView iv = (ImageView)row.findViewById(R.id.spinner_icon); iv.setImageResource(R.drawable.ic_launcher); } else { row=inflater.inflate(R.layout.spinner_view1, parent, false); TextView tv = (TextView)row.findViewById(R.id.spinner_title); tv.setText(headers[position]); } return row; } @Override public View getView(int position, View convertView, ViewGroup parent) { /* this makes adapter to use default layout posted to it in constructor * in that example it will use android.R.layout.simple_spinner_item */ return super.getView(position, convertView, parent); } } }
Jak widać cudów niewidów nie ma, a sam kod jest raczej krótszy niż dłuższy. Z ciekawostek warto wspomnieć o tym, że generalnie stworzony spinner używa 3 layouty dla generowania obiektów - standardowy android.R.layout.simple_spinner_item dla elementów wyświetlanych na kontrolce oraz spinner_view1/spinner_view2 dla elementów renderowanych wewnątrz dropView. Takie wykorzystanie adapterów może nie jest jakimś wielkim popisem umiejętności, ale wbrew pozorom nie jest oczywiste.
Drugą istotną rzeczą, która w sumie stanowi clue tego wpisu jest sam warunek określający czy generujemy widok zaznaczony, czy też nie.
if(spinner.getSelectedItemPosition() == position)Tutaj przyznam szczerze, że mimo wielu prób nie udało mi się tego rozwiązać w sposób inny niż poprzez przesłanie do adaptera obiektu, na którym będzie on pracował. Jak znajdę lepszy sposób to z pewnością wpis ten poprawię, a póki co zostaje mi się cieszyć z tego co mam :)
Rezultat
Aplikacja po uruchomieniu i kliknięciu w spinnera na emulatorze prezentuje się nadzwyczaj dobrze. Oczywiście można tutaj o wiele więcej ostylować, dodać kolorowe tła, różne radiobuttony, checkboxy i inne cuda nieznane jaskiniowcom - jednak generalna zasada działania pozostaje taka sama, a cel zrealizowany - element obecnie wybrany jest wyróżniony.Plik projektu jak zawsze można pobrać z mojego chomika: (link)
Brak komentarzy:
Prześlij komentarz