元件内建拖放(drag & drop)效果

不论是自己实作拖放效果,或是使用 JavaScript 函式库,都需要花点心思才能做出,如果不熟 JavaScript 的人还是挺麻烦。ZK 所有元件都内建拖放效果,只要启用即可。而拖放之後实际要产生什麽行为仍可以 Java 实作。

如何使用拖放效果

例如我要让一个表格中的每一列可以被拖放改变顺序。

https://ithelp.ithome.com.tw/upload/images/20211004/20050621dbURADdj8X.jpg

启用拖放效果

启用完後,滑鼠拖拉元件就会看到如上的元件被拖动的残影效果。

<listbox width="40%" apply="quickstart.DragDropComposer">
...
    <listitem draggable="true" droppable="true" >
        <listcell label="United States"/>
        <listcell label="5,093"/>
        <listcell label="19.39%"/>
    </listitem>
  • 在每个 <listitem> 上都设定 draggable="true",启用该元件可以被拖拉
  • droppable="true" 让使用者可以把元件「拖放」到 <listitem>上。

改变元件顺序

但光是启用只是拥有浏览器上可以看到的拖放视觉效果,实际上并不会改变每列顺序,这必须要透过 Java 来控制元件来改变顺序

public class DragDropComposer extends SelectorComposer<Component> {
    @Listen("onDrop = listitem")
    public void move(DropEvent event){
        Listitem listitem = (Listitem)event.getTarget();
        listitem.getParent().insertBefore(event.getDragged(), listitem);
    }
}
  • 当放下元件到 <listitem> 上时,会发出 onDrop 事件,因此我要注册对应的倾听器来变更顺序
  • event.getTarget() 传回事件发生的元件,也就是丢下去的目的元件。例如我把 France 拖放到 Germany,那 target 就是 Gerymany。 event.getDragged() 就是被拖的元件,也就是 France。
  • insertBefore(): 我把 France 插入到 Germany 前面来改变顺序。

一次拖放多个元件

可以启用 Listbox 的多选功能来达到一次拖拉多个元件的效果

https://ithelp.ithome.com.tw/upload/images/20211004/20050621H3Vgs6MWR2.jpg

<listbox multiple="true" width="50%">
    <listitem draggable="true" label="Matthew"/>
    <listitem draggable="true" label="Mark"/>
    <listitem draggable="true" label="Lucas"/>
    <listitem draggable="true" label="John"/>
</listbox>
<div droppable="true" sclass="box" height="150px" onDrop="onDrop(event)">
    丢到此区
</div>
  • multiple="true" 启用多选功能

实作倾听器

public void onDrop(DropEvent evt) {
    Listitem li = (Listitem)evt.getDragged();
    if (li.isSelected()) {
        Set selected = ((Listitem)evt.getDragged()).getListbox().getSelectedItems();
        //处理整批
    } else {
        li.setSelected(true);
       //处理单一个
    }

    Clients.showNotification("select " + selected.size());
}
  • 从 listitem 可以取得 Listbox 参照,再取得所有选择的 items (getSelectedItems()

区隔可拖放的目标

有时我希望能指定拖放特定的元件,例如一个区域只能放 email,另一个区域只能放入 contact:

https://ithelp.ithome.com.tw/upload/images/20211004/20050621Kg0fgjxu80.jpg

指定拖拉类别

draggable 上自定一个字串作为其「类别」

<listbox multiple="true" width="50%">
    <listitem draggable="email" label="Email 1"/>
    <listitem draggable="email" label="Email 2"/>
    <listitem draggable="contact" label="Contact 1"/>
    <listitem draggable="contact" label="Contact 2"/>
</listbox>

然後 droppable 指定同样的「类别」。如果你拖放的元件类别不同,ZK 会显示像上图那样的「禁止」图示,告知使用者无法放入,即便你拖放了,也不会产生 onDrop 事件。

<div sclass="box" height="50px" droppable="email" onDrop="accept(event)" >
    只接受 email
</div>
  • 当你拖放同样类别的元件时,才会呼叫 onDrop 倾听器

以上介绍拖拉的基本用法,如果对 JavaScript 熟悉的人甚至可以客制化拖拉效果,请参考 ZK Client-side Reference


<<:  Android Studio初学笔记-Day19-SharedPreferences

>>:  DAY22-导览设计之Sidebar

Day 02:二分搜寻(binary search)

第一个演算法既是叫搜寻,那我们先想像一些生活中找东西的情境。 如果有一叠照座号排好的作业,要找出28...

使用Ajax取得查询与筛选结果

data: { "key": $("#SearchKeyInput&...

[Day_22]函式与递回_(1)

函式的定义、传回值与呼叫 自订函式需要包含两个部分,分别式「函式的定义」与「函式的呼叫」。「函式的定...

Day 4 Swift语法-基础篇(2/5)-Collection Types

接下来继续我们的基本语法,今天讲的是集合型别,集合型别常常在我们程序码里面使用,我们来看一下,有什麽...

Day 24 - [Android APP] 02-界面设计

昨天讲完架构面,今天不那麽技术,来讲界面设计。 画面设计上由於介面是设计给长者使用,因此字型较大。 ...