RecyclerView does not scroll as expected

This worked for me:

itemsView.smoothScrollBy(-recyclerView.computeHorizontalScrollOffset(), 0)

In case of LinearLayoutManager with vertical orientation you can create own SmoothScroller and override calculateDyToMakeVisible() method where you can set desired view position. For example, to make the target view always to be appeared at the top side of RecyclerView after smoothScroll() write this:

class CustomLinearSmoothScroller extends LinearSmoothScroller {

    public CustomLinearSmoothScroller(Context context) {
        super(context);
    }

    @Override
    public int calculateDyToMakeVisible(View view, int snapPreference) {
        final RecyclerView.LayoutManager layoutManager = getLayoutManager();
        if (!layoutManager.canScrollVertically()) {
            return 0;
        }
        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)view.getLayoutParams();
        final int top = layoutManager.getDecoratedTop(view) - params.topMargin;
        final int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin;
        final int viewHeight = bottom - top;
        final int start = layoutManager.getPaddingTop();
        final int end = start + viewHeight;
        return calculateDtToFit(top, bottom, start, end, snapPreference);
    }

"top" and "bottom" - bounds of the target view

"start" and "end" - points between which the view should be placed during smoothScroll


I found a surprising simple workaround:

@Override
public void onClick(View v) {
    int pos = mLayoutManager.findFirstVisibleItemPosition();
    int outer = (MyAdapter.VISIBLE_ITEMS + 1) / 2;
    int delta = pos + outer - ForecastAdapter.ITEM_IN_CENTER;
    //Log.d("Scroll", "delta=" + delta);
    View firstChild = mForecast.getChildAt(0);
    if(firstChild != null) {
        mForecast.smoothScrollBy(firstChild.getWidth() * -delta, 0);
    }
}

Here I calculate the width to jump myself, that does exactly what I want.