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

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

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

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

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

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

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

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

于是乎立馬想到,Image里面應該有取PixelMap的方法,結果天助我也:
- //先創建一個img
- Image img =new Image(getContext());
- //把media資源設置進去
- 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
四.就這?
到這里,很多朋友以為結束了,nonono
為什么我會冒出一身冷汗,因為我看到了官方文檔:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-tablist-tab-0000001062229749

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

我想在底部做出一個類似的切換效果,這種界面其實還是很常見的,比如微信
有了官方文檔的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="歡迎登錄系統"
- 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>

但是仔細觀察一下,會發現,微信上面選中的頁面不僅文字會變色,圖標也會變色:

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


左邊選顏色,右邊選尺寸,下載完放到media目錄就行
把圖標都準備好之后,就要想辦法了
官方的TabList和Tab都已經實現好了,肯定不能動
那我們就用繼承吧:
- 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)方法用來設置兩個圖片,一個是普通未選中的狀態,另一個就是選中的狀態
isSelected(boolean select)來指示當Tab被選中的時候如何進行切換圖片
在主程序的tabList里面添加事件監聽:
- 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) {
- // 當某個Tab從未選中狀態變為選中狀態時的回調
- myTab mytab = (myTab)tab;
- mytab.isSelected(true);
- }
- @Override
- public void onUnselected(TabList.Tab tab) {
- // 當某個Tab從選中狀態變為未選中狀態時的回調
- myTab mytab = (myTab)tab;
- mytab.isSelected(false);
- }
- @Override
- public void onReselected(TabList.Tab tab) {
- // 當某個Tab已處于選中狀態,再次被點擊時的狀態回調
- this.onUnselected(tab);
- }
- });
大功告成,在模擬器里面運行一下:

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























