首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >安卓:不允许recyclerView滚动的自定义LinearLayoutManager

安卓:不允许recyclerView滚动的自定义LinearLayoutManager
EN

Stack Overflow用户
提问于 2016-04-18 06:09:52
回答 1查看 2K关注 0票数 0

我正在使用自定义LinearLayoutManager来禁用/启用我的recyclerView的滚动。

代码语言:javascript
复制
public class CustomLayoutManager extends LinearLayoutManager {
    private boolean isScrollEnabled = true;

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

    public void setScrollEnabled(boolean flag) {
        this.isScrollEnabled = flag;
    }

    @Override
    public boolean canScrollVertically() {
        return isScrollEnabled && super.canScrollVertically();
    }
}

当我使用它来设置我的RecyclerView时,即使我将isScrollEnabled设置为true,它也不会滚动。

代码语言:javascript
复制
    CustomLayoutManager customLayoutManager = new CustomLayoutManager(getActivity());
    customLayoutManager.setScrollEnabled(true);
    recyclerView.setLayoutManager(customLayoutManager);

有人能帮上忙吗?

EN

回答 1

Stack Overflow用户

发布于 2018-08-05 21:58:41

https://gist.github.com/mustafasevgi/7dcb18166aaf9944e6450ec2878a646a

嗨,这段代码运行得很好,但我不能使循环Recycleview mathparent

代码语言:javascript
复制
public class Layoutmameger extends LayoutManager{

private static int INTERVAL_ANGLE = 50;// The default interval angle between each items
private static float DISTANCE_RATIO = 20f; // Finger swipe distance divide item rotate angle

//Flags of scroll dirction
private static int SCROLL_LEFT = 1;
private static int SCROLL_RIGHT = 2;

private Context context;

// Size of each items
private int mDecoratedChildWidth;
private int mDecoratedChildHeight;

//Property
private int startLeft;
private int startTop;
private int mRadius;
private int intervalAngle;
private float offsetRotate; // The offset angle for each items which will change according to the scroll offset

//the range of remove from parent
private int minRemoveDegree;
private int maxRemoveDegree;

//initial position of content
private int contentOffsetX = -1;
private int contentOffsetY = -1;

private int firstChildRotate = 0;

//Sparse array for recording the attachment and rotate angle of each items
private SparseBooleanArray itemAttached = new SparseBooleanArray();
private SparseArray<Float> itemsRotate = new SparseArray<>();


public Layoutmameger(Context context) {
    this.context = context;
    intervalAngle = INTERVAL_ANGLE;
    offsetRotate = 0;
    minRemoveDegree = -90;
    maxRemoveDegree = 90;
}


@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    if (getItemCount() == 0) {
        detachAndScrapAttachedViews(recycler);
        offsetRotate = 0;
        return;
    }

    //calculate the size of child
    if (getChildCount() == 0) {
        View scrap = recycler.getViewForPosition(0);
        addView(scrap);
        measureChildWithMargins(scrap, 0, 0);
        mDecoratedChildWidth = getDecoratedMeasuredWidth(scrap);
        mDecoratedChildHeight = getDecoratedMeasuredHeight(scrap);
        startLeft = contentOffsetX == -1?(getHorizontalSpace() - mDecoratedChildWidth)/2: contentOffsetX;
        startTop = contentOffsetY ==-1?0: contentOffsetY;
        mRadius = mDecoratedChildHeight;
        detachAndScrapView(scrap, recycler);
    }

    //record the state of each items
    float rotate = firstChildRotate;
    for (int i = 0; i < getItemCount(); i++) {
        itemsRotate.put(i,rotate);
        itemAttached.put(i,false);
        rotate+= intervalAngle;
    }

    detachAndScrapAttachedViews(recycler);
    fixRotateOffset();
    layoutItems(recycler,state);
}

private void layoutItems(RecyclerView.Recycler recycler,RecyclerView.State state){
    layoutItems(recycler,state,SCROLL_RIGHT);
}

private void layoutItems(RecyclerView.Recycler recycler,
                         RecyclerView.State state,int oritention){
    if(state.isPreLayout()) return;

    //remove the views which out of range
    for(int i = 0;i<getChildCount();i++){
        View view =  getChildAt(i);
        int position = getPosition(view);
        if(itemsRotate.get(position) - offsetRotate>maxRemoveDegree
                || itemsRotate.get(position) - offsetRotate< minRemoveDegree){
            itemAttached.put(position,false);
            removeAndRecycleView(view,recycler);
        }
    }

    //add the views which do not attached and in the range
    for(int i=0;i<getItemCount();i++){
        if(itemsRotate.get(i) - offsetRotate<= maxRemoveDegree
                && itemsRotate.get(i) - offsetRotate>= minRemoveDegree){
            if(!itemAttached.get(i)){
                View scrap = recycler.getViewForPosition(i);
                measureChildWithMargins(scrap, 0, 0);
                if(oritention == SCROLL_LEFT)
                    addView(scrap,0);
                else
                    addView(scrap);
                float rotate = itemsRotate.get(i) - offsetRotate;
                int left = calLeftPosition(rotate);
                int top = calTopPosition(rotate);
                scrap.setRotation(rotate);
                layoutDecorated(scrap, startLeft + left, startTop + top,
                        startLeft + left + mDecoratedChildWidth, startTop + top + mDecoratedChildHeight);
                itemAttached.put(i,true);
            }
        }
    }
}

@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
    int willScroll = dx;

    float theta = dx/DISTANCE_RATIO; // the angle every item will rotate for each dx
    float targetRotate = offsetRotate + theta;

    //handle the boundary
    if (targetRotate < 0) {
        willScroll = (int) (-offsetRotate*DISTANCE_RATIO);
    }
    else if (targetRotate > getMaxOffsetDegree()) {
        willScroll = (int) ((getMaxOffsetDegree() - offsetRotate)*DISTANCE_RATIO);
    }
    theta = willScroll/DISTANCE_RATIO;

    offsetRotate+=theta; //increase the offset rotate so when re-layout it can recycle the right views

    //re-calculate the rotate x,y of each items
    for(int i=0;i<getChildCount();i++){
        View view = getChildAt(i);
        float newRotate = view.getRotation() - theta;
        int offsetX = calLeftPosition(newRotate);
        int offsetY = calTopPosition(newRotate);
        layoutDecorated(view, startLeft + offsetX, startTop + offsetY,
                startLeft + offsetX + mDecoratedChildWidth, startTop + offsetY + mDecoratedChildHeight);
        view.setRotation(newRotate);
    }

    //different direction child will overlap different way
    if (dx < 0)
        layoutItems(recycler, state,SCROLL_LEFT);
    else
        layoutItems(recycler,state,SCROLL_RIGHT);
    return willScroll;
}

/**
 *
 * @param rotate the current rotate of view
 * @return the x of view
 */
private int calLeftPosition(float rotate){
    return (int) (mRadius * Math.cos(Math.toRadians(90 - rotate)));
}

/**
 *
 * @param rotate the current rotate of view
 * @return the y of view
 */
private int calTopPosition(float rotate){
    return (int) (mRadius - mRadius * Math.sin(Math.toRadians(90 - rotate)));
}

private int getHorizontalSpace() {
    return getWidth() - getPaddingRight() - getPaddingLeft();
}

private int getVerticalSpace() {
    return getHeight() - getPaddingBottom() - getPaddingTop();
}

/**
 *  fix the offset rotate angle in case item out of boundary
 **/
private void fixRotateOffset() {
    if(offsetRotate < 0){
        offsetRotate = 0;
    }
    if(offsetRotate > getMaxOffsetDegree()){
        offsetRotate = getMaxOffsetDegree();
    }
}

/**
 *
 * @return the max degrees according to current number of views and interval angle
 */
private float getMaxOffsetDegree(){
    return (getItemCount()-1)* intervalAngle;
}

private PointF computeScrollVectorForPosition(int targetPosition) {
    if (getChildCount() == 0) {
        return null;
    }
    final int firstChildPos = getPosition(getChildAt(0));
    final int direction = targetPosition < firstChildPos ? -1 : 1;
    return new PointF(direction, 0);
}

@Override
public boolean canScrollHorizontally() {
    return true;
}

@Override
public void scrollToPosition(int position) {
    if(position < 0 || position > getItemCount()-1) return;
    float targetRotate = position * intervalAngle;
    if(targetRotate == offsetRotate) return;
    offsetRotate = targetRotate;
    fixRotateOffset();
    requestLayout();
}

@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
    LinearSmoothScroller smoothScroller = new LinearSmoothScroller(context) {
        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return Layoutmameger.this.computeScrollVectorForPosition(targetPosition);
        }
    };
    smoothScroller.setTargetPosition(position);
    startSmoothScroll(smoothScroller);
}

@Override
public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter) {
    removeAllViews();
    offsetRotate = 0;
}

@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
    return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}

/**
 *
 * @return Get the current positon of views
 */
public int getCurrentPosition(){
    return Math.round(offsetRotate / intervalAngle);
}

/**
 *
 * @return Get the dx should be scrolled to the center
 */
public int getOffsetCenterView(){
    return (int) ((getCurrentPosition()*intervalAngle-offsetRotate)*DISTANCE_RATIO);
}

/**
 *
 * @return Get the radius of the circle
 */
public int getRadius() {
    return mRadius;
}

/**
 *
 * @param mRadius the radius of the circle,default will be item's height
 */
public void setRadius(int mRadius) {
    this.mRadius = mRadius;
}

/**
 *
 * @return the interval angle between each items
 */
public int getIntervalAngle() {
    return intervalAngle;
}

/**
 * Default angle is 30
 * @param intervalAngle the interval angle between each items
 */
public void setIntervalAngle(int intervalAngle) {
    this.intervalAngle = intervalAngle;
}

/**
 * Default is center in parent
 * @return the content offset of x
 */
public int getContentOffsetX() {
    return contentOffsetX;
}

/**
 * Default is center in parent
 * @param contentOffsetX the content offset of x
 */
public void setContentOffsetX(int contentOffsetX) {
    this.contentOffsetX = contentOffsetX;
}

/**
 * Default is top in parent
 * @return the content offset of y
 */
public int getContentOffsetY() {
    return contentOffsetY;
}

/**
 * Default is top in parent
 * @param contentOffsetY the content offset of y
 */
public void setContentOffsetY(int contentOffsetY) {
    this.contentOffsetY = contentOffsetY;
}

/**
 * Default is 0
 * @return the rotate of first child
 */
public int getFirstChildRotate() {
    return firstChildRotate;
}

/**
 * Default is 0
 * @param firstChildRotate the rotate of first child
 */
public void setFirstChildRotate(int firstChildRotate) {
    this.firstChildRotate = firstChildRotate;
}

/**
 * The rotate of child view in range[min,max] will be shown,default will be [-90,90]
 * @param min min rotate that will be show
 * @param max max rotate that will be show
 */
public void setDegreeRangeWillShow(int min,int max){
    if(min > max) return;
    minRemoveDegree = min;
    maxRemoveDegree = max;
}

}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36682787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档