ListView Project (7)















ListView project ေလးတစ္ခု အပ်င္းေျပ ေရးၾကည္႔ရေအာင္ဗ်ာ ... အပိုင္း ( 7 )
***********************

ဘာမွ မေျပာခင္ အရင္အပိုင္းက ေပးခဲ႔တဲ႔ list_row.xml ဖိုင္ကို ဒီ post ေအာက္ဆံုးမွာ ေပးထားတဲ႔ layout အတိုင္း ယူသံုးေပးပါလို႔ ... ဒါေၾကာင့္ အခုပဲ အဲ႔ layout ဖိုင္ကို ယူလဲလိုက္ပါ။ ေနာက္ သေဘာတရားသိသြားျပီဆို ၾကိဳက္သလို ျပင္ေရးေပါ႔။

ကဲ အပိုင္း (7)။ အရင္ ListView ေတြ ေရးခဲ႔ဖူးရင္ အားလံုးကို ခဏေမ႔ထားလိုက္ပါ။ ေခါင္းကို ရွင္းထားပါ။ ျပီးေတာ႔ ကိုယ္ေရးတဲ႔ code ဟာ ဘာေၾကာင့္ ေရးလိုက္ရပါတယ္ဆိုတာကို အာရံုစိုက္ထားပါ။ ဒါမွ ဘယ္ေနရာမွ ဝင္ေရးရင္ ဘာျဖစ္သြားမလဲ? ဘာ error တက္ႏိုင္မလဲ အေျဖထုတ္တတ္သြားပါမယ္။ ဒီအပိုင္းမွာ class constructor ကေန data အဝင္အထြက္ပိုင္း ပါလာပါမယ္။ ကဲ စ ရေအာင္။

ဒီေန႔ code မယ္႔ code flow က အေပါင္း Button ကို ႏွိပ္လိုက္တာနဲ႔ Dialog Box ပြင့္လာ ၊ ျပီး Dialog Box ထဲက Add Button ကို ႏွိပ္လိုက္တာနဲ႔ ListView မွာ data လွမ္းထည္႔ျပီးျပႏိုင္ေအာင္ code ရမွာ ျဖစ္ပါတယ္။

ဆိုေတာ႔ ပထမဆံုး Dialog Box မွာ ရွိေနတဲ႕ EditText ေတြ Button ေတြကို id ခ်ိတ္ျပီး click action ဖမ္းေပးရမွာပါ။ Dialog Box အတြက္ သံုးခဲ႔တဲ႔ class က MySpecialDialog class နဲ႔ Layout က new_member_dialog.xml ဆိုေတာ႔ ဒီဖိုင္ႏွစ္ခုမွာ သြားေရးရမွာပါ။

အရင္ဆံုး xml ဖိုင္မွာ EditText ေတြ Button ေတြကို AIDE Designer ကေန သက္ဆိုင္ရာ EditText/Button ေတြေပၚေထာက္ျပီး ID ကေန id သတ္မွတ္ေပးလိုက္ပါ။ ေပးရမယ္႔ id နာမည္ေတြက -

nameEdt
phoneEdt
levelEdt
cancelBtn
addBtn

လို႔ ျဖစ္ပါတယ္။

ျပီးသြားရင္ MySpecialDialog class နဲ႔ ခ်ိတ္ဆက္မွာမို႔ MySpecialDialog class အတြင္း ထိပ္ဆံုးမွာ ဒီပစၥည္း ငါးမ်ိဳးအတြက္ သက္ဆိုင္ရာ variable ငါမ်ိဳး ေၾကျငာလိုက္ပါ။

private EditText nameEdt, phoneEdt, levelEdt;
private Button addBtn,cancelBtn;

ဒါေတြကို ဒီ class အတြင္းမွာပဲ သံုးမွာမို႔ ေရွ႕က private ထည္႔ထားတာပါ။

ျပီးသြားရင္ ဒီ class မွာ က်ေနာ္တို႔ Layout View ကို ေျပာင္းေပးခဲ႔တာက onCreateView(...) method ထဲမွာပါ။ ဒါေၾကာင့္ onCreateView() အတြင္းမွာ View ကို ျပန္ထုတ္မေပးခင္ id အမိရွာခ်ိတ္ေပးရမွာပါ။ ဒါေၾကာင့္ return statement ျဖစ္တဲ႔ return rootLayout; မတိုင္ခင္ အေပၚက ေရးရမွာပါ။( ss ျပထားပါမယ္။)

ဒီေနရာမွာ က်ေနာ္တို႔ id ခ်ိတ္ေနက် code က ( EditText  တစ္ခုအတြက္ဆိုရင္ )

nameEdt = (EditText) findViewById(R.id.nameEdt);

လို႔ ေရးခ်ိတ္ေနၾကပါ။ ဒါေပမယ္႔ ဒီ class ထဲမွာေတာ႔ ဒီ EditText တို႔ Button တို႔ ဆိုတာေတြဟာ က်ေနာ္တို႔ LayoutInflator ကေန ဆြဲယူဖြင့္ထားတဲ႔ rootLayout ဆိုတဲ႔ View ထဲမွာ ေရာက္ေနတဲ႔အတြက္ id ခ်ိတ္ရင္ rootLayout ထဲကေန ရွာခ်ိတ္ေပးရပါတယ္။

nameEdt = (EditText) rootLayout.findViewById(R.id.nameEdt);

အဓိပၸါယ္က

rootLayout(၏)findViewByID(R.id.xxxxx); (id ဘာနဲ႔ ပစၥည္း) လို႔ နားလည္ႏိုင္ပါတယ္။ ဒီအတိုင္း အေပၚက ပစၥည္းငါးခုကို id ခ်ိတ္ေပးလိုက္ပါ။

nameEdt = (EditText) rootLayout.findViewById(R.id.nameEdt);
phoneEdt = (EditText) rootLayout.findViewById(R.id.phoneEdt);
levelEdt = (EditText) rootLayout.findViewById(R.id.levelEdt);

addBtn = (Button) rootLayout.findViewById(R.id.addBtn);
cancelBtn = (Button) rootLayout.findViewById(R.id.cancelBtn);

id ခ်ိတ္ျပီးသြားရင္ Button ႏွစ္ခုကို click သိေအာင္ setOnClickListener နည္းနဲ႔ အခုလို ခ်ိတ္ေပးရမွာပါ။

addBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {

}
});

Button တစ္ခုကို setOnClickListener() နည္းနဲ႔ သံုးရင္ ဒီအေပၚက code နဲ႔ပဲ အျမဲတမ္း သံုးရမွာ ျဖစ္တာေၾကာင့္ အလြတ္ေရးတတ္ေအာင္ လုပ္ထားပါ။

(cancelBtn အတြက္လည္း အခု လို ခ်ိတ္ရန္။)

ကဲ Dialog Box ရဲ႕ EditText ေတြ Button ေတြကို သိေအာင္လုပ္ျပီးသြားျပီဆိုေတာ႔ code logic စပါမယ္။

က်ေနာ္တို႔ အေပါင္း Button ကို ႏွိပ္လိုက္ရင္ Dialog Box ပြင့္လာပါမယ္။ ပြင့္လာတဲ႔အခ်ိန္မွာ Box ထဲက EditText ေတြဆီကေန သက္ဆိုင္ရာ နာမည္တို႔ ဖုန္းနံပါတ္တို႔ Level တို႔ရဲ႕ data ေတြကို ဖမ္းယူျပီး List ထဲကို ထည္႔ျပီး ListView မွာ ျပရပါမယ္။

ဒါဆိုထည္႔ရမယ္႔ List က ဘယ္မွာလည္း? MainActivity class ဆီက က်ေနာ္တို႔ သံုးမယ္လို႔ ေၾကျငာေပးခဲ႔တဲ႔ mList ထဲ ကိုပဲျဖစ္ပါတယ္။ ဒါဆို ဒီ mList ကို MainActivity class ကေန ဘယ္လို လွမ္းေတာင္းမလဲ? အခု class ရဲ႕ class constructor ကေန လွမ္းေတာင္းလို႔ရပါတယ္။ ဒါေၾကာင့္ MySpecialDialog class ေရးတုန္းက constructor ပါ ေအာင္ ေရးခဲ႔ပါလို႔ ေျပာခဲ႔ျခင္း ျဖစ္ပါတယ္။

ဒါ အခုက်ေနာ္တို႔ ေရးခဲ႔တဲ႔ class ရဲ႕ မူလ constructor ပါ။

public MySpecialDialog( ) {

}

ဒီ constructor ကေန mList ကို လွမ္းေတာင္းမွာဆိုေတာ႔ mList ဟာ ArrayList<> အမ်ိဳးအစားမိုလို႔ ေရွ႕က type ေနာက္က variable နာမည္နဲ႔ input ေတာင္းယူလက္ခံမယ္ေပါ႔။

public MySpecialDialog(ArrayList<AIDEFighter> fighterList) {


}

variable ကို ကိုယ္ၾကိဳက္တဲ႔ နာမည္ေပးႏိုင္ပါတယ္။ MainActivity class ကေန ေပးလိုက္မွာကေတာ႔ mList ဆိုတဲ႔ စာရင္းပါပဲ။ ဒီဖက္ class မွာ ဒီ စာရင္းကို ကိုယ္ၾကိဳက္တဲ႔ နာမည္နဲ႔ ယူသံုးခြင့္ရွိပါတယ္။ ဒါေၾကာင့္ က်ေနာ္က fighterList ဆိုတဲ႔ နာမည္နဲ႔ input ကို လက္ခံယူမွာပါ။ type ကေတာ႔ ArrayList<> ပါပဲ။ ဒီ type တူေနဖို႔ပဲ အေရးၾကီးတာပါ။

constructor က input အျဖစ္ရလာတဲ႔ ဒီ fighterList ကို ဒီ class အတြင္း သံုးႏိုင္ဖို႔ class ထိပ္မွာ variable တစ္ခုေၾကျငာျပီး constructor ကေန ဖမ္းယူလိုက္ပါ။

က်ေနာ္က class ထိပ္မွာ variable တစ္ခုကို အခုလို ေၾကျငာေပးလိုက္ပါတယ္။

ArrayList<AIDEFighter> mFighterList;

ျပီးေတာ႔ ေစာေစာက List စာရင္းကို constructor ထဲကေန ဖမ္းယူလိုက္ပါတယ္။

public MySpecialDialog(ArrayList<AIDEFighter> fighterList) {

mFighterList = fighterList;

}

ဒါဆို MainActivity class ဆီက mList ကို ဒီဖက္ class က mFighterList အမည္နဲ႔ ဖမ္းယူထားႏိုင္ျပီမို႔ ဒီ class ထဲမွာ ဒီ စာရင္းကို အသံုးျပဳလို႔ ရပါျပီ။

က်ေနာ္တို႔ ထည္႔စရာ List စာရင္းေတာ႔ ရွိျပီ။ Add Button ႏွိပ္တာနဲ႔ ဒီ List စာရင္းထဲကို data ထည္႔ရမယ္။ ထည္႔ရမယ္႔ data က AIDEFighter တိုတဲ႔ object ေလးေတြ။ အဲ႔ object ထဲကို နာမည္တို႔ ဖုန္းနံပါတ္တို႔ EditText ေတြဆီက လွမ္းယူရမယ္႔ data ေတြ ထည္႔ ေပးရမွာပါ။

ဒါေတြကို တစ္ေနရာတည္းမွာ သီးသန္႔ေလးျဖစ္သြားေအာင္ အခု class ထဲမွာ method ေလးတစ္ခု ဖန္တီး code ရေအာင္ဗ်ာ။ အခု method နာမည္ကို addOneFighter လို႔ ေပးၾကစို႔။ ေနဦး အခု method က ဒီ class အတြင္းကေနပဲ ေခၚသံုးမွာမို႔ private modifier နဲ႔ ေရးေပး။

private void addOneFighter( ) {

}

ဒီအေပၚက method ထဲမွာပဲ ပထမ AIDEFighter ဆိုတဲ႔ object တစ္ခု ဖန္တီးမယ္။ ဒါေၾကာင့္ အဲ႔ object ဖန္တီးေပးဖို႔ တာဝန္ယူရတဲ႔ AIDEFighter class ရဲ႕ constructor ေခၚျပီး AIDEFighter object တစ္ခု ဖန္တီးမယ္။

AIDEFighter fighter = new AIDEFighter();

AIDEFighter ဆိုတဲ႔ object type ကို fighter ဆိုတဲ႔ နာမည္နဲ႔ ဖန္တီးယူတာေနာ္။

ျပီးရင္ နာမည္ EditText က စာကို

nameEdt.getText().toString() နဲ႕ လွမ္းယူျပီး

AIDEFighter object အတြက္ class ေရးတုန္းက setter method ျဖစ္တဲ႔ setName() method နဲ႔ object ရဲ႕ နာမည္တန္ဖိုး အခုလို လွမ္းထည္႔မယ္။

fighter.setName(nameEdt.getText().toString());

ဖုန္းနံပါတ္ အတြက္ -
fighter.setPhone(phoneEdt.getText().toString());

Level အတြက္ -
fighter.setLevel(levelEdt.getText().toString());

(AIDEFighter object တစ္ခုအတြက္ setter methods ေတြ ယူသံုးျပီး တန္ဖိုးေတြ ထည္႕သြားတာ သတိျပဳပါ။ ေနာက္အပိုင္း FighterAdapter class ကေန getter method ေတြနဲ႔ object ဆီက တန္ဖိုးအသီးသီးကို ျပန္ထုတ္ယူပါမယ္။ )

ျပီးရင္ အခု ဖန္တီး data ေတြထည္႔ေပးထားတဲ႔ fighter ဆိုတဲ႔ object ေလးကို အေပၚမွာ ဖမ္းယူထားတဲ႔ List စာရင္းထဲကို ထည္႔လိုက္မယ္။

mFighterList.add(fighter);

( ဒီေနရာမွာ add( ) ဆိုတဲ႔ method က List ေတြထဲ item ေတြ ထည္႔ဖို႔လုပ္ေပးထားတဲ႔ android က ေပးထားတဲ႔ မူရင္း method တစ္ခုပါ။ ကိုယ္က ေရးေပးစရာမလိုတာ သတိျပဳပါ။ )

ဒါဆို addOneFighter() method အျပည္႔အစံုက -

private void addOneFighter() {

AIDEFighter fighter = new AIDEFighter();

fighter.setName(nameEdt.getText().toString());
fighter.setPhone(phoneEdt.getText().toString());
fighter.setLevel(levelEdt.getText().toString());

mFighterList.add(fighter);

}

ဒီလို ထည္႔ေပးတာကို Add Button ကို click လိုက္ခ်ိန္မွ လုပ္ေပးေစခ်င္တာဆိုေတာ႔ အေပၚက Add Button onClick() ထဲ အခု method ေလးကို method call လုပ္ေပးလိုက္ရံုပါ။

addOneFighter();

List စာရင္းထဲကို AIDEFighter object ဖန္တီးထည္႔တဲ႔ အပိုင္းေတာ႔ ျပီးသြားျပီ။ ဘာက်န္ပါေသးလဲ? အခု List စာရင္းကို ListView မွာ တင္ျပဖို႔ က်န္ေသးတယ္။

ဒါနဲ႔ ListView က ဘယ္မွာ ရွိတာလဲ? MainActivity class ဆီမွာ။ ဒါဆို သြားစို႔ MainActivity class ဆီ။ :)

ListView ေပၚတင္ျပဖို႔ကိုလည္း method ေလးတစ္ခု ဖန္တီးေရးျပတာေပါ႔ဗ်ာ။ ဒါမွ method ေတြ ေရးတတ္ေရးတတ္လာမွာ။

ListView ကို ျပေပးမယ္႔ method ေရးမွာဆိုေတာ႔ နာမည္ကို showMyList လို႔ ေပးလိုက္ရေအာင္။

public void showMyList() {

}

အရင္အပိုင္းက ေျပာခဲ႔တဲ႔ ListView မွာ တင္ျပရင္ code flow က ဘယ္လို?

** List စာရင္း
** Adapter
** ListView.setAdapter(adapter);

ဟုတ္တယ္ေနာ္။

ဒါဆို အခု showMyList အတြင္း ေရးရမွာက အေပၚက code flow အတိုင္း။ List စာရင္းက ရွိျပီးသား mList ။ (MainActivity class က List စာရင္းေနာ္။ MainActivity class မွာ ေရးေနတာဆိုေတာ႔။ )

ဒါဆို Adapter အတြက္ကေရာ? ေရးျပီးသား FighterAdapter class ။ FighterAdapter class က constructor ကေန input ေတာင္းထားတာ ပါေသးလား။ ပါေသးတယ္ Context နဲ႔ List စာရင္း။ (FightAdapter class constructor ကို ျပန္ၾကည္႔ပါ။) ဒါဆို သူေတာင္းတာ ထည္႔ျပီး FighterAdapter class ကို ေခၚဖန္တီးလိုက္ရံု။

Context ဆိုတာက "this" reference ကို ေျပာတာပါ။ List စာရင္းက mList ကို ထည္႔ေပးလိုက္ရံု။ ဆိုေတာ႔ -

FighterAdapter adapter = new FighterAdapter(this,mList);

ျပီးေတာ႔ ListView ေပၚတင္ျပ။

mListView.setAdapter(adapter);

ဒါဆို showMyList( ) method အျပည္႔အစံုက ဒီလိုေပါ႔ -

public void showMyList() {
FighterAdapter adapter = new FighterAdapter(this,mList);
mListView.setAdapter(adapter);
}

ဒါက ListView ေပၚ တကယ္တင္ျပေပးမယ္႔ method ေလး။

ဆိုေတာ႔ Dialog Box က Add Button ကို ႏွိပ္လိုက္တာနဲ႔ addOneFighter() method က List ထဲကို data (object) တစ္ခု ဖန္တီးထည္႔ေပးျပီးရင္ ListView မွာ တင္ျပေပးဖို႔ MainActivity class ဆီက showMyList() method ကို လွမ္း call (run) ေပးရမွာေပါ႔။

ဆိုေတာ႔ MySpecialDialog class ဆီက Add Button onClick ခ်ိတ္ထားတဲ႔ (ဟမ္မေရးး ေမာလတ္ထွာ အဲ ဟုတ္ေပါင္ ေညာင္းလိုက္တာ လက္ ! :) )  ဆီကို သြားရေအာင္။

OK ဒီလို DialogFragment ကေနပဲျဖစ္ျဖစ္ Fragment class ေတြဆီကျဖစ္ျဖစ္ သူ႔တို႔ကို host လုပ္ထားတဲ႔ Activity class ဆီက public method တစ္ခုကို လွမ္း run/ method call လုပ္ခ်င္ရင္ ဒီလို code နဲ႔ လွမ္း run လို႔ ရပါတယ္။ အလြယ္နည္းပါ။ Intent ေတြဘာေတြနဲ႔ ကူးစရာ မလိုတဲ႔နည္းေပါ႔။

((MainActivity)getActivity()).showMyList();

ဆိုေတာ႔ ဒီ code ကို Add Button onClick အတြင္းက ေစာေစာက method call လုပ္ထားတဲ႔ addOneFighter(); ေအာက္က ေရးေပးလိုက္ပါ။ သေဘာက List ထဲကို data ထည္႔အျပီး ListView ေပၚတင္ျပေပးတဲ႔ method ကို လွမ္း call/run ေပးတာပါပဲ။ ျပီးတာနဲ႔ အခု Dialog Box ကို ပိတ္ပစ္ဖို႔ ေအာက္တစ္ေၾကာင္းက -

dismiss();

ထည္႔ေပးလိုက္ပါ။

ကဲ ဒီထိေအာင္ တစ္ဆင့္ျခင္း လိုက္ code ခဲ႔တယ္ဆိုရင္ ေနာက္ဆံုးအေနနဲ႔ AIDE က error တစ္ခု ျပေနပါမယ္။ အဲ႔ဒါကေတာ႔ က်ေနာ္တို႔ ေစာေစာက MySpecialDialog class ရဲ႕ constructor ကို ျပင္ေရးလိုက္တဲ႔အတြက္ ျဖစ္ပါတယ္။ MainAvtivity class ဆီက List စာရင္းကို ေတာင္းယူထားတာေၾကာင့္ပါ။ ဒါေၾကာင့္ အရင္ ေရးခဲ႔တဲ႔ showMyDialog() method အတြင္းက MySpecialDialog ကို ေခၚထားတဲ႔ code မွာ သူေတာင္းေနတဲ႔ List စာရင္းျဖစ္တဲ႔ mList ကို ထည္႔ေပးလိုက္ရမွာ။

ဒါဆိုရင္ အခုပိုင္း ျပီးပါျပီ။ App build လုပ္ Dialog Box ကို ဖြင့္ျပီး Add Button ကို ႏွိပ္ၾကည္႔ျပီး စမ္းသပ္ၾကည္႔လို႔ ရပါျပီ။

အဲသလို Add Button ကို ႏွိပ္လိုက္တာနဲ႔ Unfortunately .... stopped ျဖစ္ေနပါမယ္။ :)

ဘာေၾကာင့္လဲဆိုေတာ႔ Java မွာ အေရးၾကီးတဲ႔ အခ်က္တစ္ခ်က္ ေရးစရာ က်န္ေနေသးလို႔ပါ။ အဲ႔ဒါကေတာ႔ ကိုယ္ေၾကျငာထားတဲ႔ variable ကို ယူမသံုးခင္မွာ initialize (တန္ဖိုးေပး အသက္ဝင္ေအာင္) လုပ္ေပးရပါမယ္တဲ႔။ အခု က်ေနာ္တို႔ သံုးမလို႔ လုပ္ေနတဲ႔ mList ဆိုတာကို က်ေနာ္တို႔ declare လုပ္ ေၾကျငာပဲ ထားရပါေသးတယ္။ initialize မလုပ္ကေသးပါဘူး။ ဒါေၾကာင့္ mList က null (အသက္မဲ႔ ဗလာ) ျဖစ္ေနပါတယ္။ အဲ႔ဒါကို Add Button ကို ႏွိပ္လိုက္တဲ႔ မရွိတဲ႔ List စာရင္းထဲ ထည္႔ခိုင္းသလို ျဖစ္ေနလို႔ NullPointerException ျဖစ္ျပီး Unfortunately ... stopped ျဖစ္ရတာပါ။

ဒါေၾကာင့္ MainActivity class ရဲ႕ onCreate() ထဲမွာ mListView = ... ေအာက္ တစ္ေၾကာင္းကေန အခုလို mList ကို initialize လုပ္ေပးလိုက္ပါ။

mList = new ArrayList<AIDEFighter>();

မယံုရင္ ဒီ code မပါပဲ စမ္းေစသတည္းေပါ႔။

ကဲ ဆိုင့္က်ဲင္းး ...

အပိုင္း ( 8 ) ေမွ်ာ္ .... :)

list_row.xml
===========
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#64126D">

<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@android:drawable/ic_delete"
android:layout_centerVertical="true"
android:id="@+id/studentlistrowImageView1"/>

<TextView
android:layout_height="wrap_content"
android:text="Text"
android:layout_width="wrap_content"
android:layout_toRightOf="@id/studentlistrowImageView1"
android:layout_centerVertical="true"
android:id="@+id/rollTv"
android:textColor="#73E2FA"
android:paddingLeft="5dp"
android:textSize="16sp"/>

<TextView
android:layout_height="wrap_content"
android:text="Level"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:background="#FE392C"
android:textColor="#FDFDFD"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:id="@+id/listrowTextView1"/>

<Button
android:layout_height="wrap_content"
style="?android:attr/buttonStyleSmall"
android:text="Call"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:id="@+id/listrowButton1"
android:layout_alignParentBottom="true"
android:textColor="#FFFFFF"/>

<Button
android:layout_height="wrap_content"
style="?android:attr/buttonStyleSmall"
android:text="x"
android:layout_width="wrap_content"
android:layout_toLeftOf="@id/listrowButton1"
android:layout_below="@id/listrowTextView1"
android:layout_marginRight="50dp"
android:textColor="#F02A1D"/>

</RelativeLayout>

-----------------------------------------

ကိုမ်ိဳး

AIDE Android Lessons And Project Group

မွ ကူးယူတင္ထားပါသည္

#mkk_ListView


Comments