Scrollbar touch area in Android 6

2019-04-26 08:46发布

I observe new behaviour in Android 6.0 Marshmallow. The touching area of scrollbar is widther than the scrollbar. It is visible on following screenshot. Scrollbar has 20 dp (green area) and touching area is probably 48 dp (blue and green area). I would like to have the touch area above the scrollbar only:

scrollbar screenshot

I use following:

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <style name="MyTheme.Dark" parent="android:Theme.Black">
        <item name="android:fastScrollStyle">@style/Widget.FastScroll</item>
        <item name="android:scrollbarThumbVertical">@drawable/dark_scrollbar_thumb</item>
        <item name="android:scrollbarTrackVertical">@drawable/dark_scrollbar_track</item>
        <item name="android:scrollbarSize">4dp</item>
        <item name="android:fastScrollThumbDrawable">@drawable/dark_scrollbar_fast_thumb</item>
        <item name="android:fastScrollTrackDrawable">@drawable/dark_scrollbar_fast_track</item>
    </style>

    <style name="Widget.FastScroll" parent="android:Widget.Material.FastScroll">
    </style>

</resources>

dark_scrollbar_fast_thumb.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <shape>
            <size
                android:height="30dp"
                android:width="20dp" />

            <solid android:color="@android:color/transparent" />
        </shape>
    </item>

    <item android:left="8dp" android:right="8dp">
        <shape>
            <size
                android:height="30dp"
                android:width="4dp" />

            <solid android:color="@color/dark_secondary" />
        </shape>
    </item>

</layer-list>

dark_scrollbar_fast_track.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <size android:width="@dimen/1dp" />
    <solid android:color="@color/dark_scrollbar_track" />

</shape>

dark_scrollbar_fast_thumb.xml:

<item>
    <shape>
        <size
            android:height="30dp"
            android:width="20dp" />

        <solid android:color="@android:color/transparent" />
    </shape>
</item>

<item android:left="8dp" android:right="8dp">
    <shape>
        <size
            android:height="30dp"
            android:width="4dp" />

        <solid android:color="@color/dark_secondary" />
    </shape>
</item>

dark_scrollbar_fast_track.xml:

<size android:width="@dimen/1dp" />
<solid android:color="@color/dark_scrollbar_track" />

Fast scrollbar is always visible and I use following style in listviews:

<item name="android:scrollbarStyle">outsideInset</item>

But the result looks more like outsideOverlay. I can observe this issue only on Marshmallow devices.

I would like to find the attribute that causes it and change it from 48dp to 20dp. Would you please help me?

2条回答
太酷不给撩
2楼-- · 2019-04-26 09:31

Found a simple solution which honestly I don't understand completely ;) I created a view overlay for the blue section which should be touch insensitive for the fastscrollbar (parent view is a RelativeLayout).

<View
    android:id="@+id/scroll_overlay
    android:layout_width="25dp"
    android:layout_marginRight="25dp"
    android:alignParentTop="true"
    android:alignParentRight="true"
    android:layout_above="@id/my_list_view_bottom_bar"
    android:clickable="true"/>

Then in my list view fragment, I set up an OnTouchListener for the overlay view to catch the touch events. The idea was to catch the MotionEvent.ACTION_DOWN to avoid jumping to the fast scrollbar position. But following code does that already.

View scrollOverlay = (View)view.findViewById(R.id.scroll_overlay);
scrollOverlay.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return myListView.onTouchEvent(event);
    }
});
查看更多
甜甜的少女心
3楼-- · 2019-04-26 09:37

I encountered the same issue and ended up using a workaround.

The trick is to disable the fast scroll when the user is not scrolling (or 1 sec after he stopped scrolling), and reactivate it when he starts scrolling again. In order to do so, youn need to implement OnScrollListener like this and set the listener to the listview:

private int mCurrentState = 0;

@Override
public void onScrollStateChanged(AbsListView absListView, int state) {

    if (state == SCROLL_STATE_IDLE && mCurrentState != state && mListview.isFastScrollEnabled()){

        mListview.postDelayed(new Runnable() {
            @Override
            public void run() {
                mListview.setFastScrollEnabled(false);
            }
        },1000);

    }

    mCurrentState = state;
}

@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {

    if (mCurrentState == SCROLL_STATE_TOUCH_SCROLL) {


        if (!mListview.isFastScrollEnabled())
            mListview.setFastScrollEnabled(true);
    }
}

Hope this might help you

查看更多
登录 后发表回答