Android中如何将子View的坐标转换为父View的坐标

最近打算照着Android的Launcher2源码写一个精简的带有拖动功能的Launcher。在分析DragLayer类的时候发现了一个有趣方法——getDescendantCoordRelativeToSelf。通过一下两篇文章的介绍和自己的实验,总算是弄清楚了该方法的原理。

http://blog.csdn.net/hahajluzxb/article/details/8165258

http://www.cnblogs.com/platte/p/3534279.html

  下面主要分析一下代码的原理:

  首先需要知道的是,一般的坐标变换transform,包含了:平移translate,缩放scale,旋转rotate等。坐标变换改变的是坐标系,而点的坐标值是不会改变的(除非你主动去改变它),但是点是在坐标系上进行绘制的。坐标系的改变,将使得点的绘制发生改变。

  接下来是代码的分析,


/**
     *
     * @param descendant 子View
     * @param coord 子View中的某点的坐标,同时该方法返回时coord转换为在最顶层ParentView坐标系下的坐标
     * @return 返回descendant相对于顶层ParentView的缩放值
     */
    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
        float scale = 1.0f;
        
        //(coord[0],coord[1])分别是子View中所要转换的点的(x,y)坐标
        float[] pt = {coord[0], coord[1]};
        
        //子View由于旋转缩放等操作改变了子View的坐标系,这些变化反映在子View对应的Matrix上,
        //getMatrix()方法获得子View的Matrix。而mapPoints方法则可以得到在初始的坐标系下pt点的坐标
        descendant.getMatrix().mapPoints(pt);
        //计算子View x轴的缩放值
        scale *= descendant.getScaleX();
        
        //在对子View变换时,经过我的实验发现子View的Left,Right,Top,Bottom是不变的
        //因此下面两行可以计算出descendant中的点在其父View坐标系下的坐标
        pt[0] += descendant.getLeft();
        pt[1] += descendant.getTop();
        
        //通过下面的循环,递归的一层一层计算出descendant中的点在最顶层View也就是DragLayer坐标系下的坐标值
        //和x轴的总的缩放值
        ViewParent viewParent = descendant.getParent();
        while (viewParent instanceof View && viewParent != this) {
            final View view = (View)viewParent;
            view.getMatrix().mapPoints(pt);
            scale *= view.getScaleX();
            pt[0] += view.getLeft() - view.getScrollX();
            pt[1] += view.getTop() - view.getScrollY();
            viewParent = view.getParent();
        }
        
        //返回结果
        coord[0] = (int) Math.round(pt[0]);
        coord[1] = (int) Math.round(pt[1]);
        return scale;
    }





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小涵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值