آموزش ساخت ExpandableListView در برنامه نویسی اندروید
سلام دوستان در این سری از آموزش برنامه نویسی اندروید به آموزش ساخت ExpandableListView در برنامه نویسی اندروید می پردازیم همانطور که از نام آن پیداست یعنی ما یکسری گروه داریم که هر گروه دوباره خودش شامل یکسری child می شود پس قال Expand و collaps است همانند آموزش قبلی که برای Recyclerview ایجاد کرده بودیم باید عمل کنیم و با این فرق که آداپتور ما در اینجا کمی فرق می کند دا ادامه با ما همراه باشید.
پیش نمایشی از آن را قبل از استفاده باهم میبینیم.
ابتدا امر یک فایل به نام activity_main.xml ایجاد کرده و ExpandableListView را در آن قرار دهید یا از کد زیر استفاده کنید.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <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" tools:context=".MainActivity"> <ExpandableListView android:id="@+id/expandableListView" android:layout_height="match_parent" android:layout_width="match_parent" android:indicatorLeft="?android:attr/expandableListPreferredItemIndicatorLeft" android:divider="@android:color/darker_gray" android:dividerHeight="0.5dp" /> </RelativeLayout> |
در بالا از android:indicatorLeft برای قرار دادن یک عکسی که زمانی که روی آن کلیک می شود استفاده شده است با این ویزگی در سمت چپ قرار می گیرد.
android:divider خط جدا کننده هر یکی از لیست های ما را تنظیم می کند ما از یک رنگ استفاده کردیم.
android:dividerHeight فاصله هر کدام از Diver ها را تنظیم می کند.
حالا باید یک فایل به نام list_group.xml درست کنیم این فایل گروه های ما را تشکیل می دهد (شکل ظاهر هر گروه)
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/listTitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft" android:textColor="@android:color/black" android:paddingTop="10dp" android:paddingBottom="10dp" /> </LinearLayout> |
حالا باید یک فایل به نام list_item.xml درست کنیم این فایل child های ما هستند یعنی با کلیک بروی هر گروه باید یکسری Child نمایش داده شود.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/expandedListItem" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft" android:paddingTop="10dp" android:paddingBottom="10dp" /> </LinearLayout> |
حالا باید یک کلاس ایجاد کنیم که یکسری داده sample را در list قرار دهد. پس فایل ما برابر با ExpandableListDataPump.java می شود و کد های زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package ir.programchi; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class ExpandableListDataPump { public static HashMap<String, List<String>> getData() { HashMap<String, List<String>> expandableListDetail = new HashMap<String, List<String>>(); List<String> cricket = new ArrayList<String>(); cricket.add("Iran"); cricket.add("Pakistan"); cricket.add("Australia"); cricket.add("England"); cricket.add("South Africa"); List<String> football = new ArrayList<String>(); football.add("Brazil"); football.add("Spain"); football.add("Germany"); football.add("Netherlands"); football.add("Italy"); List<String> basketball = new ArrayList<String>(); basketball.add("United States"); basketball.add("Spain"); basketball.add("Argentina"); basketball.add("France"); basketball.add("Russia"); expandableListDetail.put("CRICKET TEAMS", cricket); expandableListDetail.put("FOOTBALL TEAMS", football); expandableListDetail.put("BASKETBALL TEAMS", basketball); return expandableListDetail; } } |
در بالا سه تا آرایه درست کردیم که در هر کدام یکسری آیتم تعریف کردیم و برای اینکه یک گروه و child های آن را ایجاد کنیم از Hash map استفاده کردیم و مقدار را در لیست قرار داده ایم.
کد زیر را نگاه کنید
1 | expandableListDetail.put("CRICKET TEAMS", cricket); |
اولین مقدار ورودی می شود نام گروه ما و مقدار دومی می شود child های ما که باید به صورت List های آرایه شکل باشند.
حالا برای اینکه این مقدار ها در ExpandableListView قرار گیرد باید یک آداپتور درست کنیم پس یک فایل به نام CustomExpandableListAdapter.java ایجاد کنید و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | package ir.programchi; import java.util.HashMap; import java.util.List; import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.TextView; public class CustomExpandableListAdapter extends BaseExpandableListAdapter { private Context context; private List<String> expandableListTitle; private HashMap<String, List<String>> expandableListDetail; public CustomExpandableListAdapter(Context context, List<String> expandableListTitle, HashMap<String, List<String>> expandableListDetail) { this.context = context; this.expandableListTitle = expandableListTitle; this.expandableListDetail = expandableListDetail; } @Override public Object getChild(int listPosition, int expandedListPosition) { return this.expandableListDetail.get(this.expandableListTitle.get(listPosition)) .get(expandedListPosition); } @Override public long getChildId(int listPosition, int expandedListPosition) { return expandedListPosition; } @Override public View getChildView(int listPosition, final int expandedListPosition, boolean isLastChild, View convertView, ViewGroup parent) { final String expandedListText = (String) getChild(listPosition, expandedListPosition); if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) this.context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.list_item, null); } TextView expandedListTextView = (TextView) convertView .findViewById(R.id.expandedListItem); expandedListTextView.setText(expandedListText); return convertView; } @Override public int getChildrenCount(int listPosition) { return this.expandableListDetail.get(this.expandableListTitle.get(listPosition)) .size(); } @Override public Object getGroup(int listPosition) { return this.expandableListTitle.get(listPosition); } @Override public int getGroupCount() { return this.expandableListTitle.size(); } @Override public long getGroupId(int listPosition) { return listPosition; } @Override public View getGroupView(int listPosition, boolean isExpanded, View convertView, ViewGroup parent) { String listTitle = (String) getGroup(listPosition); if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) this.context. getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.list_group, null); } TextView listTitleTextView = (TextView) convertView .findViewById(R.id.listTitle); listTitleTextView.setTypeface(null, Typeface.BOLD); listTitleTextView.setText(listTitle); return convertView; } @Override public boolean hasStableIds() { return false; } @Override public boolean isChildSelectable(int listPosition, int expandedListPosition) { return true; } } |
کلاس ما به BaseExpandableListAdapter گسترش (Extend) پیدا کرده شکل کلی کار به این صورت است که ما باید view هر گروه و هر child را به دست بیاریم در هر صورت هر دوباید به شکل آرایه باشند و بخش دوم باید این لیست ها شمارش شوند چرا که نیاز داریم به اندازه ای که داده وارد می شود نمایش داده شود باید index یا postion هر کدام را به دست بیاریم چون باید داده را در آن قرار بدهیم و نیاز داریم هر کدام از آنها یک id مشخص داشته باشند تا درصورت نیاز به ایجاد کلیک (click) بتوانیم آنها را کنترل کنیم.
و در آخر هم کد بخش MainActivity.java همانند زیر می شود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | package ir.programchi; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.Toast; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class MainActivity extends AppCompatActivity { ExpandableListView expandableListView; ExpandableListAdapter expandableListAdapter; List<String> expandableListTitle; HashMap<String, List<String>> expandableListDetail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); expandableListView = (ExpandableListView) findViewById(R.id.expandableListView); expandableListDetail = ExpandableListDataPump.getData(); expandableListTitle = new ArrayList<String>(expandableListDetail.keySet()); expandableListAdapter = new CustomExpandableListAdapter(this, expandableListTitle, expandableListDetail); expandableListView.setAdapter(expandableListAdapter); expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { Toast.makeText(getApplicationContext(), expandableListTitle.get(groupPosition) + " List Expanded.", Toast.LENGTH_SHORT).show(); } }); expandableListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() { @Override public void onGroupCollapse(int groupPosition) { Toast.makeText(getApplicationContext(), expandableListTitle.get(groupPosition) + " List Collapsed.", Toast.LENGTH_SHORT).show(); } }); expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { Toast.makeText( getApplicationContext(), expandableListTitle.get(groupPosition) + " -> " + expandableListDetail.get( expandableListTitle.get(groupPosition)).get( childPosition), Toast.LENGTH_SHORT ).show(); return false; } }); } } |
در آخر هم برای هر بخش یک click ایجاد کردیم به طور مثال زمانی که گروه Expand می شود یک پیام به کاربر نمایش داده می شود و زمانی که گروه Collaps می شود پیغام نمایش داده می شود همینطور ما برای هر Child نیز یک Toast قرار دادیم تا درصورتی که نیاز داشتید از آن استفاده کنید.
این آموزش هم به پایان رسید.
موفق و موید باشید.
سپاسگزارم
سلام خسته نباشید
ممنون بابت آموزش عالیتون
می خواستم بدونم رو هر کدوم از نام کشور ها کلیک میشه بره به اکتیویتی خودش باید چکار کنم؟
سلام باید یک رویداد کلیک برای آن تعریف کنید.
اینم کد من : ببخشید البته ولی کلافه شدم دیگه :(((
public class ExpandableCardList extends BaseExpandableListAdapter {
Context cntx;
List listHeader;
HashMap<String, List> listDataChild;
public ExpandableCardList(Context cntx, List titles, HashMap<String, List> listDataChild) {
this.cntx = cntx;
this.listHeader = titles;
this.listDataChild = listDataChild;
}
@Override
public Object getChild(int listPosition, int expandedListPosition) {
Object object=this.listDataChild.get(this.listHeader.get(listPosition))
.get(expandedListPosition);
return this.listDataChild.get(this.listHeader.get(listPosition))
.get(expandedListPosition);
}
@Override
public long getChildId(int listPosition, int expandedListPosition) {
return expandedListPosition;
}
@Override
public View getChildView(int listPosition, final int expandedListPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String expandedListText = (String) getChild(listPosition, expandedListPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.cntx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.card_detail, null);
}
TextView expandedListTextView = (TextView) convertView
.findViewById(R.id.txt_personnel_card_detail);
expandedListTextView.setText(expandedListText);
return convertView;
}
@Override
public int getChildrenCount(int listPosition) {
int t =this.listDataChild.get(this.listHeader.get(listPosition))
.size();
return this.listDataChild.get(this.listHeader.get(listPosition))
.size();
}
@Override
public Object getGroup(int listPosition) {
Object object=this.listHeader.get(listPosition);
return this.listHeader.get(listPosition);
}
@Override
public int getGroupCount() {
int t=this.listHeader.size();
return this.listHeader.size();
}
@Override
public long getGroupId(int listPosition) {
long l=listPosition;
return listPosition;
}
@Override
public View getGroupView(int listPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String listTitle = (String) getGroup(listPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.cntx.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.card_title, null);
}
TextView listTitleTextView = (TextView) convertView
.findViewById(R.id.txt_card_title);
listTitleTextView.setTypeface(null, Typeface.BOLD);
listTitleTextView.setText(listTitle);
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int listPosition, int expandedListPosition) {
return false;
}
با تشکر
میخاستم بدونم اگه بخاییم داده ها رو از سرور بگیریم و تو child نمایش بدیم باید چکار کنیم
سلام و درود
برای اینکار باید یک کلاس model دیگر درست کنید یا از همون قبلی استفاده کنید یک متغیر به نام مثلا child تعریف کنید داده ها را به صورت json پارس کنید و نمایش دهید باید در adapter هم تغییرات ایجاد کنید.
موفق باشید.
میشه یه مثال بزنید ممنون میشم
سلام لطفا اگر امکانش هست کدهای آداپتور رو بیشنرتوضیح بدید چون برای کسانی که تازه شروع کردن سخته اگر توضیح بدبد ممنون میشم
ازسایت خوبتون تشکرمیکنم کاملا ب ای من مفید بوده
سلام
ممنون از آموزش خخوبتون
میخوان بدونم اگر بخواهیم توی لیست یکی از آیتم ها فرزند نداشته باشه و با کلیک روش به جای باز شدن عملی انجام بده، امکان پذیر هست؟