【问题标题】:How to make the `scrollbar` appear on the left side?如何使“滚动条”出现在左侧?
【发布时间】:2012-06-05 07:31:31
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    示例:

    mView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
    

    【讨论】:

    • 也可以通过 xml:android:verticalScrollbarPosition="left"
    • 很遗憾不能在 NavigationView (API 23) 中工作。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      想到在旧版本的 Android 上实现您想要的一种可能性是做一些非常笨拙的事情:关闭滚动条,用左侧的窄布局镜像您的主布局,刚好足够宽以适应滚动条,并在滚动主视图时使用 scrollyBy() 手动滚动左视图(通过覆盖 onScrollChanged())。

      也就是说,除非有非常令人信服的理由将滚动条向左移动,否则我实际上并不建议这样做。在大多数情况下,您希望您的应用能够适应设备上的任何其他应用并像设备上的任何其他应用一样运行,只需让 Android 遵循其默认设置即可。

      【讨论】:

        【解决方案4】:

        试试我的 hack,似乎至少在 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);
            }
        }
        

        【讨论】:

        • 好吧,如果我在 if(Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) 的正文中调用 tryApiLevelPre11() 就可以了。
        【解决方案5】:

        你可以在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
        

        【讨论】:

          猜你喜欢
          • 2017-05-09
          • 2011-11-12
          • 1970-01-01
          • 2015-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-23
          • 1970-01-01
          相关资源
          最近更新 更多