編輯:關於Android編程
setEmptyView這個方法傳入的是一個view,
TextView emptytext=new TextView(this); emptytext.setText("the list is empty"); listview.setEmptyView(emptytext);上面的代碼有什麼問題呢?當listview為空時,emptytext能正常顯示嗎?
@android.view.RemotableViewMethod public void setEmptyView(View emptyView) { mEmptyView = emptyView; // If not explicitly specified this view is important for accessibility. if (emptyView != null && emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { emptyView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } final T adapter = getAdapter(); final boolean empty = ((adapter == null) || adapter.isEmpty()); updateEmptyStatus(empty); }
private void updateEmptyStatus(boolean empty) { if (isInFilterMode()) { empty = false; } if (empty) { if (mEmptyView != null) { mEmptyView.setVisibility(View.VISIBLE); setVisibility(View.GONE); } else { // If the caller just removed our empty view, make sure the list view is visible setVisibility(View.VISIBLE); } // We are now GONE, so pending layouts will not be dispatched. // Force one here to make sure that the state of the list matches // the state of the adapter. if (mDataChanged) { this.onLayout(false, mLeft, mTop, mRight, mBottom); } } else { if (mEmptyView != null) mEmptyView.setVisibility(View.GONE); setVisibility(View.VISIBLE); } }
對footer和header的操作相同,這裡以header為例。其實是完全相同的,最終都被封裝為FixedViewInfo,只是顯示的位置不同
ListView可以添加多個header
TextView header = new TextView(this); header.setText("this is header 1"); listview.addHeaderView(header); header = new TextView(this); header.setText("this is header 2"); listview.addHeaderView(header);header和footer連同adapter被包裝在了HeaderViewListAdapter中,
ArrayListHeaderViewListAdapter並沒有提供獲取FixedViewInfo的方法,因此無法獲取FixedViewInfo的實例。mHeaderViewInfos; ArrayList mFooterViewInfos;
BaseAdapter中默認是一種類型布局,支持多種類型布局需要在自定義的Adapter中重寫這兩個方法
public int getViewTypeCount() { return 1; } public int getItemViewType(int position) { return 0; }
否則就會數組越界。
這是因為在復用多種布局時,TypeCount是布局類型最大個數,而ItemViewType是一個下標,
這個下標的最大值就是TypeCount-1。
/** * Unsorted views that can be used by the adapter as a convert view. */ private ArrayList[] mScrapViews; public void setViewTypeCount(int viewTypeCount) { if (viewTypeCount < 1) { throw new IllegalArgumentException("Can't have a viewTypeCount < 1"); } //noinspection unchecked ArrayList [] scrapViews = new ArrayList[viewTypeCount]; for (int i = 0; i < viewTypeCount; i++) { scrapViews[i] = new ArrayList (); } mViewTypeCount = viewTypeCount; mCurrentScrap = scrapViews[0]; mScrapViews = scrapViews; }
View getScrapView(int position) { final int whichScrap = mAdapter.getItemViewType(position); if (whichScrap < 0) { return null; } if (mViewTypeCount == 1) { return retrieveFromScrap(mCurrentScrap, position); } else if (whichScrap < mScrapViews.length) { return retrieveFromScrap(mScrapViews[whichScrap], position); } return null; }
public void onItemClick(AdapterViewparent, View view, int position, long id)
這個方法的postiton並不是真實的item數據位置,當沒有header時,positon與item位置對應
當有header時,positon=headercount+item位置,也就是說
item位置=positon-headercount
listview.getHeaderViewsCount()可以獲取headercount
還有一種方法是通過包裝過的adapter直接獲取
parent.getAdapter().getItem(position);
當滑動ListView的時候,圖片自動變來變去,圖片顯示的位置也不正確。
所有的主流圖片加載庫都解決了這個問題。這個問題的原因是listview的item復用。
解決這個問題的思路都是建立當前imageview與加載的url的對應關系,使當前看到的item始終加載的是當前對應數據。
Picasso通過建立ImageView與ImageViewAction的的對應關系來加載正確圖片
void enqueueAndSubmit(Action action) { Object target = action.getTarget(); if (target != null && targetToAction.get(target) != action) { // This will also check we are on the main thread. cancelExistingRequest(target); targetToAction.put(target, action); } submit(action); }
public static final class ViewHolder { public ImageView img; public TextView name; public ViewHolder(View convertView) { img = (ImageView) convertView.findViewById(R.id.img); name = (TextView) convertView.findViewById(R.id.name); } }
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = LayoutInflater.from(ListViewActivity.this).inflate(R.layout.item_list, parent, false); viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.name.setText(data.get(position)); return convertView; }
單獨再做分析吧
ListView與Adapter都實現了接口ListAdapter,同時ListView又包裹了Adapter,從而實現適配,是典型的對象適配。
HeaderViewListAdapter是典型的裝飾模式
對Adapter進行裝飾,為Adapter擴展了footer和header
在設置Adapter時會構建一個AdapterDataSetObserver,這就是創建觀察者
adapter中包含一個數據集可觀察者DataSetObservable,這就是可觀察者
adapter的notifyDataSetChanged就是可觀察者通知觀察者數據發生了變化。
原因是tem子控件獲取了焦點,在Item布局的根布局加上android:descendantFocusability=“blocksDescendants”
的屬性就可以了。
descendantFocusability值含義:
beforeDescendants:viewgroup會優先其子類控件而獲取到焦點
afterDescendants:viewgroup只有當其子類控件不需要獲取焦點時才獲取焦點
blocksDescendants:viewgroup會覆蓋子類控件而直接獲得焦點
原因是,滾動時,列表裡面的view重繪時,用的依舊是系統默認的透明色,顏色值為#FF191919,
要改變這種情況,只需要調用listView的setCacheColorHint(0),顏色值設置為0
或者xml文件中listView的屬性 Android:cacheColorHint="#00000000"即可。
在item的layout文件中,用android:layout_height設置item的高度。運行,高度設置無效。
解決辦法:給item設定minHeight,即可。
android:divider="@drawable/dash_line"dash_line為drawable
之前一章記錄了跨應用啟動service,之前學習過startService於bindService的區別及用法。使用bindService方法,activity需要ser
Service 是一個可以在後台執行長時間運行操作而不使用用戶界面的應用組件。服務可由其他應用組件啟動,而且即使用戶切換到其他應用,服務仍將在後台繼續運行。 此外,組件可
我們知道apk生成後所有的java生成的class文件都被dx命令整合成了一個classes.dex文件,當apk運行時dalvik虛擬機加載classes.
http://git.oschina.net/scimence/sci_2048/wikis/home package com.example.sci_2048