Как сделать так, чтобы полоса прокрутки отображалась слева?

Как в Android ListView сделать так, чтобы scrollbar отображалось слева?


person Adham    schedule 31.05.2012    source источник


Ответы (5)


пример:

mView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
person FoamyGuy    schedule 31.05.2012
comment
это также возможно через xml: android:verticalScrollbarPosition=left - person android developer; 21.05.2013
comment
К сожалению, не работает в NavigationView ( API 23). - person Luten; 14.12.2015

Вы можете переместить положение полосы прокрутки влево для любого вида, используя View.SCROLLBAR_POSITION_LEFT< /а>.

person Tanvir Ahmed    schedule 31.05.2012

Как упоминалось в двух других ответах, одна из возможностей - использовать View .setVerticalScrollbarPosition() с SCROLLBAR_POSITION_LEFT. Однако есть одно важное предостережение: для этого требуется уровень API 11+, на который на момент написания приходится менее 10% установок Android. Для большинства приложений это неприемлемо.

Одна из возможностей, которая приходит на ум, чтобы выполнить то, что вы хотите в старых версиях Android, состоит в том, чтобы сделать что-то очень неуклюжее: отключить полосу прокрутки, отразить основной макет с узким макетом слева от него, достаточно широким, чтобы вместить полосу прокрутки и вручную прокрутите левое представление с помощью scrollyBy() при прокрутке основного представления (путем переопределения onScrollChanged()).

Тем не менее, я бы не стал рекомендовать это, если только нет очень веской причины переместить полосу прокрутки влево. В большинстве случаев вы хотите, чтобы ваше приложение подходило и вело себя как любое другое приложение на устройстве, просто позволяя Android следовать своим значениям по умолчанию.

person Darshan Rivka Whittle    schedule 31.05.2012

Попробуйте мой хак, вроде работает как минимум на 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);
    }
}
person Gena Batsyan    schedule 21.09.2012
comment
Ну, это работает, если я вызываю tryApiLevelPre11() внутри тела if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB). - person Eng.Fouad; 07.02.2014

вы можете добавить это в xml

android:verticalScrollbarPosition="left"

как это

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

или используйте этот код в Котлине

scrollView.verticalScrollbarPosition = View.SCROLLBAR_POSITION_LEFT
person Radesh    schedule 01.12.2020