You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断ScrollView是否可滚动?解决短文本按钮禁用问题

问题:短文本场景下ScrollView滚动监听未触发,按钮始终禁用

我有一段动态变化的文本,要求用户滚动到文本底部(阅读完全部内容)后才启用布局中的按钮。当前实现可满足长文本场景需求,但当文本长度不足以使ScrollView可滚动时,onScrollChange方法不会触发,按钮始终处于禁用状态。尝试用scrollView.isEnabled()和scrollView.isFocusable()判断均无效,这两个方法无论ScrollView是否可滚动都会返回true。

现有实现代码

scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
    @Override
    public void onScrollChange(View view, int i, int i1, int i2, int i3) {
        if (isTextViewScrolledToBottom(scrollView, mTextViewNotPDF)) {
            mAgreeButton.setEnabled(true);
            mAgreeButton.setBackground(getResources().getDrawable(R.drawable.button_bg_black_rounded));
        } else {
            mAgreeButton.setEnabled(false);
            mAgreeButton.setBackground(getResources().getDrawable(R.drawable.button_bg_grey_rounded));
        }
    }
});

private boolean isTextViewScrolledToBottom(ScrollView scrollView, TextView mTextViewNotPDF) {
    int scrollViewHeight = scrollView.getHeight();
    int textViewHeight = mTextViewNotPDF.getHeight();
    int scrollY = scrollView.getScrollY();
    return (textViewHeight) <= (scrollY + scrollViewHeight);
}

解决方案

核心思路是不依赖滚动监听的触发时机,主动检查文本与ScrollView的高度关系,同时将按钮状态更新逻辑抽离复用,覆盖短文本和长文本两种场景。

步骤1:抽离按钮状态更新逻辑

把按钮启用/禁用的逻辑单独封装成方法,方便在多个地方调用:

private void updateAgreeButtonState() {
    if (isTextViewScrolledToBottom(scrollView, mTextViewNotPDF)) {
        mAgreeButton.setEnabled(true);
        mAgreeButton.setBackground(getResources().getDrawable(R.drawable.button_bg_black_rounded));
    } else {
        mAgreeButton.setEnabled(false);
        mAgreeButton.setBackground(getResources().getDrawable(R.drawable.button_bg_grey_rounded));
    }
}

步骤2:优化底部判断方法

在判断是否滚动到底部的方法中,先检测文本是否需要滚动:如果文本高度≤ScrollView高度,直接视为已“阅读完成”,返回true:

private boolean isTextViewScrolledToBottom(ScrollView scrollView, TextView textView) {
    int scrollViewHeight = scrollView.getHeight();
    int textViewHeight = textView.getHeight();
    
    // 短文本无需滚动,直接判定为已到底部
    if (textViewHeight <= scrollViewHeight) {
        return true;
    }
    
    int scrollY = scrollView.getScrollY();
    return textViewHeight <= (scrollY + scrollViewHeight);
}

步骤3:主动触发状态检查

在文本设置完成后(尤其是动态加载文本的场景),主动调用状态更新方法,避免依赖滚动监听:

// 设置动态文本后调用
mTextViewNotPDF.setText(yourDynamicText);

// 由于View布局可能尚未完成,需监听布局完成后再检查
mTextViewNotPDF.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // 移除监听避免重复触发
        mTextViewNotPDF.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        updateAgreeButtonState();
    }
});

步骤4:更新滚动监听逻辑

滚动监听中直接调用抽离的状态更新方法即可:

scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
    @Override
    public void onScrollChange(View view, int i, int i1, int i2, int i3) {
        updateAgreeButtonState();
    }
});

这样修改后,无论文本长短,按钮都会处于正确的启用/禁用状态:短文本直接启用,长文本需滚动到底部才启用。

内容的提问来源于stack exchange,提问作者Dilum Jayasinghe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:53:19