自定义各种角度的Framlayout

本文介绍了一个自定义的Android布局组件RotateLayout,该组件允许其子视图进行旋转显示。通过属性设置旋转角度,并在测量、布局及绘制过程中考虑旋转的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.neldtv.mips.utils;

import com.neldtv.mips.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

public class RotateLayout extends ViewGroup {

    private static final String TAG = "RotateLayout";
    public static class LayoutParams extends ViewGroup.LayoutParams {

        public int angle;

        public LayoutParams(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RotateLayout_Layout);
            angle = a.getInt(R.styleable.RotateLayout_Layout_layout_angle, 0);
            a.recycle();
        }

        public LayoutParams(ViewGroup.LayoutParams layoutParams)
        {
            super(layoutParams);
        }

    }

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

    public RotateLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        setWillNotDraw(false);
    }

    public View getView()
    {
        return getChildAt(0);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {

        final View view = getView();
        if (view != null)
        {
            final LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
            if (angle != layoutParams.angle)
            {
                angle = layoutParams.angle;
                angleChanged = true;
            }

            if(angleOfSet != -1)
            {
                angle = angleOfSet;
                angleChanged = true;
            }

            if (Math.abs(angle % 180) == 90)
            {
                measureChild(view, heightMeasureSpec, widthMeasureSpec);
                setMeasuredDimension(
                        resolveSize(view.getMeasuredHeight(), widthMeasureSpec),
                        resolveSize(view.getMeasuredWidth(), heightMeasureSpec));
            }
            else
            {
                measureChild(view, widthMeasureSpec, heightMeasureSpec);
                setMeasuredDimension(
                        resolveSize(view.getMeasuredWidth(), widthMeasureSpec),
                        resolveSize(view.getMeasuredHeight(), heightMeasureSpec));
                /*setMeasuredDimension(
            			resolveSize(view.getMeasuredWidth(), widthMeasureSpec), 
            			resolveSize(view.getMeasuredHeight() + 90, heightMeasureSpec + 90));*/
            }
        }
        else
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {

        if (angleChanged || changed)
        {
            final RectF layoutRect = tempRectF1;
            final RectF layoutRectRotated = tempRectF2;
            layoutRect.set(0, 0, r - l, b - t);
            rotateMatrix.setRotate(angle, layoutRect.centerX(), layoutRect.centerY());
            rotateMatrix.mapRect(layoutRectRotated, layoutRect);
            layoutRectRotated.round(viewRectRotated);
            angleChanged = false;
        }

        final View view = getView();
        if (view != null)
        {
            view.layout(viewRectRotated.left, viewRectRotated.top, viewRectRotated.right, viewRectRotated.bottom);
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas)
    {

        canvas.save();
        canvas.rotate(-angle, getWidth() / 2f, getHeight() / 2f);
        super.dispatchDraw(canvas);
        canvas.restore();
    }

    @Override
    public ViewParent invalidateChildInParent(int[] location, Rect dirty)
    {

        invalidate();
        return super.invalidateChildInParent(location, dirty);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event)
    {

        viewTouchPoint[0] = event.getX();
        viewTouchPoint[1] = event.getY();

        rotateMatrix.mapPoints(childTouchPoint, viewTouchPoint);

        event.setLocation(childTouchPoint[0], childTouchPoint[1]);
        boolean result = super.dispatchTouchEvent(event);
        event.setLocation(viewTouchPoint[0], viewTouchPoint[1]);

        return result;
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs)
    {

        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams layoutParams)
    {

        return layoutParams instanceof LayoutParams;
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams layoutParams)
    {

        return new LayoutParams(layoutParams);
    }

    public void setAngle(int angleCmd)
    {

        Log.i(TAG, "setAngle: angle = " + angle);
        if(angleCmd != angle)
        {
            this.angleOfSet = angleCmd;
        }
        requestLayout();

    }

    private int angle;

    private final Matrix rotateMatrix = new Matrix();

    private final Rect viewRectRotated = new Rect();

    private final RectF tempRectF1 = new RectF();
    private final RectF tempRectF2 = new RectF();

    private final float[] viewTouchPoint = new float[2];
    private final float[] childTouchPoint = new float[2];

    private boolean angleChanged = true;

    private int angleOfSet = -1;

}





                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值