天天看點

ListView在Activity和Fragment中的顯示和使用

一:在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));
           

這兩種産生布局的方法有什麼不同?