Tencent/QMUI_Android · error · IllegalStateException

topView must implement from IQMUIContinuousNestedTopView

Error message

topView must implement from IQMUIContinuousNestedTopView

What it means

QMUIContinuousNestedScrollLayout.setTopAreaView() requires the view passed as the top area to implement the IQMUIContinuousNestedTopView interface, which provides scroll coordination callbacks (injectScrollNotifier, etc.). If the view does not implement it, the layout cannot drive its nested scrolling, so it throws an IllegalStateException immediately instead of failing later at runtime.

Source

Thrown at qmui/src/main/java/com/qmuiteam/qmui/nestedScroll/QMUIContinuousNestedScrollLayout.java:189

            mOnScrollListeners.add(onScrollListener);
        }
    }

    public void removeOnScrollListener(OnScrollListener onScrollListener) {
        mOnScrollListeners.remove(onScrollListener);
    }

    public void setKeepBottomAreaStableWhenCheckLayout(boolean keepBottomAreaStableWhenCheckLayout) {
        mKeepBottomAreaStableWhenCheckLayout = keepBottomAreaStableWhenCheckLayout;
    }

    public boolean isKeepBottomAreaStableWhenCheckLayout() {
        return mKeepBottomAreaStableWhenCheckLayout;
    }

    public void setTopAreaView(View topView, @Nullable LayoutParams layoutParams) {
        if (!(topView instanceof IQMUIContinuousNestedTopView)) {
            throw new IllegalStateException("topView must implement from IQMUIContinuousNestedTopView");
        }
        if (mTopView != null) {
            removeView(((View) mTopView));
        }
        mTopView = (IQMUIContinuousNestedTopView) topView;
        mTopView.injectScrollNotifier(new IQMUIContinuousNestedScrollCommon.OnScrollNotifier() {
            @Override
            public void notify(int innerOffset, int innerRange) {
                int offsetCurrent = mTopAreaBehavior == null ? 0 : -mTopAreaBehavior.getTopAndBottomOffset();
                int bottomCurrent = mBottomView == null ? 0 : mBottomView.getCurrentScroll();
                int bottomRange = mBottomView == null ? 0 : mBottomView.getScrollOffsetRange();
                dispatchScroll(innerOffset, innerRange, offsetCurrent, getOffsetRange(), bottomCurrent, bottomRange);
            }

            @Override
            public void onScrollStateChange(View view, int newScrollState) {
                // not need this. top view scroll is driven by top behavior
            }

View on GitHub (pinned to 026e7d4866)

Solutions

  1. Make the view's class implement IQMUIContinuousNestedTopView (implement getScrollHeight, getCurrentScroll, scrollBy, consumeScroll, injectScrollNotifier etc.).
  2. Alternatively use QMUI's built-in implementations such as QMUIContinuousNestedTopScrollLayout, QMUIContinuousNestedTopRecyclerView or QMUIContinuousNestedTopWebView as the top view.
  3. If a custom view cannot implement the interface, wrap it inside a class that implements IQMUIContinuousNestedTopView and delegates scrolling to it.
  4. Check you are not passing the wrong view (e.g. bottom view) to setTopAreaView.

Example fix

// before
layout.setTopAreaView(new LinearLayout(context), null);

// after
class MyTopView extends LinearLayout implements IQMUIContinuousNestedTopView {
    // implement injectScrollNotifier, consumeScroll, getScrollHeight, getCurrentScroll ...
}
layout.setTopAreaView(new MyTopView(context), null);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(topView instanceof IQMUIContinuousNestedTopView)) {
    throw new IllegalArgumentException("topView must implement IQMUIContinuousNestedTopView");
}
layout.setTopAreaView(topView, null);

Type guard

boolean isTopAreaViewValid(View v) {
    return v instanceof IQMUIContinuousNestedTopView;
}

Try / catch

try {
    layout.setTopAreaView(topView, layoutParams);
} catch (IllegalStateException e) {
    Log.e(TAG, "topView invalid, falling back to default", e);
    layout.setTopAreaView(new QMUIContinuousNestedTopScrollLayout(context), layoutParams);
}

Prevention

When it happens

Trigger: Calling setTopAreaView(view, layoutParams) with a plain View, ViewGroup, RecyclerView without implementing IQMUIContinuousNestedTopView, or a custom view that forgot the interface.

Common situations: Developers replacing the default QMUIContinuousNestedTopScrollLayout/WebView with a custom header view, or copying sample code that passes a raw layout, hit this on first layout inflation.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of Tencent/QMUI_Android@026e7d4866 (2026-09-06). Data as JSON: /api/errors/2aeeafb6837743aa. Report an issue: GitHub.