騰訊新聞的橫向和縱向拖動
素材清單
無
涉及的技能
- 動態面板的疊加嵌套
- 交互事件:OnDragStart,OnDrag,OnDragDrop,This.x,This.y,DragX,DragY。
案例效果
本例模擬騰訊新聞的手勢滑動效果,橫向滑動屏幕切換新聞頻道,縱向滑動屏幕查看頻道內的新聞列表。
移動鏈接如下:
橫向和縱向拖拽
橫向滑動屏幕,在要聞、視頻等頻道進行切換,縱向滑動時,向下滑動到頂端和向上滑動到底端都有盡頭,切換頻道時橫向滑動超過一半就自動滑過去,不足一半恢復當前頻道。
簡明步驟
- 主界面布局。
- 添加第二層負責拖拽功能的動態面板及其頻道內容。
- 判斷和確定拖拽方向。
- 橫向縱向拖拽頻道列表。
- 拖拽結束的交互優化。
具體步驟及說明
1. 主界面布局。
1.新建一個項目,命名為“橫向和縱向滑動綜合
”。
2.向默認的home頁添加一個動態面板,參數如下:
| 名稱 | 類型 | 坐標 | 尺寸 |
| ------------ | ------------- | ------------ |
| dpMain
| Dynamic Panel | 0,0
| 414,736
|
將其鎖定方便操作其他控件。
3.添加5個 Label 到主屏上方作為頻道名,分別命名為要聞
,視頻
,科技
等。使用上對齊
和水平分布
功能進行對齊操作。
4.在這幾個 label 下面動態面板上面放置一個白色矩形作為導航欄背景,坐標和尺寸為(0,0,414,70)
。通過widget manager 調整控件之間的層次結構如圖, 圖中的 navi 就是導航欄背景矩形。
5.同樣的方法在主屏下方制作 Tab 欄新聞
和關心
,Tab 欄坐標是(0,736-70,414,70)
。
將字體調整到18的大小,所有控件鎖定,主界面制作完畢。
2. 添加第二層負責拖拽功能的動態面板。
1.添加動態面板到dpMain
的state1中,作為拖拽內容的容器,它的高是主屏幕的高度減去導航欄和 tab 欄的高度70,參數如下:
| 名稱 | 類型 | 坐標 | 尺寸 |
| ------------ | ------------- | ------------ |
| dpDrag
| Dynamic Panel | 0,70
| 414,736-70-70
|
2.雙擊dpDrag
的 state1,添加2個動態面板,參數如下:
| 名稱 | 類型 | 坐標 | 尺寸 |
| ------------ | ------------- | ------------ |
| dpNews
| Dynamic Panel | 0,0
| 414,1000
|
| 名稱 | 類型 | 坐標 | 尺寸 |
| ------------ | ------------- | ------------ |
| dpVideo
| Dynamic Panel | 414,0
| 414,1000
|
dpNews的高度需要超過主屏高度來實現縱向拖動顯示新聞列表,這里暫時設置成1000。
dpVideo的 x 坐標設置成主屏寬度414,這樣正好和dpNews連接并列橫置,高度同dpNews。
3.分別制作新聞和視頻板塊的內容。
分別雙擊dpNews
和dpVideo
,進入他們的 state1,上方放置圖片作為新聞圖片,下方放置新聞列表,參數自定,添加一個 label 新聞圖片
提示一下現在是在哪個頻道,效果大致如圖即可。
4.widget manager 的結構如下圖:
至此,界面設計完畢,接下來添加交互。
3. 判斷和確定拖拽方向。
1.判斷用戶是橫向還是縱向拖動。
參數 DragX 用于記錄橫向的拖拽距離,DragY 用于記錄縱向的拖拽距離,如果DragX > DragY,就是說用戶橫向的拖拽距離大于縱向拖拽的距離,即用戶是在橫向拖拽。
向左拖拽,DragX是負值,向右拖拽,DragX是正值。向上拖拽,DragY 是負值,向下拖拽,DragY 是正值。所以,比較是時候是絕對值進行比較。
2.通過 OnDragStart 事件來判斷拖拽方向。
OnDragStart事件是在用戶的拖拽行為已經開始進行了,但物體還沒有跟隨手指開始移動時發生的動作。
雙擊dpDrag
的 state1,單擊選中dpNews
的 state1,雙擊OnDragStart
事件,在打開的窗口中點擊add condition
添加條件判斷。
第一個下拉菜單選擇value
,點擊fx
,在出現的新窗口中,點擊insert variable or function
,尋找并選擇 abs 函數,計算絕對值。將括號中的x
替換成DragX
,點擊OK
。結果如下圖:
在中間條件選擇中選擇is greater than
,在下一個fx
中,參考前一個fx
,設置成[[math.abs(dragy)]]
,也可以自行打字輸入。最后結果如下圖:
3.創建一個自定義變量dragDirection
,用來作為拖拽方向的標志,如果是橫向拖動,就設置為horizontal
,如果是縱向的,就設置為vertical
。
在用例編輯器中,選中set variable value
,在右側找到add variable
,在彈出的窗口中找到加號添加自定義變量,命名為dragDirection
,確定后,在用例編輯器中右側窗口選中它打鉤。在下方的set variable to
中的文本框中手動輸入horizontal
,確定。
OnDragStart 事件中的用例顯示如下圖:
4.雙擊OnDragStart
,添加case2。
case 2會自動設置條件為else if true
,也就是說 case 1不成立就會執行 case 2的情況。
本例中,case 1不成立,就是說用戶在做縱向的拖拽,導致了 DragX 小于 DragX
這時應將dragDirection
變量設置成vertical
。方法參考上面。最后結果如下圖:
4. 橫向縱向拖拽頻道列表。
1.當 DragY 大于0,向下拖拽時,如果dpNews
的 y 坐標大于0了,代表我們已經拖拽到動態面板的最頂部,就不能繼續向下拖拽了。
在dpNews
的 state1中,繼續編輯用例,添加條件。這里用到了2個條件同時滿足,需要在編輯第一個關于 DragY 的條件后,點擊加號添加第二個關于 This.y 的條件,結果如下圖:
2.當 DragY 小于0,向上拖拽時,如果dpNews
的 y 坐標小于736(主屏高度)-70(導航欄高度)-70(tab 欄高度)-1000(新聞內容的動態面板高度)了,結果是-404,即我們還可以向上拖拽的距離只有404,這時我們已經拖拽到動態面板的最底部,就不能繼續向上拖拽了。
在dpNews
的 state1中,繼續編輯用例,添加此條件case 2
,方法同上,結果如圖:
3.當 DragX 大于0,向右拖拽時,如果dpNews
的 x 坐標大于0了,代表我們已經拖拽到動態面板的最左邊,就不能繼續向右拖拽了。
在dpNews
的 state1中,繼續編輯用例,添加此條件case 3
,方法同上,結果如圖:
4.只要dragDirection
等于horizontal
,我們就讓新聞頻道和視頻頻道一起橫向移動。
在dpNews
的 state1中,繼續編輯用例,添加此條件case 4
。
在左側窗口中添加 actions,單擊選擇move
,在右側的configure actions
窗口中,在兩個新聞的動態面板前打鉤選中,在下面的參數 move 中選擇with drag x
進行橫向拖拽。結果如圖:
5.最后一個 case 5
直接添加縱向移動,結果如圖:
6.預覽效果。這時候要聞頻道可以上下拖拽,不能向右,可以向左拖拽出視頻頻道,但不流暢。且在視頻頻道無法拖回到要聞頻道。我們應該加上視頻的向右拖拽交互。
參考上面的操作,我們給dpVideo
也添加類似的交互用例。這個操作可以使用用例的復制功能。我們選中dpNews
,在它的交互用例中選中OnDragStart
,右邊有個小三角,選擇里面的copy
命令。
再回來選中dpVideo
,在右側的小三角中選擇paste
,即可復制交互。可以同樣的方案復制OnDrag
事件中的交互用例,稍作修改,只有case 5
不同,結果如下圖:
5. 拖拽結束的交互優化。
1.在拖拽結束的時候要判斷一下是哪個頻道在當前屏幕上,如果各有半個屏幕,我們要自動完成拖拽,呈現整個頻道頁面。
我們來添加OnDragStop
事件。如果頻道移動超過半個屏幕即414/2的空間,拖拽動作就算停止了,我們也要講下一個頻道移動到屏幕上,同時將移動出去的頻道 y 坐標設置為0作為復位,下一次再看到它時還是初始的第一條新聞紀錄。
添加dpNews
的用例過程如下圖:
第一個
move
使用了500ms 的線性過度來平移兩個頻道,第二個
move是第一個
move`動作后,不用過度動畫直接將新聞頻道定位在坐標(-414,0),作為復位的動作
2.如果沒有移動到屏幕一半的情況下,我們應該對屏幕位置進行復位,彈回到剛才的頻道。用例設置的最終結果如圖:
3.同法設置 dpVideo 的用例設置最終結果如圖: