HarmonyOS從Text的寶藏屬性想到的TabList新玩法
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
一.前言
前幾天,運(yùn)營小姐姐跟我說再發(fā)幾篇文章有望沖擊星光計劃創(chuàng)作先鋒獎,我一看有這等好事,哈,說笑呢,我是為了那些獎品嗎,這不是小瞧我么,對于這個請求,依我的性格那當(dāng)然
直接答應(yīng)啊,能拿大獎造福大家不香么.
于是乎我只好拿出昨天發(fā)現(xiàn)的壓箱底的寶藏內(nèi)容,沖擊一波大獎,誰都不許攔哈.
哈哈,開個小玩笑.
二.Text隱藏的王炸,全網(wǎng)暫時還未發(fā)掘
那既然要拿獎,總得拿出點(diǎn)真東西出來,于是打開了塵封的文檔,這一看可不得了,看起來簡單的text一點(diǎn)不簡單啊,直把我驚了一身冷汗.
事情是這樣的,我們知道所有的控件幾乎都是拿Text做Base繼承出來的,那Text里面有些什么呢?

就是他了,你說,你說說,沒想到濃眉大眼的Text也叛變啦.你這不是把Image的飯碗給搶了嗎.
跟據(jù)文檔,輕松就做出一個控件效果:

但是這就完了嗎.
我現(xiàn)在想實現(xiàn)在程序運(yùn)行的時候動態(tài)改變這個圖該怎么辦.
三.動態(tài)修改上方圖標(biāo)
既然是動態(tài)修改,那自然就要在代碼上下功夫了
Text類里面查看一下,果然有Element相關(guān)的接口:

哈哈,天意,這里面的參數(shù)寫得明明白白,我們可以設(shè)置上下左右四個方向的圖標(biāo)
話不多說,趕緊試一下
可是這個Element是什么呢.點(diǎn)進(jìn)去一看,心涼一半:

原來是個超類啊,這讓我怎么用,官方文檔貌似沒有講這個的.
經(jīng)過在論壇的搜索,發(fā)現(xiàn)這么一篇寶藏文:
https://harmonyos.51cto.com/posts/8592
一句漫不經(jīng)心的說話,將我疑惑解開:

原來你有兒子啊,話不多說,拿來就用

造出一個Element需要這三個東西,其中下面兩個我不認(rèn)識,去看Resource感覺挺復(fù)雜,那就只有PixelMap能用了
那怎么生成一個PixelMap呢:

這里面提供了幾個靜態(tài)方法,對我而言,都沒有用
突然我想到在哪用過PixelMap,記得我的朋友應(yīng)該還記得那篇文章:
#星光計劃2.0#應(yīng)用開發(fā)-獨(dú)家發(fā)布-攝像頭掃描二維碼(Java版)
這里面有過把Image轉(zhuǎn)換成PixelMap的方法:

于是乎立馬想到,Image里面應(yīng)該有取PixelMap的方法,結(jié)果天助我也:
- //先創(chuàng)建一個img
- Image img =new Image(getContext());
- //把media資源設(shè)置進(jìn)去
- img.setPixelMap(ResourceTable.Media_setting_large);
- //直接取出生成PixelMapElement
- PixelMapElement pixelMapElement= new PixelMapElement(img.getPixelMap());
接下來的事情就簡單了:
- Text account_text = (Text) findComponentById(ResourceTable.Id_text_helloworld);
- account_text.setAroundElements(null, pixelMapElement, null, null);
后面效果就是這樣:

其實這篇文章也解答了一位老兄今年1月份的帖子:
https://harmonyos.51cto.com/answer/386
四.就這?
到這里,很多朋友以為結(jié)束了,nonono
為什么我會冒出一身冷汗,因為我看到了官方文檔:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-tablist-tab-0000001062229749

這里展示了一個頂部標(biāo)簽頁,一般新聞,資訊,論壇類會用這種,我想要一個什么樣的效果呢?

我想在底部做出一個類似的切換效果,這種界面其實還是很常見的,比如微信
有了官方文檔的buff,很快我們就能做出一個類似的效果:
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alignment="top"
- ohos:orientation="vertical"
- >
- <Text
- ohos:id="$+id:text_helloworld"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:top_margin="200vp"
- ohos:layout_alignment="horizontal_center"
- ohos:text="歡迎登錄系統(tǒng)"
- ohos:text_size="30fp"
- ohos:text_color="#58d421"
- ohos:element_top="$media:home_large"
- />
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:top_margin="60vp"
- ohos:left_margin="30vp"
- ohos:orientation="horizontal"
- >
- <Text
- ohos:height="30vp"
- ohos:width="50vp"
- ohos:text_size="20fp"
- ohos:text="賬號:"
- ohos:text_color="#58d421"
- />
- <TextField
- ohos:id="$+id:account_input"
- ohos:height="30vp"
- ohos:width="230vp"
- ohos:left_margin="10vp"
- ohos:text_size="20fp"
- ohos:background_element="$graphic:text_filed_style"
- />
- </DirectionalLayout>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:top_margin="10vp"
- ohos:left_margin="30vp"
- ohos:orientation="horizontal"
- >
- <Text
- ohos:height="30vp"
- ohos:width="50vp"
- ohos:text_size="20fp"
- ohos:text="密碼:"
- ohos:text_color="#58d421"
- />
- <TextField
- ohos:id="$+id:pwd_input"
- ohos:height="30vp"
- ohos:width="230vp"
- ohos:text_input_type="pattern_password"
- ohos:left_margin="10vp"
- ohos:text_size="20fp"
- ohos:padding="0vp"
- ohos:background_element="$graphic:text_filed_style"
- />
- </DirectionalLayout>
- <Button
- ohos:top_margin="50vp"
- ohos:id="$+id:main_btn"
- ohos:height="50vp"
- ohos:width="100vp"
- ohos:clickable="true"
- ohos:text="登陸"
- ohos:layout_alignment="center"
- ohos:text_size="20vp"
- ohos:text_color="#58d421"
- ohos:scrollbar_background_color="#3FC390EF"
- ohos:background_element="$graphic:capsule_button_element"
- />
- <TabList
- ohos:id="$+id:main_tabList"
- ohos:height="150vp"
- ohos:width="match_parent"
- ohos:text_size="20fp"
- ohos:layout_alignment="bottom"
- ohos:orientation="horizontal"
- ohos:normal_text_color="black"
- />
- </DirectionalLayout>

但是仔細(xì)觀察一下,會發(fā)現(xiàn),微信上面選中的頁面不僅文字會變色,圖標(biāo)也會變色:

接下來就是見證奇怪的時刻
五.制作按下圖片換色效果
為了實現(xiàn)這一步,最簡單的做法是找兩張圖片,比如一張彩色,一張黑色,那這種圖片哪里找呢?
在這個網(wǎng)站幾乎常見不常見的圖標(biāo)都能找到:
https://www.iconfont.cn/search/index?spm=a313x.7781069.1998910419.28&searchType=icon&q= home&page=1&fromCollection=-1&fills=&tag=
選中一個喜歡的圖標(biāo),點(diǎn)擊下載按鈕:


左邊選顏色,右邊選尺寸,下載完放到media目錄就行
把圖標(biāo)都準(zhǔn)備好之后,就要想辦法了
官方的TabList和Tab都已經(jīng)實現(xiàn)好了,肯定不能動
那我們就用繼承吧:
- class myTab extends TabList.Tab {
- PixelMapElement normal;
- PixelMapElement pressed;
- Color defaultColor = Color.BLACK;
- public myTab(TabList list,Context context) {
- list.super(context);
- this.setTextColor(defaultColor);
- }
- public void setImage(int normal_img,int pressed_img){
- Image img = new Image(getContext());
- img.setPixelMap(normal_img);
- normal = new PixelMapElement(img.getPixelMap());
- img.setPixelMap(pressed_img);
- pressed = new PixelMapElement(img.getPixelMap());
- super.setAroundElements(null,normal,null,null);
- }
- public void isSelected(boolean select){
- this.setTextColor(select?Color.BLUE:defaultColor);
- super.setAroundElements(null,select ? pressed : normal,null,null);
- }
- }
這里我們用myTab繼承了TabList里面的Tab類,就不去講語法了,總之這樣就行
注意這里面的兩個方法:
setImage(int normal_img,int pressed_img)方法用來設(shè)置兩個圖片,一個是普通未選中的狀態(tài),另一個就是選中的狀態(tài)
isSelected(boolean select)來指示當(dāng)Tab被選中的時候如何進(jìn)行切換圖片
在主程序的tabList里面添加事件監(jiān)聽:
- TabList tabList = (TabList) findComponentById(ResourceTable.Id_main_tabList);
- myTab tab = new myTab(tabList,getContext());
- tab.setText("home");
- tab.setImage(ResourceTable.Media_home_large,ResourceTable.Media_home_large_pushed);
- tabList.addTab(tab);
- myTab tab2 = new myTab(tabList,getContext());
- tab2.setText("my");
- tab2.setImage(ResourceTable.Media_my_large,ResourceTable.Media_my_large_pushed);
- tabList.addTab(tab2);
- myTab tab3 = new myTab(tabList,getContext());
- tab3.setText("setting");
- tab3.setImage(ResourceTable.Media_setting_large,ResourceTable.Media_setting_large_pushed);
- tabList.addTab(tab3);
- tabList.setFixedMode(true);
- tabList.addTabSelectedListener(new TabList.TabSelectedListener() {
- @Override
- public void onSelected(TabList.Tab tab) {
- // 當(dāng)某個Tab從未選中狀態(tài)變?yōu)檫x中狀態(tài)時的回調(diào)
- myTab mytab = (myTab)tab;
- mytab.isSelected(true);
- }
- @Override
- public void onUnselected(TabList.Tab tab) {
- // 當(dāng)某個Tab從選中狀態(tài)變?yōu)槲催x中狀態(tài)時的回調(diào)
- myTab mytab = (myTab)tab;
- mytab.isSelected(false);
- }
- @Override
- public void onReselected(TabList.Tab tab) {
- // 當(dāng)某個Tab已處于選中狀態(tài),再次被點(diǎn)擊時的狀態(tài)回調(diào)
- this.onUnselected(tab);
- }
- });
大功告成,在模擬器里面運(yùn)行一下:

里面有幾下圖片變藍(lán)然后又變白其實是出發(fā)了上面的onReselected(TabList.Tab tab)方法,我這里做法是直接變成未選中,大家也可以選擇忽略這個方法,根據(jù)自己的應(yīng)用場景靈活使用.
六.尚未解決的問題
1.本次使用了遠(yuǎn)程的tabList實現(xiàn)了底部文字及圖標(biāo)的切換效果,但是是利用切圖片的方式實現(xiàn)了,有沒有辦法能夠直接修改圖片的顏色,望有大神告知
2.使用原生的TabList方式做出這樣一個效果就是貌似PixelMapElement無法設(shè)置圖片的大小,這就是為什么大家會看到我的meida資源的圖片會有l(wèi)arge字樣,有沒有辦法設(shè)置圖片的大小希望有大神能告知
3.點(diǎn)擊Tab切換頁面的效果時間關(guān)系沒有做,而且本文重點(diǎn)也不在這,如果有想知道如何切換真正的頁面搜索論壇里面TabList有其他大牛寫的例子
七.總結(jié)
這篇文章屬于拋磚引玉,主要是想說明一個不經(jīng)意的發(fā)現(xiàn)也能發(fā)散出精彩的創(chuàng)意,可能在別人看來我這沒什么,但是技術(shù)這東西,都是自己才能懂.
之前鴻蒙系統(tǒng)很多功能總有網(wǎng)友說這有什么用,我想說的是:到底有什么用,不要問別人,問自己,有沒有那雙真正能發(fā)現(xiàn)精彩的眼睛.
用一張楚團(tuán)長的表情包與大家共勉:
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)