创建闹钟页面
本节我们将开发创建闹钟页面。这个页面有主列表页面点击“+”后跳转进入,可选择时间,铃声,时长和输入名称,最后保存返回主列表页面。整个页面使用DirectionalLayout垂直布局,从上到下依次排列控件。
1.开发创建闹钟的页面的xml资源文件
1.1 在entry>src>main>resources>base>element>string.json中添加新的文字资源
{
"name": "suretomodify",
"value": "是否保存更改?"
},
{
"name": "save",
"value": "保存"
},
{
"name": "giveup",
"value": "放弃"
},
{
"name": "ok",
"value": "确定"
},
{
"name": "cancel",
"value": "取消"
},
{
"name": "clockname",
"value": "闹钟名"
},
{
"name": "defaultName",
"value": "早起闹钟"
},
{
"name": "clockBell",
"value": "闹钟声音"
},
{
"name": "clockDuration",
"value": "闹钟时长"
},
{
"name": "oneMinute",
"value": "1 分钟"
},
{
"name": "fiveMinute",
"value": "5 分钟"
},
{
"name": "tenMinute",
"value": "10 分钟"
},
{
"name": "minute",
"value": "分钟"
},
{
"name": "createNew",
"value": "新建闹钟"
}
1.2 在entry>src>main>resources>base>layout目录里添加资源文件ability_add_clock.xml,使用DirectionalLayout垂直布局,从上到下依次添加控件。 ability_add_clock.xml
<?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:orientation="vertical">
<DependentLayout
ohos:id="$+id:app_bar"
ohos:height="56vp"
ohos:width="match_parent"
ohos:padding="10vp"
>
<Image
ohos:id="$+id:image_cancel"
ohos:height="24vp"
ohos:width="24vp"
ohos:left_margin="20vp"
ohos:foreground_element="$media:cancel"
ohos:vertical_center="true"/>
<Text
ohos:id="$+id:text_clockname"
ohos:height="match_content"
ohos:width="match_content"
ohos:right_of="$id:image_cancel"
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="$string:createNew"
ohos:text_size="24fp"
ohos:vertical_center="true"
ohos:left_margin="20vp"
/>
<Image
ohos:id="$+id:image_ok"
ohos:height="24vp"
ohos:width="24vp"
ohos:right_margin="20vp"
ohos:foreground_element="$media:ok"
ohos:align_parent_right="true"
ohos:vertical_center="true"/>
</DependentLayout>
<TimePicker
ohos:id="$+id:time_picker"
ohos:height="match_content"
ohos:width="match_parent"
ohos:selected_text_color="#007DFF"
ohos:selected_text_size="20fp"
/>
<DependentLayout
ohos:id="$+id:layout_name"
ohos:height="match_content"
ohos:width="match_parent"
ohos:top_margin="10vp"
>
<Text
ohos:id="$+id:item_text_nameLabel"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:clockname"
ohos:text_size="20fp"
ohos:layout_alignment="center"
ohos:top_margin="10vp"
ohos:bottom_margin="10vp"
ohos:left_margin="20vp"/>
<Image
ohos:id="$+id:icon_right_name"
ohos:height="24vp"
ohos:width="12vp"
ohos:align_parent_right="true"
ohos:right_margin="20vp"
ohos:top_margin="10vp"
ohos:image_src="$graphic:right_grey"/>
<Text
ohos:id="$+id:text_name"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:defaultName"
ohos:text_size="20fp"
ohos:layout_alignment="center"
ohos:top_margin="10vp"
ohos:bottom_margin="10vp"
ohos:right_margin="10vp"
ohos:left_of="$id:icon_right_name"/>
<Component
ohos:height="1vp"
ohos:width="match_parent"
ohos:background_element="$graphic:list_divider"
ohos:below="$id:text_name"/>
</DependentLayout>
<DependentLayout
ohos:id="$+id:layout_bell"
ohos:height="match_content"
ohos:width="match_parent">
<Text
ohos:id="$+id:text_bellLabel"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="闹钟铃声"
ohos:text_size="20fp"
ohos:layout_alignment="center"
ohos:top_margin="10vp"
ohos:bottom_margin="10vp"
ohos:left_margin="20vp"/>
<Image
ohos:id="$+id:icon_right_bell"
ohos:height="24vp"
ohos:width="12vp"
ohos:align_parent_right="true"
ohos:right_margin="20vp"
ohos:top_margin="10vp"
ohos:image_src="$graphic:right_grey"/>
<Text
ohos:id="$+id:item_text_bell"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="Cannon"
ohos:text_size="20fp"
ohos:layout_alignment="center"
ohos:top_margin="10vp"
ohos:bottom_margin="10vp"
ohos:right_margin="10vp"
ohos:left_of="$id:icon_right_bell"/>
<Component
ohos:height="1vp"
ohos:width="match_parent"
ohos:background_element="$graphic:list_divider"
ohos:below="$id:text_bellLabel"/>
</DependentLayout>
<DependentLayout
ohos:id="$+id:layout_duration"
ohos:height="match_content"
ohos:width="match_parent">
<Text
ohos:id="$+id:item_text_durationLabel"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:clockDuration"
ohos:text_size="20fp"
ohos:layout_alignment="center"
ohos:top_margin="10vp"
ohos:bottom_margin="10vp"
ohos:left_margin="20vp"/>
<Image
ohos:id="$+id:icon_right_duration"
ohos:height="24vp"
ohos:width="12vp"
ohos:align_parent_right="true"
ohos:right_margin="20vp"
ohos:top_margin="10vp"
ohos:image_src="$graphic:right_grey"/>
<Text
ohos:id="$+id:item_text_duration"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:fiveMinute"
ohos:text_size="20fp"
ohos:layout_alignment="center"
ohos:top_margin="10vp"
ohos:bottom_margin="10vp"
ohos:right_margin="10vp"
ohos:left_of="$id:icon_right_duration"/>
<Component
ohos:height="1vp"
ohos:width="match_parent"
ohos:background_element="$graphic:list_divider"
ohos:below="$id:item_text_durationLabel"/>
</DependentLayout>
</DirectionalLayout>
1.3 在entry>src>main>resources>base>layout目录里,添加dialog_edit_name.xml,用于编辑名称弹出对话框。 dialog_edit_name.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:top_padding="10vp"
ohos:start_padding="12vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:clockname"
ohos:layout_alignment="vertical_center"
ohos:text_size="20fp"/>
<TextField
ohos:id="$+id:textField_name"
ohos:height="match_content"
ohos:width="match_parent"
ohos:bottom_padding="8vp"
ohos:element_cursor_bubble="#00000000"
ohos:end_padding="12vp"
ohos:text=""
ohos:multiple_lines="false"
ohos:text_alignment="vertical_center"
ohos:text_size="16fp"
ohos:top_padding="8vp"
ohos:basement="#000099"
ohos:vertical_center="true"/>
</DirectionalLayout>
1.4 在entry>src>main>resources>base>layout目录里,添加dialog_edit_bell.xml,用于编辑闹钟弹出对话框。 dialog_edit_bell.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:top_padding="10vp"
ohos:start_padding="12vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:clockBell"
ohos:layout_alignment="vertical_center"
ohos:text_size="20fp"/>
<RadioContainer
ohos:id="$+id:radio_container_bell"
ohos:height="match_content"
ohos:width="200vp"
ohos:layout_alignment="left"
ohos:orientation="vertical"
ohos:top_margin="16vp"
ohos:left_margin="4vp">
<RadioButton
ohos:id="$+id:radio_btn_bellCanon"
ohos:height="40vp"
ohos:width="match_content"
ohos:text="Canon"
ohos:text_size="16fp"
ohos:text_color_on="#FF3333"/>
<RadioButton
ohos:id="$+id:radio_btn_bellClassic"
ohos:height="40vp"
ohos:width="match_content"
ohos:text="Classic"
ohos:text_size="16fp"
ohos:text_color_on="#FF3333"/>
<RadioButton
ohos:id="$+id:radio_btn_bellArmy"
ohos:height="40vp"
ohos:width="match_content"
ohos:text="Army"
ohos:text_size="16fp"
ohos:text_color_on="#FF3333"/>
</RadioContainer>
</DirectionalLayout>
1.5 在entry>src>main>resources>base>layout目录里,添加dialog_edit_duration.xml,用于编辑时长弹出对话框。 dialog_edit_duration.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:top_padding="10vp"
ohos:start_padding="12vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:clockDuration"
ohos:layout_alignment="vertical_center"
ohos:text_size="20fp"/>
<RadioContainer
ohos:id="$+id:radio_container_duration"
ohos:height="match_content"
ohos:width="200vp"
ohos:layout_alignment="left"
ohos:orientation="vertical"
ohos:top_margin="16vp"
ohos:left_margin="4vp">
<RadioButton
ohos:id="$+id:radio_btn_duration1"
ohos:height="40vp"
ohos:width="match_content"
ohos:text="$string:oneMinute"
ohos:text_size="16fp"
ohos:text_color_on="#FF3333"/>
<RadioButton
ohos:id="$+id:radio_btn_duration5"
ohos:height="40vp"
ohos:width="match_content"
ohos:text="$string:fiveMinute"
ohos:text_size="16fp"
ohos:text_color_on="#FF3333"/>
<RadioButton
ohos:id="$+id:radio_btn_duration10"
ohos:height="40vp"
ohos:width="match_content"
ohos:text="$string:tenMinute"
ohos:text_size="16fp"
ohos:text_color_on="#FF3333"/>
</RadioContainer>
</DirectionalLayout>
2.实现创建闹钟的slice逻辑开发,弹框选择,以及保存后返回主页面
2.1 新增DataConstants类,提供闹钟时长和铃声的基础数据。 DataConstants.java
package com.madixin.clock.setting.constants;
import java.util.HashMap;
import java.util.Map;
public class DataConstants {
private static Map<Integer, Integer> durationMap;
private static Map<Integer, String> bellMap;
static {
durationMap = new HashMap<>();
durationMap.put(0, 1);
durationMap.put(1, 5);
durationMap.put(2, 10);
bellMap = new HashMap<>();
bellMap.put(0, "Cannon");
bellMap.put(1, "Classic");
bellMap.put(2, "Army");
}
public static int getDutration(int id) {
return durationMap.getOrDefault(id, 0);
}
public static String getBell(int id) {
return bellMap.getOrDefault(id, "Cannon");
}
}
2.2 在common har包中添加ResourceUtil类,从String.json中获取字符串 ResourceUtil.java
package com.madixin.clock.common.util;
import ohos.app.Context;
import ohos.global.resource.Element;
public class ResourceUtil {
private static final String TAG = ResourceUtil.class.getName();
public static String getString(Context context, int id) {
try {
Element element = context.getResourceManager().getElement(id);
return element.getString();
} catch (Exception e) {
e.printStackTrace();
LogUtil.error(TAG, e.getMessage());
}
return "";
}
}
2.3 考虑到后期需要开发编辑页面,部分代码和界面可重用,因此添加BaseClockAbilitySlice继承AbilitySlice,并实现创建和添加页面的公共方法。使用clockInstance保存当前闹钟实例信息,编辑时使用CommonDialog弹框输入,保存后使用terminate关闭当前页面,返回主列表页面。 BaseClockAbilitySlice.java
package com.madixin.clock.setting.slice;
import com.madixin.clock.common.util.LogUtil;
import com.madixin.clock.common.util.ResourceUtil;
import com.madixin.clock.setting.ResourceTable;
import com.madixin.clock.setting.constants.DataConstants;
import com.madixin.clock.setting.model.Clock;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.IDialog;
public class BaseClockAbilitySlice extends AbilitySlice {
private static final String TAG = BaseClockAbilitySlice.class.getName();
private static final float DIALOG_BOX_CORNER_RADIUS = 36.0f;
private Text textName;
private Text textDuration;
private Text textBell;
protected TimePicker timePicker;
private boolean isModify = false;
protected Clock clockInstance = new Clock();
protected void initView() {
textName = (Text) findComponentById(ResourceTable.Id_text_name);
textDuration = (Text) findComponentById(ResourceTable.Id_item_text_duration);
textBell = (Text) findComponentById(ResourceTable.Id_item_text_bell);
timePicker = (TimePicker) findComponentById(ResourceTable.Id_time_picker);
textName.setText(clockInstance.getName());
textDuration.setText(DataConstants.getDutration(clockInstance.getDuration()) + " " + ResourceUtil.getString(this, ResourceTable.String_minute));
textBell.setText(DataConstants.getBell(clockInstance.getBell()));
timePicker.setHour(clockInstance.getHour());
timePicker.setMinute(clockInstance.getMinute());
timePicker.showSecond(false);//不显示秒
//返回主界面
Image imageCancel = (Image) findComponentById(ResourceTable.Id_image_cancel);
imageCancel.setClickedListener(component -> {
if (isModify) {
CommonDialog alertDialog = new CommonDialog(this);
TextField textFieldName = new TextField(this);
textFieldName.setText(ResourceTable.String_suretomodify);
textFieldName.setTextSize(20, Text.TextSizeType.FP);
DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig();
layoutConfig.alignment = LayoutAlignment.CENTER;
textFieldName.setLayoutConfig(layoutConfig);
alertDialog.setContentCustomComponent(textFieldName);
alertDialog.setButton(IDialog.BUTTON1, ResourceUtil.getString(this, ResourceTable.String_giveup), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
iDialog.destroy();
backToMainSlice(false);
}
});
alertDialog.setButton(IDialog.BUTTON3, ResourceUtil.getString(this, ResourceTable.String_save), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
iDialog.destroy();
saveClock();
backToMainSlice(true);
}
});
alertDialog.show();
} else {
backToMainSlice(false);
}
});
//保存闹钟
Image imageOk = (Image) findComponentById(ResourceTable.Id_image_ok);
imageOk.setClickedListener(component -> {
saveClock();
backToMainSlice(true);
});
//编辑闹钟名
Component layoutName = findComponentById(ResourceTable.Id_layout_name);
if (layoutName != null) {
layoutName.setClickedListener(component -> {
editClockName();
});
}
//编辑闹钟时长
Component layoutDuration = findComponentById(ResourceTable.Id_layout_duration);
if (layoutDuration != null) {
layoutDuration.setClickedListener(component -> {
editDuration();
});
}
//编辑闹钟铃声
Component bellDuration = findComponentById(ResourceTable.Id_layout_bell);
if (bellDuration != null) {
bellDuration.setClickedListener(component -> {
editBell();
});
}
}
/**
* 返回闹钟首页
*
* @param isRefresh 是否刷新界面
*/
private void backToMainSlice(boolean isRefresh) {
Intent resultIntent = new Intent();
resultIntent.setParam("isRefresh", isRefresh);
setResult(resultIntent);
terminate();
}
private void editBell() {
isModify = true;
CommonDialog bellDialog = new CommonDialog(this);
Component dialogLayout = LayoutScatter.getInstance(this)
.parse(ResourceTable.Layout_dialog_edit_bell, null, false);
RadioContainer containerBell = (RadioContainer) dialogLayout.findComponentById(ResourceTable.Id_radio_container_bell);
containerBell.mark(clockInstance.getBell());
bellDialog.setCornerRadius(DIALOG_BOX_CORNER_RADIUS);
bellDialog.setContentCustomComponent(dialogLayout);
bellDialog.setButton(IDialog.BUTTON1, ResourceUtil.getString(this, ResourceTable.String_cancel), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
iDialog.destroy();
}
});
bellDialog.setButton(IDialog.BUTTON3, ResourceUtil.getString(this, ResourceTable.String_ok), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
clockInstance.setBell(containerBell.getMarkedButtonId());
textBell.setText(DataConstants.getBell(clockInstance.getBell()));
iDialog.destroy();
}
});
bellDialog.show();
}
private void editClockName() {
isModify = true;
CommonDialog nameDialog = new CommonDialog(this);
Component dialogLayout = LayoutScatter.getInstance(this)
.parse(ResourceTable.Layout_dialog_edit_name, null, false);
TextField textFieldName = (TextField) dialogLayout.findComponentById(ResourceTable.Id_textField_name);
nameDialog.setContentCustomComponent(dialogLayout);
nameDialog.setCornerRadius(DIALOG_BOX_CORNER_RADIUS);
textFieldName.setText(textName.getText());
nameDialog.setButton(IDialog.BUTTON1, ResourceUtil.getString(this, ResourceTable.String_cancel), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
iDialog.destroy();
}
});
nameDialog.setButton(IDialog.BUTTON3, ResourceUtil.getString(this, ResourceTable.String_ok), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
iDialog.destroy();
textName.setText(textFieldName.getText());
clockInstance.setName(textFieldName.getText());
}
});
nameDialog.show();
}
private void editDuration() {
isModify = true;
CommonDialog durationDialog = new CommonDialog(this);
Component dialogLayout = LayoutScatter.getInstance(this)
.parse(ResourceTable.Layout_dialog_edit_duration, null, false);
RadioContainer containerDuration = (RadioContainer) dialogLayout.findComponentById(ResourceTable.Id_radio_container_duration);
containerDuration.mark(clockInstance.getDuration());
durationDialog.setCornerRadius(DIALOG_BOX_CORNER_RADIUS);
durationDialog.setContentCustomComponent(dialogLayout);
durationDialog.setButton(IDialog.BUTTON1, ResourceUtil.getString(this, ResourceTable.String_cancel), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
iDialog.destroy();
}
});
durationDialog.setButton(IDialog.BUTTON3, ResourceUtil.getString(this, ResourceTable.String_ok), new IDialog.ClickedListener() {
@Override
public void onClick(IDialog iDialog, int i) {
clockInstance.setDuration(containerDuration.getMarkedButtonId());
LogUtil.info(TAG, "editDuration : " + clockInstance.getDuration());
textDuration.setText(((RadioButton) containerDuration.getComponentAt(clockInstance.getDuration())).getText());
iDialog.destroy();
}
});
durationDialog.show();
}
protected void saveClock() {
}
}
2.4 新增AddClockAbilitySlice类,继承BaseClockAbilitySlice。主要实现initClock初始化和saveClock保存闹钟操作。
package com.madixin.clock.setting.slice;
import com.madixin.clock.common.util.LogUtil;
import com.madixin.clock.common.util.ResourceUtil;
import com.madixin.clock.setting.ResourceTable;
import com.madixin.clock.setting.manager.ClockManager;
import ohos.aafwk.content.Intent;
import java.util.Calendar;
public class AddClockAbilitySlice extends BaseClockAbilitySlice {
private static final String TAG = AddClockAbilitySlice.class.getName();
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_add_clock);
initClock();
initView();
}
private void initClock() {
Calendar calendar = Calendar.getInstance();
clockInstance.setName(ResourceUtil.getString(this, ResourceTable.String_defaultName));
clockInstance.setHour(calendar.get(Calendar.HOUR_OF_DAY));
clockInstance.setMinute(calendar.get(Calendar.MINUTE));
clockInstance.setDuration(0);
clockInstance.setBell(0);
clockInstance.setEnable(true);
}
@Override
protected void saveClock() {
clockInstance.setHour(timePicker.getHour());
clockInstance.setMinute(timePicker.getMinute());
ClockManager.getInstance(this.getApplicationContext()).createNewClock(clockInstance);
LogUtil.info(TAG, "createNewClock:" + clockInstance.toString());
}
}
3.实现从主页面点击“+”后的跳转逻辑
3.1 在entry>src>main>config.json里添加AddClockAbilitySlice的action信息。
"actions": [
"action.system.home",
"action.clock.addclock"
]
3.2 在MainAbility里添加AddClockAbilitySlice的路由。
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
addActionRoute("action.clock.addclock", AddClockAbilitySlice.class.getName());
}
3.3 在MainAbilitySlice的onstart增加添加按钮的响应事件,跳转AddClockAbilitySlice,以及添加onResult接收从跳转AddClockAbilitySlice的返回。
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initTablist();
initListContainer();
imageAddClock = (Image) this.findComponentById(ResourceTable.Id_image_add_clock);
imageAddClock.setClickedListener(component -> {
presentForResult(new AddClockAbilitySlice(), new Intent(), 0);
});
}
@Override
protected void onResult(int requestCode, Intent resultIntent) {
super.onResult(requestCode, resultIntent);
if (requestCode == 0 && resultIntent != null) {
Boolean isRefresh = resultIntent.getBooleanParam("isRefresh", false);
LogUtil.info(TAG, "onResult isRefresh is " + isRefresh);
if (isRefresh) {
List<Clock> clockList = getAllClocks();
listViewClockItemProvider.setDataList(clockList);
listClockContainer.setItemProvider(listViewClockItemProvider);
}
}
}
4.小结
本章完成了闹钟创建页面的开发。
下一步我们将开发闹钟修改界面。
5.代码地址:
github,提交记录:640a9f5962b2fecb535ff98f77960fb0d3cf4031