最近在uni-app做app的時候做到了分享的功能,基本上實現了,但是在web-view頁面的分享是不起效果的(因為uni-app的機制說明了webview的層級是最高的),后來幾經周轉,終於用 plus.nativeObj.View 做了一個底部彈出,特此記錄一下,附帶代碼
首先寫了一個全局的js文件,(因為我好多頁面都用到這個分享)
//plus.nativeObj.view解決彈窗問題,webview層級壓制 var nvMask,nvImageMenu; export default { show({list,cancelText,sharedata},callback){ if(!list){ list = [{ "img":"https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/9a952c80-6080-11eb-a16f-5b3e54966275.png", "text":"圖標文字" }] } if(list.length>8){ return uni.showToast({ title: '目前版本最多支持8個圖標', icon: 'none' }); } //數據 var strShareUrl = sharedata.strShareUrl var strShareTitle = sharedata.strShareTitle var strShareSummary = sharedata.strShareSummary var strShareImageUrl = sharedata.strShareImageUrl var shareId = sharedata.id //以下為計算菜單的nview繪制布局,為固定算法,使用者無關關心 var screenWidth = plus.screen.resolutionWidth //以360px寬度屏幕為例,上下左右邊距及2排按鈕邊距留25像素,圖標寬度55像素,同行圖標間的間距在360寬的屏幕是30px,但需要動態計算,以此原則計算4列圖標分別的left位置 //圖標下的按鈕文字距離圖標5像素,文字大小12像素 //底部取消按鈕高度固定為44px //TODO 未處理橫屏和pad,這些情況6個圖標應該一排即可 var margin = 20, iconWidth = 60, icontextSpace = 5, textHeight = 12 var left1 = margin / 360 * screenWidth var iconSpace = (screenWidth - (left1 * 2) - (iconWidth * 4)) / 3 //屏幕寬度減去左右留白間距,再減去4個圖標的寬度,就是3個同行圖標的間距 if (iconSpace <= 5) { //屏幕過窄時,縮小邊距和圖標大小,再算一次 margin = 15 iconWidth = 40 left1 = margin / 360 * screenWidth iconSpace = (screenWidth - (left1 * 2) - (iconWidth * 4)) / 3 //屏幕寬度減去左右留白間距,再減去4個圖標的寬度,就是3個同行圖標的間距 } var left2 = left1 + iconWidth + iconSpace var left3 = left1 + (iconWidth + iconSpace) * 2 var left4 = left1 + (iconWidth + iconSpace) * 3 var top1 = left1 var top2 = top1 + iconWidth + icontextSpace + textHeight + left1 nvMask = new plus.nativeObj.View("nvMask", { //先創建遮罩層 top: '0px', left: '0px', height: '100%', width: '100%', backgroundColor: 'rgba(0,0,0,0.2)' }); nvMask.addEventListener("click", function() { //處理遮罩層點擊 nvMask.hide(); nvImageMenu.hide(); }) nvImageMenu = new plus.nativeObj.View("nvImageMenu", { //創建底部圖標菜單 bottom: '0px', left: '0px', height: (iconWidth + textHeight + 2 * margin)*Math.ceil(list.length/4) +44+'px',//'264px', width: '100%', backgroundColor: 'rgb(255,255,255)' }); let myList = [] list.forEach((item,i)=>{ myList.push({ tag: 'img', src: item.img, position: { top: eval('top'+( parseInt(i/4) +1)), left: eval('left'+(1+i%4)), width: iconWidth, height: iconWidth } }) myList.push({ tag: 'font', text: item.text, textStyles: { size: textHeight }, position: { top: eval('top'+(parseInt(i/4)+1)) + iconWidth + icontextSpace, left: eval('left'+(1+i%4)), width: iconWidth, height: textHeight } }) }) //繪制底部圖標菜單的內容 nvImageMenu.draw([ { tag: 'rect',//菜單頂部的分割灰線 color: '#e7e7e7', position: { top: '0px', height: '1px' } }, { tag: 'font', text: cancelText,//底部取消按鈕的文字 textStyles: { size: '14px' }, position: { bottom: '0px', height: '44px' } }, { tag: 'rect',//底部取消按鈕的頂部邊線 color: '#e7e7e7', position: { bottom: '45px', height: '1px' } }, ...myList ]) nvMask.show() nvImageMenu.show() //5+應支持從底部向上彈出的動畫 nvImageMenu.addEventListener("click",e=>{ //處理底部圖標菜單的點擊事件,根據點擊位置觸發不同的邏輯 // console.log("click menu"+JSON.stringify(e)); if (e.screenY > plus.screen.resolutionHeight - 44) { //點擊了底部取消按鈕 nvMask.hide(); nvImageMenu.hide(); } else if (e.clientX < 5 || e.clientX > screenWidth - 5 || e.clientY < 5) { //屏幕左右邊緣5像素及菜單頂部5像素不處理點擊 } else { //點擊了圖標按鈕 var iClickIndex = -1 //點擊的圖標按鈕序號,第一個圖標按鈕的index為0 var iRow = e.clientY < (top2 - (left1 / 2)) ? 0 : 1 var iCol = -1 if (e.clientX < (left2 - (iconSpace / 2))) { iCol = 0 } else if (e.clientX < (left3 - (iconSpace / 2))) { iCol = 1 } else if (e.clientX < (left4 - (iconSpace / 2))) { iCol = 2 } else { iCol = 3 } if (iRow == 0) { iClickIndex = iCol } else { iClickIndex = iCol + 4 } // console.log("點擊按鈕的序號: " + iClickIndex); // if (iClickIndex >= 0 && iClickIndex <= 5) { //處理具體的點擊邏輯,此處也可以自行定義邏輯。如果增減了按鈕,此處也需要跟着修改 // } // callback(iClickIndex) if (iClickIndex >= 0 && iClickIndex <= 5) { //處理具體的點擊邏輯,此處也可以自行定義邏輯。如果增減了按鈕,此處也需要跟着修改 var strProvider="",strScene="" switch (iClickIndex) { case 0: strProvider = "weixin" strScene = "WXSceneSession" break; case 1: strProvider = "weixin" strScene = "WXSenceTimeline" break; case 2: strProvider = "sinaweibo" break; case 3: strProvider = "qq" break; case 4: uni.setClipboardData({ data: strShareUrl, complete() { uni.showToast({ title: "已復制到剪貼板" }) } }) break; case 5: plus.share.sendWithSystem({ content: strShareUrl, }) break; } if (strProvider!="") { //點擊了0-3序號的這4個按鈕 uni.share({ provider: strProvider, scene:strScene, type: 0, href: strShareUrl, title: strShareTitle, summary: strShareSummary, imageUrl: strShareImageUrl, success: function(res) { console.log("success:" + JSON.stringify(res)); callback(shareId) }, fail: function(err) { console.log("fail:" + JSON.stringify(err)); } }) } } this.hide() } }) /* nvImageMenu.addEventListener("touchstart", function(e) { if (e.screenY > (plus.screen.resolutionHeight - 44)) { //TODO 這里可以處理按下背景變灰的效果 } }) nvImageMenu.addEventListener("touchmove", function(e) { //TODO 這里可以處理按下背景變灰的效果 if (e.screenY > plus.screen.resolutionHeight - 44) {} }) nvImageMenu.addEventListener("touchend", function(e) { //TODO 這里可以處理釋放背景恢復的效果 }) */ }, hide(){ nvMask.hide() nvImageMenu.hide() } }
然后在你的父組件引用
在你的methods中引入方法
share(item){ var that = this var sharedata = { strShareUrl: that.$port.bbs_h5, strShareTitle: item.type, strShareSummary: item.topName, strShareImageUrl: item.img, id:item.id } uniImageMenu.show({ list:that.$global.shareList, //底部的分享列表數組 cancelText:that.$global.resertText, //取消分享的文字 sharedata:sharedata //分享的內容 }, index => { // that.shareNum(index) //此處是你執行的操作 }) },
紅色標注的是必須引用的,好了,親測可用,歡迎討論