[android]对齐方式准则/对齐在 GUI 生成器中发现算法

标签: Java Android
发布时间: 2017/3/19 18:16:33
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我试着来实现类似于许多 GUI 生成器的行为︰ 当前被拖动的组件应在与另一个组件的对齐方式对齐,如果他们几乎在水平或垂直的线,与它。 我目前的做法是组件的,遍历所有放置组件并检查是否任何的四个边 (几乎) 与被拖动边缘对齐︰

for (v in rootView.relativeLayout.children()) {
    // x
    val left = event.rawX - dXInit
    val right = event.rawX - dXInit + view.width
    val leftEdgeRange = (v.leftEdge() - 50 .. v.leftEdge() + 50)
    val rightEdgeRange = (v.rightEdge() - 50 .. v.rightEdge() + 50)

    when (left) {
        in leftEdgeRange -> x = v.leftEdge()
        in rightEdgeRange -> x = v.rightEdge()
    }
    when (right) {
        in leftEdgeRange -> x = v.leftEdge() - view.width
        in rightEdgeRange -> x = v.rightEdge() - view.width
    }
    // y
    val top = event.rawY - dYInit
    val bottom = event.rawY - dYInit + view.height
    val topEdgeRange = (v.topEdge() - 50 .. v.topEdge() + 50)
    val bottomEdgeRange = (v.bottomEdge() - 50 .. v.bottomEdge() + 50)

    when (top) {
        in topEdgeRange -> y = v.topEdge()
        in bottomEdgeRange -> y = v.bottomEdge()
    }
    when (bottom) {
        in topEdgeRange -> y = v.topEdge() - view.height
        in bottomEdgeRange -> y = v.bottomEdge() - view.height
    }
}

fun View.topEdge() = y
fun View.bottomEdge() = y + height
fun View.leftEdge() = x
fun View.rightEdge() = x + width

但这似乎效率不高,因为这就所谓 onTouch ,所以这个循环相当经常运行。有更好的方法吗?一般或 Java 答案是欢迎的。

解决方法 1:

更有效的方法就是减少o (n)循环,遍历到的所有意见O ( log n)搜索最近边缘像一些排序代表 TreeSet TreeMap ,哪些是平衡二叉查找树。这,当然,需要你来存储四个单独排序的表达式的每个 leftEdgerightEdgetopEdge ,和 bottomEdge

一个简单的例子就是 (只显示 leftEdge ,其余的都是类似):

val viewsByLeftEdge = TreeMap<Int, View>()

若要添加 view 成地图,只需使用︰

viewsByLeftEdge[view.leftEdge()] = view

(注意,是否几个视图具有相同的左边的缘值,只有最后一个将存储在这张地图)

在那之后,而不是遍历所有视图,你可以找到最近的左边的缘到给定 left 协调︰

val floorL = viewsByLeftEdge.floorKey(left)
val ceilingL = viewsByLeftEdge.ceilingKey(left)
val nearestL = when {
    floorL == null -> ceilingL
    ceilingL == null -> floorL
    ceilingL - left < left - floorL -> ceilingL
    else -> floorL
}

if (nearestL in left - 50 .. left + 50)
    x = nearestL

在这里, .floorKey(x) 返回小于或等于的地图中的最高的边缘坐标 x ,或 null 如果没有这种坐标。同样, .ceilingKey(x) 返回最低协调是更大的地图中, x ,或 null

这需要O ( log n) time 和将会更快比遍历任何重大的次数的所有视图。如果你不需要得到 view 通过其边缘,简化代码替换 TreeMap<Int, View>TreeSet<Int> (函数然后是 floor(x)ceiling(x)

它是由你在你的代码中放置的地图,在里面放满你 View s 和撰写的功能会更好的适应您的代码设计的四个边。

赞助商