Merhaba arkadaşlar, Bu dersimizde Expandable ListView i anlatacağım. ListView türünden meydana gelen fakat ona göre biraz karmaşık bir yapıya sahip olan bu android bileşeni ile alt alta verileri listeleme yapabileceğimiz gibi bunları belirli başlıklar altında gösterebiliriz. Kısaca mantığını açıklayacak olursam, ana bir başlık altında listeleyeceğimiz elemanlarımız olacaktır. Ana başlığımızı parent olarak kabul edersek, elemanlarımızda ilgili parent lara bağlı olan veriler olacaktır. Her listview’in içini doldurmamız ve istediğimiz tarzda hazırlamamız için bir bir Adapter gereklidir bu durum Expandable ListvView içinde geçerlidir. Bu yüzden ana classımız dışında bir de Adapter oluşturacağız.
Biraz önce bahsettiğim gibi iki çeşit bileşen kullanmamız gerecek birini parent olarak düşüneceğiz ve şimdi oluşturacağız. Bu parent bileşeni için layout xml (listview_header.xml) kısmını yaratalım. Bunu daha iyi anlamak için şöyle açıklayalım; ana başlık olarak başlığın tipini oluşturup, başlık kısmınında arka plan rengini aşağıdaki kod ile oluşturmuş olacağız. Her bir başlığımızı parent olarak nitelendirdik bunu daha iyi kavrayabilmeniz için söyledim çünkü her bir ailenin (parent) ın çocukları (child) olduğunu düşünürsek bu yapının mantığını daha iyi anlamış oluruz. (Linked List bileşenini bilenler için bir çağırışım yapmış olabilir bu konu, mantık olarak benzer, içerik olarak tabiki de farklıdır )
Android Expandable ListView
listview_header.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#ffff00" > <TextView android:id="@+id/txt_parent" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Medium Text" android:textColor="#000000" android:textAppearance="?android:attr/textAppearanceMedium" /> </LinearLayout>
listview_header.xml oluşturduktan sonra şimdi ise listview_child.xml layout kısmını oluşturalım. Parent larımıza bağlı olan değişkenlerimiz de yazı yani TextView ler yer almasını istiyoruz. Bunun oluşturulması ise gayet basit aşağıdaki kodu incelersek göreceğiz.
listview_child.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/txt_items" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusableInTouchMode="false" android:text="Medium Text" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#000000" /> </LinearLayout>
Şimdi de Main sınıfının layout xml ine bakalım. Burda android bileşenlerinden id sini expand_listview yaptığımız ExpandableListView i yerleştirelim.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.com.project.expandablelistview.MainActivity" > <ExpandableListView android:id="@+id/expand_listview" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/arkaplannew" > </ExpandableListView> </RelativeLayout>
ExpandableListView bileşenini de ekledikten sonra şimdi içini doldurmak için oluşturmamız gereken adapter ımızı yaratalım.
Adapterımızı BaseExpandableListAdapter tipinden türetmek için extends ediyoruz. Böylece unimplemented methods karşımıza çıkacaktır bu sınıftan türetmeye çalıştığımızda methodumuzu kullanabilmemiz için hazır fonksiyonları tanımlamamız gerekecektir. Bu methodları ekle dediğimiz zaman da otomatik olarak bu fonksiyonlar kod kısmımıza eklenecektir.
public class ExpandListViewAdapter extends BaseExpandableListAdapter{ public List<String> list_parent; public HashMap<String, List<String>> list_child; public Context context; public TextView txt; public TextView txt_child; public LayoutInflater inflater; @Override public int getGroupCount() { return list_parent.size(); } public ExpandListViewAdapter(Context context, List<String> list_parent,HashMap<String, List<String>> list_child) { this.context = context; this.list_parent = list_parent; this.list_child = list_child; } @Override public int getChildrenCount(int groupPosition) { return list_child.get(list_parent.get(groupPosition)).size(); } @Override public Object getGroup(int groupPosition) { return list_parent.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return list_child.get(list_parent.get(groupPosition)).get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View view, ViewGroup parent) { String title_name = (String)getGroup(groupPosition); if(view == null) { inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.listview_header,null); } txt = (TextView)view.findViewById(R.id.txt_parent); txt.setText(title_name); return view; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) { // kaçıncı pozisyonda ise başlığımızın elemanı onun ismini alarak string e atıyoruz String txt_child_name = (String)getChild(groupPosition, childPosition); if(view==null) { inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.listview_child, null); // fonksiyon adından da anlaşılacağı gibi parent a bağlı elemanlarının layoutunu inflate ediyoruz böylece o görüntüye ulaşmış oluyoruz } if(getGroup(groupPosition).toString().equals("GALATASARAY")) { // Eğer başlığımızın ismi GALATASARAY ise elemanlarının yer aldığı arka plan rengini kırmızı yapıyoruz view.setBackgroundColor(Color.RED); } else if(getGroup(groupPosition).toString().equals("FENERBAHCE")) { // Eğer başlığımızın ismi FENERBAHCE ise elemanlarının yer aldığı arka plan rengini mavi yapıyoruz view.setBackgroundColor(Color.BLUE); } // listview_child ulaştığımıza göre içindeki bileşeni de kullanabiliyoruz daha sonradan view olarak return ediyoruz txt_child = (TextView)view.findViewById(R.id.txt_items); txt_child.setText(txt_child_name); return view; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; // expandablelistview de tıklama yapabilmek için true olmak zorunda } }
Yukarıdaki kodun içinde gerekli açıklamaları yapmaya çalıştım. Hangi parentımıza bağlı kaç tane elemanımız var getChildren methodu ile anında bulabiliriz. getChildView ve getGroupView methodları parentlarımız ile birlikte childlarımız için önceden oluşturmuş olduğumuz layout kısmına ulaşmamızı ve görsel olarak ExpandableListView bileşenini şekillendirmemize yardımcı olur. Adapter kısmını da hallettiğimize göre MainActivity sınıfımıza bakalım.
public class MainActivity extends Activity { public List<String> list_parent; public ExpandListViewAdapter expand_adapter; public HashMap<String, List<String>> list_child; public ExpandableListView expandlist_view; public List<String> gs_list; public List<String> fb_list; public int last_position = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); expandlist_view = (ExpandableListView)findViewById(R.id.expand_listview); Hazırla(); // expandablelistview içeriğini hazırlamak için // Adapter sınıfımızı oluşturmak için başlıklardan oluşan listimizi ve onlara bağlı olan elemanlarımızı oluşturmak için HaspMap türünü yolluyoruz expand_adapter = new ExpandListViewAdapter(getApplicationContext(), list_parent, list_child); expandlist_view.setAdapter(expand_adapter); // oluşturduğumuz adapter sınıfını set ediyoruz expandlist_view.setClickable(true); expandlist_view.setOnChildClickListener(new OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { String child_name = (String)expand_adapter.getChild(groupPosition, childPosition); //Toast.makeText(getApplicationContext(),"hey" + child_name, Toast.LENGTH_LONG).show(); AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setMessage(child_name) .setTitle("Mobilhanem Expandablelistview") .setCancelable(false) .setPositiveButton("TAMAM", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); AlertDialog alert = builder.create(); alert.show(); return false; } }); /* expandlist_view.setOnGroupExpandListener(new OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { if(last_position != -1 && last_position != groupPosition) { expandlist_view.collapseGroup(last_position); } last_position = groupPosition; } }); */ } public void Hazırla() { list_parent = new ArrayList<String>(); // başlıklarımızı listemelek için oluşturduk list_child = new HashMap<String, List<String>>(); // başlıklara bağlı elemenları tutmak için oluşturduk list_parent.add("GALATASARAY"); // ilk başlığı giriyoruz list_parent.add("FENERBAHCE"); // ikinci başlığı giriyoruz gs_list = new ArrayList<String>(); // ilk başlık için alt elemanları tanımlıyoruz gs_list.add("Muslera"); gs_list.add("Sabri"); gs_list.add("Chejdou"); gs_list.add("Semih Kaya"); gs_list.add("Telles"); gs_list.add("Selçuk İnan"); gs_list.add("Felipe Melo"); gs_list.add("Hamit"); gs_list.add("Weslej Sneijder"); gs_list.add("Bruma"); gs_list.add("Burak Yılmaz"); fb_list = new ArrayList<String>(); // ikinci başlık için alt elemanları tanımlıyoruz fb_list.add("Volkan Demirel"); fb_list.add("Gökhan Gönül"); fb_list.add("Bekir"); fb_list.add("Caner Erkin"); fb_list.add("Mehmet Topal"); fb_list.add("Emre"); fb_list.add("Alper Potuk"); fb_list.add("Mehmet Topuz"); fb_list.add("Diego"); fb_list.add("Sow"); fb_list.add("Emenike"); list_child.put(list_parent.get(0),gs_list); // ilk başlığımızı ve onların elemanlarını HashMap sınıfında tutuyoruz list_child.put(list_parent.get(1), fb_list); // ikinci başlığımızı ve onların elemanlarını HashMap sınıfında tutuyoruz } }
MainActivity sınıfımız için açıklamaları yine kod kısmında yapmaya çalıştım. ExpandableListView imizi oluştururkan Adapter sınıfını kullanarak içini dolduruyoruz. Hazırla fonksiyonu Adapterımızda kullanacağımız HashMap ve List imizi hazırlamamıza yardımcı oluyor kod a bakarsak gerekli açıklamaları göreceksiniz.
Adapterı set ettikten sonra parent larımızın elemanlarına ulaşmak yani child lara ulaşmak için ExpandableListView imize setOnChildClickListener özelliğini veriyoruz. Hangi child a tıklıyorsak onun içindeki değeri Alert Dialog yapımızı oluşturarak mesaj kısmında gösteriyoruz. Tıklama olayında ise, adapterımızın getChild fonksiyonuna ulaşarak groupPosition ve childPosition parametrelerini vererek tıklamış olduğumuz child a doğru bir şekilde ulaşmış olduk daha sonra onu String e cast ederek child_name değişkeninin içine attık. Alert Dialog kullanarak da child_name değerini kullanıcıya gösterdik.
Not: Tıkladığımız child a ulaşabilmek için Adapterımızın içinde yer alan isChildSelectable fonksiyonun true return etmesi gerektiğine dikkat edelim. Eğer tıkladığınızda child lara ulaşamıyorsanız muhtemelen bu fonksiyonda return false demektir.
ExpandableListView bileşenine setOnGroupExpandListener özelliğini verdiğimizde ise tıklama olayında gerçekleşebilecek işlemleri yapabilmemize yardımcı olur kod lara baktığınızda yorum içine aldığım yeri açıp incelerseniz eğer her bir parent a tıkladığım an diğer parent açık ise kapanmasını sağlar. Zaten yorumları kaldırmadan çalıştırdığınız an ise, hangi parent a tıklıyorsak o açılır konuma geçer ve parent lar birbirinden etkilenmezler.
Evet gördüğünüz gibi ExpandableListView bileşenini sizlere anlatmaya çalıştım. Kaynak kodu indirip uygulamayı çalıştırdığınız anda ise Galatasaray ve Fenerbahçe’nin ilk 11 lerini göreceksiniz 🙂 bu kavramı böyle bir uygulama yaparak anlatmak istedim umarım faydalı olmuştur. Konu hakkında soru ve önerilerinizi çekinmeden yorum bırakabilirsiniz. Bol Android’li günler sizin olsun
Sizlerden ricamız facebook.com/mobilhanem sayfamızı beğenmenizdir. Birdahaki dersimize kadar kendinize iyi bakın.
Tüm Android Ders, Proje ve Kaynak Kodlar için tıklayınız.
güzel paylaşım tşk ederiz çoğu kişiye yararlı olacak birbilgi
önemli değil insallah devam edeceğiz işe yarar dersler paylaşmaya kolay gelsin 🙂
Bu listeye checkbox nasıl ekleyebiliriz
Merhabalar, check box ekleyebilmek için , custom olarak listview oluşturma mantığı ile aynı View Holder ismini verdiğimiz bir class oluşturabilirsiniz daha sonradan burda check box ı belirtip ExpandListViewAdapter methodu var incelersen onun içinde set edebilirsin. listview_child.xml de yaratmayı da unutma check box u. Daha iyi kafanda oluşması açısından bu link deki örneğe de bakabilirsin. http://custom-android-dn.blogspot.com.tr/2013/01/how-to-create-custom-expandablelistview.html . Kolay gelsin.
Tamamdır deneyeceğim teşekkürler.
Hocam iyi akşamlar…
Bu açılabilir liste de listeden herhangi bir elemana tıklayınca başlığı ve içeriği göstermesini nasıl sağlarız acaba…
mesela Muslera nın üzerine tıklayınca Muslera nın hakkında bilgi verecek… Doğum tarihi yaşı gibi bilgileri
Merhabalar,
Kodu incelerseniz eğer expandable listview e tıklanınca setOnChildClickListener çalışıyor o kodun içinde de childPosition u alabiliyorsun böylece tıklamış olduğun hangi item ise ona ulaşmış olursun.. yazmış olduğum bu kodu incele altında Toast mesajı var, yorumu kaldır uygulamayı çalıştırınca görüceksin ki tıkladığın ne ise onun ismini gösterecek.. kolay gelsin
String child_name = (String)expand_adapter.getChild(groupPosition, childPosition);
Alper hocam cevabınız için çok teşekkür ederim:)
Hocam ilginize teşekkür ederim… Dediğinizi yaptım ancak benim dediğim toast mesajı değilde Sabri yazan yere sabri ile ilgili bilgiler… Resimde yazdım
Pop up yani AlertDialog içinde mi olacak ?
evet Hocam
Merhabalar,
Toast mesajı kullanmayacaksan eğer ve şekilde gösterdiğin gibi bir yapı kurmak istiyorsan, Custom Alert Dialog yapmalısın android in kendi Alert Dialog yapısını özelleştirmen gerekiyor. bunu incelersen eğer nasıl olduğunu anlayacaksın.. kolay gelsin.. yine takılırsan sorabilirsin http://www.android-ios-tutorials.com/android/custom-android-dialog-alertdialog-example/
Alper Hocam arkadaşları farklı siteye yönlendirmek yerine Türkçe kaynak kodlu kendi dersimize yönlendririrseniz sevinirim:))
http://www.mobilhanem.com/android-custom-dialog-alert-dialog-yapimi/
Türkçe kaynak ararsanda bizim dersimize bakabilirsin Fragment kullanılarak yapıldı incelersin, ama yok ben fragment yapısını uygulamamda kullanmak istemiyorum dersen eğer activity yapısı içinde de kullanabilirsin karar senin.. iki linkide incele, geri dönüş yaparsanda sevinirim buraya http://www.mobilhanem.com/android-custom-dialog-alert-dialog-yapimi/
Telefon rehberine ulaşıyorum ama içindeki bilgileri göremiyorum yardımcı olur musunuz
bu dersimizi incelemelisiniz http://www.mobilhanem.com/android-listview-fragment-telefon-rehberi-uygulamasi/
Mesela muslera nın içine edit text nasıl koyabiirim
yukarıdaki yapıyı incelersen eğer listview_child.xml layoutunu göreceksin orada sadece TextView kullanıldığım için sadece yazılar ortaya çıkıyor onu özelleştirmen gerekiyor LinearLayout’un ( horizontal ) içine atarsın TextView ile EditText i böylece yazıların yanında Edittext ler oluşur. Sadece “muslera” nın yanında olmasını istiyorsanda adapter kısmında ilk elemana göre düzenlersin anlattığım şekilde
Merhabalar altI üstü bir açılıp kapanabilir menu yapcaz kodlar da çok uzun üstelik sınav da burdan sorumluyum nasıl olcak bilmiyorum . Kodlara bakıyorum kodlar bana kisacasi atın beni denizlere ?????
Merhabalar, kodları incelemeye çalışınca mantığını anlamaya çalışın listview yapısına iyi bir şekilde hakimseniz expandeble listview i anlamanız daha kolay olacaktır., ayrıca bütün kod yapısını baştan sona yaz demeyecektir heralde hocanız demi 🙂
Yaz diyeceği için atın beni denizlere diyorum ya???
acilir pencerinin alt ögelerine button click yapip baska bir activity sayfasina gitme sansimiz varmidir acaba?
meraba firebase üzerinde exapdable listview yapısını kullanıyorum ama benim yapım bi parent kismi ve sadece child icin gecerli alt menununde altını yapabilecegim bi kaynak yardımcı olur musunuz lütfen
Merhaba, öncelikle çok teşekkürler, harika bir anlatım olmuş. Benim yapmaya çalıştığım şey bir expandable içinde başka bir tanesi daha açılsın ve içiçe açılabilen itemlerın . ben bunu nasıl sağlayabilirim?:)