zoukankan      html  css  js  c++  java
  • android layerlist 里面的rotate标签得到三角形原理详解

    在android 中。有各种各样的drawable。其中,比较常用的drawable有一个LayerDrawable,对应的xml标签为layerlist。里面可以按照先后顺序,放置一个个i的item。就像这样:

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item >
        <shape android:shape="rectangle">
            <solid android:color="#ff8800"></solid>
        </shape>
    </item>
        <item >
            <shape android:shape="oval">
                <solid android:color="#ff0088"></solid>
                <corners android:radius="5px"/>
            </shape>
        </item>
    </layer-list>
    

    然后以它为background 应用到view上面,以textview为例,得到的结果是这样。在这里插入图片描述
    这里我设置了textview的宽度与高度都相等,所以显示出了一个正方形里面套了一个圆形。如果宽高改为自适应的话就是长方形加椭圆了。
    下面开始说明我要讨论的重点。之前看到过几篇博客,为了实现提示引导信息,要展示一个提示框,里面还有个小三角形的小尾巴。大概是这个样子。在这里插入图片描述
    这里主要用了layerlist实现了下面那个三角形,然后让这个三角形相对上面的textview做相应的偏移,就达到了以上的效果。其实实现这个效果的方法还有许多种,如.9图片,或者干脆做一个普通的图片,或者通过canvas在画布上面绘制一个Path等。这里咱们就说说用相对简单有效的layerlist怎么实现,以及实现它的原理。
    上面的三角形实现部分代码如下。

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate android:pivotX="135%"
                android:pivotY="15%"
                android:fromDegrees="45">
            <shape android:shape="rectangle">
                <solid android:color="#ff8800"></solid>
            </shape>
        </rotate>
    </item>
    </layer-list>
    

    在这里,你看到了layerlist标签下面只有一个item,没错,因为实现这个效果没有用到层叠。只用一个rotate标签做了旋转操作,里面包裹了一个shape标签,这个shape标签是一个矩形类型的。
    我们观察rotate标签的其他几个属性。感觉到这几个属性莫名其妙。但是确实实现了由矩形旋转成为三角形的效果。为了能弄清问题,我先解释一下具体属性的意思,pivotX,旋转中心的x坐标,用百分比表示,原点在左上角,总的宽高都由具体的view决定。pivotY,旋转中心的y坐标。fromDegrees,要旋转的角度。这里应该注意,相对应的有个toDegree,不过这里用不上。因为这两个属性都是在rotate animation里面能够用上,设置开始旋转的角度,结束旋转的角度,这里,咱们的layerlist是静态的,所以只取得fromDegree就够了,后面跟上要旋转的角度,整数就按照Direction.CW旋转,也就是顺时针旋转,负数就按照Direction.CCW逆时针旋转。
    下面印证一下我们的观点,

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate android:pivotX="50%"
                android:pivotY="50%"
                android:fromDegrees="45">
            <shape android:shape="rectangle">
                <solid android:color="#ff8800"></solid>
            </shape>
        </rotate>
    </item>
    </layer-list>
    

    将旋转中心设置为自己的宽高中心点,由此顺时针旋转45度。将会得到一个这样的图形。
    在这里插入图片描述
    为什么会得到一个正八边形呢?乍一看感觉理解不透,可仔细一想,这不是旋转以后被正方形边界给截取了么?截取了旋转后正方形的四个角,我们看不见边界外面了。不就成了正八边形了么?(其实他是有边界的,边界就是你给这个view指定的宽高所围成的正方形。)
    这里我们清楚了原理,下面我们就按照我们的要求对矩形做旋转吧!要知道,旋转中心也有可能在矩形之外哦,就比如最开始那个倒置的三角形。它的旋转中心超过了它自己的范围。为了达到更好的展示效果,我们用canvas把边框还有旋转中心画出来,让我们有更直观的认识。
    自定义一个view复写onDraw方法,下面只展示onDraw方法里面的代码。
    1,宽高充满全屏,translate canvas 画布圆点。使画出的内容尽量在中间。
    2,画出一个宽高都为300像素的正方形。
    3,再用同样的矩形画在新建的空bitmap上面。然后用Matrix绕旋转中心旋转这个矩形,模拟最开始的,旋转中心,x坐标3001.35=405,y坐标 3000.15=45。顺时针旋转45度。
    4,将这个旋转过后的bitmap画到画布上面看效果。用到
    canvas.drawBitmap(bitmap,matrix,null),最后一个paint参数这里没有用,可传空。

     canvas.translate(500,300);
            Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);
            paint.setColor(Color.rgb(0xff,00,00));
            canvas.drawRect(0,0,300,300,paint);
            Bitmap bitmap=Bitmap.createBitmap(300,300,Bitmap.Config.ARGB_8888);
            Canvas bc=new Canvas(bitmap);
            paint.setColor(Color.rgb(0x00,0x55,00));
            bc.drawRect(0,0,300,300,paint);
            Matrix matrix=new Matrix();
            matrix.setRotate(45,405,45);
            canvas.drawBitmap(bitmap,matrix,null);
            paint.setStrokeWidth(10);
            canvas.drawPoint(405,45,paint);
            paint.setStrokeWidth(1);
            paint.setTextSize(30);
            canvas.drawText("(405,45) 旋转中心,旋转度数 CW 45度",405,45,paint);
            canvas.drawText("(0,0) 原点",0,0,paint);
    

    上面的代码不难理解,运行后得到下面的效果。
    在这里插入图片描述
    看到结果,红的的正方形,绕着旋转中新(405,45)顺时针旋转了45度后,恰到好处的成了一个被红色矩形截取得到的我们想要的三角形。
    最后补充一下。我们知道,旋转一个图片,无非就是一个图形的所有点绕着旋转中心画圆弧。如下图,旋转中心图示:
    在这里插入图片描述

    所以,知道了旋转开始位置,旋转结束位置,这样就变成了求旋转中心的坐标。也就是在前后图片上各区对应的两个点,连接,作垂线。相交的那个点。

  • 相关阅读:
    钉钉内网穿透一键启动cmd脚本
    vscode的开发配置文件
    'scope' is defined but never used解决方法
    微信小程序使用echarts不跟随父元素滑动
    小程序图片开发工具能显示真机调试和体验版不显示
    Web端在线实时聊天,基于WebSocket(前后端分离)
    在vue项目中使用scss,以及vscode适配scss语法(解决使用scss语法编辑器报错)
    自动按需引入组件用不了(Vant)
    npm ERR! Unexpected end of JSON input while parsing near '...'解决方法
    div和img垂直居中的方法
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/13625130.html
Copyright © 2011-2022 走看看