RecyclerView的可滚动的列表实现,视图相邻的视图在屏幕上部分或完全可见(水平3个item,第一个和第三个显示一部分,第二个完全显示)
效果如图:

基于RecyclerView完成的(自定义控件)
public class DiscreteRecyclerView extends RecyclerView {    public static final int NO_POSITION = DiscreteRecyclerLayoutManager.NO_POSITION;    private static final int DEFAULT_ORIENTATION = DSVOrientation.HORIZONTAL.ordinal();    private DiscreteRecyclerLayoutManager layoutManager;    private List scrollStateChangeListeners;    private List onItemChangedListeners;    private boolean isOverScrollEnabled;    public DiscreteRecyclerView(Context context) {        super(context);        init(null);    }    public DiscreteRecyclerView(Context context, AttributeSet attrs) {        super(context, attrs);        init(attrs);    }    public DiscreteRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(attrs);    }    private void init(AttributeSet attrs) {        scrollStateChangeListeners = new ArrayList<>();        onItemChangedListeners = new ArrayList<>();        int orientation = DEFAULT_ORIENTATION;        if (attrs != null) {            TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DiscreteRecyclerView);            orientation = ta.getInt(R.styleable.DiscreteRecyclerView_dsv_orientation, DEFAULT_ORIENTATION);            ta.recycle();        }        isOverScrollEnabled = getOverScrollMode() != OVER_SCROLL_NEVER;        layoutManager = new DiscreteRecyclerLayoutManager(                getContext(), new ScrollStateListener(),                DSVOrientation.values()[orientation]);        setLayoutManager(layoutManager);    }    @Override    public void setLayoutManager(LayoutManager layout) {        if (layout instanceof DiscreteRecyclerLayoutManager) {            super.setLayoutManager(layout);        } else {            throw new IllegalArgumentException(getContext().getString(R.string.dsv_ex_msg_dont_set_lm));        }    }    @Override    public boolean fling(int velocityX, int velocityY) {        boolean isFling = super.fling(velocityX, velocityY);        if (isFling) {            layoutManager.onFling(velocityX, velocityY);        } else {            layoutManager.returnToCurrentPosition();        }        return isFling;    }    @Nullable    public ViewHolder getViewHolder(int position) {        View view = layoutManager.findViewByPosition(position);        return view != null ? getChildViewHolder(view) : null;    }    /**     * @return adapter position of the current item or -1 if nothing is selected     */    public int getCurrentItem() {        return layoutManager.getCurrentPosition();    }    public void setItemTransformer(DiscreteScrollItemTransformer transformer) {        layoutManager.setItemTransformer(transformer);    }    public void setItemTransitionTimeMillis(@IntRange(from = 10) int millis) {        layoutManager.setTimeForItemSettle(millis);    }    public void setSlideOnFling(boolean result){        layoutManager.setShouldSlideOnFling(result);    }    public void setSlideOnFlingThreshold(int threshold){        layoutManager.setSlideOnFlingThreshold(threshold);    }    public void setOrientation(DSVOrientation orientation) {        layoutManager.setOrientation(orientation);    }    public void setOffscreenItems(int items) {        layoutManager.setOffscreenItems(items);    }    public void setClampTransformProgressAfter(@IntRange(from = 1) int itemCount) {        if (itemCount <= 1) {            throw new IllegalArgumentException("must be >= 1");        }        layoutManager.setTransformClampItemCount(itemCount);    }    public void setOverScrollEnabled(boolean overScrollEnabled) {        isOverScrollEnabled = overScrollEnabled;        setOverScrollMode(OVER_SCROLL_NEVER);    }    public void addScrollStateChangeListener(@NonNull ScrollStateChangeListener<?> scrollStateChangeListener) {        scrollStateChangeListeners.add(scrollStateChangeListener);    }    public void addScrollListener(@NonNull ScrollListener<?> scrollListener) {        addScrollStateChangeListener(new ScrollListenerAdapter(scrollListener));    }    public void addOnItemChangedListener(@NonNull OnItemChangedListener<?> onItemChangedListener) {        onItemChangedListeners.add(onItemChangedListener);    }    public void removeScrollStateChangeListener(@NonNull ScrollStateChangeListener<?> scrollStateChangeListener) {        scrollStateChangeListeners.remove(scrollStateChangeListener);    }    public void removeScrollListener(@NonNull ScrollListener<?> scrollListener) {        removeScrollStateChangeListener(new ScrollListenerAdapter<>(scrollListener));    }    public void removeItemChangedListener(@NonNull OnItemChangedListener<?> onItemChangedListener) {        onItemChangedListeners.remove(onItemChangedListener);    }    private void notifyScrollStart(ViewHolder holder, int current) {        for (ScrollStateChangeListener listener : scrollStateChangeListeners) {            listener.onScrollStart(holder, current);        }    }    private void notifyScrollEnd(ViewHolder holder, int current) {        for (ScrollStateChangeListener listener : scrollStateChangeListeners) {            listener.onScrollEnd(holder, current);        }    }    private void notifyScroll(float position,                              int currentIndex, int newIndex,                              ViewHolder currentHolder, ViewHolder newHolder) {        for (ScrollStateChangeListener listener : scrollStateChangeListeners) {            listener.onScroll(position, currentIndex, newIndex,                currentHolder,                newHolder);        }    }    private void notifyCurrentItemChanged(ViewHolder holder, int current) {        for (OnItemChangedListener listener : onItemChangedListeners) {            listener.onCurrentItemChanged(holder, current);        }    }    private void notifyCurrentItemChanged() {        if (onItemChangedListeners.isEmpty()) {            return;        }        int current = layoutManager.getCurrentPosition();        ViewHolder currentHolder = getViewHolder(current);        notifyCurrentItemChanged(currentHolder, current);    }    private class ScrollStateListener implements DiscreteRecyclerLayoutManager.ScrollStateListener {        @Override        public void onIsBoundReachedFlagChange(boolean isBoundReached) {            if (isOverScrollEnabled) {                setOverScrollMode(isBoundReached ? OVER_SCROLL_ALWAYS : OVER_SCROLL_NEVER);            }        }        @Override        public void onScrollStart() {            if (scrollStateChangeListeners.isEmpty()) {                return;            }            int current = layoutManager.getCurrentPosition();            ViewHolder holder = getViewHolder(current);            if (holder != null) {                notifyScrollStart(holder, current);            }        }        @Override        public void onScrollEnd() {            if (onItemChangedListeners.isEmpty() && scrollStateChangeListeners.isEmpty()) {                return;            }            int current = layoutManager.getCurrentPosition();            ViewHolder holder = getViewHolder(current);            if (holder != null) {                notifyScrollEnd(holder, current);                notifyCurrentItemChanged(holder, current);            }        }        @Override        public void onScroll(float currentViewPosition) {            if (scrollStateChangeListeners.isEmpty()) {                return;            }            int currentIndex = getCurrentItem();            int newIndex = layoutManager.getNextPosition();            if (currentIndex != newIndex) {                notifyScroll(currentViewPosition,                    currentIndex, newIndex,                    getViewHolder(currentIndex),                    getViewHolder(newIndex));            }        }        @Override        public void onCurrentViewFirstLayout() {            post(new Runnable() {                @Override                public void run() {                    notifyCurrentItemChanged();                }            });        }        @Override        public void onDataSetChangeChangedPosition() {            notifyCurrentItemChanged();        }    }    public interface ScrollStateChangeListener {        void onScrollStart(@NonNull T currentItemHolder, int adapterPosition);        void onScrollEnd(@NonNull T currentItemHolder, int adapterPosition);        void onScroll(float scrollPosition,                      int currentPosition,                      int newPosition,                      @Nullable T currentHolder,                      @Nullable T newCurrent);    }    public interface ScrollListener {        void onScroll(float scrollPosition,                      int currentPosition, int newPosition,                      @Nullable T currentHolder,                      @Nullable T newCurrent);    }    public interface OnItemChangedListener {        /*         * This method will be also triggered when view appears on the screen for the first time.         * If data set is empty, viewHolder will be null and adapterPosition will be NO_POSITION         */        void onCurrentItemChanged(@Nullable T viewHolder, int adapterPosition);    }}
源码:https://github.com/DickyQie/android-discrete-recyclerview

 

更多相关文章

  1. Android(安卓)Navigation Drawer简记
  2. android 更新界面视图 Handler和runOnUiThread
  3. Android(安卓)Material Design-Defining Shadows and Clipping V
  4. Material-Design
  5. android之ListView的Adapter使用
  6. Android(安卓)UI开发第三十四篇——SlidingPaneLayout
  7. 【Android】使用Gallery组件实现循环显示图像
  8. Android图片动画播放
  9. Android学习笔记10——Android的调试

随机推荐

  1. Android(安卓)消息机制——你真的了解Han
  2. Android之带group指示器的ExpandableList
  3. 增加android 拥有root权限的服务
  4. Android(安卓)8.0 拨号流程分析
  5. AsyncTask的使用及源码分析
  6. Android与iOS在交互细节上的区别
  7. statusbar上根据不同语言,添加PM,AM,或者上
  8. android studio生成签名导打包的方法
  9. android APK Expansion Files
  10. [置顶] ANDROID垃圾回收器机制和强引用、