以编程方式自定义滚动条



我的要求是,只要视图的总高度大于列表允许的高度,就显示一个带有滚动条的垂直视图列表。

此外,我需要以编程方式自定义滚动条的外观(背景和拇指)。(在运行时,我的活动将接收所有用于渲染的数据:用作滚动条背景的位图、滚动条宽度和用作滚动条拇指的位图。)

ListView似乎是一个很好的候选者,只是我找不到通过编程自定义滚动条的方法。我在列表中阅读了这个问题滚动条查看。。。自定义它。但是,它使用了一个主题,而AFAIK不可能通过编程创建一个新的主题。

所以我的问题是:

  1. 有没有办法通过编程方式自定义滚动条(在ListView中)的外观?

  2. [只有在第一个问题的答案是"绝对不可能"的情况下]你认为还有其他方法可以实现这些要求(以及一些实现这些要求的工作示例)

谢谢。

编辑(23/12)

我发现了这个隐藏类android.widget.ScrollBarDrawable。这可能是构建解决方案的一个很好的起点(现在没有时间进行调查)。

有没有一种方法可以通过编程方式自定义滚动条(在ListView中)的外观?

从字面上看,它看起来不像它,只是因为没有用于操作它的setter。

可以想象,您可以创建自己的ViewBenView子类,用处理动态更改的BenScrollBarDrawable替换隐藏的ScrollBarDrawable。但是,您需要创建BenViewGroupBenAbsListViewBenListView,克隆它们的无Ben对应的源代码,使它们链接到BenView以继承此行为。而且,由于ViewGroupAbsListViewListView中的一个在任何Android版本中都会发生更改,因此您实际上需要这些类的N个副本,并在运行时根据API级别选择正确的副本。然后,你的应用程序在制造商对ViewGroupAbsListViewListView进行修补的一些设备上可能仍然表现得很奇怪,你不会使用他们的代码。

我怀疑这是否值得,特别是因为滚动条在默认情况下除了滚动时是不可见的。

你有没有其他方法来实现这些需求(以及一些实现这些需求的工作示例)

处理您自己的触摸事件来进行自己的滚动和滚动条操作。这是否比上述解决方案少,还有待商榷。

我刚刚为RecyclerView遇到了同样的问题,并像这个一样解决了它

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
/**
* Created on 22.3.2016.
*
* @author Bojan Kseneman
* @description A recycler view that will draw the scroll bar with a different color
*/
public class CustomScrollBarRecyclerView extends RecyclerView {
private int scrollBarColor = Color.RED;
public CustomScrollBarRecyclerView(Context context) {
super(context);
}
public CustomScrollBarRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollBarRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setScrollBarColor(@ColorInt int scrollBarColor) {
this.scrollBarColor = scrollBarColor;
}
/**
* Called by Android {@link android.view.View#onDrawScrollBars(Canvas)}
**/
protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b) {
scrollBar.setColorFilter(scrollBarColor, PorterDuff.Mode.SRC_ATOP);
scrollBar.setBounds(l, t, r, b);
scrollBar.draw(canvas);
}
/**
* Called by Android {@link android.view.View#onDrawScrollBars(Canvas)}
**/
protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b) {
scrollBar.setColorFilter(scrollBarColor, PorterDuff.Mode.SRC_ATOP);
scrollBar.setBounds(l, t, r, b);
scrollBar.draw(canvas);
}
}

这些方法是在View类中定义的,因此相同的原理应该适用于其他视图,如ScrollView和ListView。

只需更改android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb"并根据您的需要打造一款可抽型。

<ListView android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb" /> 

在绘图中:

<shape xmlns:android="http://schemas.android.com/apk/res/android" > 
<gradient android:angle="0" android:endColor="#6699FF" android:startColor="#3333FF" />
<corners android:radius="1dp" /> 
<size android:width="1dp" /> 
</shape>

我想这就是你想要的!

如果您只需要支持API 24或更高版本,则可以使用自定义drawable来完成此任务。你需要决定如何让drawable与活动进行沟通。这里有一个可能的解决方案。

res/drawable/my_custom_scrollbar_thumb.xml

<com.example.RegisteredMutableDrawable安卓:id="@+id/scroll_thumb"/>

res/drawable/my_custom_scrollbar_track.xml

<com.example.RegisteredMutableDrawable安卓:id="@+id/scroll_track"/>

布局文件中的某个位置

<列表视图android:sollbarTrackVertical="@drawable/my_custom_scrollbar_track"android:sollbarThumbVertical="@drawable/my_custom_scrollbar_thumb">

可绘制的实现

public class RegisteredMutableDrawable extends DrawableWrapper
{
public static interface Registrar
{
public void register(int _id, RegisteredMutableDrawable _drawable);
}
public static Registrar registrar;
private static int[] ATTRS = new int[] { android.R.attr.id };
public RegisteredMutableDrawable()
{
super(null);
}
public void inflate(Resources _res, XmlPullParser _parser, AttributeSet _as, Theme _theme)
throws XmlPullParserException, IOException
{
super.inflate(_res, _parser, _as, _theme);
final Registrar r = registrar;
if (r != null)
{
final TypedArray ta = _res.obtainAttributes(_as, ATTRS);
final int id = ta.getResourceId(0, 0);
ta.recycle();
r.register(id, this);
}
}
}

在您的活动

public class MyActivity extends Activity implements RegisteredMutableDrawable.Registrar
{
@Override public void onCreate(Bundle _icicle)
{
super.onCreate(_icicle);
RegisteredMutableDrawable.registrar = this;
setContentView(R.layout.whatever);
RegisteredMutableDrawable.registrar = null; // don't leak our activity!
}
@Override public void register(int _id, RegisteredMutableDrawable _drawable)
{
switch(_id)
{
case R.id.scroll_thumb:
_drawable.setDrawable(myThumbDrawable);
break;
case R.id.scroll_track:
_drawable.setDrawable(myTrackDrawable);
break;
}
}
}

您可以使用jquery插件(jquery.nicescroll.js)来实现这一点。更多详细信息,请访问http://areaaperta.com/nicescroll/