如何判断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
相关产品推荐
相关产品推荐

