以编程方式自定义ScrollBar

时间:2012-12-14 14:10:34

标签: android scrollbar

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

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

ListView似乎是一个很好的选择,除了我找不到以编程方式自定义scrollBar的方法。 我读了这个问题scrollBar in a listView...customizing it.但是,它正在使用一个主题,而AFAIK则不可能以编程方式创建一个新主题。

所以我的问题:

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

  2. [只有当第一个答案是“明确无法”时]你是否看到任何其他方式来实现这些要求(以及一些实施例子)

  3. 感谢。

    编辑(23/12)

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

5 个答案:

答案 0 :(得分:6)

  

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

从字面上看,它看起来并不像,只是因为没有设置器来操纵它。

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

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

  

您是否看到任何其他方式来实现这些要求(以及一些实施例子)

处理您自己的触摸事件以进行自己的滚动并执行自己的滚动条。这是否比上述解决方案更少的工作还有争议。

答案 1 :(得分:2)

我刚刚遇到了与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类中定义的,因此相同的printcible应该适用于ScrollView和ListView等其他视图。

答案 2 :(得分:0)

只需更改android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb" 并根据您的需要创建一个drawable。

<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>

我认为这就是你想要的!

答案 3 :(得分:0)

如果仅需要支持API 24或更高版本,则可以使用自定义可绘制对象来完成此任务。您需要确定如何允许可绘制对象与活动进行通信。这是一种可能的解决方案。

res / drawable / my_custom_scrollbar_thumb.xml

  

res / drawable / my_custom_scrollbar_track.xml

  

布局文件中的某处

  

可绘制的实现

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;
        }
    }
}

答案 4 :(得分:-1)

您可以使用jquery插件(jquery.nicescroll.js)来实现此目的。更多细节访问 http://areaaperta.com/nicescroll/