مشخصات مقاله
-
4075
-
0.0
-
11364
-
0
-
1
آموزش نحوه ی استفاده از List در اندروید-استفاده از list در android
دوره آموزش برنامه نویسی اندروید
کلیه حقوق مادی و معنوی این مقاله متعلق به آموزشگاه تحلیل داده می باشد و هر گونه استفاده غیر قانونی از آن پیگرد قانونی دارد.
آموزش نحوه ی استفاده از List در اندروید قسمت اول
نحوه کار با listview در اندروید بسیار ساده است. این مبحث آموزشی چگونگی استفاده از ListView به همراه Activity ها و Fragment ها را در محیط اندروید به شما می آموزد و بر حسب ویرایش 4.4 Eclipse، 1.7 جاوا و اندروید 5.0 نوشته شده است.
فهرست محتوا
1. کاربرد List در اندروید
استفاده از لیست در اندروید
View هایی مختص مدیریت list ها در محیط اندروید
ورودی های احتمالی که در لیست جای می گیرند
Adapter ها
فلیتر کردن و مرتب سازی داده ها توسط آداپتور
بروز رسانی داده ها در آداپتور
تخصیص گوش فراخوان
2. آداپتورهای پیش فرض محیط اندروید
بکارگیری کلاس ArrayAdapter
نمونه ای از کاربرد ListView در Activity
3. پیاده سازی آداپتور اختصاصی
طراحی و تولید آداپتور سفارشی
ایجاد طرح کلی ویژه ی هر یک از سطرهای list
مثالی از یک آداپتور اختصاصی
بروز رسانی مدل داده از طریق آداپتور
4. ListActivity و ListFragment
مخزن پیش فرض (default container) ویژه ی استفاده از ListView
بکارگیری شمای سفارشی (custom layout) به همراه کلاس های ListActivity و FragmentActivity
Placeholder برای لیست تهی
5. تمرین : استفاده از ListView و ListActivity
6. تمرین
7. آموزش : پیاده سازی آداپتور اختصاصی
8. ListView و ارتباط آن با افزایش کارایی
انگیزه افزایش کارایی و بهبود سرعت در دستگاه های اندروید
عملیات سنگین و زمان بر
اجتناب از بارگذاری مجدد شمای کلی ((layout inflation و ایجاد اشیإ جاوا
اجتناب از بکارگیری متد findViewById () با پیاده سازی ViewHolder
مثال
9. فعال سازی selection modeبرای ListView از طریق فراخوانی متد setChoiceMode ()
10. آموزش نحوه ی استفاده از contextual action mode برای ListView
11. پیاده سازی عملیات undo
چه زمانی باید عملیات undo را پیاده کرد؟
مثال
12. بهینه سازی کارایی
13. آموزش نحوه ی نمایش دو آیتم به صورت همزمان در یک ListView
14. انتخاب چندین آیتم در ListView
ارتباط وتعامل بین مدل و ListView
آموزش : Domain Model و Rows interaction
15. پیاده سازی ExpandableListView
ExpandableListView
مثالی از ExpandableListView
16. آموزش متفرقه
افزودن longclick listener به آیتم های لیست
سربرگ و زیربرگ (header & footer)
SimpleCursorAdapter.17
18. کتابخانه های منبع آزاد دیگر (open source libraries)
1. کاربرد List در اندروید
استفاده از لیست در اندروید
نمایش المان ها به صورت فهرست وار یا در قالب لیست، الگویی متعارف در برنامه های کاربردی گوشی های همراه می باشد. کاربر فهرستی از آیتم ها را می بیند و با استفاده از قابلیت اسکرول تمامی بخش های لیست را مشاهده می کند. Activity مذکور در تصویر زیر به نمایش گذاشته شده است.
![]()
به طور معمول کاربر از طریق action bar، به عنوان مثال از طریق دکمه ی تجدید(refresh button)، با لیست مورد نظر تعامل برقرار می کند. آیتم های موجود در لیست نیز قاعدتاً برای کاربر قابل گزینش می باشند. کاربر بسته به انتخابش action bar را بروزرسانی می کند یا صفحه ی جامعی برای گزینش راه اندازی می کند. این امر در زیر به تصویر کشیده شده که مجرد انتخاب یک آیتم توسط کاربر activity دیگری راه اندازی می شود.
![]()
View هایی ویژه ی مدیریت list ها در محیط اندروید
اندروید با عرضه ی کلاس های ListView و ExpandableListView به کاربر این امکان را می دهد که فهرستی از آیتم ها با قابلیت اسکرول بوجود آورد.
کلاس ExpandableListView آیتم ها را گروه بندی می کند.
ورودی های احتمالی که در لیست جای می گیرند
ورودی های لیست (مقصود درایه ها یا آیتم هایی است که در لیست قرار دارند) می تواند هر شئ دلخواه جاوایی باشد. آداپتور داده های مناسب و مورد نظر را از شی داده (data object) استخراج کرده و داده ی ذکر شده را به views در ردیف ListView تخصیص می دهد.
آیتم های نام برده data model های لیست خوانده می شوند. آداپتور این توانایی را دارد که داده ها را به عنوان ورودی دریافت کند.
Adapter ها
Adapter مدل داده را مدیریت می کند و آن را متناسب با ورودی های فردی در ابزارک تطبیق ((adapt می دهد. آداپتور کلاس BaseAdapter را به ارث می برد.
خط ها یا ردیف های موجود در ابزارک (widget) که داده ها را نمایش می دهند، هریک متشکل از یک شمای کلی (layout) است و این شما بسته به سلیقه ی شما ممکن است بسیار پیچیده یا ساده باشد.
یک سطر متعارف در لیست، به طور عموم حاوی یک تصویر در سمت چپ و دو خط متنی در قسمت میانی خود، مطابق تصویر زیر، می باشد.
![]()
فایل layout متعلق به تصویر بالا در زیر به نمایش گذاشته شده است.
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<imageview android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignparentbottom="true"
android:layout_alignparenttop="true"
android:layout_marginright="6dip"
android:contentdescription="TODO"
android:src="@drawable/ic_launcher" />
<textview android:id="@+id/secondLine"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_alignparentbottom="true"
android:layout_alignparentright="true"
android:layout_torightof="@id/icon"
android:ellipsize="marquee"
android:singleline="true"
android:text="Description"
android:textsize="12sp" />
<textview android:id="@+id/firstLine"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@id/secondLine"
android:layout_alignparentright="true"
android:layout_alignparenttop="true"
android:layout_alignwithparentifmissing="true"
android:layout_torightof="@id/icon"
android:gravity="center_vertical"
android:text="Example application"
android:textsize="16sp" />
</relativelayout>
آداپتور طرح کلی (layout) مختص هر سطر را در متد getView () خود inflate کرده، سپس داده های مربوطه را به هر view در ردیف اختصاص می دهد.
آداپتور به واسطه ی متد setAdapter به ListView اختصاص داده می شود.
نکته
آداپتورها نه تنها توسط ListView بلکه توسط view های دیگر که AdapterView را به ارث می برند (extend) از جمله Spinner، GridView، Gallery و StackView مورد استفاده قرار می گیرد.
فلیتر کردن و مرتب سازی داده ها توسط آداپتور
مرتب سازی و فیلتر داده ها نیز توسط آداپتور صورت می گیرد. تنها کافی است منطق لازمه را در آداپتور اختصاصی خود پیاده کنید.
بروز رسانی داده ها در آداپتور
NotifyDataSetChanged () زمانی فراخوانده می شود که داده ها تغییر یافته یا داده ی جدیدی در دسترس قرار بگیرد. متد notifyDataSetInvalidated () نیز در صورتی فراخوانی می شود که داده ی مورد نظر دیگر در دسترس نباشد.
تخصیص گوش فراخوان
برای اینکه به انتخابات انجام شده در لیست واکنش لازم صورت گیرد، کافی است یک onItemClickListener به ListView خود اضافه کنید.
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent، View view،
int position، long id) {
Toast.makeText(getApplicationContext()،
"Click ListItem Number " + position، Toast.LENGTH_LONG)
.show();
}
});
2. آداپتورهای پیش فرض محیط اندروید
اندروید آداپتورهای پیش فرض خود را ارائه می دهد که عبارتند از ArrayAdapter و CurserAdapter.
ArrayAdapter داده های مبتنی بر Arrays و java.util.list در دست گرفته و مدیریت می کند.
SimpleCursorAdapter نیز مدیریت داده های مربوط به پایگاه داده را در دست می گیرد.
بکارگیری کلاس ArrayAdapter
Arrayadapter در واقع ArrayList (لیست آرایه ای) از اشیا را به آیتم های View تبدیل کرده که درون container / مخزن ListView بارگذاری می شود(. کلاس ArrayAdapter لیست یا آرایه ای از اشیا جاوا را به عنوان ورودی (input) بکار می برد (با آن ها به عنوان ورودی برخورد می کند). هر شی جاوایی در یک سطر نگاشت می شود (map). به صورت پیش فرض کلاس مذکور متد toString () شی مورد نظر را به یک view در row layout نگاشت می کند.
می توانید شناسه (ID) view را در سازنده (constructer) کلاس ArrayAdapter تعریف کنید، در غیر این صورت android.R.id.text1 به عنوان شناسه ی پیش فرض بکار گرفته می شود.
کلاس ArrayAdapter به شما این امکان را می دهد با فراخوانی متد clear ()، کلیه ی عناصر ساختار داده ای زیربنا و اساسی (underlying data structure) را حذف کنید. همچنین به شما این اجازه را می دهد با صدا زدن متد add () المان های جدید و با فراخوانی متد addAll () یک مجموعه یا collection جدید اضافه کنید.
پی در پی می توانید ساختار داده ای زیربنا را مستقیم و بدون واسطه اصلاح (modify) کنید و به دنبال آن متد notifyDataSetChanged () را صدا بزنید تا از این طریق آداپتور را از اصلاحات و تغییرات بوجود آمده (در داده) مطلع سازید.
توجه
اگر می خواهید داده را در آداپتور تغییر دهید، لازم است ابتدا بخاطر داشته باشید که ساختار داده ای زیربنا باید از این عملیات پشتیبانی کند. این امر درمورد کلاس ArrayList حکم می کند اما نه درباره ی آرایه ها (arrays).
نمونه ای از کاربرد ListView در Activity
تکه کد زیر فایل layout ای به نام activity_listviewexampleactivity.xml را نشان می دهد که حامل ListView می باشد.
<listview xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
مثال زیر استفاده از ListView را در یک activity نشان می دهد و همچنین به جای row layout از طرح بندی پیش فرض / default layout محیط اندروید (android platform) استفاده می کند. سپس حذف آیتم های لیست را نمایش داده و برای حذف از انیمیشن استفاده می کند.
package com.vogella.android.listview.withanimation;
public class ListViewExampleActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listviewexampleactivity);
final ListView listview = (ListView) findViewById(R.id.listview);
String[] values = new String[] { "Android"، "iPhone"، "WindowsMobile"،
"Blackberry"، "WebOS"، "Ubuntu"، "Windows7"، "Max OS X"،
"Linux"، "OS/2"، "Ubuntu"، "Windows7"، "Max OS X"، "Linux"،
"OS/2"، "Ubuntu"، "Windows7"، "Max OS X"، "Linux"، "OS/2"،
"Android"، "iPhone"، "WindowsMobile" };
final ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < values.length; ++i) {
list.add(values[i]);
}
final StableArrayAdapter adapter = new StableArrayAdapter(this،
android.R.layout.simple_list_item_1، list);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent، final View view،
int position، long id) {
final String item = (String) parent.getItemAtPosition(position);
view.animate().setDuration(2000).alpha(0)
.withEndAction(new Runnable() {
@Override
public void run() {
list.remove(item);
adapter.notifyDataSetChanged();
view.setAlpha(1);
}
});
}
});
}
private class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String، Integer> mIdMap = new HashMap<String، Integer>();
public StableArrayAdapter(Context context، int textViewResourceId،
List<String> objects) {
super(context، textViewResourceId، objects);
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i)، i);
}
}
@Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
@Override
public boolean hasStableIds() {
return true;
}
}
}
3. پیاده سازی آداپتور اختصاصی
طراحی و تولید آداپتور سفارشی
ArrayAdapter به این خاطر که تنها قابلیت نگاشت toString () را به یک view در row layout دارد، کلاسی با کارایی محدود تلقی می گردد. جهت مدیریت و کنترل تخصیص داده و همچنین توانایی پشتیبانی از چندین view، مجبورید آداپتور سفارشی و ویژه ی خود را ایجاد و پیاده سازی کنید.
برای این منظور باید آداپتور موجود (arrayadpater) را به ارث ببرید یا از کلاس BaseAdapter مستقیم یک زیرکلاس (subclass) ایجاد کنید.
نکته
برنامه نویسان ترجیح می دهند برای نوشتن آداپتور اختصاصی به جای به ارث بردن مستقیم از کلاس BaseAdapter، کلاس ArrayAdapter را به ارث ببرند (بسط دهند)، و این به خاطر ساده تر بودن فرایند دومی نسبت به اولی می باشد.
ایجاد طرح کلی ویژه ی هر یک از سطرهای list
آداپتور باید مختص هریک از سطرهای لیست یک طرح کلی (layout) ایجاد کند. نمونه ی instance ListView متد getView () را برای تک تک عناصر داده فرا می خواند. در این متد، آداپتور، row layout )نمای سطری( را ایجاد کرده و داده را به view ها در طرح کلی نگاشت (map) می کند.
عنصر ریشه ی (root) این طرح بندی به طور عموم از نوع ViewGroup (layout manager) بوده و خود شامل چندین view دیگر از جمله ImageView و TextView می باشد. تصویر زیر لیستی با طرح بندی متفاوت ویژه ی سطرهای ذوج و فرد را برای شما به نمایش می گذارد.
داخل متد getView () یک XML مبتنی بر طرح کلی ظاهر (inflate) می کنید، سپس محتوای هریک از viewها را بر اساس شی جاوا (برای این سطر) انتخاب می کنید. به منظور ظاهر کردن فایل XML layout، می توان از سیستم سرویس LayoutInflator بهره گرفت.
نکته
می توان جهت دسترسی به سرویس ذکر شده، از متد اکتویتی getLayoutInflator () استفاده کرد یا با فراخوانی متد method call context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) به آن دست یافت.
پس از انجام این فرایند (inflating the layout)، آداپتور به دنبال view های مرتبط گشته سپس آن ها را با داده های مورد نظر پر می کند. جهت یافتن عناصر فردی (هر المان) در طرح کلی، باید متد findViewById () را در view سطح بالا فراخوانی کنید.
مثالی از یک آداپتور اختصاصی
همان طور که مشاهده می کنید مثال ذیل پیاده سازی و بکارگیری یک آداپتور سفارشی را نمایش می دهد. آداپتور نام برده فرض می گیرد شما دو فایل png (no.png و yes.png) در یکی از پوشه های res/drawable خود دارید. کد، فایل XML layout را ظاهر کرده، view های مربوطه را در layout پیدا می کند سپس محتوای آن را بر اساس داده ی ورودی (input data) سِت می کند.
package de.vogella.android.listactivity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public MySimpleArrayAdapter(Context context، String[] values) {
super(context، R.layout.rowlayout، values);
this.context = context;
this.values = values;
}
@Override
public View getView(int position، View convertView، ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.rowlayout، parent، false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
textView.setText(values[position]);
// change the icon for Windows and iPhone
String s = values[position];
if (s.startsWith("iPhone")) {
imageView.setImageResource(R.drawable.no);
} else {
imageView.setImageResource(R.drawable.ok);
}
return rowView;
}
}
بروز رسانی مدل داده از طریق آداپتور
سطر (row) همچنین می تواند دربردارنده ی views باشد که با مدل داده ای زیربنا (underlying data model) همکاری دارند. به طور مثال، این اجازه را دارید یک Checkbox در نمای سطری خود داشته باشید که در صورت انتخاب آن، داده ی زیربنا تغییر می یابد.
4. ListActivity و ListFragment
مخزن پیش فرض (default container) ویژه ی استفاده از ListView
اندروید fragment ها و کلاس های activity تخصصی فراوانی جهت آسان سازی مدیریت لیست ارائه می هد.
چنانچه قصد دارید لیست در activity خود بکارببرید، باید از کلاس ListActivity استفاده کنید. در صورتی که بخواهید از لیست در fragment های خود استفاده کنید، کلاس ListFragment را مورد استفاده قرار دهید.
لزومی ندارد طرح کلی (layout) به این المان ها اختصاص دهید. اگر هیچ layout ی هم تعریف نکنید، activity یا fragment خود به صورت پیش فرض، یک ListView دربردارد. ListActivity و ListFragment همچنین به شما امکان می دهد متد onListItemClick () را به منظور مدیریت گزینش و انتخاب آیتم های لیست بازنویسی (override) کنید.
هر دو کلاس برای شما این امکان را فراهم می کند که آداپتور را با متد setListAdapter () به ListView پیش فرض متصل (set) کنید.
نمونه کد زیر پیاده سازی ساده ی کلاس ListFragment را نمایش می دهد.
package de.vogella.android.fragments;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.app.ListFragment;
public class MyListFragment extends ListFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] values = new String[] { "Android"، "iPhone"، "WindowsMobile"،
"Blackberry"، "WebOS"، "Ubuntu"، "Windows7"، "Max OS X"،
"Linux"، "OS/2" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity()،
android.R.layout.simple_list_item_1، values);
setListAdapter(adapter);
}
@Override
public void onListItemClick(ListView l، View v، int position، long id) {
// do something with the data
}
}
مثال زیر استفاده از ListActivity را نمایش می دهد.
package de.vogella.android.listactivity;
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
public class MyListActivity extends ListActivity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
String[] values = new String[] { "Android"، "iPhone"، "WindowsMobile"،
"Blackberry"، "WebOS"، "Ubuntu"، "Windows7"، "Max OS X"،
"Linux"، "OS/2" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this،
android.R.layout.simple_list_item_1، values);
setListAdapter(adapter);
}
}
بکارگیری شمای سفارشی (custom layout) به همراه کلاس های ListActivity و FragmentActivity
می توان یک شمای اختصاصی با ListActivity و FragmentActivity بکاربرد. در این مورد، fragment یا activity در شمای کلی ارائه شده، به دنبال ListView ی با خصیصه ی از پیش تعیین شده ی android:id که به android:id/list متصل شده می گردد. این کاربرد در زیر با مثال به نمایش گذاشته شده
<listview android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
توجه
چنانچه شناسه (ID) فوق یا ListView را در layout خود دخیل نکنید، مجرد نمایش activity یا fragment اپلیکیشن ازکار می افتد (crash رخ می دهد).
Placeholder برای لیست تهی
همچنین می توان view ای با شناسه ی @android:id/emptyدر layout استفاده کرد. در صورت تهی بودن ListView،activity و fragment مربوطه این view را به صورت اتوماتیک نمایش می دهند و در غیر این صورت آن را پنهان می سازند. به عنوان مثال، می توان پیام خطا در چنین view ای نمایش داد.
5. تمرین : استفاده از ListView و ListActivity
تمرین پیش رو نحوه ی استفاده از ListView را در یک ListActivity به نمایش می گذارد. در این تمرین کلاس از پیش تعریف شده ی ArrayAdapter و یک layout موجود اندروید را برای سطرها مورد استفاده قرار می دهیم.
پروژه ی جدیدی به نام de.vogella.android.listactivity به همراه activity به اسم MyListActivity ایجاد کنید.
کلاس MyListActivtiy را بر اساس نمونه کد زیر تغییر دهید. توجه داشته باشید که متد setContentView () بکارگرفته نشده است.
package de.vogella.android.listactivity;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MyListActivity extends ListActivity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
String[] values = new String[] { "Android"، "iPhone"، "WindowsMobile"،
"Blackberry"، "WebOS"، "Ubuntu"، "Windows7"، "Max OS X"،
"Linux"، "OS/2" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this،
android.R.layout.simple_list_item_1، values);
setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l، View v، int position، long id) {
String item = (String) getListAdapter().getItem(position);
Toast.makeText(this، item + " selected"، Toast.LENGTH_LONG).show();
}
}
