天天看點

Android Widget源碼分析系列文章之AbsListViewAbsListView的源碼剖析

Android Widget源碼分析系列文章之AbsListView

  • AbsListView的源碼剖析
    • 繼承的類
    • 實作的接口
    • 相關的成員變量
    • 内部定義的接口
      • OnScrollListener
      • SelectionBoundsAdjuster
    • 構造函數
    • 成員函數
      • initAbsListView
      • setOverScrollMode
      • performItemClick
      • contentFits
      • setFastScrollAlwaysVisible
      • pointToPosition

AbsListView的源碼剖析

這是一個基本的類,可以被用來實作虛拟化的清單。一個清單沒有一個空間的定義在這裡。例如,這個類的子類展示了清單的内容以九宮格、旋轉木馬或者是堆棧。

繼承的類

AdapterView

實作的接口

  1. TextWatcher ,監聽字元的變化
  2. ViewTreeObserver.OnGlobalLayoutListener,OnGlobalLayoutListener 是ViewTreeObserver的内部類,當一個視圖樹的布局發生改變時,可以被ViewTreeObserver監聽到,這是一個注冊監聽視圖樹的觀察者(observer),在視圖樹的全局事件改變時得到通知。ViewTreeObserver不能直接執行個體化,而是通過getViewTreeObserver()獲得。
  3. Filter.FilterListener,用一個過濾的模式,限制輸入的字元的内容,内部的函數是通知過濾操作的結束。
  4. ViewTreeObserver.OnTouchModeChangeListener,注冊一個觀察者來監聽視圖樹,當視圖樹的布局、視圖樹的焦點、視圖樹将要繪制、視圖樹滾動等發生改變時,ViewTreeObserver都會收到通知,ViewTreeObserver不能被執行個體化,可以調用View.getViewTreeObserver()來獲得。
  5. RemoteViewAdapter.RemoteAdapterConnectionCallback,一個接口針對RemoteAdapter 去通知其他的類當這個Adapters被真正的連接配接到他們真實的服務,或者是真實的解除連接配接。

相關的成員變量

逐一的對這個類中的定義的成員變量進行定義,基本意思以及功能作用。

  1. TRANSCRIPT_MODE_DISABLED, 這是一個public類型修飾的常量。表面的意思是禁止文字記錄的模式,實際上的意思是不允許自動滾動到使用者指定的位置。
  2. TRANSCRIPT_MODE_NORMAL,這是public類型修飾的常量。這個清單将會自動滾動到底部,當一個資料集合改變的通知被收到,并且隻有這個最後一個條目在螢幕上是真實可見的時候。
  3. TRANSCRIPT_MODE_ALWAYS_SCROLL,這是public類型修飾的常量。這個清單将會自動滾動到底部,不論目前螢幕上可見的條目是什麼。
  4. TOUCH_MODE_REST,預測我們并不是處于手指觸摸的中間。
  5. TOUCH_MODE_DONE_WAITING,預測我們已經等待每一件我們能夠等待的事情。但是這個使用者的手指始終是出于按下的狀态。
  6. TOUCH_MODE_SCROLL,預測使用者的手指是處于滾動的狀态。
  7. TOUCH_MODE_FLING,預測目前的視圖是處于被翻動的狀态。
  8. TOUCH_MODE_OVERSCROLL,預測這個手勢是過度的滾動,是一種滾動超過了開始或者是結束。
  9. TOUCH_MODE_OVERFLING,達到了邊緣,并且繪制回彈的效果。
  10. LAYOUT_NORMAL,普通的布局,經常一個來自于視圖系統的沒有請求的布局。
  11. LAYOUT_FORCE_TOP,顯示第一個條目。
  12. LAYOUT_SET_SELECTION ,強制選中的條目到螢幕指定的位置。
  13. LAYOUT_FORCE_BOTTOM,顯示最後一個條目。
  14. LAYOUT_SPECIFIC,建立一個選中的條目,呈現在一個指定的位置,并且建構這個視圖的剩餘的部分從這裡開始。這個頂部是被特殊的指定。
  15. LAYOUT_SYNC,布局與資料的改變同步發生了變化,恢複同步的位置,去讓他的頂部在他指定的位置。
  16. LAYOUT_MOVE_SELECTION,布局作為使用航海的鑰匙的結果。
  17. CHOICE_MODE_NONE,普通的清單,沒有預測的選擇。
  18. CHOICE_MODE_SINGLE,清單支援一個選擇。
  19. CHOICE_MODE_MULTIPLE,清單支援多個選擇。
  20. CHOICE_MODE_MULTIPLE_MODAL,這個清單支援多個選擇在一個模态的選擇模式。
  21. mOwnerThread,對應的是視圖被建立的線程。
  22. mChoiceMode,控制是否/怎樣這個使用者也許選擇/檢測在清單中的條目。
  23. mCheckedItemCount,目前有多少清單的條目被選中。
  24. mDrawSelectorOnTop,預測是否這個清單的選擇器應該繪制在子節點頂部還是底部。
  25. mSelector,圖檔用來繪制選擇器。
  26. mSelectorPosition,目前被選中的條目在清單中的位置。
  27. mRecycler,這個資料集合用來存儲沒有被使用的視圖,這些視圖在接下來的布局中可能被用到,避免建立新的視圖的對象。
  28. mVelocityTracker,決定了滾動的速度。
  29. mScrollingCacheEnabled,當設定位true, 這個清單将會自動丢棄子視圖的緩存,當滾動的時候。
  30. mSmoothScrollbarEnabled,判斷是基于像素的滾動,還是基于條目的滾動。
  31. mFastScroll,幫助類的對象繪制和控制快速滾動的滑塊。

内部定義的接口

OnScrollListener

  1. SCROLL_STATE_IDLE,視圖目前處于靜止的狀态。
  2. SCROLL_STATE_TOUCH_SCROLL,使用者通過觸摸滾動視圖,并且使用者目前的手指還是處于螢幕上。
  3. SCROLL_STATE_FLING,使用者之前已經通過觸摸,操作了一次滑動,目前處于滑動狀态,即将停止。
  4. onScrollStateChanged,回調方法将會被觸發,當清單視圖或者是九宮格的視圖被滾動。這個方法将會被調用當滾動的視圖的下一個資料幀将會被繪制。
  5. onScroll,當滾動行為結束後被調用。

SelectionBoundsAdjuster

  1. adjustListItemSelectionBounds,允許清單的條目去調整他被選中的矩形的邊界。

構造函數

  1. initAbsListView, 初始化清單的相關的元件。
  2. mOwnerThread = Thread.currentThread(),建立目前UI操作所在的線程。
  3. setVerticalScrollBarEnabled(true),設定允許顯示垂直的滾動條。
  4. initializeScrollbarsInternal,初始化垂直的滾動條的内部的業務邏輯。

成員函數

initAbsListView

  1. 代碼片段
// Setting focusable in touch mode will set the focusable property to true
        setClickable(true);
        setFocusableInTouchMode(true);
        setWillNotDraw(false);
        setAlwaysDrawnWithCacheEnabled(false);
        setScrollingCacheEnabled(true);

        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
        mTouchSlop = configuration.getScaledTouchSlop();
        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
        mOverscrollDistance = configuration.getScaledOverscrollDistance();
        mOverflingDistance = configuration.getScaledOverflingDistance();

        mDensityScale = getContext().getResources().getDisplayMetrics().density;
           
  1. setClickable(true),設定目前的UI是可以被點選的
  2. setFocusableInTouchMode(true),設定目前的UI在觸摸的模式下是可以擷取焦點的。
  3. setWillNotDraw,如果這個View控件在他自己的内部沒有做任何的繪制,設定這個标志位允許以後的優化。
  4. setAlwaysDrawnWithCacheEnabled,預測是否這個ViewGroup是否将會總是嘗試繪制它的子節點使用它們自己的緩存。這個屬性可以被設定位true,當這個緩存的渲染略微不同于子節點的正常的渲染。渲染是可以不同的,比如,當這個緩存的品質被設定為低。當設定屬性是被禁用,這個ViewGroup将會使用它的子節點的繪制的緩存,僅僅當被詢問的時候。這個是它的子類的任務去告訴ViewGroup什麼時候開始使用這個繪制的緩存,以及什麼時候停止使用。
  5. 剩下的幾個屬性的初始化,包括觸摸的門檻值、最小以及最大的速度、滑動的最大的區間以及分辨率的初始化。

setOverScrollMode

在這個函數中,判斷是否允許使用者滑動超過邊界,這也就決定了mEdgeGlowTop以及mEdgeGlowBottom是否進行初始化。

performItemClick

contentFits

傳回true,如果清單的内容目前完全是在視圖的邊界内。

setFastScrollAlwaysVisible

設定是否這個快速的緩動應該被展示,而不是标準的滑動塊。這将決定了是否允許使用快速滑動。

if (isOwnerThread()) {
                setFastScrollerAlwaysVisibleUiThread(alwaysShow);
            } else {
                post(new Runnable() {
                    @Override
                    public void run() {
                        setFastScrollerAlwaysVisibleUiThread(alwaysShow);
                    }
                });
            }
           

邏輯上的線程切換,值得代碼的借鑒。

pointToPosition

将一個坐标點轉換位一個清單的條目的索引。

public int pointToPosition(int x, int y) {
        Rect frame = mTouchFrame;
        if (frame == null) {
            mTouchFrame = new Rect();
            frame = mTouchFrame;
        }

        final int count = getChildCount();
        for (int i = count - 1; i >= 0; i--) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.VISIBLE) {
                child.getHitRect(frame);
                if (frame.contains(x, y)) {
                    return mFirstPosition + i;
                }
            }
        }
        return INVALID_POSITION;
    }
           

繼續閱讀