「本文正在參加星光計劃3.0--夏日挑戰賽」
前言
在上期内容的分享中,筆者介紹了如何搭建基礎的頁面架構(為之後的開發做準備),以及應用圖像和标簽的修改、應用的全屏化。而在本期,筆者就在上期的基礎上繼續展開數獨小遊戲項目的搭建。
上期的内容回顧——>>https://ost.51cto.com/posts/14383

正文
本期,筆者将介紹如何利用代碼布局建立網格區域的UI。
首先,筆者所說的網格區域指的是下圖被圈出的部分:
事實上,因為網格區域用于承載數獨的題目,它同時也是玩家主要面向的部分,是以網格區域的邏輯就是這個項目最核心的功能。網格區域中有兩種顔色的網格,其中,藍色網格内的數字是應用為使用者提供的提示數字,白色網格則需要使用者根據數獨的規則合理填入數字,兩種格子的數量加起來共計64個。而現在我們面臨的問題是——我們如何将這個6x6的平面網格系統搭建起來呢?
筆者的思路是,先設計網格區域的UI,再完善網格區域的互動邏輯。而本期将介紹的内容就是如何設計網格區域的UI。
網格區域中共有36格子,那麼這些格子需要用什麼UI元件做呢?Button元件無疑可以嘗試一下。那麼我們接下來所要做的就是把Button元件設計成每一個格子,然後讓他們按一定的順序排起來,組成一個網格系統。由于格子的數量較多,是以我們不能用XML布局一個一個定義,這樣不僅效率慢,而且占用記憶體。而如果我們選擇使用Java代碼布局的話,我們就可以利用for循環來渲染button元件,以此做到高效簡潔。
當然,我們還面臨另一個問題——設計好的格子應該通過什麼布局排起來呢?因為我們是通過for循環來生成格子的,在這樣的前提下,隻有坐标布局才能與for循環無縫融合。
以下是通過代碼布局設計網格區域的UI的具體步驟。
完善GameAbilitySlice
由于數獨小遊戲項目的遊戲界面是用GameAbilitySlice承載的,是以我們首先要完善之前新建立的GameAbilitySlice。打開GameAbilitySlice,将代碼修改為如下:
package com.example.project.slice;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
public class GameAbilitySlice extends AbilitySlice {
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
}
@Override
protected void onBackground() {
super.onBackground();
}
}
這樣以後,GameAbilitySlice就繼承了AbilitySlice的類,并且它被寫入了onStart和onBackground兩個生命周期回調函數。
設計題目
在設計網格區域之前,我們需要先建立一個數獨題目(這樣之後每個格子的顔色和數字才能被确定),這個題目的資訊需要用資料承載。
在這裡,我們将利用數組的形式存儲數獨題目。定義一個6x6的數組——将代碼修改為如下:
package com.example.project.slice;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
public class GameAbilitySlice extends AbilitySlice {
//定義一個數組
int[][] grid_c0=new int[6][];
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
//為數組指派
grid_c0[0]=new int[]{0,0,0,0,1,0};
grid_c0[1]=new int[]{1,0,2,4,0,0};
grid_c0[2]=new int[]{6,2,3,0,0,5};
grid_c0[3]=new int[]{5,0,0,2,3,6};
grid_c0[4]=new int[]{0,6,4,3,5,0};
grid_c0[5]=new int[]{3,1,0,5,0,4};
}
@Override
protected void onBackground() {
super.onBackground();
}
}
可以看出,我們首先在GameAbilitySlice的内部定義了一個列數為6的數組grid_c0(即數組每行有六個數字),然後我們又在onStart函數内部為這個數組的每一列(第0列到第五列)指派,這樣grid_co就可以寫成矩陣:
0 1 6 5 0 3
0 0 2 0 6 1
0 2 3 0 4 0
0 4 0 2 3 5
1 0 0 3 5 0
0 0 5 6 0 4
通過代碼布局的方式建立GameAbilitySlice的UI界面
首先,在onStart内(”為數組指派”的下方)加入下列代碼:
PositionLayout layout1=new PositionLayout(getContext());
layout1.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
layout1.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
這樣做的目的是——在onStart的方法内建立一個PositionLayout的對象。并且,這個對象的高度和寬度繼承了父元件(其父元件可以認為是手機螢幕)的尺寸。PositionLayout的中文名是坐标布局,它屬于一種容器元件[容器元件是用來放置其它常用子元件(如按鈕元件,文本元件)的]。我們這裡之是以用坐标布局,而不是用其它布局,是因為坐标布局可以用坐标(x,y)來确定其子元件的位置。相較于方向布局和依賴布局,坐标布局更加直覺和精确,這也是我們選用坐标布局的主要原因。
建立網格區域
首先,我們事先定義一些資料,以便在後面使用:
int x;
int y;
int number;
String string0;
接着,我們為Button元件建立兩種背景元素:
ShapeElement element0=new ShapeElement();
element0.setRgbColor(new RgbColor(255,255,255)); //設定RGB顔色(白色)
element0.setStroke(5,new RgbColor(0,0,0)); //設定邊框的厚度和顔色(黑色)
ShapeElement element3=new ShapeElement();
element3.setRgbColor(new RgbColor(0,125,225)); //設定RGB顔色(藍色)
element3.setStroke(5,new RgbColor(0,0,0)); //設定邊框的厚度和顔色(黑色)
于是,我們得到了element0和element3兩種背景元素,他們分别可以把Button元件裝飾成藍色網格狀和白色網格狀。
之後,我們通過雙重for循環來渲染Button元件,并在坐标布局的協助下,利用這些Button元件構成一個網格:
for (y=0;y<6;y++){
for (x=0;x < 6; x++) {
Button button = new Button(this); //建立Button對象
number=grid_c0[x][y]; //按照兩個for循環的序列對數組grid_c0取值(x代表grid_c0對應的行數,y代表grid_c0對應的列數)
string0=String.valueOf(number);
button.setText(string0); //将number由整形變量轉化為字元串,然後把它設定為button顯示的文字
button.setTextColor(Color.WHITE);
button.setTextSize(75);
button.setComponentSize(160, 160);
//定義按鈕的尺寸,按鈕内文字的大小和顔色
button.setContentPosition(65+160* x, 230+160*y);
//定義按鈕的位置,設位置為T,那麼T是關于x和y的函數
if (number==0) { //判斷number是否為0
button.setText("");
button.setBackground(element0);
button.setTextColor(Color.BLACK);
//如果是0,button将不顯示任何文字,并且使用element0作為button的背景元素
}else{
button.setBackground(element3);
//如果不是0,button顯示文字,并且使用element3作為button的背景元素
}
layout1.addComponent(button); //将button元件加入到坐标布局中
}
}
這段代碼看起來稍微有點複雜,但隻要了解好代碼各層的邏輯關系,了解起來還是不費勁的。首先,我們設定了兩個for循環,可以看出,以y為變量的for循環嵌套着以x為變量的for循環,這意味着,變量x每完成一次0到5循環,變量y的值才加1,于是這兩個for循環會共同生成36個Button元件。
每生成一個Button元件時,系統都會根據這個元件在兩個for循環中對應的x和y值,對grid_c0進行取值,以及确定這個Button元件的坐标。這樣以後,網格區域每行每列的數字就能與grid_c0每行每列的數字對應起來(也就是跟數獨題目對應起來)。
接着,我們還加入了一個判斷條件,如果這個Button元件對grid_c0取到的數字為0,那麼它将作為待使用者填入數字的白色空白網格;如果這個Button元件對grid_c0取到的數字不是0(設其為t),那麼它将作為用于提示的藍色網格(這個網格将顯示數字t)。
最後,我們再加上如下代碼:
setUIContent(layout1);
這樣以後,我們之前所建立的坐标布局對象layout1就被成功設定為GameAbilitySlice的UI架構了。
如果想檢視設計的UI效果,我們可以打開MainAbility,把setMainRoute方法内的InitialAbilitySlice修改為GameAbilitySlice(這樣就可以修改應用預設顯示的頁面)。當我們打開模拟機時,我們看到的第一個頁面就是GameAbilitySlice了。
效果圖如下:
顯然,圖中網格區域中數字的分布與數組grid_c0的矩陣的數字排布一緻,隻不過,網格區域中的白色格子在矩陣中用數字0表示。
0 1 6 5 0 3
0 0 2 0 6 1
0 2 3 0 4 0
0 4 0 2 3 5
1 0 0 3 5 0
0 0 5 6 0 4
結尾
本期的内容就先分享到這裡,更多關于數獨小遊戲項目精彩的内容我将在下期繼續為大家揭曉。
想了解更多關于開源的内容,請通路: