鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

前言

基於安卓平臺的SlidingMenu側滑選單元件(https://github。com/jfeinstein10/SlidingMenu),實現了鴻蒙化遷移和重構,程式碼已經開源到(https://gitee。com/isrc_ohos/sliding-menu_ohos),歡迎各位下載使用並提出寶貴意見!

背景

SlidingMenu_ohos提供了一個側滑選單的導航框架,使選單可以隱藏在手機螢幕的左側、右側或左右兩側。當用戶使用時,透過左滑或者右滑的方式調出,既節省了主螢幕的空間,也方便使用者操作,在很多主流APP中都有廣泛的應用。

效果展示

由於選單從左右兩側調出的顯示效果相似,此處僅以選單從左側調出為例進行效果展示。

元件未啟用時,應用顯示主頁面。單指觸控式螢幕幕左側並逐漸向右滑動,選單頁面逐漸顯示,主頁面逐漸隱藏。向右滑動的距離超過某個閾值時,選單頁面全部顯示,效果如圖1所示。

鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

圖1 選單展示和隱藏效果圖

Sample解析

Sample部分的內容較為簡單,主要包含兩個部分。一是建立SlidingMenu_ohos元件的物件,可根據使用者的實際需求,呼叫Library的介面,對元件的具體屬性進行設定。二是將設定好的元件新增到Ability中。下面將詳細介紹元件的使用方法。

1、匯入SlidingMenu類

import com。jeremyfeinstein。slidingmenu。lib。SlidingMenu;

2、設定Ability的佈局

此佈局用作為主頁面的佈局,在元件隱藏的時候顯示。

DirectionalLayout directionalLayout = (DirectionalLayout)LayoutScatter。getInstance(this)。parse(ResourceTable。Layout_activity_main,null,false);setUIContent(directionalLayout);

3、例項化元件的物件

SlidingMenu slidingMenu = null;try { //初始化SlidingMenu例項 slidingMenu = new SlidingMenu(this);} catch (IOException e) { e。printStackTrace();} catch (NotExistException e) { e。printStackTrace();}

4、設定元件屬性

此步驟可以根據具體需求,設定元件的位置、觸發範圍、佈局、最大寬度等屬性。

//設定選單放置位置slidingMenu。setMode(SlidingMenu。LEFT);//設定元件的觸發範圍slidingMenu。setTouchScale(100); //設定元件的佈局slidingMenu。setMenu(ResourceTable。Layout_layout_left_menu);//設定選單最大寬度slidingMenu。setMenuWidth(800);

5、關聯Ability

attachToAbility()方法是Library提供的重要方法,用於將選單元件關聯到Ability。其引數SLIDING_WINDOW和SLIDING_CONTENT是選單的不同模式,SLIDING_WINDOW模式下的選單包含Title / ActionBar部分,選單需在整個手機頁面上顯示,如圖2所示;SLIDING_CONTENT模式下的選單不包括包含Title / ActionBar部分,選單可以在手機頁面的區域性範圍內顯示,如圖3所示。

try { //關聯Ability,獲取頁面展示根節點 slidingMenu。attachToAbility(directionalLayout,this, SlidingMenu。SLIDING_WINDOW);} catch (NotExistException e) { e。printStackTrace();} catch (WrongTypeException e) { e。printStackTrace();} catch (IOException e) { e。printStackTrace();}

鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

圖2 SLIDING_WINDOW展示效果圖

鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

圖3 SLIDING_CONTENT展示效果圖

Library解析

Library的工程結構如下圖所示,CustomViewAbove表示主頁面,CustomViewBehind表示選單頁面,SlidingMenu主要用於控制主頁面位於選單頁面的上方,還可以設定選單的寬度、觸發範圍、顯示模式等屬性。為了方便解釋,以下均以手指從左側觸控式螢幕幕並向右滑動為例進行講解,選單均採用SLIDING_WINDOW的顯示模式。

鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

圖4 Library的工程結構

1、CustomViewAbove主頁面

CustomViewAbove需要監聽觸控、移動、抬起和取消等Touch事件,並記錄手指滑動的距離和速度。

(1)對Touch事件的處理

Touch事件決定了選單的顯示、移動和隱藏。例如:在選單的觸發範圍內,手指向右滑動(POINT_MOVE)時,選單會跟隨滑動到手指所在位置。手指抬起(PRIMARY_POINT_UP)或者取消滑動(CANCEL)時,會依據手指滑動的距離和速度決定選單頁面的下一狀態是全部隱藏還是全部顯示。

switch (action) { //按下 case TouchEvent。PRIMARY_POINT_DOWN: 。。。。。 mInitialMotionX=mLastMotionX=ev。getPointerPosition(mActivePointerId)。getX(); break; //滑動 case TouchEvent。POINT_MOVE: …… //選單滑動到此時手指所在位置(x) left_scrollto(x); break; //抬起 case TouchEvent。PRIMARY_POINT_UP: …… //獲得選單的下一狀態(全屏顯示或者全部隱藏) int nextPage = determineTargetPage(pageOffset, initialVelocity,totalDelta); //設定選單的下一狀態 setCurrentItemInternal(nextPage,initialVelocity); …… endDrag(); break; //取消 case TouchEvent。CANCEL: …… //根據選單當前狀態mCurItem設定選單下一狀態 setCurrentItemInternal(mCurItem); //結束拖動 endDrag(); break; }

(2)對滑動的距離和速度的處理

手指抬起時,滑動的速度和距離分別大於最小滑動速度和最小移動距離,判定此時的操作為快速拖動,選單立即彈出並全部顯示,如圖5所示。

private int determineTargetPage(float pageOffset, int velocity, int deltaX) { //獲得當前選單狀態,0:左側選單正在展示,1:選單隱藏,2:右側選單正在展示 int targetPage = getCurrentItem(); //針對快速拖動的判斷 if (Math。abs(deltaX) > mFlingDistance && Math。abs(velocity) > mMinimumVelocity) { if (velocity > 0 && deltaX > 0) { targetPage -= 1; } else if (velocity < 0 && deltaX < 0){ targetPage += 1; } }}

鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

圖5 快速拖動效果圖

當手指抬起並且不滿足快速拖動標準時,需要根據滑動距離判斷選單的隱藏或顯示。若選單已展開的部分超過自身寬度的1/2,選單立即彈出全部顯示,,效果圖如圖1所示;若不足自身寬度的1/2,則立即彈回全部隱藏,效果圖如圖6所示。

//獲得當前選單狀態,0:左側選單正在展示,1:選單隱藏,2:右側選單正在展示switch (mCurItem){ case 0: targetPage=1-Math。round(pageOffset); break; case 1: //選單隱藏時,首先要判斷此時選單的放置狀態是左側還是右側 if(current_state == SlidingMenu。LEFT){ targetPage = Math。round(1-pageOffset); } if(current_state == SlidingMenu。RIGHT){ targetPage = Math。round(1+pageOffset); } break; case 2: targetPage = Math。round(1+pageOffset); break; }

鴻蒙開源第三方元件——SlidingMenu_ohos側滑選單元件

圖6 緩慢拖動效果圖

(3)選單顯示和隱藏的實現

主頁面的左側邊線與手指的位置繫結,當手指向右滑動時,主頁面也會隨手指向右滑動,在這個過程中選單頁面漸漸展示出來,實現選單頁面隨手指滑動慢慢展開的視覺效果。

void setCurrentItemInternal(int item,int velocity) { //獲得選單的目標狀態 item = mViewBehind。getMenuPage(item); mCurItem = item; final int destX = getDestScrollX(mCurItem); /*選單放置狀態為左側,透過設定主頁面的位置實現選單的彈出展示或彈回隱藏 1。destX=0,主頁面左側邊線與螢幕左側邊線對齊,選單被全部遮擋,實現選單彈回隱藏 2。destX=MenuWidth,主頁面左側邊線向右移動與選單總寬度相等的距離,實現選單彈出展示*/ if (mViewBehind。getMode() == SlidingMenu。LEFT) { mContent。setLeft(destX); mViewBehind。scrollBehindTo(destX); } ……}// 選單放置在左側時的選單滑動操作public void left_scrollto(float x) { //當menu的展示寬度大於最大寬度時僅展示最大寬度 if(x>getMenuWidth()){ x=getMenuWidth(); } //主頁面(主頁面左側邊線)和選單(選單右側邊線)分別移動到指定位置X mContent。setLeft((int)x); mViewBehind。scrollBehindTo((int)x);}

2、CustomViewBehind 選單頁面

CustomViewBehind為選單頁面,邏輯相比於主頁面簡單許多。主要負責根據主頁面中的Touch事件改變自身狀態值,同時向外暴露介面,用於設定或者獲取選單頁面的最大寬度、自身狀態等屬性。

// 設定選單最大寬度public void setMenuWidth(int menuWidth) { this。menuWidth = menuWidth;}// 獲得選單最大寬度public int getMenuWidth() { return menuWidth;}

3。 SlidingMenu

分別例項化CustomViewAbove和CustomViewBehind的物件,並按照主頁面在上選單頁面在下的順序分別新增到SlidingMenu的容器中。

//新增選單子控制元件addComponent(mViewBehind, behindParams);//新增主頁面子控制元件addComponent(mViewAbove, aboveParams);

專案貢獻人

徐澤鑫 鄭森文 朱偉 陳美汝 王佳思 張馨心