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