در سه مطلب قبلی (اینجا و اینجا و اینجا) درباره دیتابیس یا پایگاه داده در اندروید نوشتم. در این مطلب میخواهم درباره جنبههای پیشرفتهتری از پایگاه داده صحبت کنم. برای کار همان مثال قبلی که درباره Person بود را ادامه میدهم. البته همزمان با امکانات پیشرفتهتری از اندروید و لیست ویو هم آشنا خواهید شد.
جستجو
نمایش لیستی از اشیا همواره چیزی نیست که میخواهیم. گاهی اوقات دوست داریم اطلاعات نمایش داده شده را بر اساس بعضی ویژگیها فیلتر کنیم و فقط بخشی از اطلاعات را نمایش دهیم. برای این کار باید در پایگاه داده جستجو کنیم یه به عبارت دقیقتر کوئریهای خود را محدودتر کنیم تا فقط اطلاعاتی که میخواهیم را به ما برگرداند.
برای شروع یک ادیت تکست EditText به بالای صفحه لیست Person اضافه میکنیم. به محض این که کاربر شروع به تایپ در این ادیت تکست بکند، اطلاعات نمایش داده شده در لیست فیلتر شده و فقط اسامیای را نمایش میدهد که مشابه متن وارد شده توسط کاربر هستند. برای شروع به سراغ فایل layout میرویم:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/filterEditText" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ListView android:id="@+id/personListView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout>
همانطور که میبینید طراحی صفحه را تغییر داده و یک چیدمان خطی یا LinearLayout را به عنوان ویوی اصلی قرار داده و داخل آن یک EditText و ListView قرار دادیم.
حالا به سراغ اکتیویتی میرویم. اولین کاری که میکنیم تعریف کردن یک ادیت تکست و find کردن آن است (به نظرم دیگر به سطحی رسیدهاید که لازم نباشد در هر مرحله تغییرات این چنینی در کد را ننویسم!)
حالا باید کاری بکنیم که هر بار که کاربر چیزی در ادیت تکست وارد میکند ما بفهمیم و لیست را بر اساس آن فیلتر کنیم.
(در پرانتز میگویم که سادهتر بود در جلوی ادیت تکست یک دکمه میگداشتیم تا کاربر با کلیک کردن بر روی آن جستجو را انجام دهد اما میخواهم با یک تیر چند هدف بزنم: جستجو را یاد بگیرید، یاد بگیرید که چطور حرفهایتر با EditText کار کنید و از نوشتن برنامهای حرفهایتر لذت ببرید!)
برای فهمیدن تغییرات ادیت تکست آن هم درست در زمانی که کاربر شروع به نوشتن در آن میکند از TextWatcher استفاده میکنیم:
filterEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } });
حالا هر زمان که کاربر متن داخل ادیت تکست را تغییر دهد بلافاصله از طریق این تکست واچر مطلع میشویم. هر کدام از این سه تابع نوع حاصی از تغییر را به ما اطلاع میدهند. در حال حاضر وارد جزئیات TextWatcher نمیشویم. متدی که ما لازم داریم afterTextChanged است:
@Override public void afterTextChanged(Editable s) { search(s.toString()); }
با این کار به برنامه میگوییم با هر تغییری که کاربر در متن ادیت تکست وارد میکند، متد search صدا زده شود. حالا متدی با نام search در اکتیویتی ایجاد میکنیم:
private void search(String s) { }
فعلاً اکتیویتی را رها کرده و به سراغ PersonDatabaseAdapter میرویم. باید تابعی بنویسیم که عبارت جستجو را گرفته و لیستی از Person به ما برگرداند که شرایط جستجو را داشته باشند. برای این کار تابع readAllPersons را تغییر میدهیم تا نیازی به دوباره کاری و تکرار این همه کد نداشته باشیم:
public ArrayList<Person> readAllPerson(String search) { //... }
حالا باید اول کار چک کنیم آیا کاربر متنی را برای جستجو فرستاده است یا نه:
// ... String[] columns = new String[]{"id", "name", "family"}; String selection = null; String[] selectionArgs = null; String groupBy = null; String having = null; String orderBy = null; String limit = null; if( search != null && !search.isEmpty()) { }
حالا اگر کاربر چیزی را برای جستجو فرستاده باشد، کمی دستکاری در این متغیرها کار ما را راه میاندازد:
if( search != null || !search.isEmpty()) { selection = "name LIKE ? OR family LIKE ?"; selectionArgs = new String[] {search + "%", search + "%"}; }
با این کار جستجو را محدود به مواردی میکنیم که name یا family آنها یا search شروع میشود.
حالا برمیگردیم به اکتیویتی. اول به خاطر تغییری که در امضای متد readAllPersons دادیم باید خط زیر را اصلاح کنیم:
persons = databaseAdapter.readAllPerson();
در این مثال ما میخواهیم اول همه رکوردها را نمایش داده و بعد بر اساس متنی که کاربر وارد میکند آن را فیلتر کنیم. بنابراین کافی است null را به این تابع بفرستیم تا همه چیز مثل قبل کار کند:
persons = databaseAdapter.readAllPerson(null);
حالا میرویم سراغ متد search. به نظرم از اینجای کار را میتوانید حدس بزنید: تابع readAllPersons را با مقداری که کاربر وارد کرده صدا میزنیم و لیست Person های برگشتی را میدهیم به لیست ویو برای نمایش:
private void search(String s) { persons = databaseAdapter.readAllPerson(s); PersonListAdapter personListAdapter = new PersonListAdapter(persons, this); personListView.setAdapter(personListAdapter); }
تبریک میگم! حالا ما یک برنامه داریم که واقعاً در دیتابیس جستجو میکند. برای امتحان چند اسم و فامیل در دیتابیس ذخیره میکنیم و بعد به سراغ لیست میرویم:
حالا به محض این که شروع به تایپ کردن بکنید میبینید لیست کوچکتر و کوچکتر میشود:
با دیتابیس کارهای زیادی میشود انجام داد اما من در همین جا مطلب دیتابیس را میبندم و در مطلب بعدی به سراغ خود لیست ویو میروم!
کد کامل پروژه را در گیتهاب اسمارتلب آپلود کردم: دانلود کد از گیتهاب
راستی چرا کانال اسمارتلب در تلگرام را دنبال نمیکنید؟
سلام خیلی خوبه… اما لطفا سورس تمام شده سرچ را در دیتابیس ، در آخر همین مطلب قرار بدین چون خیلی تکه تکه هستند کد ها و کمی گیج کننده اس!
بازم ممنون بابت زحماتتون
سلام.
بزودی کد کامل رو تو گیتهاب میذارم تا بتونید دانلود کنید.
با تشکر از آموزشای خوبتون
منتظر آموزشای بعدیتون هستیم
سپاسگزارم و همین تشویقهای شما باعث دلگرمی من در ادامه کار میشن
سلام
اول از همه ممنون بابت به اشتراک گذاشتن آموزش های اندروید. خسته نباشید.
دوم اینکه یه سوال دارم که متاسفانه ربطی به موضوع بالا نداره ولی سایت رو گشتم و پستی مربوط به زبان ندیدم که اونجا سوالم رو بپرسم.
وقتی که layout فارسی رو به برنامه اضافه میکنم همه چیز خود به خود راست به چپ میشه که عالیه. اما من نیاز دارم که مثلا یه vertical linear layout با متعلقات داخلش توی صفحم راست به چپ نشه و توی همون فرم انگلیسی که تعریف کردم بمون. چطور باید این رو از بقیه جدا کنم؟
سلام
سپاسگزارم از محبتتون.
برای اون لیاوت خطی عمودی که میخواید محتویاتش چپ چین بمونه ویژگی android
:gravity=”left” رو تعریف کنید.
ممنون بابت پاسختون. اما مشکلم فقط gravity نیست برای مثال نمیخوام اعداد هم فارسی بشن یا فرمت ها به زبان فارسی تغییر کنن
خیلی عالیه ممنون ازتون
آموزش ها عالیه. تازه از طراحی سایت دارم میام سمت اندروید و امروز کار با دیتابیس رو به کمک سایت شما و چند تا سایت خارجی دیگه یاد گرفتم. منتظر مطالب آموزشی دیگه هم هستم. ترجیحا کار با ویوهای متریل دیزاین!
راستی راهی هست که بتونیم از سایت شما حمایت مالی کنیم که زودتر آموزش بذارید؟
سلام. متشکرم بابت لطف شما. درباره حمایت هم همین نظرات ارزشمند شما بهترین حمایت از اسمارتلب است. سپاسگزارم.
سلام
سوالی داشتم که اگر بتونین راهنماییم کنین خیلی ممنون میشم ازتون
اینکه یه برنامه اندروید شبیه مخاطبین تلفن ساختم که عملیات هایی مثل حذف کردن،ایجاد و ویرایش کردن مخاطبین رو انجام میده
این نرم افزار روی گوشی جواب داد اما هدف من اینه که بعد از خروجی گرفتن از برنامه به صورت apk از قبل یه سری اطلاعات هم در دیتابیس موجود باشه و نشون بده
“یعنی حفظ اطلاعات دیتابیس در ضمن خروجی گرفتن از برنامه” بدون اینکه بخوام از دیتابیس های از پیش ساخته توسط نرم افزار های مختلف استفاده کنم و توسط اندروید استادیو فراخونیشون کنم!
چون در حالت عادی برای این منظور هر دیوایسی یه دیتابیس داره که جدول هاش خالی از هر گونه اطلاعات هستش که هر کاربری فقط خودش باید حذف و اضافه و ویرایش کردن و … رو انجام بده
با تشکر
سلام
نمیدونم چی بگم … هر چی بگم کم گقتم … واقعا عالی بود
خیلی ساده و روان توضیح داداه بودید … بابت زحماتی که کشیدید ازتون متشکرم
سلام
تشکر میکنم از آموزشهای عالی و شیوه بیان عالیتون
منتظر سری بعد آموزش ها هستم
آقا چند فصل دیگه مونده؟
اصلا قراره ادامه بدید یا نه؟
لطف کنید اعلام کنید
دوست دارم مطالب بیشتری بنویسم ولی چند وقت اخیر به شدت سرم شلوغه و فرصتی برای نوشتن ندارم. انشاالله از این هفته یک کار نو رو شروع میکنم تو اسمارتلب که احتمالا به درد خیلیها میخوره 🙂
سلام.وقتتون بخیر.
برای یک بخشی،نیاز دارم که برنامه طوری باشه که هر کاربر بتونه پست ثبت کنه و کاربرهای دیگه بتونن زیر پست مورد نظرشون،نظرشونو ثبت کنن.
گویا باید از دیتا بیس استفاده کنم.
الان ینی هم ثبت پست و نظر برام سواله و هم ارتباطشون که بگم این نظر برای کدوم پسته.
سلام وقت بخیر …
بسیار ممنونم به خاطر این مطالبی که میزارید واقعا خیلی مفید بودن برام
توی بیشتر سایتا گشتم یکی از بهترین و کامل ترین مطالب در مورد پایگاه داده ها در آندروید بود …
فقط اگ میشه حذف رکورد رو هم بگین چجوریه .. چون آخه من هر کاری میکنم رکورد حذف نمیشه ..
یک ادیت تکست با یک دکمه اضافه کردم، توی ادیت تکست آیدی رکورد وارد میکنم بعد توی کد دکمه به لانگ تبدیلش میکنم و به تابع دلیت ارسالش میکنم ولی بازم لیست رو میبینم رکورد حذف نشده .. اگ میشه این مشکل رو برام حل کنید واقعا خیلی برام مهمه …مرسی
آیا پس از حذف رکورد، لیست رو رفرش میکنید؟
تابع ریفرش ننوشتم ولی برنامه رو میبندم بازش میکنم رکوردای قبلی هستن حذف نشدن 🙁
بستن برنامه به معنای نابود شدن برنامه نیست. بهتره تابعی برای رفرش کردن لیست بنویسید.
سلام
چطوری میتونیم به edit text قابلیت تشخیص زبان ورودی رو اضافه کنیم؟
ینی اگر متن ورودی انگلیسی بود یک سری متد هارو اجرا کنه
وقتی که فارسی بود متد های دیگری رو اجرا کنه
سلام
برای کنترل یک EditText وقتی که کاربر شروع میکند به وارد کردن متن، از کلاس TextWatcher استفاده کنید.
در همین فصل مثالی از استفاده از این کلاس آمده است. کاراکتری را که کاربر وارد میکند چک کنید و ببینید آیا در محدوده یونیکد فارسی قرار دارد یا نه و بعد به تناسب کار دلخواه خودتان را انجام دهید.
سلام خیلی ممنون از اموزشاتون واقعا مفید بودن
سوالم اینه که برا پاک کردن item از همین دیتا بیس و listAll چطوری باید عمل کرد
هر کاری کردم نشد
سلام و وقت به خیر.
یک سوال داشتم از خدمت تون. من براش OnItemClickListener برای رفتن به مطلب مورد نظر تعریف کردم اما برای تمام مطالب فقط اولین متن رو باز می کنه، چجوری درستش کنم
با تشکر از مطالب بسیار خوب و کاربردی
کدتون رو بفرستید تا ببینم مشکل از کجا است
ممنون از توجه تون/ به دو صورت امتحان کردم که از هردو همان نتیجه رو گرفتم.
.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view,
int position, long id)
{
Intent intenet = new Intent(getBaseContext(), DeatailsActivity.class);
String res_id = resultBooks.get(position).get("position").toString();
i.putExtra("position", res_id);
startActivity(intenet);
هم چنین
setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent(context,IADetailsActivity.class);
Bundle extras = new Bundle();
extras.putInt(“position”,getAdapterPosition());
intent.putExtras(extras);
/*
int i=getAdapterPosition();
intent.putExtra(“position”, getAdapterPosition());*/
context.startActivity(intent);
باتشکر
سلام خسته نباشید
اگر امکانش هست آموزش اتصال به فایل دیتابیس آماده را هم بگذارید
تشکر
سلام
من میخاستم در AIDE یک قسمت جستجوطراحی کنم که متنای داخل اکتییوتی رو نمایش بده ولی نمیشه لطفا کمکم کنید
سلام. تجربه کار با این برنامه رو ندارم.