代码已经整理好,效果如下图:

    GravitySnapHelper:

/* * Copyright (C) 2016 The Android Open Source Project * Copyright (C) 2016 Rúben Sousa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific languag`e governing permissions and * limitations under the License. */package com.haiersmart.sfnation.widget;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.LinearSnapHelper;import android.support.v7.widget.OrientationHelper;import android.support.v7.widget.RecyclerView;import android.view.Gravity;import android.view.View;import com.haiersmart.sfnation.R;public class GravitySnapHelper extends LinearSnapHelper {    private OrientationHelper mVerticalHelper;    private OrientationHelper mHorizontalHelper;    private int mGravity;    private boolean mIsRtlHorizontal;    private boolean mSnapLastItemEnabled;    SnapListener mSnapListener;    boolean mSnapping;    private RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {        @Override        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {            super.onScrollStateChanged(recyclerView, newState);            if (newState == RecyclerView.SCROLL_STATE_SETTLING) {                mSnapping = false;            }            if (newState == RecyclerView.SCROLL_STATE_IDLE && mSnapping && mSnapListener != null) {                int position = getSnappedPosition(recyclerView);                if (position != RecyclerView.NO_POSITION) {                    mSnapListener.onSnap(position);                }                mSnapping = false;            }        }    };    public GravitySnapHelper(int gravity) {        this(gravity, false, null);    }    public GravitySnapHelper(int gravity, boolean enableSnapLastItem) {        this(gravity, enableSnapLastItem, null);    }    public GravitySnapHelper(int gravity, boolean enableSnapLastItem, SnapListener snapListener) {        if (gravity != Gravity.START && gravity != Gravity.END                && gravity != Gravity.BOTTOM && gravity != Gravity.TOP) {            throw new IllegalArgumentException("Invalid gravity value. Use START " +                    "| END | BOTTOM | TOP constants");        }        mSnapListener = snapListener;        mGravity = gravity;        mSnapLastItemEnabled = enableSnapLastItem;    }    @Override    public void attachToRecyclerView(@Nullable RecyclerView recyclerView)            throws IllegalStateException {        if (recyclerView != null) {            if (mGravity == Gravity.START || mGravity == Gravity.END) {                mIsRtlHorizontal                        = recyclerView.getContext().getResources().getBoolean(R.bool.is_rtl);            }            if (mSnapListener != null) {                recyclerView.addOnScrollListener(mScrollListener);            }        }        super.attachToRecyclerView(recyclerView);    }    @Override    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,                                              @NonNull View targetView) {        int[] out = new int[2];        if (layoutManager.canScrollHorizontally()) {            if (mGravity == Gravity.START) {                out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager), false);            } else { // END                out[0] = distanceToEnd(targetView, getHorizontalHelper(layoutManager), false);            }        } else {            out[0] = 0;        }        if (layoutManager.canScrollVertically()) {            if (mGravity == Gravity.TOP) {                out[1] = distanceToStart(targetView, getVerticalHelper(layoutManager), false);            } else { // BOTTOM                out[1] = distanceToEnd(targetView, getVerticalHelper(layoutManager), false);            }        } else {            out[1] = 0;        }        return out;    }    @Override    public View findSnapView(RecyclerView.LayoutManager layoutManager) {        View snapView = null;        if (layoutManager instanceof LinearLayoutManager) {            switch (mGravity) {                case Gravity.START:                    snapView = findStartView(layoutManager, getHorizontalHelper(layoutManager));                    break;                case Gravity.END:                    snapView = findEndView(layoutManager, getHorizontalHelper(layoutManager));                    break;                case Gravity.TOP:                    snapView = findStartView(layoutManager, getVerticalHelper(layoutManager));                    break;                case Gravity.BOTTOM:                    snapView = findEndView(layoutManager, getVerticalHelper(layoutManager));                    break;            }        }        mSnapping = snapView != null;        return snapView;    }    /**     * Enable snapping of the last item that's snappable.     * The default value is false, because you can't see the last item completely     * if this is enabled.     *     * @param snap true if you want to enable snapping of the last snappable item     */    public void enableLastItemSnap(boolean snap) {        mSnapLastItemEnabled = snap;    }    private int distanceToStart(View targetView, OrientationHelper helper, boolean fromEnd) {        if (mIsRtlHorizontal && !fromEnd) {            return distanceToEnd(targetView, helper, true);        }        return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();    }    private int distanceToEnd(View targetView, OrientationHelper helper, boolean fromStart) {        if (mIsRtlHorizontal && !fromStart) {            return distanceToStart(targetView, helper, true);        }        return helper.getDecoratedEnd(targetView) - helper.getEndAfterPadding();    }    /**     * Returns the first view that we should snap to.     *     * @param layoutManager the recyclerview's layout manager     * @param helper        orientation helper to calculate view sizes     * @return the first view in the LayoutManager to snap to     */    private View findStartView(RecyclerView.LayoutManager layoutManager,                               OrientationHelper helper) {        if (layoutManager instanceof LinearLayoutManager) {            int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();            if (firstChild == RecyclerView.NO_POSITION) {                return null;            }            View child = layoutManager.findViewByPosition(firstChild);            float visibleWidth;            // We should return the child if it's visible width            // is greater than 0.5 of it's total width.            // In a RTL configuration, we need to check the start point and in LTR the end point            if (mIsRtlHorizontal) {                visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child))                        / helper.getDecoratedMeasurement(child);            } else {                visibleWidth = (float) helper.getDecoratedEnd(child)                        / helper.getDecoratedMeasurement(child);            }            // If we're at the end of the list, we shouldn't snap            // to avoid having the last item not completely visible.            boolean endOfList = ((LinearLayoutManager) layoutManager)                    .findLastCompletelyVisibleItemPosition()                    == layoutManager.getItemCount() - 1;            if (visibleWidth > 0.5f && !endOfList) {                return child;            } else if (mSnapLastItemEnabled && endOfList) {                return child;            } else if (endOfList) {                return null;            } else {                // If the child wasn't returned, we need to return                // the next view close to the start.                return layoutManager.findViewByPosition(firstChild + 1);            }        }        return null;    }    private View findEndView(RecyclerView.LayoutManager layoutManager,                             OrientationHelper helper) {        if (layoutManager instanceof LinearLayoutManager) {            int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();            if (lastChild == RecyclerView.NO_POSITION) {                return null;            }            View child = layoutManager.findViewByPosition(lastChild);            float visibleWidth;            if (mIsRtlHorizontal) {                visibleWidth = (float) helper.getDecoratedEnd(child)                        / helper.getDecoratedMeasurement(child);            } else {                visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child))                        / helper.getDecoratedMeasurement(child);            }            // If we're at the start of the list, we shouldn't snap            // to avoid having the first item not completely visible.            boolean startOfList = ((LinearLayoutManager) layoutManager)                    .findFirstCompletelyVisibleItemPosition() == 0;            if (visibleWidth > 0.5f && !startOfList) {                return child;            } else if (mSnapLastItemEnabled && startOfList) {                return child;            } else if (startOfList) {                return null;            } else {                // If the child wasn't returned, we need to return the previous view                return layoutManager.findViewByPosition(lastChild - 1);            }        }        return null;    }    int getSnappedPosition(RecyclerView recyclerView) {        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();        if (layoutManager instanceof LinearLayoutManager) {            if (mGravity == Gravity.START || mGravity == Gravity.TOP) {                return ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition();            } else if (mGravity == Gravity.END || mGravity == Gravity.BOTTOM) {                return ((LinearLayoutManager) layoutManager).findLastCompletelyVisibleItemPosition();            }        }        return RecyclerView.NO_POSITION;    }    private OrientationHelper getVerticalHelper(RecyclerView.LayoutManager layoutManager) {        if (mVerticalHelper == null) {            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);        }        return mVerticalHelper;    }    private OrientationHelper getHorizontalHelper(RecyclerView.LayoutManager layoutManager) {        if (mHorizontalHelper == null) {            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);        }        return mHorizontalHelper;    }    public interface SnapListener {        void onSnap(int position);    }}

    build.gradle

compile 'com.android.support:design:25.0.0'compile 'com.android.support:appcompat-v7:25.0.0'compile 'com.android.support:recyclerview-v7:25.0.0'compile 'com.android.support:cardview-v7:25.0.0'

    方法调用:

recycler_view1.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));SnapHelper snapHelperStart = new GravitySnapHelper(Gravity.TOP);snapHelperStart.attachToRecyclerView(recycler_view1);

    

    地址:

https://github.com/geeklx/MyApplication/tree/master/p015_recycleview_gundong_vertical


更多相关文章

  1. android 用代码画虚线边框背景
  2. ListView点击效果设置
  3. 使用反射调用android API中的hide方法
  4. android中wifi原理及流程分析(很经典)
  5. android操作系统默认的图片
  6. android api 中文 (73)—— AdapterView
  7. android中wifi原理及流程分析(很经典)
  8. Android内嵌H5(2)
  9. ListView点击效果设置

随机推荐

  1. Android自动提示--AutoCompleteTextView
  2. Android(安卓)P Camera架构
  3. cocos2d js 3.0window下配置笔记
  4. 获得a meta-data 的值
  5. Android(安卓)AVD 安装电子市场
  6. parsing XML: unbound prefix
  7. Android中动态设置多继承Style/Theme
  8. 【Android动态布局】之【使用addView方法
  9. 2011.09.01(3)——— android service star
  10. Android(安卓)读写文件的N种写法