一:在Fragment中顯示ListView
1.在Fragment中顯示ListView,主要用到ListFragment這個類,建立一個類繼承ListFragment,ListFragment内置了ListView,是以無需覆寫Fragment的onCreateView()方法或者為Fragment生成一個帶有ListView的布局,ListFragment預設實作 一個全屏ListView布局;
2.把Fragment托管到Activity中;
<span style="font-size:14px;">public abstract class SingleFragmentActivity extends FragmentActivity {
protected abstract Fragment createFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager manager = getFragmentManager();
Fragment fragment = manager.findFragmentById(R.id.fragmentContainer);
if(fragment == null) {
fragment = createFragment();
manager.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}</span>
}
在這裡有一個比較好的技巧,因為在Activity中托管Fragment基本都是開啟事務添加添加FragmentContainer和Fragment執行個體,這樣幾乎每一個建立的Activity托管Fragment都要用到同一套代碼,要是托管多少個Fragment就在多少個Activity中編寫同一套代碼,會顯得很傻,是以可以通過建立一個抽象類,并提供一個抽象方法用于建立Fragment的執行個體。然後讓每一個需要托管Fragment的Activity都繼承這個抽象類,并實作父類的抽象方法就可以了
3.有了ListView之後,接下來就是建立擴充卡,也就是ArrayAdapter<T>執行個體,把ListView和資料集串聯起來,這一步在Fragment和Activity中都幾乎相同。
4.最後可以使用setListAdapter(ListAdapter)為ListFragment管理的内置ListView設定Adapter。
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.crime_title);
crimes = CrimeLab.get(getActivity()).getCrimes();
CrimeAdapter adapter = new CrimeAdapter(getActivity(), android.R.layout.simple_list_item_1, crimes);
setListAdapter(adapter);
}
要注意的是,其中的getActivity()是ListFragment的便利方法,表示傳回托管的Activity,這樣就可以在fragment中處理activity的相關事務,其實ListFragment中還有類似的便利方法,getListAdapter()表示傳回設定在ListFragment清單視圖的adapter,setListAdapter()表示為ListFragment管理的内置ListView設定Adapter。
當你想優化這個ListView,有下面這些方面可以優化:
1.為每一個item設定點選事件
這通過覆寫ListFragment的onListItemClick(ListView l, View v, int position, long id)實作
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
//getListAdapter()傳回設定在ListFragment的adapter
Crime c = ((CrimeAdapter)getListAdapter()).getItem(position);
Intent intent = new Intent(getActivity(), CrimeActivity.class);
intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, c.getId());
startActivity(intent);
}
2.定制清單項
首先建立一個你理想中清單項布局,然後建立類繼承ArrayAdapter<T>,覆寫getView(int position, View converView, ViewGroup parent)
private class CrimeAdapter extends ArrayAdapter<Crime>{
SimpleDateFormat fm = new SimpleDateFormat("E,M月d日,yyyy");
ViewHolder viewHolder;
//調用
public CrimeAdapter(ArrayList<Crime> crimes){
super(getActivity(), 0, crimes);
}
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_crime,
null);
viewHolder = new ViewHolder();
viewHolder.titleTextView = (TextView) convertView.
findViewById(R.id.crime_list_item_titleTextView);
viewHolder.dateTextView = (TextView) convertView.
findViewById(R.id.crime_list_item_dateTextView);
viewHolder.solvedCheckBox = (CheckBox) convertView.
findViewById(R.id.crime_list_item_solvedCheckBox);
convertView.setTag(viewHolder);
}
Crime c = getItem(position);
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.titleTextView.setText(c.getTitle());
viewHolder.dateTextView.setText(fm.format(c.getDate()));
viewHolder.solvedCheckBox.setChecked(c.isSolved());
return convertView;
}
private class ViewHolder{
TextView titleTextView;
TextView dateTextView;
CheckBox solvedCheckBox;
}
}
3.雖然我們在代碼中用if語句來判定是否存在了布局,這樣避免了每次都要産生一次新布局,但是listView的控件仍然每一次加載布局時都會重新執行個體化一遍控件。是以,在上述代碼中了,我們建立一個内部類ViewHolder,在ArrayAdapter的子類中建立ViewHolder執行個體,把控件的執行個體都放在viewHolder的執行個體中,然後調用view的setTag()方法把viewHolder對象儲存到View中。當converView不為空時調用View的getTag()把viewHolder取出來。
二:在Activity中顯示ListView
因為Activity沒有内置ListView,是以需要在activity布局中添加ListView控件,并在Activity中獲得ListView執行個體,接下來也是跟Fragment的第三步一樣,建立擴充卡把listView和資料集連接配接起來,隻不過最後Fragment中用的是setListAdapter(ListAdapter),而Activity需要用ListView執行個體去調用setAdapter(ListAdapter)。接下來的優化Fragment和Activity幾乎都差不多,這裡便不再多說。
最後還有一點值得思考
View convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_crime, null);
View converView = LayoutInflater.from(getContext().inflate(R.layout.list_item_ctime,null));
這兩種産生布局的方法有什麼不同?