如何更改自定义视图大小取决于子列表

时间:2018-04-26 10:24:49

标签: android android-recyclerview android-custom-view

我有自定义视图(扩展LinearLayout),其中包含RecyclerView。当我添加新项目时,RecyclerView不会更改大小。我认为问题是我的自定义视图没有为RecyclerView提供足够的空间。 问题:如何更改自定义视图的高度取决于chlid recylerview大小?

如果我错了,请纠正我

CustomView:

public class ExpandableView extends LinearLayout {


    private Settings mSettings ;
    private int mExpandState;
    private ValueAnimator mExpandAnimator;
    private ValueAnimator mParentAnimator;
    private AnimatorSet mExpandScrollAnimatorSet;
    private  int mExpandedViewHeight;
    private  boolean mIsInit = true;

    private boolean isAllowedExpand = false;

    private ScrolledParent mScrolledParent;
    private OnExpandListener mOnExpandListener;


    public ExpandableView(Context context) {
        super(context);
        init(null);
    }

    public ExpandableView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public ExpandableView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init(AttributeSet attrs) {
        setOrientation(VERTICAL);
        this.setClipChildren(false);
        this.setClipToPadding(false);

        mExpandState = ExpandState.PRE_INIT;
        mSettings = new Settings();
        if(attrs!=null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ExpandableView);
            mSettings.expandDuration = typedArray.getInt(R.styleable.ExpandableView_expDuration, Settings.EXPAND_DURATION);
            mSettings.expandWithParentScroll = typedArray.getBoolean(R.styleable.ExpandableView_expWithParentScroll,false);
            mSettings.expandScrollTogether = typedArray.getBoolean(R.styleable.ExpandableView_expExpandScrollTogether,true);
            typedArray.recycle();
        }


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int childCount = getChildCount();
        if(childCount!=2) {
            throw new IllegalStateException("ExpandableLayout must has two child view !");
        }
        if(mIsInit) {
            ((MarginLayoutParams)getChildAt(0).getLayoutParams()).bottomMargin=0;
            MarginLayoutParams marginLayoutParams = ((MarginLayoutParams)getChildAt(1).getLayoutParams());
            marginLayoutParams.bottomMargin=0;
            marginLayoutParams.topMargin=0;
            marginLayoutParams.height = 0;
            mExpandedViewHeight = getChildAt(1).getMeasuredHeight();
            mIsInit =false;
            mExpandState = ExpandState.CLOSED;
            View view = getChildAt(0);
            if (view != null){
                view.setOnClickListener(v -> toggle());
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if(mSettings.expandWithParentScroll) {
            mScrolledParent = Utils.getScrolledParent(this);
        }
    }

    private int getParentScrollDistance () {
        int distance = 0;
        if(mScrolledParent == null) {
            return distance;
        }
        distance = (int) (getY() + getMeasuredHeight() + mExpandedViewHeight - mScrolledParent.scrolledView.getMeasuredHeight());
        for(int index = 0; index < mScrolledParent.childBetweenParentCount; index++) {
            ViewGroup parent = (ViewGroup) getParent();
            distance+=parent.getY();
        }
        return distance;
    }

    private void verticalAnimate(final int startHeight, final int endHeight ) {
        int distance = getParentScrollDistance();

        final View target = getChildAt(1);

        mExpandAnimator = ValueAnimator.ofInt(startHeight,endHeight);
        mExpandAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                target.getLayoutParams().height = (int) animation.getAnimatedValue();
                target.requestLayout();
            }
        });

        mExpandAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                if(endHeight-startHeight < 0) {
                    mExpandState = ExpandState.CLOSED;
                    if (mOnExpandListener != null) {
                        mOnExpandListener.onExpand(false);
                    }
                } else {
                    mExpandState=ExpandState.EXPANDED;
                    if(mOnExpandListener != null) {
                        mOnExpandListener.onExpand(true);
                    }
                }
            }
        });

        //todo ??????????????????????
        mExpandState=mExpandState==ExpandState.EXPANDED?ExpandState.CLOSING :ExpandState.EXPANDING;

        mExpandAnimator.setDuration(mSettings.expandDuration);
        if(mExpandState == ExpandState.EXPANDING && mSettings.expandWithParentScroll && distance > 0) {

            mParentAnimator = Utils.createParentAnimator(mScrolledParent.scrolledView, distance, mSettings.expandDuration);

            mExpandScrollAnimatorSet = new AnimatorSet();

            if(mSettings.expandScrollTogether) {
                mExpandScrollAnimatorSet.playTogether(mExpandAnimator,mParentAnimator);
            } else {
                mExpandScrollAnimatorSet.playSequentially(mExpandAnimator,mParentAnimator);
            }
            mExpandScrollAnimatorSet.start();

        } else {
            mExpandAnimator.start();
        }
    }

    public void setExpand(boolean expand) {
        if (mExpandState == ExpandState.PRE_INIT) {return;}

        getChildAt(1).getLayoutParams().height=expand?mExpandedViewHeight:0;
        requestLayout();
        mExpandState=expand?ExpandState.EXPANDED:ExpandState.CLOSED;
    }

    public boolean isExpanded() {
        return mExpandState==ExpandState.EXPANDED;
    }

    public void toggle() {
        if (isAllowedExpand){
            if(mExpandState==ExpandState.EXPANDED) {
                close();
            }else if(mExpandState==ExpandState.CLOSED) {
                expand();
            }
        }
    }

    public void expand() {
        verticalAnimate(0,mExpandedViewHeight);
    }

    public void close() {
        verticalAnimate(mExpandedViewHeight,0);
    }





    public interface OnExpandListener {
        void onExpand(boolean expanded) ;
    }

    public void setOnExpandListener(OnExpandListener onExpandListener) {
        this.mOnExpandListener = onExpandListener;
    }


    public void setExpandScrollTogether(boolean expandScrollTogether) {
        this.mSettings.expandScrollTogether = expandScrollTogether;
    }

    public void setExpandWithParentScroll(boolean expandWithParentScroll) {
        this.mSettings.expandWithParentScroll = expandWithParentScroll;
    }

    public void setExpandDuration(int expandDuration) {
        this.mSettings.expandDuration = expandDuration;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if(mExpandAnimator!=null&&mExpandAnimator.isRunning()) {
            mExpandAnimator.cancel();
            mExpandAnimator.removeAllUpdateListeners();
        }
        if(mParentAnimator!=null&&mParentAnimator.isRunning()) {
            mParentAnimator.cancel();
            mParentAnimator.removeAllUpdateListeners();
        }
        if(mExpandScrollAnimatorSet!=null) {
            mExpandScrollAnimatorSet.cancel();
        }
    }

    public void setAllowedExpand(boolean allowedExpand) {
        isAllowedExpand = allowedExpand;
    }

    public void refreshView(){

        ViewGroup.LayoutParams params = this.getLayoutParams();
        Log.d("tag", "params - " + params.height);
    }
}

1 个答案:

答案 0 :(得分:1)

RecyclerView 适配器中指定您的项目高度,如下所示:

LinearLayout.LayoutParams relParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
relParams.height = 100;
relParams.width = Utility.getScreenWidth(mContext);
holder.yourDesireView.setLayoutParams(relParams);

这是屏幕宽度计算器方法:

public static int getScreenWidth(Context context) {
    if (context == null) {
        return 0;
    }
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return metrics.widthPixels;
}

我认为这会有所帮助......