Ultra-Pull-To-Refresh動態添加View不能正常顯示BUG解決方法

    上文講到Ultra-Pull-To-Refresh框架的簡單示例,在動態添加PtrFrameLayout或者PtrClassicFrameLayout時踩到坑了,無法顯示添加的子View。代碼如下:

  1. PtrFrameLayout ptrLayout = new PtrFrameLayout(this);
  2. ptrLayout.setLayoutParams(new PtrFrameLayout.LayoutParams (PtrFrameLayout.LayoutParams.MATCH_PARENT,PtrFrameLayout.LayoutParams.MATCH_PARENT));
  3. WebVeiw mWeb = new WebView(this);
  4. mWeb.setLayoutParams(new ViewGroup.LayoutParams (ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
  5. ptrLayout.addView(mWeb);

    結果就是提示如下信息

  1. The content view in PtrFrameLayout is empty. Do you forget to specify its id in xml layout file?
    通過查看源碼,PtrFrameLayout這個ViewGroup動態添加子View時,還未加進來就調用了onFinishInflate方法,此時獲取的子View對象當然爲空;所以通過手動調用onFinishInflate()方法來再次獲取子View。

    對PtrFrameLayout源碼加入以下一段代碼:

  1. public void addViewForPtrFrameLayout(View child) {
  2.        super.addView(child);
  3.        if (this.getContentView() == null) {//獲取不到子View時再調用一次onFinishInfalte()
  4.            this.onFinishInflate();
  5.        }
  6. }

然後將原來的ptrLayout.addView(mWeb)改用addViewForPtrFrameLayout(mWeb),來動態添加WebView,這樣修改並未讓WebView正常顯示出來,別急還差一步。看下onFinishInflate()源碼

  1. protected void onFinishInflate() {
  2.        final int childCount = getChildCount();
  3.        if (childCount > 2) {
  4.            throw new IllegalStateException("PtrFrameLayout only can host 2 elements");
  5.        } else if (childCount == 2) {
  6.            if (mHeaderId != 0 && mHeaderView == null) {
  7.                mHeaderView = findViewById(mHeaderId);
  8.            }
  9.            if (mContainerId != 0 && mContent == null) {
  10.                mContent = findViewById(mContainerId);
  11.            }
  12.            // not specify header or content
  13.            if (mContent == null || mHeaderView == null) {
  14.                View child1 = getChildAt(0);
  15.                View child2 = getChildAt(1);
  16.                if (child1 instanceof WDPtrUIHandler) {
  17.                    mHeaderView = child1;
  18.                    mContent = child2;
  19.                } else if (child2 instanceof WDPtrUIHandler) {
  20.                    mHeaderView = child2;
  21.                    mContent = child1;
  22.                } else {
  23.                    // both are not specified
  24.                    if (mContent == null && mHeaderView == null) {
  25.                        mHeaderView = child1;
  26.                        mContent = child2;
  27.                    }
  28.                    // only one is specified
  29.                    else {
  30.                        if (mHeaderView == null) {
  31.                            mHeaderView = mContent == child1 ? child2 : child1;
  32.                        } else {
  33.                            mContent = mHeaderView == child1 ? child2 : child1;
  34.                        }
  35.                    }
  36.                }
  37.            }
  38.        } else if (childCount == 1) {
  39.            mContent = getChildAt(0);
  40.        } else {
  41.            mIsFinishInflate = true;
  42.            TextView errorView = new TextView(getContext());
  43.            errorView.setClickable(true);
  44.            errorView.setTextColor(0xffff6600);
  45.            errorView.setGravity(Gravity.CENTER);
  46.            errorView.setTextSize(20);
  47.            errorView.setText("The content view in PtrFrameLayout is empty. Do you forget to specify its id in xml layout file?");
  48.            mContent = errorView;
  49.            addView(mContent);
  50.        }
  51.        if (mHeaderView != null) {
  52.            mHeaderView.bringToFront();
  53.        }
  54.        super.onFinishInflate();
  55.    }

    第一次加載失敗時,添加了一個errorView的TextView;再次調用onFinishInflate()方法時,此時ViewGroup存在三個子View:TextView、Header、WebView。childCount() > 3,然後就拋異常了。將45-53行部分代碼刪除或者改爲其他非添加子View的處理就OK了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章