Android五天樂(第三天)ListFragment與ViewPager,androidviewpager
1ListFragment
今天首先學習了一種非常常用的展示情境:列表展示。
昨天學習了使用Fragmet來代替activity進行設計,今天在託管單個fragment的基礎上,掌握託管一個布局list。先看下效果:
因為Fragment列表需要使用ArrayList儲存,而為了使Fragment對象受acrivity等生命週期影響, 建立如下單例類:
public class CrimeLab { private ArrayList<Crime> mCrimes; private static CrimeLab sCrimeLab; private Context mAppContext; private CrimeLab(Context context){ mAppContext=context; mCrimes=new ArrayList<Crime>(); for(int i=0;i<100;i++){ Crime c =new Crime(); c.setTitle("Crime #"+i); c.setSolved(i%2==0); mCrimes.add(c); } } public static CrimeLab get(Context c){ if(sCrimeLab==null){ sCrimeLab=new CrimeLab(c.getApplicationContext()); } return sCrimeLab; } public ArrayList<Crime> getmCrimes(){ return mCrimes; } public Crime getCrime(UUID id){ for (Crime c: mCrimes){ if(c.getId().equals(id)){ return c; } } return null; }}
同時,還要建立相應的fragment布局檔案和類檔案,實際上,存在專門支援list fragment的類:ListFragment。繼承這個類即可,之後可使用其內建的listadapter。
為什麼使用adapter呢? 因為我們的fragmentlab中建立了100個fragment對象,而我們不可能在一個頁面中把他們全部顯示出來,而是需要顯示時才建立對象。adapter就是從模型層獲得資料,並把它提供給ListView顯示的橋樑。
private class CrimeAdapter extends ArrayAdapter<Crime>{ public CrimeAdapter(ArrayList<Crime> crimes){ super(getActivity(),0,crimes); } @Override public View getView(int position,View convertView,ViewGroup parent){ if(convertView==null){ convertView=getActivity().getLayoutInflater().inflate(R.layout.list_item_crime,null); } Crime c=getItem(position); TextView titleTextView=(TextView)convertView.findViewById(R.id.crime_list_item_titleTextView); titleTextView.setText(c.getTitle()); TextView dateTextView=(TextView)convertView.findViewById(R.id.crime_list_item_dateTextView); dateTextView.setText(c.getDate().toString()); CheckBox solvedCheckBox=(CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox); solvedCheckBox.setChecked(c.isSolved()); return convertView; } }
實現自己定製Adapater的代碼,之所以要實現自己的adapter,是因為在list的每一個條目我們定製了自己的布局。如代碼中的list_item_crime.
這樣就得到了list顯示的fragment。
2ViewPager
ViewPager可以實現左右滑動螢幕切換查看不同清單項目的功能。
ViewPager需要藉助於Adapter才能夠提供視圖。 通過PagerAdapter的子類:FragmentStatePagerAdapter來處理兩者間的配合問題。
這裡需要實現兩個方法,getCount()和getItem()。程式碼範例如下:
mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) { @Override public int getCount(){ return mCrimes.size(); } @Override public Fragment getItem(int pos) { Crime crime=mCrimes.get(pos); return CrimeFragment.newInstance(crime.getId()); } });
3 fragment資料轉送
跟activity類似,fragment間也可以進行資料轉送。而且fragment級的資料轉送會使編程更加靈活。
試想如下情境: 在CrimeFragment中需要按鍵調出DatePickerFragment, 後者的初始化需要前者提供的資料。同時,DatePickerFragment的返回值也要作用於CrimeFragment。
需要做的事情有如下幾步:
1)從CrimeFragment 初始化DatePickerFragment時, 將資料作為構造參數傳入
2)DatePickerFragment構造時,將傳入的值儲存到argument
3)DatePickerFragment渲染時,取arguments中值
4)DatePickerFragment將值回傳給CrimeFragment
為實現以上過程,首先要在DatePickerFragment 編寫newInstance方法, 改方法可以在執行個體化DatePickerFragment時被調用並接受參數,同時在fragment create前準備好資料
public static DatePickerFragment newInstance(Date date){ Bundle args=new Bundle(); args.putSerializable(EXTRA_DATE,date); DatePickerFragment fragment=new DatePickerFragment(); fragment.setArguments(args); return fragment; }
返回資料時,則覆蓋onActivityResult方法。
互動過程如: