首頁 web前端 js教程 JavaScript使用DeviceOne開發實戰(三)仿微信應用_javascript技巧

JavaScript使用DeviceOne開發實戰(三)仿微信應用_javascript技巧

May 16, 2016 pm 03:28 PM

這是一個系列的文檔,長期目標是利用DeviceOne開發一些目前使用廣泛的優質手機應用,我們會最大化的實現這些應用的每一個功能和細節,不只停留在簡單的UI模仿和Demo階段,而是一個基本上可以使用的實際App。 

在實現的過程中,會有很多困難,還會發現有一些功能目前缺乏組件支援而無法實現,也會碰見各種行動開發中都會碰到的常見技術問題。一步一步的操作和問題的解決可以讓開發者直覺的了解透過DeviceOne如何開發一個實際App,也可以了解行動開發本身的許多技術細節,可以讓App開發者少走很多彎路。

這篇文件主要介紹微信的模仿。

第一部分是框架的建造

UE和UI設計,通常App的開發需要產品人員的UE設計和美工人員的UI設計,這二步驟完成後才開始功能實作。我們現在是模仿已有的微信,這些步驟都可以省去,看下圖是美工提供的主介面UI設計圖,裡面的元素的尺寸都標示了。
 


1.新專案:我們選擇了Simple template,選擇空模板是因為我們可以更細緻的講解開發的過程。實際上這個專案是可以選擇Multi View with ViewShower範本比較合適。

 2.簡單分析一下主介面,整個主介面的尺寸是iphone6的尺寸750*1334. 分上下二個部分,底部是一個Bottom Bar導航欄,上面是4個獨立的介面,這4個介面永遠只有一個介面顯示,其他三個介面在記憶體中,靠底部的導航來切換,這個適合用do_ViewShower為框架的主體如下圖:

對應這個設計,我們在新建的專案上刪除自動產生的button,加入一個do_ALayout元件和do_ViewShower元件,設定它們的高寬和x,y座標:


3.接下來我們為ViewShower增加4個分頁,在這裡我還強調一下,實際App會多人參與,我們的程式碼結構要清晰易讀,命名盡量使用英文,實在不行使用中文全拼,包括要建立多層子目錄,不要都混在一起。這裡我們增加4個子目錄:chats, contacts, discover, me. 右鍵每個子目錄,選擇New--Other--DeviceOne--UI File,建立4個index.ui,對應的index.ui.js會自動生成。

這裡注意把這4個ui檔案對應的根節點ALayout的高度設定為1220,因為這4個ui檔案都是主介面的ViewShower的子view,不應該超過ViewShower的大小。

另外為每個ui裡都加上一個label,標記中文名,只是一會兒debug看真實效果更清楚。

4.Bottom Bar內簡單加入4個按鈕,然後加入對應的js程式碼實作ViewShower的頁面切換功能。這裡提一個技巧,選取2個或以上組件,可以使用各種對齊方式的功能,如下圖:


5.在index.ui.js裡加入ViewShower初始化的程式碼和按鈕的點擊事件。

var viewshower = ui("viewshower");
var page = sm("do_Page");
// 为viewshower增加4个子页面
viewshower.addViews([ {
    id : "chats",// 页面的标示
    path : "source://view/chats/index.ui"// 页面的路径
}, {
    id : "contacts",
    path : "source://view/contacts/index.ui"
}, {
    id : "discover",
    path : "source://view/discover/index.ui"
}, {
    id : "me",
    path : "source://view/me/index.ui"
} ]);
// 初始化先显示第一个页面
viewshower.showView("chats");
var button1 = ui("do_Button_1");
button1.on("touch", function() {
    viewshower.showView("chats");
});
var button2 = ui("do_Button_2");
button2.on("touch", function() {
    viewshower.showView("contacts");
});
var button3 = ui("do_Button_3");
button3.on("touch", function() {
    viewshower.showView("discover");
});
var button4 = ui("do_Button_4");
button4.on("touch", function() {
    viewshower.showView("me");
});
登入後複製

6.我們來真機看看運行效果,啟動設計器的調試服務,啟動手機端的調試程序,最後我們看到的效果圖如下,iOS和Android界面完全一樣。點擊底部的4個按鈕,切換效果都是好的:

7. 這節的內容就到這裡,框架工作完成了嗎?只能說框架的第一步工作完成,如果我們有很多同事一起開發這個App的話,我們可以把工作開始分開並行,接下來分成5個部分:

* Bottom Bar的完成
* /chats/index.ui的完成
* /contacts/index.ui的完成
* /discover/index.ui的完成
* /me/index.ui的完成
多人並行工作的前提是程式碼版本管理例如SVN,GIT,我們這裡使用GIT,位址是https://github.com/do-project/Fake-Weixin,每一節結束後我們都會提交GIT服務,你可以下載這個節點的程式碼參考。我們也會在附件附加這一節的項目代碼。

下一節我們完成第一個子任務,BottomBar的實作。

----------------------------------------------- --------------

這一節主要是完成底部導覽列的實作。

0. 我們先來分析一下介面效果圖和設計圖

 

整個底部導覽分4個重複的部分,每個部分由一個圖片ImageView和底部標題Label,以及右上角標示,這個標示可以用圓角Label來實現,這個標示缺省的時候應該是隱藏的。

1. 第一步我們得找到對應的圖片資源,通常開發這些資源由美工提供,我們現在模仿微信,最好的方式是從微信原生安裝包裡獲取,不能直接靠截圖,而是打開微信ios,android安裝包,ios的安裝包是ipa和android的安裝包apk都是壓縮文件,解開可以獲取到一些圖片資源。目前我只需要底部8個圖標,包括未點中以及點中的高亮圖標,外面把這些圖標放在image目錄下

2. 先刪除先前增加的4個臨時按鈕,然後按照美工提供的尺寸資料佈局好新的組件,包括4個do_ImageView組件和4個Label組件以及4個右上角的Label
簡單計算可以得到ImageView的大小是60*60。這裡有一個小技巧,設定好一組ImageView和Label後選中2個組件,然後右鍵“Copy”,然後再"Paste"三次,還可以選中多個組件各種對齊。

再細調一下,把圖片和文字設定好,圖片設定就是設定ImageView的source屬性,Label需要設定文字居中,設定textAlign屬性為center,設定字體,設定背景色,前景色等等,設定右上角三個Label的visible為false。中間加上一個ALayout設定背景為灰色,作為ViewShower和Bottom Bar上下的分割線. 這裡要注意,右上角的正圓形Label的實作方式就是設定border屬性,border設定為FF0000FF,1,15 表示界線的顏色是紅色,寬度1,圓角半徑15(Label的寬高都是30),因此實現正圓。

 

在真機上測試一下效果,iPhone和Android手機真機的效果圖如下:

3. 這時候會有2個問題,如果給ImageView上新增點擊事件的話,使用者必須點中這個圖片才能觸發點擊,這樣體驗不好。第二個問題是圖片在Android上稍微有點變形,如果在例如iPhone4上,可能圓形會變成橢圓,這個問題是因為不同手機寬高比的差異。

要解決的方法是:

* 把Bottom Bar所在的ALayout增加4個一樣大小的子ALayout,然後把imageview,label都放在對應的子ALayout上,然後給子ALayout增加點擊事件,這樣用戶的手指只要接觸到差不多位置都能觸發事件
* 把上面的4個子ALayout的isStretch屬性改成false,這個原理可以參考文檔 ALayout的範例demo

4. 修改index.ui.js,添加代码主要是在底部bottom bar切换按钮的时候修改所有图标的颜色和字的前景色。

var button = ui("do_Button_");
var imageview = ui("do_ImageView_");
var label = ui("do_Label_");
button.on("touch", function() {
    showView("chats");
});
var button = ui("do_Button_");
var imageview = ui("do_ImageView_");
var label = ui("do_Label_");
button.on("touch", function() {
    showView("contacts");
});
var button = ui("do_Button_");
var imageview = ui("do_ImageView_");
var label = ui("do_Label_");
button.on("touch", function() {
    showView("discover");
});
var button = ui("do_Button_");
var imageview = ui("do_ImageView_");
var label = ui("do_Label_");
button.on("touch", function() {
    showView("me");
});
function showView(name) {
    viewshower.showView(name);
    if (name == "chats") {
        imageview.source = "source://image/tabbar_mainframeHL.png";
        label.fontColor = "BBFF";
    } else {
        imageview.source = "source://image/tabbar_mainframe.png";
        label.fontColor = "FFFFF";
    }
    if (name == "contacts") {
        imageview.source = "source://image/tabbar_contactsHL.png";
        label.fontColor = "BBFF";
    } else {
        imageview.source = "source://image/tabbar_contacts.png";
        label.fontColor = "FFFFF";
    }
    if (name == "discover") {
        imageview.source = "source://image/tabbar_discoverHL.png";
        label.fontColor = "BBFF";
    } else {
        imageview.source = "source://image/tabbar_discover.png";
        label.fontColor = "FFFFF";
    }
    if (name == "me") {
        imageview.source = "source://image/tabbar_meHL.png";
        label.fontColor = "BBFF";
    } else {
        imageview.source = "source://image/tabbar_me.png";
        label.fontColor = "FFFFF";
    }
}
登入後複製

到此为止,底部导航栏基本实现完成,这一节比较简单,主要是一些细致的ui拖拽调整。我们用调试版本看一下Android,iOS的效果都非常不错。

我们开始实现ViewShower的第一页主体内容.

---------------------------------------------------------------------------------------

接上一节 底部导航 ,我们这一节主要是完成微信4个主页面的第一个页面“微信”页面,这一节内容比较多,我们分多个跟帖来完成

0 老规矩,先分析一下UI,由三个大部分组成,系统状态栏,工具栏和微信聊天记录列表。

1. 系统状态栏高度40,背景黑色,我们注意到微信的首页4个子页面都有这个系统状态栏,这样我们需要做一个整体框架的调整,没有必要为4个子页面都添加一个状态栏,只需要在ViewShower上添加一个就可以,对应的ViewShower和子页面的高度都变成1180.

对应设计器里index.ui, chats/index.ui, contacts/index.ui, discover/index.ui, me/index.ui 都要作相应的height,y属性值的变化。效果如下:


2. 我们回到chats/index.ui ,先增加工具导航栏(高度80)和里面的标题和工具按钮,这个需要增加加号的资源文件,因为这个文件是chats页面专有的,所以存在image/chats/bar_add.png下。
我们看看真机效果,我们注意到顶部多出一块黑色区域,这是设计器里的增加的状态栏,因为这个页面是从系统状态栏开始往下绘制的,所以会把设计器里这一部分多出来,

要解决的方法是修改app.js,openPage增加一个statusBarState参数(API文档),设置为transparent表示页面从屏幕最顶端开始绘制。

var d1 = require("deviceone");
var app = d1.sm("do_App");
app.on("loaded", function() {
    this.openPage({
        source : "source://view/index.ui",
        statusBarState : "transparent"
    });
});
登入後複製

再来看看真机效果图:

3. 主体部分是一个do_ListView,接下来设置ListView的cell和数据。
ListView的cell指列表框的每一行,比如ListView有100行数据,实际上可见的屏幕永远只能看到8,9行左右,所以我们手势上下滑动的时候并没有创建100行,而是重复使用这8,9行,只不过替换里面的数据而已。我们称之为行模板,在DeviceOne里这种模板也是一个ui文件,比如这里我们在chats子目录下新建一个chat_cell.ui,这个ui基本界面如下:


按照美工的设计尺寸我们来拖拽UI

这里同样需要考虑纯圆变形问题,需要设置好文字大小,前景色等属性,大家可以看到里面有多个do_Label,do_ImageView组件,由于模板ui是靠后期绑定数据的,所以在设计阶段都是空白的。


接下来我们需要设计chat_cell.ui对应的数据,通常为了用户体验,需要尽可能的减少网络交互,页面打开的时候通常先读取本地的数据文件,把界面显示出来,然后再考虑是否要进行网络连接来获取最新数据,所以App开发需要仔细考虑数据的本地化读写和数据的时效性的平衡。
DeviceOne的传递数据基本上都是标准的JSON格式。如下图,chat_cell.ui里的组件属性和JSON数据结构对应的关系

对应的映射关系的代码在chat_cell.ui.js如下,我们可以看到映射关系的左边是组件id.组件属性名,右边是数据JSON的key名称:

//related to chat_cell.ui
var root = ui("$");;//$是这个ui文件根节点组件的通配符,如果指定组件的id,也可以用id来获取对象
root.setMapping({
    "photo_imageview.source" : "photo",
    "name_label.text" : "name",
    "lastmessage_label.text" : "lastmessage.message",
    "lasttime_label.text" : "lastmessage.time",
    "unread_label.visible" : "unread",
    "unread_label.text" : "unread-count",
    "name_label.fontColor" : "isgroup",
});
登入後複製

对应的数据本应该是第一次运行从网络上获取之后再缓存到本地的,我们是模拟,所以先手动生成一个文件到data/chats/chat.json

4. 我们回到chats/index.ui,我们需要给这里ui文件里的listview设置模板,绑定数据。
设置index.ui 里的listview的templates属性为 source://view/chats/chat_cell.ui
注意:chat_cell.ui存储在source/default/view/chats/chat_cell.ui,但是source://的根节点指的是 source/default/目录
在index.ui.js里添加绑定数据的代码

//related to index.ui
var storage = sm("do_Storage");
var listdata = mm("do_ListData");
var listview = ui("listview");
var json_path = "data://chats/chat.json";//本地缓存的数据
if (storage.fileExist(json_path)) {
    storage.readFile(json_path, function(data, e) {
        //deviceone.print(JSON.stringify(data));
        listdata.addData(data);
        listview.bindItems(listdata);
        listview.refreshItems();
    })
}
var page = sm("do_Page");
page.on("loaded",function(){
    //这个页面加载完显示出来后触发这个事件
    //我们可以在这个事件里去获取最新的网络数据,来更新listview和data/chats/chat.json
});
登入後複製

我们在真机上看看效果


在运行中有几个细节:

* 上下滑动的时候,图片不断的刷新,原因是我们的ImageView的source是网络图片,每次显示的时候都是从网络上获取的,所以这里需要把chat_cell.ui里的ImageView的cacheType属性换成"always" 意思是只从网络上读取一次就会缓存到本地,下一次不会再从网络上读取了。关于cacheType属性参考API文档
* ImageView也是圆角的,圆角通常可以使用border属性来设置,但是android只有ImageView不能通过border来设置圆角,ImageView还有一个专有属性radius来设置Android才有效,这个我们以后可以改进

5. 处理右上角的add按钮,点击弹出菜单

先给右上角ImageView的enable属性设置为true,才可以处理点击事件,在chats/index.ui.js里添加代码

var add_button = ui("add_imageview");
add_button.on("touch", function() {
    var menu = ui("menu_id");
    if (menu) {//如果已经add过,就只是让这个view显示,而不是add一个新的
        if (menu.visible == false)
            menu.visible = true;
    } else {
        main.add("menu_id", "source://view/chats/chat_add_menu.ui");
    }
});
登入後複製

其中chat_add_menu.ui 是弹出的菜单对应的ui文件,这个ui文件的根节点大小和chat/index.ui一样,这样确保我点击任何空白处都可以关闭这个菜单(实际上是隐藏这个菜单),我们在这个ui文件里把对应的布局都拖拽好,其中需要添加4个资源png文件。

这里有个小技巧,顶部的三角形标记只能通过一个ImageView加载一个三角形图标来实现。

我们再给chat_add_menu的根节点添加点击事件,点击的时候把自己隐藏,在chat_add_menu.js

var root = ui("$");
root.on("touch",function(){
    root.visible = false;
});
登入後複製

最后我们先看看真机效果,点击加号弹出菜单,点击任何地方都把菜单隐藏。


这一节暂时先到这里,我们先开始拖拽后几个主页面,那几个页面基本完成后再重新回到这一个页面来细琢。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何創建和發布自己的JavaScript庫? 如何創建和發布自己的JavaScript庫? Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

如何在瀏覽器中優化JavaScript代碼以進行性能? 如何在瀏覽器中優化JavaScript代碼以進行性能? Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何使用瀏覽器開發人員工具有效調試JavaScript代碼? 如何使用瀏覽器開發人員工具有效調試JavaScript代碼? Mar 18, 2025 pm 03:16 PM

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

如何使用源地圖調試縮小JavaScript代碼? 如何使用源地圖調試縮小JavaScript代碼? Mar 18, 2025 pm 03:17 PM

本文說明瞭如何使用源地圖通過將其映射回原始代碼來調試JAVASCRIPT。它討論了啟用源地圖,設置斷點以及使用Chrome DevTools和WebPack之類的工具。

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

See all articles