zoukankan      html  css  js  c++  java
  • android -------- RecyclerView的可(多个Item水平,垂直)滚动列表的实现

    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<ScrollStateChangeListener> scrollStateChangeListeners;
        private List<OnItemChangedListener> 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<T extends ViewHolder> {
    
            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<T extends ViewHolder> {
    
            void onScroll(float scrollPosition,
                          int currentPosition, int newPosition,
                          @Nullable T currentHolder,
                          @Nullable T newCurrent);
        }
    
        public interface OnItemChangedListener<T extends ViewHolder> {
            /*
             * 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


     
  • 相关阅读:
    uTenux-OS-Task再探
    uTenux——LED驱动讲解
    uTenux——HelloWord
    uTenux——重新整理底层驱动库
    template的超级bug
    [LeetCode] Integer to Roman
    [LeetCode] Roman to Integer
    [LeetCode]Flatten Binary Tree to Linked List
    [LeetCode] LRU Cache [Forward]
    [LeetCode] Reorder List
  • 原文地址:https://www.cnblogs.com/zhangqie/p/10718845.html
Copyright © 2011-2022 走看看