如何使“滚动条”出现在左侧?

时间:2012-05-31 02:55:38

标签: android android-listview android-scrollview android-scrollbar

在Android ListView中,如何让scrollbar出现在左侧?

5 个答案:

答案 0 :(得分:52)

示例:

mView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);

答案 1 :(得分:3)

您可以使用View.SCROLLBAR_POSITION_LEFT为任何视图向左移动滚动条位置。

答案 2 :(得分:3)

正如其他两个答案所提到的,一种可能性是View.setVerticalScrollbarPosition()SCROLLBAR_POSITION_LEFT一起使用。然而,一个巨大的警告是,这需要API级别11+,在撰写本文时占Android安装的比例不到10%。对于大多数应用程序,这是不可接受的。

想到在旧版Android上实现你想要的东西的一种可能性就是做一些非常糟糕的事情:关闭滚动条,用一个狭窄的布局镜像你的主要布局到它的左边,足够宽适合滚动条,并在滚动主视图时用scrollyBy()手动滚动左视图(通过覆盖 onScrollChanged())。

那就是说,除非有一个非常令人信服的理由将滚动条移到左边,否则我实际上不会建议这样做。在大多数情况下,只需让Android遵循其默认设置,您就希望自己的应用能够适应设备上的任何其他应用,并且与其他应用相似。

答案 3 :(得分:1)

尝试我的黑客,似乎至少在2.2及以上版本上工作。

import java.lang.reflect.Field;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ListView;

/**
 * This class fixes the lack of setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT) before API level 11
 * @author Genadz Batsyan
 */

public class ListViewWithLeftScrollBar extends ListView {
    private static final String LOG_TAG = ListViewWithLeftScrollBar.class.getSimpleName();
    private static final boolean DEBUG = true;

    private boolean patchInvalidate;

    public ListViewWithLeftScrollBar(Context context) {
        super(context);
        moveVerticalScrollbarToTheLeft();
    }

    public ListViewWithLeftScrollBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        moveVerticalScrollbarToTheLeft();
    }

    public ListViewWithLeftScrollBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        moveVerticalScrollbarToTheLeft();
    }

    @Override
    public void invalidate(Rect r) {
        invalidate(r.left, r.top, r.right, r.bottom);
    }

    @Override
    public void invalidate(int left, int top, int right, int bottom) {
        int width = right - left;
        if (DEBUG) log("invalidate original w:"+ getWidth() +" h:"+ getHeight()+"  rect:"+left+", "+top+", "+right+", "+bottom);
        if (patchInvalidate && right == getWidth() && top == 0 && bottom == getHeight() && width < 30) {
            // The above condition should ensure that ListView is VERY likely to be invalidating the scrollbar.
            // In fact ListView appears to not invalidate anything except the scrollbar, ever.
            left = 0;
            right = left + width;
            if (DEBUG) log("invalidate patched  w:"+ getWidth() +" h:"+ getHeight()+"  rect:"+left+", "+top+", "+right+", "+bottom);
        }
        super.invalidate(left, top, right, bottom);
    }

    private void moveVerticalScrollbarToTheLeft() {
        try {
            if (DEBUG) log("moveVerticalScrollbarToTheLeft: Trying API Level >=11");
            tryApiLevel11();
            if (DEBUG) log("moveVerticalScrollbarToTheLeft: API Level >=11 success");
        } catch (Throwable t1) {
            if (DEBUG) {
                log("moveVerticalScrollbarToTheLeft: API Level >=11 FAILED");
                t1.printStackTrace();
            }
            try {
                if (DEBUG) log("moveVerticalScrollbarToTheLeft: Trying hack for API Level <11");
                tryApiLevelPre11();
                patchInvalidate = true;
                if (DEBUG) log("moveVerticalScrollbarToTheLeft: API Level <11 hack success");
            } catch (Throwable t2) {
                if (DEBUG) {
                    log("moveVerticalScrollbarToTheLeft: API Level <11 hack FAILED");
                    t2.printStackTrace();
                }
            }
        }
    }

    @SuppressLint("NewApi")
    private void tryApiLevel11() {
        setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
    }

    private void tryApiLevelPre11() throws Exception {
        Class<?> viewClass = View.class;

        Field scrollCacheField = viewClass.getDeclaredField("mScrollCache");
        scrollCacheField.setAccessible(true);
        Object scrollCache = scrollCacheField.get(this);
        if (DEBUG) log("scrollCache: "+ scrollCache);

        Field scrollBarField = scrollCache.getClass().getDeclaredField("scrollBar");
        scrollBarField.setAccessible(true);
        Object scrollBar = scrollBarField.get(scrollCache);
        if (DEBUG) log("scrollBar: "+ scrollBar);

        Field verticalThumbField = scrollBar.getClass().getDeclaredField("mVerticalThumb");
        verticalThumbField.setAccessible(true);
        Object verticalThumb = verticalThumbField.get(scrollBar);
        if (DEBUG) log("verticalThumb: "+ verticalThumb);

        Drawable verticalThumbDrawable = (Drawable) verticalThumb;
        Drawable replacementVerticalThumbDrawable = new LayerDrawable(new Drawable[]{ verticalThumbDrawable }) {
            @Override
            public void setBounds(int left, int top, int right, int bottom) {
                if (DEBUG) log("setBounds original: "+left+", "+top+", "+right+", "+bottom);
                int width = right - left;
                left = 0;
                right = left + width;
                if (DEBUG) log("setBounds patched:  "+left+", "+top+", "+right+", "+bottom);
                super.setBounds(left, top, right, bottom);
            }       
        };
        verticalThumbField.set(scrollBar, replacementVerticalThumbDrawable);
    }

    private static void log(String msg) {
        Log.d(LOG_TAG, msg);
    }
}

答案 4 :(得分:0)

您可以在xml中添加它

android:verticalScrollbarPosition="left"

像这样

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:verticalScrollbarPosition="left"
    android:scrollbarThumbVertical="@drawable/scrollbar"
    />

或在Kotlin中使用此代码

scrollView.verticalScrollbarPosition = View.SCROLLBAR_POSITION_LEFT