临文乍了了,彻卷兀若无。这篇文章主要讲述Android Studio第十八期 - Snaphelper相关的知识,希望能为你提供帮助。
代码已经整理好,效果如下图:
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
【Android Studio第十八期 - Snaphelper】本文出自 “梁肖技术中心” 博客,请务必保留此出处http://liangxiao.blog.51cto.com/3626612/1871713
推荐阅读
- Android Studio第十九期 - Glin架构
- Android的UI设计
- Android Studio 中Gradle配置sonarqube
- Android7.0 之 行为变更
- Android蓝牙4.0之玩爆智能穿戴家具进阶篇
- 关于React Native项目在android上UI性能调试实践
- Tiny4412 Android 启动流程
- FTE/6个月的亚马逊面试经验SDE-1实习– AmazeWow
- C#中的HashSet介绍与用法示例