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度后,恰到好处的成了一个被红色矩形截取得到的我们想要的三角形。
最后补充一下。我们知道,旋转一个图片,无非就是一个图形的所有点绕着旋转中心画圆弧。如下图,旋转中心图示:
在这里插入图片描述

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

posted on 2020-09-07 09:38  莫水千流  阅读(989)  评论(0编辑  收藏  举报