您的当前位置:首页正文

Android RatioConstraintLayout工具类

2024-12-01 来源:个人技术集锦
自定义布局文件
/**
 * 可以设置自身宽高比的ConstraintLayout。
 * 宽高比的确定是根据横竖屏确定的,如果是横屏的话就根据高度和比例确定宽度,如果是竖屏就根据宽度和比例确定高度。
 * 默认有点击缩放效果,可以设置是否有缩放效果。
 */
public class RatioConstraintLayout extends ConstraintLayout {

    private boolean canScale;

    private double mHeightRatio;

    private double mWidthRatio;

    public RatioConstraintLayout(Context context) {
        this(context, null);
    }

    public RatioConstraintLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RatioConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RatioConstraintLayout);
        canScale = ta.getBoolean(R.styleable.RatioConstraintLayout_canScale, true);
        String ratio = ta.getString(R.styleable.RatioConstraintLayout_wh_ratio);
        if (!TextUtils.isEmpty(ratio)) {
            String[] wh = ratio.split("\\:");
            if (wh.length == 2) {
                mWidthRatio = Double.valueOf(wh[0]);
                mHeightRatio = Double.valueOf(wh[1]);
            }
        }
        ta.recycle();
    }

    @Override
    public ViewGroup.LayoutParams getLayoutParams() {
        ViewGroup.LayoutParams layoutParams = super.getLayoutParams();
//        //获取屏幕方向
//        int orientation = getContext().getResources().getConfiguration().orientation;
//        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
//            layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
//            layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
//        } else {
//            layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
//            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
//        }
        return layoutParams;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));

        int[] specs = new int[2];
        if (mWidthRatio == 0 || mHeightRatio == 0) {
            specs[0] = widthMeasureSpec;
            specs[1] = heightMeasureSpec;
        }

        //获取屏幕方向
        int orientation = getContext().getResources().getConfiguration().orientation;
        //根据横竖屏来确定宽高
        //横屏
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            int measuredHeight = this.getMeasuredHeight();
            int width = (int) (measuredHeight * (mWidthRatio / mHeightRatio));
            specs[0] = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
            specs[1] = heightMeasureSpec;
        } else {
            int measuredWidth = this.getMeasuredWidth();
            int height = (int) (measuredWidth * (mHeightRatio / mWidthRatio));
            specs[0] = widthMeasureSpec;
            specs[1] = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        }

        super.onMeasure(specs[0], specs[1]);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                startScalePress(this);
                break;
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                startScaleRelease(this);
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    public static void startScale(View view, float scaleValue, float defaultScale, int duration) {
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animationScaleX = ObjectAnimator.ofFloat(view, "scaleX", scaleValue, defaultScale);
        ObjectAnimator animationScaleY = ObjectAnimator.ofFloat(view, "scaleY", scaleValue, defaultScale);
        animationScaleX.setDuration(duration);
        animationScaleY.setDuration(duration);
        animatorSet.playTogether(animationScaleX, animationScaleY);
        animatorSet.start();
    }

    public static void startScalePress(View view) {
        startScale(view, 1F, 0.92F, 250);
    }

    public static void startScaleRelease(View view) {
        startScale(view, 0.92F, 1F, 250);
    }

}

自定义布局属性attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--动画开关-->
    <attr name="canScale" format="boolean" />
    <!--宽高比-->
    <attr name="wh_ratio" format="string" />

    <declare-styleable name="RatioConstraintLayout">
        <attr name="canScale" />
        <attr name="wh_ratio" />
    </declare-styleable>
</resources>
测试使用的布局
<com.kotlin.myapplication.RatioConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
			<!--竖屏就根据宽度和比例确定高度-->
            android:layout_width="@dimen/x200"
            <!--横屏就根据高度和比例确定宽度-->
            android:layout_height="@dimen/x500"
            app:canScale="true"
            app:wh_ratio="0.618:1"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="MissingConstraints">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@color/colorAccent" />

        </com.kotlin.myapplication.RatioConstraintLayout>
运行效果:

竖屏:

显示全文