آموزش ساخت صفحه علاقه مندی ها و افزودن به علاقه مندی (سورس اضافه شد - آموزش تکمیل شد)
آموزش تکمیل شد
توجه!!!
لطفا اگه سوال و مطلبی هست زیر همین پست بصورت نظر کامنت کنید فقط و از گذاشتن پاسخ (که بصورت یک پست جداگانه در میاد) خودداری کنید،تا بتونیم یه فایل آموزشی تر و تمیز داشته باشیم که همه بتونن به راحتی ازش بهره ببرند.
با تشکر از همکاریتون.
سلااااام و شب همتون بخیر.
از اونجایی که خیلی از دوستان مشکل داشتند در این مورد من هم تصمیم گرففتم یه آموزش کامل در این مورد بگذارم.
این آموزشی که اینجا براتون گذاشتم طبق قسمتی از آموزش های آقای "پوریا انجمنی" در سایت NikAndroid نگاشته شده است.
خوب، حالا ماجرا چیه؟
ممکنه خیلی از شماها ندونید، اما یکی از مواردی که مارکتی مثل بازار از خیلی از نرم افزارها ایراد میگیره و اونهارو ثبت نمیکنه اینه که قسمتی مربوط به علاقه مندی ها برای کاربر وجود نداره. حالا این چیه؟
برای اپلیکیشن هایی که محتویی هستن و محتوی دارند ( مثل کتاب و بانک SMS یا ازین جور چیزا ) اینه که باید این امکان وجود داشته باشه که کاربر صفحه ای که دوست داره یا پیامکی رو که مورد علاقش هست بتونه تیک بزنه و بعد ااون رو در قسمتی به اسم علاقه مندی ها ببینه ( مثل خیلی از ماها که اگه جایی از کتاب مهم باشه برامون، گوشه کتاب رو یه لای کوچیک میزنیم تا بعدا بهش مراجعه کنیم).
خب حالا چه چیزهایی نیاز داریم:
- صفحه علاقه مندی ها
- ایجاد دکمه اضافه شدن به علاقه مندی ها در صفحه مربوط به مطلب
- ایجاد ارتباط با دیتابیس در کلاس database
- 2کلاس Content_list و Fav_list
- 4 قالب Layout به نامهای contentlist.xml و content_row.xml برای کلاس Content_list و favlist.xml و fav_row.xml برای کلاس Fav_list
این آزمایش در 4 بخش زیر انجام خواهد شد:
- قسمت اول:ساخت دیتابیس، مقدمات دیتابیس، کارهای ابتدایی بر روی صفجه Main
- قسمت دوم: ساخت صحفحه مطالب، توابع دیتابیسی آن و دکمه افزودن به علاقه مندی ها
- قسمت سوم: ساخت صفحه علاقه مندی ها، توابع دیتابیسی و دیگر کارهای باقی مانده
- قسمت چهارم: جمع بندی و پاسخ به سوالهای اساسی
سعی می کنم که ایشالله تا فرداشب کل موارد رو جمع کنم و در پایان هم سورس پروژه هم خود فایل APK رو در اختیارتون خواهم گذاشت. پس با لایکهاتون دلگرمم کنید ;) <3
قسمت اول
آماده سازی دیتابیس و توابع دیتابیسی و صفحه Main
استارت کار
دقیقا نمیدونم از کجا باید شروع کنم :D ولی خب کم کم باهم جلو میریم
اولِ اولِ اول از همه. به فایل دیتابیستون برید و باید یه فیلد به اسم fav بهش اضافه کنید یا درواقع کلا فایل دیتابیستون یه چیزی به اسم fav یا هرچی که مد نظرتون هست بسازید و مقدارش رو بگذارید "0" ، من دیتابیسمو با 3 فیلد ID Content Fav ساختم:
حالا میریم سروقت برنامه. یه پروژه ایجاد کنید اسمش مهم نیس هرچی دلتون خواست. اول از همه یه کلاس به اسم databse ایجاد کنید میخوایم اونجا کارای دیتابیسمونو انجام بدیم. خوب حالا اون فایل دیتابیسی که ساخته بودیم رو درگ کنید توی پوشه assets و هر اسمی دوست داشتین واسش بزارین و پسوند ".db" رو حتما حذف کنید. مثلا فایل من بود thedb.db که پسوند .db رو ورداشتم شد این:
حالا وقت کدنویسیه :P
اول از همه فایل دیتابیسمون رو extends میکنیم از SQLiteOpenHelper:
public class database extends SQLiteOpenHelper {
}
توی کلاس دیتابیس باید 3تا چیزتعریف کنیم،اول: آدرسی که قراره دیتابیس اونجا کپی بشه و بعدا استفاده بشه ، دوم: اسم فایل دیتابیسمون، سوم: هم یه کلید برای اینکه به کمک کارهای دیتابیسمون بیاد:
public final String path="data/data/com.mytest.favtest/databases/";//package khodra benvisid
public final String Name="thedb";//name database khodra bedune pasvande".db" inja benvisid
public SQLiteDatabase mydb; //kar rah andaze db
بجای com.mytest.favtest اسم پکیجتون و بجای thedb اسم دیتابیستون رو قرار بدید ( واسه همین میگفتم .dbرو وردارین چون اینجا و یه جای دیگه به مشکل میخوردیم)
تو مرحله بعد یه راه انداز واسه دیتابیسمون باید بسازیم که به شرح زیرٍ:
اول از همه یه context تعریف می کنیم و اسم دیتابیسمون رو اوجا مینویسیم. یه 2تا تابع onCrate و onUpgarde هم هستن که به اونا کاری نداریم ولی دست نزنید باید باشن. اگه حذف کنین اکلیپس ازتون ایراد میگیره:
private final Context mycontext;
public database(Context context) {
super(context, "thedb", null, 1);//name database ra bedune pasvande ".db" inja benvisid
mycontext=context;
}
@Override
public void onCreate(SQLiteDatabase arg0) {}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {}
حالا 2تا تابع open و close برای دیتابیسمون تعریف می کنیم که که بتونیم بعدا توی کار با دیتابیسمون به کار ببندیمشون. به فایل open میگیم که آقا برو از اون آدرسی که بهت دایدم "Path" اون دیتابیسی که بهت معرفی کریدم "Name" رو باز کن. close هم که میزنه میبنده دیتابیسو. دستشم درد نکنه!! :
public void open(){
mydb=SQLiteDatabase.openDatabase(path+Name, null, SQLiteDatabase.OPEN_READWRITE);
}
public void close(){
mydb.close();
}
حالا مهمترین بخش. اول یه تایع chekdb تعریف می کنیم میگیم که آقا تو برو توی اون آدرس path و ببین که آیا از ما دیتابیسی با اون نام اونجا کپی شده یا نه؟ اگه شده بود true اگه نشده بود false رو برگردون. یه تابع هم معرفی می کنیم به اسم copydatabase که بره به اون آدرس که داده بودیم و اون فایلی دیتابیسی که اسمشو داده بودم رو کپی کنه. حالا یه تابع به اسم useable تعریف میکنیم میگیم آقای usable تو بیا checkdb رو اجرا کن ببین چی میگه؟ اگه گفت که جای دیتابیس خالیه که copydatabasbe رو اجرا کن و دیتابیس رو کپی کن. اگه خالی نبود و فایلمون قبلا کپی شده.دیگه هیچ دست به کاری نزن.
حالا واسه چی ما کلا اینکارو می کنیم؟ واسه اینکه شاید قبلا یه نسخه قبلی رو کاربر نصب کرده حالا ما بیایم دوباره یه جیز روش نصب کنیم که سیو های کاربر بدبخت میپره که! فرض کنید طرف 200 تا پیامک یا مطلب رو به لیستش علاقه مندی هاش اضافه کرده (فیلد fav رو از 0 به 1 تبدیل کرده ) حالا بیایم به این کپی کردن دیتابیس همه fav ها 0 میشن و طرف هرچی سیو کرده بود میپره!
خلاصه کداش به شرح زیرٍ:
public boolean checkdb(){
SQLiteDatabase db=null;
try{
db=SQLiteDatabase.openDatabase(path+Name, null, SQLiteDatabase.OPEN_READONLY);
}
catch(SQLException e)
{
}
return db !=null ? true:false ;
}
public void copydatabase() throws IOException{
OutputStream myOutput = new FileOutputStream(path+Name);
byte[] buffer = new byte[1024];
int length;
InputStream myInput = mycontext.getAssets().open(Name);
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myInput.close();
myOutput.flush();
myOutput.close();
}
public void useable(){
boolean checkdb=checkdb();
if(checkdb){
}else{
this.getReadableDatabase();
try{
copydatabase();
}catch(IOException e){
}
}
}
از توابع try و catch هم استفاده می کنید که در موقع بروز خطا نزنه برنامه رو نبنده.
حالا میرسم به ابتدای ماجرا تازه :D
در صفحه main.xml من 2تا کلید درست کردم و اسم مطالب و علاقه مندی ها واسش گذاشتم.
حالا در کلاس Main میایم و اون تابعی که گفته بودیما که uasble اینا اونرو فراخونی می کنیم. درضمن 2تا کلاس هم جدید میسازیم به اسم Content_list و Fav_list و توی صفحه Main بهشون لینک میدیم. یادتون نره تو منیفست این 2تا کلاس رو هم تعریف کنید:
private database db;
private Button conbtn,favbtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//sakhtane file dabatse va copy kardanesh tu gushiye shoma baraye avalin bar
db = new database(this);
db.useable();
//payane sakhte database
//raftan be safheye mataleb
conbtn=(Button) findViewById(R.id.content_list_btn);
conbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent i=new Intent(Main.this,Content_list.class);
startActivity(i);
}
});
//raftan be safheye alaghemandiha
favbtn=(Button) findViewById(R.id.fav_list);
favbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent i=new Intent(Main.this,Fav_list.class);
startActivity(i);
}
});
}
تا اینجارو داشته باشین دیگه الان نصفه شبه ساعت 1:15 منم چشمام سنگین شده. ایشلا فردا تا آخر شب 2تا قست افزودن به علاقه مندی ها و صفحه علاقه مندی هارو هم واستون اوکی می کنم.
فقط لطفا خواهشا تا اینجا اگه سوالی دارین یا مطلبی هست زیر همین پست کامنت کنین. زیرش پست جدید نزنید که نظم مطالب بهم نریزه و یه آموزش صاف و تر و تمیز داشته باشیم که بمونه واسه هممون.
قربونتون شبتون بخیر <3
قسمت دوم
ساخت صفحه مطالب و گزینه افزودن به علاقه مندی ها
دوباره سلام، میریم که قسمت دوم رو داشته باشیم ;)
خوب ما الان میخواییم یه صفحه درست کنیم که اونجا بتونیم مطالبی که در دریتابیس داریم بگیریم و در این صفحه نمایش بدیم.
خوب اول از همه یه کلاس با نام Content_list درست میکنیم و اون رو extends میکنیم از ListActivity :
public class Content_list extends ListActivity {
}
بعدش میایم در پوشه Layout یه فایل xml به نام contentlist.xml درست می کنیم که اونجا بتونیم مطالبمون رو لیست کنیم. در اونجا 2تا مورد هست. 1: یه LargeText میزاریم و مینویسیم "مطالب" و زیرش یه ListView میندازیم و در قسمت کد نویسیش android:id رو از @+id/listView1 به @android:id/list تغییر میدیم که به شکل و شرح زیرٍ:
<?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/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00ff55"
android:gravity="center"
android:padding="5dp"
android:text="مطالب"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
و بعدش یه فایل xml دیگه میسازیم fav_row.xml در اونجا ما درواقع شکل و شمایل اون اول ListView مون رو معلوم میکنیم که مطلبمون رو چطوری نشون بده! در اون صفحه یه LargTest قرار میدیم واسه اینکه متن مطلبون رو نشون بده (حالا اگه دوست داتشین TextViewهم میتونین بگذارین ) و یه ImageView میذاریم و سورسش رو عکس favoff انتخاب میکنیم حالا این چیه؟ همونطور که در عکس زیر میبینید این درواقع همون دکمه ماست که وقتی روش کلیک کنین اون مطلب اضافه میشه به علاقه مندی ها و عکسش از favoff به favon تغییر میکنه. ( در پوشه سورس که در اختیارتون میگذارم این عکس ها هست کلا خیالتون راحت ) خب سورس این صفحه و عکسش به شرح زیر مباشدیه:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/content_titr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
android:layout_marginTop="15dp"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ImageView
android:id="@+id/fav_btn"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignTop="@+id/content_titr"
android:layout_marginLeft="21dp"
android:src="@drawable/favoff" />
</RelativeLayout>
یه نکته بسیار بسیار مهم، من از آخرین نسخه اکلیپس استفاده می کنم که قابلیت RelativeLayout داره و با درگ دراپ کردن خیلی راحت هرجای صفحه که دلم بخواد عناصر رو قرار میدم. اگه شما از نسخه ی قدیمی که مثل استاده استفاده می کنید یادتون باشه که این Relative Layoute و شما اینو کپی نکنین و از همون LiearLayout استفاده کنین و Largtext و ImageView رو بگذارید (البته اگه دوست داشتین میتونین از ImageButoon هم استفاده کنین، من همینجوری از این استفاده کردم ) در آخر یادتون نره که به LargText و ImageView حتما ID بدید من به LargText دادم content_titr و به ImageView دادم fav_btn .
حالا میریم سر اصل کاریا ;)
اول به کلاس database که ایجاد کرده بودیم رجوع میکنیم و باید 4 تا تابع بسازیم که 2تاش واسه نشون دادن مطالبه و 2تاش مربوط علاقه مندی ها. توابع به شرح زیرند:
تابع اول Count : در این تابع ما یه Cursor داریم که بهش میگیم برو از فایل دیتابیس و table به نام content رو بگرد ببین کلا چندتا مطلب داریم ( این واسه اینکه که بعد تو تابع for ازش استفاده می کنیم که در ادامه متوجه خواهید شد ) و اونارو میریزیم توی یه متغییری به اسم s یا هرچی دوست داشتین و میگیم که مقدار s رو return کن:
//tedade matalebi k darim ro bedast miyarim ta betunim listeshun konim
public Integer Count(){
Cursor cu=mydb.rawQuery("select * from content", null);
int s=cu.getCount();
return s;
}
تابع دوم Content_display : در این تابع ما دو مقدار اسم table و عدد row رو میگیریم که استفاده میشه واسه اون تابع for که در ادامه خواید دید و درواقع اطلاعات مطالب رو از دیتابیس میگریه و نشون میده، و در آخر هم بهش میگیم که بر اساس ID این مطالب رو ترتیب و منظم کن و بعدشم مقدایر رو میریزیم توی s و میگیم که return کن:
//namayesh dahandeye Matne mataleb jahate estefade dar classe Content_list
public String Content_display(String table,int row){
Cursor cu=mydb.rawQuery("select * from "+table+" order by ID", null);
cu.moveToPosition(row);
String s=cu.getString(1);//in 1 neshun dahande filde Contente ke dar database filde 1 ast
return s;
}
تابع سوم Fav_display : این تابعم درواقع کاملا مثل بالاست و فقط با این تفاوت که مقدار فیلد Fav از دیتابیسمون رو برمیگردونه و همچنین اینکه دیگه لازم نیست اینجا order by ID کنیم چون همون تو قسمت Content_display یه بار order شده و همه چی مرتبه دیگه لازم نیست انجا هم همونکارو بکنیم. ( البته میتونیم این 2تا تابع رو یکی کنیم و در قسمت String s=cu.getString بجای اون عدد 1 یه متغییر به اسم field بگذاریم و تابع مقدار فیلد رو بگیره و اوجا که لازم داریم بگیم 1 اگه خواستیم fav رو بگریم عدد 2 رو بگذاریم. اگر متوجه نشدین چیه جریانش خودتونو اذیت نکنین، از همین روشی که گذاشتم استفاده کنید ;) ) :
//chek konande va neshan dahande 0 ya 1 budan Fav jahate estefade dar classe Content_list
public String Fav_display(String table,int row){
Cursor cu=mydb.rawQuery("select * from "+table, null);
cu.moveToPosition(row);
String s=cu.getString(2);//in 2 neshun dahande filde Fav ke dar database filde 2 ast
return s;
}
تابع چهارم Fav_update : در اینجا تابع ما 3تا مقدار رو میگیره که اسم table، مقدار matn و مقدار value رو میگیره. طرز کار این تابع اینکه که وقتی روی اون دکمه Favoff کلیک کرد این تابع یه مقدار 1 "Value" بر میگردونه و متن اون مطلب رو بعد این تابع میره توی table میگرده ببینه که اون متن ما کجاست اونوقت فید Favاش رو به از 0 به 1 تغییر میده. همینطور برعکس اگه 1 بود 0 میکنه:
//Update konande meghdare Fav ke dar classe Content_list az an estefade kardim
public void Fav_update(String table,String matn,String value){
ContentValues cv=new ContentValues();
cv.put("Fav", value);
mydb.update("content", cv, "Content='"+matn+"'", null);
}
خب تا اینجا ما توابع دیتابیسی مورد نظرمون رو درست کردیم، بریم و برسیم به صفحه Content_list و کد نویسی های اون قسمت ;)
اول از همه ما اینجا 3تا متغییر تعریف میکنیم به موارد زیر که در ادامه استفاده خواهند شد:
private database db;
private String[] Matn;
private String[] Fav;
در این کلاس ما2 تا تابع داریم که عبارت اند از توابع onCreate , load و یک کلاس که در همونجا تعریف می کنیم به اسم AA یا همون ArrayAdapter که کمکمون میکنه تا مطالبمون رو لیست کنیم. حالا میریم که شروع کنیم کدنویسیشو:
اول از همه به تابع load میریسیم که مطالبمون رو از دیتابیس میگیره و برامون آماده نمایش میکنه، ابتدای امر دیتابیسمون رو open و سپس close میکنیم.
همونجا یه متغییر int تعریف می کنیم و اسمشو میگذاریم s و میگیم برو از تابع Count که تو دیتابیس درست کرده بودیم تعداد مطالبی که داریم رو بگیر و بریز این تو. و 2 متغییر Matn و Fav رو آماده میکنیم تا مقادیر رو بگیرن.
حالا یه حلقه for تعریف میکنیم و میگیم آقا دونه دونه برو جلو و مقادیر Matn رو از تابع Content_dispaly و مقدار Fav رو از تابع fav_display بگیر و نگه داشته باش تا ازت بخوام.
//Tabe'e load kare daryafte te'alat va amade saziye uno vasamun anjam mide
private void load(){
db.open();
int s=db.Count();
Matn=new String[s];
Fav=new String[s];
for(int i=0;i<s;i++){
Matn[i]=db.Content_display("content", i); //matn ro az filde Content migire
Fav[i]=db.Fav_display("content", i); //0 ya 1 budane filde Fav ro migire
}
db.close();
}
خب حالا میریم و کلاس AA رو تعریف می کنیم. این کلاس 2تا تابع AA و getView توی خودش داره که به شکل زیر میبینید:
class AA extends ArrayAdapter<String>{
public AA(){
}
public View getView(final int position, View convertView, ViewGroup parent){
}
}
خب ما میایم در تابع public AA تعریف می کنیم که یک المنت Super در خودش داره که در اون 3 مقدار اسم کلاس اصلی، قالب لیست ویوو و متنی که قراری به عنوان اصل درونش قرار بگیره رو معرفی می کنیم که به شکل زیر است:
public AA(){
super(Content_list.this,R.layout.content_row,Matn);
}
حالا میرسیم به تابع View GetView . در اینجا ما اول از همه باید براش دوباره تعریف کنیم که قالب اون ردیف هامون چیه و چشکلیه به همیندلیل یه Layoutinflater واسش تعریف می کنیم که دسترسی بدیم بهش بعدش واسش میگیم که آقا این View هامون چه قالبی دارن به شرح زیر:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater in=getLayoutInflater();
View row=in.inflate(R.layout.content_row, parent, false);
خب در اینجا باید 2تا متغییر از نوع TextView و ImageView تعریف کنیم و بهش دسترسی بدیم با استفاده از findViewbyId به اون تیتر و دکمه fav_btn که تعریف کرده بودیم تا متن رو توی خودش قرار بده ( البته حواسم نبود میخواستم تعریف کنم Content_matn نوشتم توی سورس Content_titr حالا فرقی نمیکنه کلا گفتم خواستم بگم که یه وقت گیج نشید بین تیتر و متنو اینا :v ) در پشت ImageView یه فینال هم میگذاریم چون تابع بعدا بهتون گیر میده در جلوتر خودش اگه شما نزارین مجبورتون میکنه که ImageView رو از نوع final تعیین کنید. که کلا به شرح زیر:
TextView matn=(TextView) row.findViewById(R.id.content_titr);
final ImageView fav_icon=(ImageView) row.findViewById(R.id.fav_btn);
حالا میایم تعریف می کنیم میگیم که آقا اگه Fav اون مطلب 0 بود تو اون عکس Favoff رو نشون بده و اگه 1 بود عکس Favon رو در قسمت دکمه نشون بده. که اینکارو با استفاده از دستور شرطی if انجام میدیم:
//inja chek mikonim ke age Fav=0 bud favoff ro neshun bede age nabud faveon ro
if(Fav[position].equals("1")){
fav_icon.setImageResource(R.drawable.favon);
}else{
fav_icon.setImageResource(R.drawable.favoff);
}
و زیرش هم تعریف می کنم که متن هایی که گرفتی رو در جای خودش منتشر کن:
//matnhai k az Content grefti ro tu ghesmate marbute neshun bede
matn.setText(Matn[position]);
نوبت به اصل ماجرا رسید ;)
در اینجا ما یه تابع setOnClickListener تعریف می کنیم واسه اون آیکون Favو میگیم که وقتی که روت کلیک شداز دیتابیس چک کن اگر اون مطلب ما fav=1 بود تو بیا با استفاده از تابع Fav_update که تو کلاس دیتابیس تعریف کرده بودیم عدد 0 رو تو جاش بگذار و همنطور عکس favon رو به favoff تغییر بده همچنین به کلیک Fav[position]=0 بده که توی همین صفحه لازمش داریم، ( میتونین تست کنین و نزارین ببینید تا چی میشه ;) ) و اگر هم Fav ما 1 نبود یعنی 0 بود که همه چی رو برعکس انجام بده یعنی بهش مقدرا 1 بده و آیکون رو به favonتغییر بده و Fav[position]=1 بکن:
//inja migim age click shod ru icone Fav chek che ettefaghi biofte
fav_icon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
db.open();
if(Fav[position].equals("1")){
//age Fav=1 bud tu database 0 ro zakhire kon va icon ro be favoff tabdil kon
db.Fav_update("content", Matn[position], "0");
fav_icon.setImageResource(R.drawable.favoff);
Fav[position]="0";
}else{
//age Fav=0 bud tu database 1 ro zakhire kon va icon ro be favon tabdil kon
db.Fav_update("content", Matn[position], "1");
fav_icon.setImageResource(R.drawable.favon);
Fav[position]="1";
}
db.close();
}
});
و در آخر هم تابع رو return به row میکنیم:
return (row);
و در آخرین مرحله میرسیم به تابع معروف خودمون یعنی onCreate ;)
در این تابع اول از همه setContentView رو براش تنظیم می کنیم که بهش Layout به نام contentlist که باهم ساختیم رو معرفی میکنیم و یه بار توابع دیتابیس رو براش فراخونی میکنیم، بعدش تابع load و بعد از اون تابع setListAdapter رو که کلاس AA رو فراخونی میکنه تا موارد رو توی لیست قرار بده به شرح زیر:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contentlist);
db=new database(this);
load();
setListAdapter(new AA());
}
خب کار ما تو این قسمت تموم میشه و دیگه کاری نداریم همه چی اوکی هست. یه شمای کللی از کد های کلاس Content_list رو در زیر براتون آوردم که یهوقت گیج نشید که جدا جدا نوشتم واستون:
package com.mytest.favtest;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class Content_list extends ListActivity {
private database db;
private String[] Matn;
private String[] Fav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contentlist);
db=new database(this);
load();
setListAdapter(new AA());
}
//Jahate List kardane Dadeha
class AA extends ArrayAdapter<String>{
public AA(){
super(Content_list.this,R.layout.content_row,Matn);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater in=getLayoutInflater();
View row=in.inflate(R.layout.content_row, parent, false);
TextView matn=(TextView) row.findViewById(R.id.content_titr);
final ImageView fav_icon=(ImageView) row.findViewById(R.id.fav_btn);
//inja chek mikonim ke age Fav=0 bud favoff ro neshun bede age nabud faveon ro
if(Fav[position].equals("1")){
fav_icon.setImageResource(R.drawable.favon);
}else{
fav_icon.setImageResource(R.drawable.favoff);
}
//matnhai k az Content grefti ro tu ghesmate marbute neshun bede
matn.setText(Matn[position]);
//inja migim age click shod ru icone Fav chek che ettefaghi biofte
fav_icon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
db.open();
if(Fav[position].equals("1")){
//age Fav=1 bud tu database 0 ro zakhire kon va icon ro be favoff tabdil kon
db.Fav_update("content", Matn[position], "0");
fav_icon.setImageResource(R.drawable.favoff);
Fav[position]="0";
}else{
//age Fav=0 bud tu database 1 ro zakhire kon va icon ro be favon tabdil kon
db.Fav_update("content", Matn[position], "1");
fav_icon.setImageResource(R.drawable.favon);
Fav[position]="1";
}
db.close();
}
});
return (row);
}
}
//Tabe'e load kare daryafte te'alat va amade saziye uno vasamun anjam mide
private void load(){
db.open();
int s=db.Count();
Matn=new String[s];
Fav=new String[s];
for(int i=0;i<s;i++){
Matn[i]=db.Content_display("content", i); //matn ro az filde Content migire
Fav[i]=db.Fav_display("content", i); //0 ya 1 budane filde Fav ro migire
}
db.close();
}
}
و نتیجه کار ما هم به شکل زیر درومد که یکی 2تا از fav_btn هارو هم کلیک کردم که بدونین کار میکنه واقعا P:
خب، ناگهان چه زود دیر می شود :((((
رسیدیم به انتهای این قسمت از برنامه، به پایان آمد این دفتر، حکایت همچنان باقیست! :P
شوخی ;) این پروژه رو حتما تا اینجا انجام بدین ببینیم به کجا میرسیم اگه سوالی بود لطفا فقط این زیر کامنت و نظر کنین و پست جدید نزارین لطفا تا همه چیز تمیز پیش بره
اگر امروز ایشالله پرسپولیس بازی رو برد، من قسمت سوم و آخر رو همین امشب اوکی میکنم، اگه نه که خدا میدونه!! :)))))))))))
فدا همتون، منتظر لایک و کامنتاتون هستم <3
قسمت سوم
ساخت صفحه fav_list و دستورات دیتابسی و اتمام کار
سلاااااااااااام شب همتون بخیر
اول اول اول از همه باید برد پرپولیس رو به همه تبریک بگم ;) میبنم که صدای اس تق لالی ها در نمیاد :)))))))
خب خب خب، نوبتی هم که باشه نوبت قسمت آخر این مجموعست، میریم که داشته باشیم آخر کارو :P
مثل مرحله قبل اول از همه یه کلاس به اسم Fav_list ایجاد میکنیم.
بعد میایم توی Layout ها و 2تا xml به نام های favlist و fav_row ایجاد میکنیم دقییییقا به همون شکل xml ها تو قسمت قبل دیگه اینجارو توضیح نمیدم و فقط کد و عکسشو میزارم.
کد xml فایل favlist.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/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff3555"
android:gravity="center"
android:padding="5dp"
android:text="علاقه مندی ها"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
عکسش:
کد های لایه fav_row :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/fav_matn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="15dp"
android:layout_marginTop="22dp"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ImageView
android:id="@+id/fav_del"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignTop="@+id/fav_matn"
android:layout_marginLeft="19dp"
android:src="@drawable/deletfav" />
</RelativeLayout>
و اینم عکسش:
خب خب خب، طبق معمول اوب میریم سراغ کد نویسی قسمت دیتابیسمون ;)
در اینجا ما 2تا تابع تعریف خواهیم کرد. یکی Fav_count که همون کار Count رو در دیتابیس قسمت دوم انجام میده منتهی اینبار برای Fav. و تابع Fav_display که درواقع کار نشون دادن مطالب و مقادیرمون رو انجام میده. در این صفحه از تابع Fav_update هم که تو قسمت قبل ساخته بودیم استفاده میکنیم. حالا بریم یکم این توابع رو دقیقتر بشکافیم:
تابع Fav_count : در این تابع ابتدا اسم table رو از ما میگیره و ما بهشم میگیم که اقای rawQuery شما لطفا برو تویدیتابیمون و اون tableکه بهت معرفی کردیم بگرد ببین کدوم مطالبی ما مقدار Fav اش مساوی با 1 هست. تعداد اینایی که 1 داره رو بشمر لطفا که میخوایم ازش توی حلقه for استفاده کنیم ( یه نکته مه قابل توجه که در قسمت قبل من واسه تابع Count اصن اسم table رو نگرفتم و یه سره توی دستور دیتابیسمون اسم جدول رو یه راست نوشتم content اما اینجا واسه این اسم table رو نیاوردم و ازش خواستم اسم table رو بهش بدین که بعدا تو پروژهاتون که از چندتا table استفاده کردین بدونین که میتونین اینجوری هم اسم tableهای مختلف رو بگیرین، فقط خواستم انعطاف رو بشتر نشون بدم ) :
//tedade matalebi k Fav'eshun 1 hast ro bedast miyarim ta betunim listeshun konim
public Integer Fav_count(String table){
Cursor cu=mydb.rawQuery("select * from "+table+" where Fav=1", null);
int s=cu.getCount();
return s;
}
تابع Fav_display : در این تابع 3 تا مقدار اسم table مقدار و عدد row ( جهت استفاده در حلقه for ) و مقدار field رو میگیره، حالا این مقدار field چیه تو ادامه متوجه میشین. به تابعمون میگیم که آقا دونه دونه برو جلو و اون مطالبی که Fav=1 هست رو واسمون یه جا لیست کن و بریز تو متغییرهامون و بعد مقدار s رو reurtn کن که ما استفاده کنیم. حالا اون مقدار field چیه؟ یادتونه تو قسمت قبل گفتم که میتونیم تابع Content_display رو طوری تعریف کنیم که دیگه احتیاج به Fav_display نباشه ؟ این همونه. ما اینجا کلا یه تابع تعریف کردیم که مقدار فیلد رو میگیره حالا این مقدار فیلد چیه؟ موقعیت فیلد Content و فیلد Fav رو در دیتابیسمون نشون میده. اگه دقت کنین ID صفر ست، Contet یک، و Fav جایگاهش 2 . کاربردش رو توی صفحه Fav_list بیشتر متوجه میشین:
//ba in dastur migim k agha harchi matlab ke Fav'eshun 1 hast ro vasamun bala biyar bebinim
public String Fav_display(String table,int row,int field){
Cursor cu=mydb.rawQuery("select * from "+table+" where Fav=1", null);
cu.moveToPosition(row);
String s=cu.getString(field);
return s;
}
حالا میرسیم به صفحه ی کلاس Fav_list اووووووف!!
در این کلاس دقیقا مثل کلاس قبلی یعنی Content_list عمل میکنیم و با اندک تغییرات.
قبل از هرکاری مثل سری قبل ابتدا کلاس Fav_listرو extends می کنیم از ListActivity و بعدش 3 تا متغییر زیر رو در بالا تعریف می کنیم:
public class Fav_list extends ListActivity {
private database db;
private String[] Matn;
private String[] Fav;
}
ما در اینجا باز 3تابع onCreate و AA و load رو داریم. بازهم مثل قبل با load شروع میکنیم:
تابع load : اول یه بار دیتابیسمون رو Open و Closeمیکنیم که بعدا فراموشمون نشه :D
میایم یه متغییر int به اسم s تا بره از تابع دیتابیسمون Fav_count تعداد مطالب Fav=1 رو بگیره. و بعدشم 2تا متغییر Matn و Fav رو آماده میکنیم تا این مقادیر رو در خودشون قرار بدن:
db.open();
//shomordane matalebi k Fav=1 darand
int s=db.Fav_count("content");
//matalebi k Fav=1 hast ro maghadireshuno begiro beriz tu fildhaye marbute
Matn=new String[s];
Fav=new String[s];
بعدش میایم یه یه حلقه for تشکیل میدیم که با استفاده از اون s به عنوان خط شمارشمون ازش استفاده کنین و مقادیر رو بگیریم. در این حلقه با استفاده از تابع دیتابیسی Fav_display شروع میکنیم به مقدار گیری. یادتون Field رو. اون اینجا استفاده میشه. اگه دقت کنید میبینید واسه Matn ما مقدار فیلد رو 1 گذاشتیم که یعنی اون مقادیری که تو فیلد 1 هست درواقع مقدار مطلبمونه اونه بریز تو Matn و در پایینش field رو گذاشتیم 2 چون فیلد Fav فیلد شماره 2 ماست تو جدول دیتابیسمون و مقادیر اونو میگیره و میریزه تو Fav:
//halgheye meghdargiri
for(int i=0;i<s;i++){
Matn[i]=db.Fav_display("content", i, 1);
Fav[i]=db.Fav_display("content", i, 2);
}
خب میایم در این مرحله یه کار جالب انجام میدیم، ببینید فرض کنید طرف هیچ چیزی رو علامت نزده و به لیست علاقه مندی هاش استفاده نکرده! خب چی میشه؟ یارو اگه بزه صفحه علاقه مندی هارو میره توش و میبینه که ا!!! اینجا که هیچی نیست! خیلی ضایعش یه صفحه خالی. پس چیکار میکنیم؟ یه تابع if درست میکنیم و بهش میگیم که اگه مقدار s=0 بود یعنی هیچ مطلبی علامت زده نشده بود واسه علاقه مندی های تو یه متن تکست به این مضمون که ( لیست علاقه مندی هاتون خالیه ) رو toast کن. :
//agar hich matlabi Fav=1 nabud begu k list khaliye
if(s==0){
finish();
Toast.makeText(getApplicationContext(), "لیست علاقه مندیهای شما خالی است", Toast.LENGTH_LONG).show();
}
در آخرش میایم تابع setListAdapter رو اینجا مینویسم و دیتابیس رو close میکنم. اگه یاتون باشه این setListAdapter رو در قسمت قبل در تابع اولیه onCreate ایتفاده کرده بودم اما اینجا در این قسمت حالا در ادامه میفهمید که چرا اینکارو کردم:
setListAdapter(new AA());
db.close();
میریم که تابع کلاس AA رو داشته باشیم.
دقیقا عین قسمت قبل اول کلاس AA مون exntends شده از ArrayAdapter بعشد داخلش اول یه تابع public AA داره که داخلش یه المنت super داریم که بهش میگیم کلا اسم کلاسی که توش هستیم چیه، قالب لیست ویوومونو یه بار آدرس میدیم و مقدار Matn رو به عنوان محتوی بهش معرفی میکنیم:
//etelat ro tuye list kon va tu listView namayesh bede
class AA extends ArrayAdapter<String>{
public AA(){
super(Fav_list.this,R.layout.fav_row,Matn);
}
بعد این تابع public یه تابع public دیگه داریم که یک View هست به نام getView که قبلا توضیح دادیم و واسش رابط LayoutInflater رو تعریف می کنیم و بعدش دوباره قالب ردیفهامونو بهش معرفی میکنیم:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater in=getLayoutInflater();
View row=in.inflate(R.layout.fav_row, parent,false);
زیر اون هم TextView مطلبون و ImageView مطلبمون که از نوع فینال هست رو بهش معرفی میکنیم و متصل میکنیم که تغییرات روشون اعمال بشه و بعدش بهش میگیم که مقدار مطلب رو به Matne مون تخصیص بده:
//eretbat dadane matn va icon be tavabeshan
TextView name=(TextView) row.findViewById(R.id.fav_matn);
final ImageView fav_del=(ImageView) row.findViewById(R.id.fav_del);
خب دیگه اینجا همشون Fav=1 شده اند. پس یه دکمه تعریف میکنیم که بتونیم ازش بعنوان دکمه ای استفاده کنیم که با زدنش اون مطلب از لیستمون پاک بشه درواقع Fav=0 بشه. در بالا اگه دقت کنیم ImageView رو به اون آیدی نسبت دادیم که نوشته fav_del هست که درواقع این همون آیکونیه که شکلش ضربدره قرمزه ;)
حالا اول این متغییر fav_del رو setOnClickListener میکنیم و بهشم میگیم که اگه روت کلیک شد دیتابیس رو Open کن و بعد با استفاده از اون تابع Fav_update که تو قسمت قبل ساخته بودیمش استفاده کن و مقدار Fav=0 کن بعدش دستابیس رو ببند و یه بار تابع load رو اجرا کن و اون مقداری که حذف شده رو دیگه نشون نمیده چون اونجا گه گفتم setListAdapter رو تو load میزاریم واسه همین بود چون یه بار دیگه ListView از نو ساخته باید بشه و اونی که Fav=1 نسیت رو دیگه نباید نشون بده. در آخخر هم تابع رو reurtnمیکنیم به row ها تا لیست آپدیت و اومی بشه :
//agar ruye dokmeye delet click shod Fav ro dar database 0 kon va matlab ro az safhe alaghemandiha hazf kon
fav_del.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
db.open();
db.Fav_update("content", Matn[position], "0");
db.close();
load();
}
});
return (row);
حالای میایم که تابع onCreate رو به خدمتش میرسیم. اول از همه setContentView رو بهش از Layout ها آدرس Fav_list رو میدیم که استفاده کنه و بعدش یه بار تابع کمکی دیتابیس رو اجرا میکنیم و بعدش هم تایع load رو که میشه این:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favlist);
db=new database(this);
load();
}
خب ازونجایی که ممکنه که گیج شده باشین یه بار کلا این کلاس و صفحه Fav_list رو باهم مرور میکنیم:
package com.mytest.favtest;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class Fav_list extends ListActivity {
private database db;
private String[] Matn;
private String[] Fav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favlist);
db=new database(this);
load();
}
//etelat ro tuye list kon va tu listView namayesh bede
class AA extends ArrayAdapter<String>{
public AA(){
super(Fav_list.this,R.layout.fav_row,Matn);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater in=getLayoutInflater();
View row=in.inflate(R.layout.fav_row, parent,false);
//eretbat dadane matn va icon be tavabeshan
TextView name=(TextView) row.findViewById(R.id.fav_matn);
final ImageView fav_del=(ImageView) row.findViewById(R.id.fav_del);
//takhsis dadan matn be ghesmate matn
name.setText(Matn[position]);
//agar ruye dokmeye delet click shod Fav ro dar database 0 kon va matlab ro az safhe alaghemandiha hazf kon
fav_del.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
db.open();
db.Fav_update("content", Matn[position], "0");
db.close();
load();
}
});
return (row);
}
}
//load kon va begir maghadiri k lazeme ro az database
private void load(){
db.open();
//shomordane matalebi k Fav=1 darand
int s=db.Fav_count("content");
//matalebi k Fav=1 hast ro maghadireshuno begiro beriz tu fildhaye marbute
Matn=new String[s];
Fav=new String[s];
//halgheye meghdargiri
for(int i=0;i<s;i++){
Matn[i]=db.Fav_display("content", i, 1);
Fav[i]=db.Fav_display("content", i, 2);
}
//agar hich matlabi Fav=1 nabud begu k list khaliye
if(s==0){
finish();
Toast.makeText(getApplicationContext(), "لیست علاقه مندیهای شما خالی است", Toast.LENGTH_LONG).show();
}
setListAdapter(new AA());
db.close();
}
}
اینم یه عکس از تست این صفحه ;)
خب آموزشمون اینجا به اتمام رسید دیگه کاری نداریم. اگه سوالی یا مطلبی بود در خدمتتونم.
البته یه قسمت 4 هم داریم که اونو میذارم وقتی امتیاز پست به 15 20 رسید واستون منتشر میکنم امشب که یک ویدئو از تست اپ هست و فایلهای سورسش بعلاوه خود فایل APK.
منتظر لایکها و پیامهاتون هستم ;)
قسمت چهارم - پایان
سورس تمرین و فایل APK
خب، همونطور که قول داده بودم میتونید از لینک زیر سورس تمرین و فایل APK رو دانلود کنید
توجه کنید که من این برنامه رو در آخرین نسخه اکلیپس ساختم:
منتظر نظات پیشنهادات و امتیاز های شما هستم <3 ;)
این تاپیک به آقای «پوریا انجمنی» گزارش خواهد شد، و چنانچه ایشان تأیید کنند که این یک کپی است و اجازه درج آن را به کاربر sadra نداده اند، این تاپیک حذف خواهد شد و احتمالاً عواقب بعدی هم خواهد داشت.
پاسخ آقای انجمنی دریافت شد:
سلام
محتوای تاپیکی که اعلام کردید رو بررسی کردم و متاسفانه بله آموزشها بدون کوچکترین تغییری کپی برداری شده بودند، در صورتی که اموزشها با ذکر منبع و آدرس دهی واضح باشن از نظر من مشکلی نداره، باز هم با اینحال خودتون مختارید،
ممنون از توجهتون
در نهایت :
با توجه به پاسخ فوق، حتماً بصورت مشخص و گویا، لینک سایت و نام صاحب اثر را در ابتدای متون خود درج نمایید. طبق قوانین جدید سایت، این موضوع Ban کاربر منتشر کننده را می طلبید که با توجه به رضایت صاحب اثر، این اتفاق نخواهد افتاد.
امیدوارم هر چند که قانون Copy Right نداریم اما تا جای ممکن به آن پایبند باشیم.
یکی از ارورها...در این قسمته..در خط دوم..cursor......
این هم ارور: at com.example.amir.searchsqlite.database3.Count(database3.java:98)
public Integer Count(){
Cursor cu=mydb.rawQuery("select * from content_row", null);
int s=cu.getCount();
return s;
}
//namayesh dahandeye Matne mataleb jahate estefade dar classe Content_list
public String Content_display(String table,int row){
Cursor cu=mydb.rawQuery("select * from "+table+" order by ID", null);
cu.moveToPosition(row);
String s=cu.getString(1);
return s;
}
سلام
ممنون بابت اموزشتون.،من سورس شما رو دانلود کردم و تو اندروید استودیو باز کردم تا قبل اینکه کلاسا رو باز کنم مشکلی نبود ولی
تا یه کلاس رو باز کردم کل برنامه پراز ارور شد و به قسمت R مربوط به ریسورسه و همینطور به منیفست گیر میده که خودم فک میکنم از اندروید استودیو باشه..عکساشم میذارم..ممنون میشم راهنمایی بفرمایید
.یاعلی
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .