Android:在自定义视图中启用滚动条

时间:2011-09-05 20:09:36

标签: java android scrollbar

我实现了一个扩展RelativeLayout的自定义布局。它显示了许多在运行时创建的不同元素,并且可以使用scrollTo()和scrollBy()在两个维度中滚动。滚动有效,现在我想添加标准的Android滚动条。

使用Scrollviews是不可能的,因为我需要在两个维度上滚动布局,所以我尝试按照此处的描述进行操作:Android: Enable Scrollbars on Canvas-Based View

我已经使用一些(虚假)值实现了所有的compute *方法并启用了滚动条。但我仍然无法让他们出现。任何想法可能是什么问题?

在各种邮件列表和SO上有很多这样的问题,但到处答案似乎是“1。调用setHorizo​​ntalScrollbarEnabled(true),2。实现所有的计算*方法,3。调用awakenScrollbars()” 。据我所知,我已经完成了所有这些,甚至尝试使用initializeScrollbars()但没有任何反应,文档也没有提供任何帮助。

public NodeLayout(Context context) {
    super(context);

    setVerticalScrollBarEnabled(true);
    setHorizontalScrollBarEnabled(true);

    TypedArray a = context.obtainStyledAttributes(R.styleable.View);
    initializeScrollbars(a);
    a.recycle();
}

@Override
protected int computeHorizontalScrollExtent() {
    return 5;
}

@Override
protected int computeHorizontalScrollOffset() {
    return 10;
}

@Override
protected int computeHorizontalScrollRange() {
    return 50;
}

@Override
protected int computeVerticalScrollExtent() {
    return getHeight() / 2;
}

@Override
protected int computeVerticalScrollOffset() {
    return getHeight() / 2;
}

@Override
protected int computeVerticalScrollRange() {
    return getHeight();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    awakenScrollBars();
    invalidate();
    return true;
}

这就是我的attrs.xml文件的样子:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="View">
<attr name="android:background"/>
<attr name="android:clickable"/>
<attr name="android:contentDescription"/>
<attr name="android:drawingCacheQuality"/>
<attr name="android:duplicateParentState"/>
<attr name="android:fadeScrollbars"/>
<attr name="android:fadingEdge"/>
<attr name="android:fadingEdgeLength"/>
<attr name="android:fitsSystemWindows"/>
<attr name="android:focusable"/>
<attr name="android:focusableInTouchMode"/>
<attr name="android:hapticFeedbackEnabled"/>
<attr name="android:id"/>
<attr name="android:isScrollContainer"/>
<attr name="android:keepScreenOn"/>
<attr name="android:longClickable"/>
<attr name="android:minHeight"/>
<attr name="android:minWidth"/>
<attr name="android:nextFocusDown"/>
<attr name="android:nextFocusLeft"/>
<attr name="android:nextFocusRight"/>
<attr name="android:nextFocusUp"/>
<attr name="android:onClick"/>
<attr name="android:padding"/>
<attr name="android:paddingBottom"/>
<attr name="android:paddingLeft"/>
<attr name="android:paddingRight"/>
<attr name="android:paddingTop"/>
<attr name="android:saveEnabled"/>
<attr name="android:scrollX"/>
<attr name="android:scrollY"/>
<attr name="android:scrollbarAlwaysDrawHorizontalTrack"/>
<attr name="android:scrollbarAlwaysDrawVerticalTrack"/>
<attr name="android:scrollbarDefaultDelayBeforeFade"/>
<attr name="android:scrollbarFadeDuration"/>
<attr name="android:scrollbarSize"/>
<attr name="android:scrollbarStyle"/>
<attr name="android:scrollbarThumbHorizontal"/>
<attr name="android:scrollbarThumbVertical"/>
<attr name="android:scrollbarTrackHorizontal"/>
<attr name="android:scrollbarTrackVertical"/>
<attr name="android:scrollbars"/>
<attr name="android:soundEffectsEnabled"/>
<attr name="android:tag"/>
<attr name="android:visibility"/>
</declare-styleable>
</resources>

我正在为Android 3.0开发。

2 个答案:

答案 0 :(得分:9)

刚刚遇到同样的问题并最终弄明白了。

“问题”是您正在扩展RelativeLayout,这是ViewGroup的子类。我发现你在你的问题中做了什么来获得自定义View来显示滚动条没有问题,但当我扩展ViewGroup或其子类之一时,没有出现滚动条。

我终于记得ViewGroup默认情况下不会画自己。我在自定义ViewGroup构造函数中添加了一行: setWillNotDraw(false);

你知道什么,滚动条出现了!

希望有所帮助。

答案 1 :(得分:2)

Fyi,在Android 3.2 / Google TV和Android 3.2.1 / Tablet上,&lt; declare-styleable /&gt;扩展ViewGroup时,解决方案的一部分不是可选的。问题似乎是除非&lt; declare-styleable /&gt;中的所有相应滚动条属性都被加载,否则View中用于绘制滚动条的滚动条可绘制和大小都不会被加载。已设定。在3.2上的布局期间,未能设置一些有效数量的属性会导致空指针异常。我还怀疑GridView / ListView / AbsListView / AdapterView系列类没有设置水平滚动条属性,如果这就是你正在追逐的东西。

一般步骤似乎是:

  • 使用&lt; declare-styleable /&gt; (如上所述)。
  • 在构造函数的早期调用initScrollbars(如上所述)。
  • 调用initScrollbars后调用setHorizo​​ntalScrollbarEnabled / setrVerticalScrollBarEnbled。
  • 根据需要实现三个computeHorizo​​ntalScrollXXX和computeVerticalScrollXXX的集合。
  • 根据需要频繁调用awakenScrollBars()以显示滚动条。
  • 最有可能的是,必须在构造函数中调用setWillNotDraw(false)。滚动条绘图在View中实现;但实际上我自己也称这种方法。
  • 考虑调用setScrollBarStyle来控制滚动条的位置。最有用的自定义视图滚动将最终剪切到填充边距,如果它们被放置在填充矩形之外,这将搞砸View的滚动条绘图,因为我们无法访问View中的相同隐藏方法观点。

我认为就是这样。在Android 6.0上工作的所有机会......很小甚至没有。 : - /