Android: ConstraintLayout工具类,用于动态修改ConstraintLayout中控件四个方向的依赖关系

最近要用Android做一个课程表,我的思路是用ConstraintLayout中的辅助线画出一个类似的表格布局
在这里插入图片描述
然后从数据库中读取课程信息,动态生成一个个Botton按钮做为课程的控件(Botton自带Tooltips属性,这样可以浮动显示出课程的详细信息),并且根据每一次课程的上课时间和地点,绘制这次课程四个方向的依赖,达到准确的显示效果。

读取课程数量后动态添加Botton简单,但是添加四个方向的依赖就不简单了,可以去开发者平台上看一下ConstraintLayout的接口,确实是为可视化界面设计而生,代码方法对人不太友好,之后在网上找到了一个大佬写好的工具类,然后自己做了更新和修改,使其更符合Android X的特性

工具类:

import android.os.Build;
import android.transition.TransitionManager;
import androidx.annotation.IdRes;
import androidx.annotation.RequiresApi;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;

/**
 * 用于修改ConstraintLayout布局中的控件的依赖关系
 * Created by xiaolei on 2017/9/8.
 * Update by cimo on 2020/4/18
 * 添加了End_to_Start_of/Start_to_End_of/Start_to_Start_of/End_to_End_of关系
 * 添加了setWidthAndHeight方法设置控件高度和宽度
 * 
 * 备注:动态生成的控件,请使用这个工具类中的setWidth(),setHeight()方法来修改其大小
 */

public class ConstraintUtil {
    private ConstraintLayout constraintLayout;
    private ConstraintBegin begin;
    private ConstraintSet applyConstraintSet = new ConstraintSet();
    private ConstraintSet resetConstraintSet = new ConstraintSet();

    public ConstraintUtil(ConstraintLayout constraintLayout) {
        this.constraintLayout = constraintLayout;
        resetConstraintSet.clone(constraintLayout);
    }

    /**
     * 开始修改
     *
     * @return
     */
    public ConstraintBegin begin() {
        synchronized (ConstraintBegin.class) {
            if (begin == null) {
                begin = new ConstraintBegin();
            }
        }
        applyConstraintSet.clone(constraintLayout);
        return begin;
    }

    /**
     * 带动画的修改
     *
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public ConstraintBegin beginWithAnim() {
        TransitionManager.beginDelayedTransition(constraintLayout);
        return begin();
    }

    /**
     * 重置依赖
     */
    public void reSet() {
        resetConstraintSet.applyTo(constraintLayout);
    }

    /**
     * 带动画的重置
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void reSetWidthAnim() {
        TransitionManager.beginDelayedTransition(constraintLayout);
        resetConstraintSet.applyTo(constraintLayout);
    }

    public class ConstraintBegin {
        /**
         * 清除某个空间的关系
         * 注意:这里不仅仅会清除关系,还会清除对应控件的宽高为 w:0,h:0
         *
         * @param viewIds
         * @return
         */
        public ConstraintBegin clear(@IdRes int... viewIds) {
            for (int viewId : viewIds) {
                applyConstraintSet.clear(viewId);
            }
            return this;
        }

        /**
         * 清除某个控件的,某个关系
         *
         * @param viewId
         * @param anchor
         * @return
         */
        public ConstraintBegin clear(int viewId, int anchor) {
            applyConstraintSet.clear(viewId, anchor);
            return this;
        }

        /**
         * 为某个控件设置 margin
         *
         * @param viewId 某个控件ID
         * @param left   marginLeft
         * @param top    marginTop
         * @param right  marginRight
         * @param bottom marginBottom
         * @return
         */
        public ConstraintBegin setMargin(@IdRes int viewId, int left, int top, int right, int bottom) {
            setMarginLeft(viewId, left);
            setMarginTop(viewId, top);
            setMarginRight(viewId, right);
            setMarginBottom(viewId, bottom);
            return this;
        }

        /**
         * 为某个控件设置 marginLeft
         *
         * @param viewId 某个控件ID
         * @param left   marginLeft
         * @return
         */
        public ConstraintBegin setMarginLeft(@IdRes int viewId, int left) {
            applyConstraintSet.setMargin(viewId, ConstraintSet.LEFT, left);
            return this;
        }

        /**
         * 为某个控件设置 marginRight
         *
         * @param viewId 某个控件ID
         * @param right  marginRight
         * @return
         */
        public ConstraintBegin setMarginRight(@IdRes int viewId, int right) {
            applyConstraintSet.setMargin(viewId, ConstraintSet.RIGHT, right);
            return this;
        }

        /**
         * 为某个控件设置 marginTop
         *
         * @param viewId 某个控件ID
         * @param top    marginTop
         * @return
         */
        public ConstraintBegin setMarginTop(@IdRes int viewId, int top) {
            applyConstraintSet.setMargin(viewId, ConstraintSet.TOP, top);
            return this;
        }

        /**
         * 为某个控件设置marginBottom
         *
         * @param viewId 某个控件ID
         * @param bottom marginBottom
         * @return
         */
        public ConstraintBegin setMarginBottom(@IdRes int viewId, int bottom) {
            applyConstraintSet.setMargin(viewId, ConstraintSet.BOTTOM, bottom);
            return this;
        }

        /**
         * 为某个控件设置关联关系 End_to_Start_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin End_toStartof(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.END, endId, ConstraintSet.START);
            return this;
        }

        /**
         * 为某个控件设置关联关系 Start_to_End_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Start_toEndof(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.START, endId, ConstraintSet.END);
            return this;
        }

        /**
         * 为某个控件设置关联关系 Start_to_Start_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Start_toStartof(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.START, endId, ConstraintSet.START);
            return this;
        }

        /**
         * 为某个控件设置关联关系 End_to_End_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin End_to_End_of(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.END, endId, ConstraintSet.END);
            return this;
        }

        /**
         * 为某个控件设置关联关系 left_to_left_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Left_toLeftOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.LEFT, endId, ConstraintSet.LEFT);
            return this;
        }

        /**
         * 为某个控件设置关联关系 left_to_right_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Left_toRightOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.LEFT, endId, ConstraintSet.RIGHT);
            return this;
        }

        /**
         * 为某个控件设置关联关系 top_to_top_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Top_toTopOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.TOP, endId, ConstraintSet.TOP);
            return this;
        }

        /**
         * 为某个控件设置关联关系 top_to_bottom_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Top_toBottomOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.TOP, endId, ConstraintSet.BOTTOM);
            return this;
        }

        /**
         * 为某个控件设置关联关系 right_to_left_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Right_toLeftOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.RIGHT, endId, ConstraintSet.LEFT);
            return this;
        }

        /**
         * 为某个控件设置关联关系 right_to_right_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Right_toRightOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.RIGHT, endId, ConstraintSet.RIGHT);
            return this;
        }

        /**
         * 为某个控件设置关联关系 bottom_to_bottom_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Bottom_toBottomOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.BOTTOM, endId, ConstraintSet.BOTTOM);
            return this;
        }

        /**
         * 为某个控件设置关联关系 bottom_to_top_of
         *
         * @param startId
         * @param endId
         * @return
         */
        public ConstraintBegin Bottom_toTopOf(@IdRes int startId, @IdRes int endId) {
            applyConstraintSet.connect(startId, ConstraintSet.BOTTOM, endId, ConstraintSet.TOP);
            return this;
        }

        /**
         * 为某个控件设置宽度
         *
         * @param viewId
         * @param width
         * @return
         */
        public ConstraintBegin setWidth(@IdRes int viewId, int width) {
            applyConstraintSet.constrainWidth(viewId, width);
            return this;
        }

        /**
         * 某个控件设置高度
         *
         * @param viewId
         * @param height
         * @return
         */
        public ConstraintBegin setHeight(@IdRes int viewId, int height) {
            applyConstraintSet.constrainHeight(viewId, height);
            return this;
        }

        /**
         * 某个控件设置宽度和高度
         *
         * @param viewId
         * @param height
         * @return
         */
        public ConstraintBegin setWidthAndHeight(@IdRes int viewId, int height, int width) {
            applyConstraintSet.constrainHeight(viewId, height);
            applyConstraintSet.constrainWidth(viewId, width);
            return this;
        }

        /**
         * 提交应用生效
         */
        public void commit() {
            applyConstraintSet.applyTo(constraintLayout);
        }

    }
}

使用方法( 以我的课程表实现为基础 ):

{
	//获取基础布局,比如这里,我要在id为myScheduleConstraintLayout的布局上进行绘制
	ConstraintLayout constraintLayout = binding.myScheduleConstraintLayout;
	
	//根据classItem中的课程信息创建带有课程信息的button按钮
	MaterialButton button = createClassButton(classItem);
	
	//将带有课程信息的button按钮加入到基础文件中(这时候只是加入到布局中,并没有绘制)
	constraintLayout.addView(button);
	
	//获取添加单次课元素后的constraintLayout布局,并生成ConstraintUtil绘制工具对象: drawer
	ConstraintLayout constraintLayoutNew = binding.myScheduleConstraintLayout;
	ConstraintUtil constraintUtilNew = new ConstraintUtil(constraintLayoutNew);
	ConstraintUtil.ConstraintBegin drawer = constraintUtilNew.beginWithAnim();
	
	//绘制刚刚加入的button按钮,设置高度和宽度为0,
	//为button和辅助线guideline添加Start_toStartof和End_toStartof依赖
	drawer.setWidthAndHeight(button.getId(),0,0);
	drawer.Start_toStartof(button.getId(),R.id.guideline_r6);
	drawer.End_toStartof(button.getId(),R.id.guideline_r7);

	//绘制结束后记得提交绘制结果
	drawer.commit();
	
}

看一下效果:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值