一、交互类组件

1、Switch组件

实际开发中一般作为某些功能的开关。

一般开关的文字是不显示的。

一般只设置滑块和滑轨的颜色和样式。

  • 滑道背景 :ohos:track_element="#FF0000"
  • 滑块颜色 :ohos:thumb_element="#07C160"

练习:改变状态弹出吐司

XML文件:

<Switch
    ohos:id="$+id:choose"
    ohos:height="40vp"
    ohos:width="100vp"
    ohos:text_state_on="开"
    ohos:text_state_off="关"
    ohos:text_size="20vp"
    />

Java文件:

public class MainAbilitySlice extends AbilitySlice implements AbsButton.CheckedStateChangedListener {

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //找到开关组件
        Switch choose = (Switch) findComponentById(ResourceTable.Id_choose);


        //给开关组件绑定事件
        //单击事件
        //状态改变事件
        choose.setCheckedStateChangedListener(this);

    }


    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    //当开关组件状态发生改变的时候,那么就会调用这个方法
    //参数一:表示状态改变的那个开关组件
    //参数二:表示组件当前的状态
    @Override
    public void onCheckedChanged(AbsButton absButton, boolean b) {
        if(b){
            //ToastUtils.showDialog(this,"开关开启了");
            //可以打开某个设置
        }else{
            //ToastUtils.showDialog(this,"开关关闭了");
            //可以关闭某个设置
        }
    }
}

开发中的switch

        开发中,switch一般是在设置中,作为开关使用的。

        开启或者关闭之后,会把设置保存到本地或者上传给服务器进行保存。下一次打开APP的时候就不需要再次设置,使用上一次的设置记录即可。一般情况下,会在本地和服务器都保存一下。程序刚启动的时候,会读取本地的保存的设置,如果没有再访问服务器获取默认设置信息。或者每次修改完本地配置文件的时候,都会对文件进行一个算法加密,将计算出来的结果保存到服务器中,每次打开app的时候对比一下服务器和本地记录的是否一致,如果不一致,证明用户在没有联网的时候重新设置过了,会重新上传文件信息,如果一致就不上传。

2、Slider滑块组件

基本用法:

<Slider
    ohos:height="50vp"
    ohos:width="300vp"
    进度颜色,左边的
    ohos:progress_color="#FF0000"
    滑块颜色
    ohos:thumb_element="#00FF00"
    未完成进度颜色
    ohos:background_instruct_element="#0000FF"
    次一级的进度值
    ohos:vice_progress="80"
    次一级的进度颜色
    ohos:vice_progress_element="#923456"
    是否允许用户操作滑块
    ohos:enabled="true"
    max = "100"
    min = "0"
    />
可以设置的参数如图所示:

相关事件:

ValueChangedListener(值改变事件)

接口中的方法:

  • ①:onProgressUpdated(参数一,参数二,参数三)

当滑块组件中的值改变的时候,调用该方法。

参数一:滑块对象

参数二:当前进度值

参数三:当前滑块组件是否可以调节进度

  • ②:onTouchStart

按上滑块的时候触发

  • ③:onTouchend

离开滑块的时候触发

代码示例:

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:alignment="center"
            ohos:orientation="vertical">

    <Slider
        ohos:id="$+id:slider"
        ohos:height="50vp"
        ohos:width="300vp"
        ohos:background_instruct_element="#0000FF"
        ohos:enabled="true"
        ohos:progress_color="#FF0000"
        ohos:thumb_element="#00FF00"
        ohos:vice_progress="80"
        ohos:vice_progress_element="#923456"
        ohos:max="100"
        ohos:min="0"
        />

</DirectionalLayout>
Java文件:
public class MainAbilitySlice extends AbilitySlice implements Slider.ValueChangedListener {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //找到滑块组件
        Slider slider = (Slider) findComponentById(ResourceTable.Id_slider);

        //给滑块组件绑定一个事件
        //进度值改变事件
        slider.setValueChangedListener(this);
    }


    //当滑块组件中的进度值改变的时候,就会调用这个方法
    //参数一:滑块组件对象
    //参数二:当前的进度值
    //参数三:当前滑块是否可以被滑动
    @Override
    public void onProgressUpdated(Slider slider, int i, boolean b) {
        ToastUtils.showDialog(this,"当前的进度值为:" + i);

    }

    //当用户用鼠标或者用手指
    //按下滑块不松的时候,会调用该方法
    @Override
    public void onTouchStart(Slider slider) {
        ToastUtils.showDialog(this,"按下不松");
    }

    //松开滑块的时候,会调用该方法。
    @Override
    public void onTouchEnd(Slider slider) {
        ToastUtils.showDialog(this,"松开");
    }
}

练习:相亲app

需求1:拖动滑块的同时放大或者缩小图片

需求2:移动图片

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:alignment="center"
    ohos:orientation="vertical">

    <Image
        ohos:id="$+id:img"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:image_src="$media:girl1"/>

    <Slider
        ohos:id="$+id:slider"
        ohos:height="50vp"
        ohos:width="300vp"

        ohos:background_instruct_element="#0000FF"
        ohos:max="100"
        ohos:min="0"
        />
</DirectionalLayout>
public class MainAbilitySlice extends AbilitySlice implements Slider.ValueChangedListener,
Component.TouchEventListener {
    Image img;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        //业务逻辑
        //1.滑动滑块之后,需要放大或者缩小妹子的照片
        //2.可以拖动妹子的放大之后的照片

        //找到图片组件还有滑块组件

        img = (Image) findComponentById(ResourceTable.Id_img);
        Slider slider = (Slider) findComponentById(ResourceTable.Id_slider);

        //给滑块组件绑定事情
        slider.setValueChangedListener(this);

        //给图片绑定一个滑动事件(触摸事件)
        img.setTouchEventListener(this);
    }


    //参数一:表示进度值变化的那个滑块组件对象
    //参数二:表示当前进度值
    //参数三:表示当前滑块是否可以被滑动
    @Override
    public void onProgressUpdated(Slider slider, int i, boolean b) {
        //根据进度值i来放大或者缩小图片即可
        if(i == 0){
            i = 1;
        }
        float result = (float) (i * 0.1);
        img.setScale(result,result);
    }


    //因为当我们按下滑块或者松开滑块的时候,暂时不需要做什么事情
    //所以,下面的两个方法,在本案例中,暂时用不到
    @Override
    public void onTouchStart(Slider slider) {
        //记录用户看美女的开始时间
    }

    @Override
    public void onTouchEnd(Slider slider) {
    
    }

    //x1和y1表示手指按下不松的位置
    float x1;
    float y1;

    float imgX;
    float imgY;
    //参数一:表示当前操作的组件对象。(图片)
    //参数二:动作对象
    //返回值:true 可以触发后续操作 false 只能触发第一个操作(按下不松)
    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        MmiPoint position = touchEvent.getPointerPosition(0);
        int action = touchEvent.getAction();
        if(action == TouchEvent.PRIMARY_POINT_DOWN){
            // 按下不松 获取手指的位置
            x1 = position.getX();
            y1 = position.getY();

            //获取图片的位置
            imgX = img.getTranslationX();
            imgY = img.getTranslationY();
        }else if(action == TouchEvent.POINT_MOVE){
            //移动手指

            //获取的就是手指当前的位置
            float moveX = position.getX();
            float moveY = position.getY();
            // 拿着手指当前的位置,跟x1和y1相减,就可以得到手指移动的距离
            //x和y表示手指分别在x轴和y轴移动了多少距离
            float x = moveX - x1;
            float y = moveY - y1;
            //把图片也移动这么多距离就可以
            //是在图片原有位置的基础上,再移动x和y的距离
            img.setTranslation(imgX + x , imgY + y);
        }else if(action == TouchEvent.PRIMARY_POINT_UP){
            //松开手指
            //统计用户看美女的结束时间
            //得到用户观看美女的总时间
        }
        return true;
    }
}

3、ListContainer

概述:

        ListContainer是一个列表容器类组件。在这里的每一行,我们都可以看做是一个item。如下图所示,包裹了所有item的红色的容器,就是ListContainer

注意细节:

  • ① 每一行其实就是一个独立的item
  • ② 在屏幕的上面和下面,还有很多没有展示出来的item。 当我们用手指往上滑动的时候,就可以到下面的item。 当我们用手指往下滑动的时候,就可以到上面的item 只不过划出屏幕的item会被销毁,而没有划入屏幕的item 还没有创建出来。
  • ③ 如果item过多,在内存会有垃圾。这个问题下面学习。

实现步骤:

  • 1. item去指定一个布局xml文件
  • 2. 书写一个javabean类表示item
  • 3. 写一个适配器类去管理item
  • 4. 将适配器交给ListContainer

代码实现:

子界面中的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:alignment="center"
    ohos:orientation="vertical">



    <ListContainer
        ohos:id="$+id:listcontainer"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:layout_alignment="horizontal_center"/>


</DirectionalLayout>
itemxml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_content"
    ohos:orientation="horizontal">

    <Text
        ohos:id="$+id:text"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="00:00"
        ohos:text_size="20fp"/>

</DirectionalLayout>
Javabean类:
public class Item {
    //记录的值就是赋值给item里面的text
    private String text;

    public Item() {
    }

    public Item(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
适配器类:
public class ItemProvider extends BaseItemProvider {
    //集合
    //集合中就装了所有的item的对象。
    private ArrayList<Item> list;
    private AbilitySlice as;

    public ItemProvider(ArrayList<Item> list, AbilitySlice as) {
        this.list = list;
        this.as = as;
    }

    public ArrayList<Item> getList() {
        return list;
    }

    public void setList(ArrayList<Item> list) {
        this.list = list;
    }

    public AbilitySlice getAs() {
        return as;
    }

    public void setAs(AbilitySlice as) {
        this.as = as;
    }

    //总数据的个数
    //多少个item
    @Override
    public int getCount() {
        return list.size();
    }

    //i 表示索引
    //根据索引返回数据
    @Override
    public Object getItem(int i) {
        if(list != null && i >= 0 && i < list.size()){
            return list.get(i);
        }
        return null;
    }

    //返回某一项的id
    @Override
    public long getItemId(int i) {
        return i;
    }

    //结论:
    //1.加载一个item,就需要调用一次getComponent方法
    //2.虽然索引为13的item还没有在界面中显示出来。
    //3.当item划出屏幕的时候,item就会被销毁。
    //如果页面再次往下滑动的时候,会再次调用getComponent方法。

    //但是ListContainer也会进行预加载。
    //返回item中要加载的布局对象
    //参数一:当前要加载哪一行item (item的索引)
    //参数二:表示要销毁的item的布局对象
    //参数三:优化
    @Override
    public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
        DirectionalLayout dl = (DirectionalLayout) LayoutScatter.getInstance(as).parse(ResourceTable.Layout_itemview,
null, false);
    }
    //获取每一个item里面的数据
    Item item = list.get(i);
    //把数据加载到布局里面的Text中
    Text text = (Text) dl.findComponentById(ResourceTable.Id_itemtext);
    text.setText(item.getText());
    //当上面的四行代码执行完毕之后,我就获取到了一个有数据的布局对象
    //此时我们只要把布局对象dl返回出去就可以了
    //其实就是因为在Item当中,最外层的就是这个dl布局对象
    return dl;
    }
}
AbilitySlice类:
public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //找到ListContainer
        ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_listcontainer);

        //创建集合并给集合添加数据
        ArrayList<Item> datasList = getData();

        //创建一个Item的管理员对象(适配器对象)
        //并把要展示的所有数据和要加载的页面传递过去
        ItemProvider itemProvider = new ItemProvider(datasList,this);

        //把适配器交给列表容器组件
        listContainer.setItemProvider(itemProvider);

    }


    //以后这些数据,并不是我们在app中写的。
    //都是服务器传递过来的。

    public ArrayList<Item> getData(){
    //访问服务器获取要展示的数据。
    ArrayList<Item> list = new ArrayList<>();
    //给集合添加数据
    for (int i = 0; i < 100; i++) {
        list.add(new Item("item" + i));
    }
    return list;
  }
}

内存优化:

  • 1. 加载一个itemgetComponent方法就要被调用一次。
  • 2. 假设屏幕中最多显示12item,此时第13item还没有在界面中显示出来。但是,ListContainer也会进行预加载。

预加载的好处:避免卡顿。

  • 3. item划出屏幕的时候,就会被销毁。当页面再次往下滑动的时候,会再次调用getComponent方法,加载本地xml文件,创建一个新的item布局对象。当item加载过多,内存中的垃圾就会过多,所以我们要优化。
  • 4. 优化的核心:让划出屏幕的item不销毁,而是继续复用

代码示例:

    //但是ListContainer也会进行预加载。
    //返回item中要加载的布局对象
    //参数一:当前要加载哪一行item (item的索引)
    //参数二:表示要销毁的item的布局对象
    //参数三:优化
    @Override
    public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
        DirectionalLayout dl;
        if(component != null){
            dl = (DirectionalLayout)component;
        }else{
            //获取每一个item里面的布局对象
            dl = (DirectionalLayout) LayoutScatter.getInstance(as).parse(ResourceTable.Layout_itemview, null, false);
    }
    //获取每一个item里面的数据
    Item item = list.get(i);
    //把数据加载到布局里面的Text中
    Text text = (Text) dl.findComponentById(ResourceTable.Id_itemtext);
    text.setText(item.getText());

    //当上面的四行代码执行完毕之后,我就获取到了一个有数据的布局对象
    //此时我们只要把布局对象dl返回出去就可以了
    //其实就是因为在Item当中,最外层的就是这个dl布局对象
    return dl;
  }

练习:搭建微信页面

最终效果图:

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:alignment="center"
    ohos:orientation="vertical">


    <ListContainer
        ohos:id="$+id:listcontainer"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:layout_alignment="horizontal_center"/>


</DirectionalLayout>
itemxml文件:
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_content"
    ohos:orientation="horizontal">


    <Image
        ohos:id="$+id:img"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:image_src="$media:photo"/>

    <DirectionalLayout
        ohos:height="50vp"
        ohos:width="240vp"
        ohos:orientation="vertical"
        ohos:left_margin="10vp">

        <Text
            ohos:id="$+id:title"
            ohos:height="20vp"
            ohos:width="240vp"
            ohos:text="标题"
            ohos:text_size="20fp"
            ohos:top_margin="5vp"
            />
        <Text
            ohos:id="$+id:itemtext"
            ohos:height="15vp"
            ohos:width="240vp"
            ohos:text="消息"
            ohos:text_size="15fp"
            ohos:top_margin="5vp"
            />
    </DirectionalLayout>

    <Text
        ohos:id="$+id:time"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="00:00"
        ohos:text_size="20fp"/>

</DirectionalLayout>
Javabean类:
public class Item {
    //记录的值就是赋值给item里面的text
    private int img;

    private String title;
    private String text;
    private String time;

    public Item() {
    }

    public Item(int img, String title, String text, String time) {
        this.img = img;
        this.title = title;
        this.text = text;
        this.time = time;
    }

    public int getImg() {
        return img;
    }

    public void setImg(int img) {
        this.img = img;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}
适配器类:
public class ItemProvider extends BaseItemProvider {

    //集合

    //集合中就装了所有的item的对象。

    private ArrayList<Item> list;
    private AbilitySlice as;

    public ItemProvider(ArrayList<Item> list, AbilitySlice as) {
        this.list = list;
        this.as = as;
    }

    public ArrayList<Item> getList() {
        return list;
    }

    public void setList(ArrayList<Item> list) {
        this.list = list;
    }

    public AbilitySlice getAs() {
        return as;
    }

    public void setAs(AbilitySlice as) {
        this.as = as;
    }

    //总数据的个数
    //多少个item
    @Override
    public int getCount() {
        return list.size();
    }

    //i 表示索引
    //根据索引返回数据
    @Override
    public Object getItem(int i) {
        if(list != null && i >= 0 && i < list.size()){
            return list.get(i);
        }
        return null;
    }

    //返回某一项的id
    @Override
    public long getItemId(int i) {
        return i;
    }


    //结论:
    //1.加载一个item,就需要调用一次getComponent方法
    //2.虽然索引为13的item还没有在界面中显示出来。
    //3.当item划出屏幕的时候,item就会被销毁。

    //如果页面再次往下滑动的时候,会再次调用getComponent方法。
    //但是ListContainer也会进行预加载。
    //返回item中要加载的布局对象
    //参数一:当前要加载哪一行item (item的索引)
    //参数二:表示要销毁的item的布局对象
    //参数三:优化
    @Override
    public Component getComponent(int i, Component component, ComponentContainer                 componentContainer) {
        DirectionalLayout dl;
        if(component != null){
            dl = (DirectionalLayout)component;
        }else{
            //获取每一个item里面的布局对象
            dl = (DirectionalLayout) LayoutScatter.getInstance(as).parse(ResourceTable.Layout_itemview, null, false);
        }
        //获取每一个item里面的数据
        Item item = list.get(i);
        //把数据加载到布局里面的Text中
        Text text = (Text) dl.findComponentById(ResourceTable.Id_itemtext);
        text.setText(item.getText());

        //当上面的四行代码执行完毕之后,我就获取到了一个有数据的布局对象
        //此时我们只要把布局对象dl返回出去就可以了
        //其实就是因为在Item当中,最外层的就是这个dl布局对象
        return dl;
    }
}
AbilitySlice类:
public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //找到ListContainer
        ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_listcontainer);

        //创建集合并给集合添加数据
        ArrayList<Item> datasList = getData();

        //创建一个Item的管理员对象(适配器对象)
        //并把要展示的所有数据和要加载的页面传递过去
        ItemProvider itemProvider = new ItemProvider(datasList,this);

        //把适配器交给列表容器组件
        listContainer.setItemProvider(itemProvider);

    }

    //以后这些数据,并不是我们在app中写的。
    //都是服务器传递过来的。
    public ArrayList<Item> getData(){
        //访问服务器获取要展示的数据。
        ArrayList<Item> list = new ArrayList<>();
        //给集合添加数据
        for (int i = 0; i < 100; i++) {
            list.add(new Item(ResourceTable.Media_photo,"标题","item" + i,"00:00"));
        }

        return list;
    }
}

4、Picker

基本用法:

        picker是滑动选择器组件。在一些app中选择地址的时候会用到,但是一般是三个picker选择器组合在一起使用。

如图所示:

代码示例:

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:alignment="center"
    ohos:orientation="vertical">

    <Picker

        ohos:id="$+id:picker"
        ohos:height="match_content"
        ohos:width="100vp"
        ohos:normal_text_size="20fp"
        ohos:selected_text_size="20fp"
        ohos:normal_text_color="#21a8fd"
        ohos:selected_text_color="#FF0000"
        ohos:max_value="6"
        ohos:min_value="0"
        ohos:value="0"
        />

</DirectionalLayout>
Java文件:
public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //星期一 ~ 星期日

        //1.找到滑动选择器Picker的对象
        Picker picker = (Picker) findComponentById(ResourceTable.Id_picker);

        //把要展示的内容全部放在集合中
        ArrayList<String> list = new ArrayList<>();
        list.add("星期一");
        list.add("星期二");
        list.add("星期三");
        list.add("星期四");
        list.add("星期五");
        list.add("星期六");
        list.add("星期日");


        /*//2.给滑动选择器设置展示的内容
        picker.setFormatter(
            new Picker.Formatter() {
                @Override
                public String format(int i) {
                    //参数i表示当前选择的数字
                    //返回值就是要展示的内容。
                    //return i + "";
                    return list.get(i);
                }
            }
        );*/

        //优化

        /* picker.setFormatter(
            (int i)->{
                return list.get(i);
            }
        );*/

    
        // picker.setFormatter(i->list.get(i));

        //还可以用方法引用去优化代码
        picker.setFormatter(list::get);

    }
}

练习:省市区三级联动

<?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="center"
    ohos:orientation="horizontal">

<Picker
    ohos:id="$+id:province"
    ohos:height="match_content"
    ohos:width="100vp"
    ohos:normal_text_size="20fp"
    ohos:selected_text_size="20fp"
    ohos:value="0"/>


    <Picker
        ohos:id="$+id:city"
        ohos:height="match_content"
        ohos:width="100vp"
        ohos:normal_text_size="20fp"
        ohos:selected_text_size="20fp"
        ohos:left_margin="10vp"
        ohos:value="0"/>

    <Picker
        ohos:id="$+id:district"
        ohos:height="match_content"
        ohos:width="100vp"
        ohos:normal_text_size="20fp"
        ohos:selected_text_size="20fp"
        ohos:left_margin="10vp"
        ohos:value="0"/>


</DirectionalLayout>

public class Province {
    //1.表示省份的名字
    private String name;
    //2.集合,记录省份里面所有城市的名字
    private ArrayList<String> list;

    public Province() {
    }

    public Province(String name, ArrayList<String> list) {
        this.name = name;
        this.list = list;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ArrayList<String> getList() {
        return list;
    }

    public void setList(ArrayList<String> list) {
        this.list = list;
    }
}
public class MainAbilitySlice extends AbilitySlice implements Picker.ValueChangedListener {
    Picker province;
    Picker city;
    Picker district;
    ArrayList<Province> provinceList;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);


        //1.找到三个滑动选择器组件
        province = (Picker) findComponentById(ResourceTable.Id_province);
        city = (Picker) findComponentById(ResourceTable.Id_city);
        district = (Picker) findComponentById(ResourceTable.Id_district);


        //2.创建集合,用来存储,省,市,区的信息。
        //省市的联动 和 市区的联动是一样的。

        provinceList = getData();

        //3.给三个滑动选择器组件设置默认显示数据
        //要告诉滑动选择器,最大值展示到多少
        province.setMaxValue(provinceList.size() - 1);
        //暂时只给前面的省和市进行设置
        province.setFormatter(i->provinceList.get(i).getName());


        //要告诉滑动选择器,最大值展示到多少
        city.setMaxValue(provinceList.get(0).getList().size() - 1);
        city.setFormatter(i->provinceList.get(0).getList().get(i));


        //给Picker滑动选择器绑定监听
        province.setValueChangedListener(this);

    }



    //参数一:表示当前数据变动的那个滑动选择器对象
    //参数二:表示旧值 (原来选中的值)
    //参数三:表示新值(现在选中的值)
    @Override
    public void onValueChanged(Picker picker, int oldValue, int newValue) {
        if(picker == province){
            //判断当前选择的是哪个省
            //选择哪个省,就可以把当前省对应的市设置到第二个滑动选择器中。

            //获取到当前省份的对象
            Province chooseProvince = provinceList.get(newValue);

            //设置城市的滑动选择器
            city.setMaxValue(chooseProvince.getList().size() - 1);
            city.setFormatter(i->chooseProvince.getList().get(i));

            //当前面更换省份的时候,中间的城市需要从第一个开始展示
            city.setValue(0);

        }
    }


    //在以后实际工作中
    //这些数据,是不需要我们自己在app里面手动书写的
    //一般是服务器给我们传递过来的。
    public ArrayList<Province> getData(){
        //创建一个集合用来存储所有的省份
        ArrayList<Province> provinceList = new ArrayList<>();



        //创建一个江苏省的集合,用来存储所有的城市
        ArrayList<String> jiangSuCitys = new ArrayList<>();
        jiangSuCitys.add("南京市");
        jiangSuCitys.add("苏州市");
        jiangSuCitys.add("无锡市");
        jiangSuCitys.add("扬州市");
        jiangSuCitys.add("徐州市");
        jiangSuCitys.add("泰州市");

        ArrayList<String> zheJiangCitys = new ArrayList<>();
        zheJiangCitys.add("杭州市");
        zheJiangCitys.add("宁波市");
        zheJiangCitys.add("温州市");
        zheJiangCitys.add("绍兴市");
        zheJiangCitys.add("嘉兴市");
        zheJiangCitys.add("舟山市");


        ArrayList<String> fuJianCitys = new ArrayList<>();
        fuJianCitys.add("福州市");
        fuJianCitys.add("厦门市");
        fuJianCitys.add("泉州市");
        fuJianCitys.add("莆田市");
        fuJianCitys.add("宁德市");
        fuJianCitys.add("龙岩市");

        //把省份的对象添加到provinceList集合中
        provinceList.add(new Province("江苏省",jiangSuCitys));
        provinceList.add(new Province("浙江省",zheJiangCitys));
        provinceList.add(new Province("福建省",fuJianCitys));

        //把存储所有省份的集合返回即可
        return provinceList;

    }
}

5 DatePickerTimePicker

  • DatePickerTimePicker都是时间选择器。
  • DatePicker:表示年月日
  • TimePicker:表示时分秒

代码示例:

<?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="center"

    ohos:orientation="vertical">

    <DatePicker
        ohos:id="$+id:datepicker"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:normal_text_size="20fp"
        ohos:selected_text_size="20fp"/>


    <Text
        ohos:id="$+id:text"
        ohos:height="40vp"
        ohos:width="300vp"
        ohos:text_size="35fp"/>


    <TimePicker
        ohos:id="$+id:timepicker"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:normal_text_size="20fp"
        ohos:selected_text_size="20fp"/>


</DirectionalLayout>
public class MainAbilitySlice extends AbilitySlice implements DatePicker.ValueChangedListener {
    Text text;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //1.找到两个组件
        DatePicker datePicker = (DatePicker) findComponentById(ResourceTable.Id_datepicker);
        text = (Text) findComponentById(ResourceTable.Id_text);
        TimePicker timePicker = (TimePicker) findComponentById(ResourceTable.Id_timepicker);

        //2.给时间滑动选择器设置事件(监听)
        datePicker.setValueChangedListener(this);
        timePicker.setTimeChangedListener(new TimePicker.TimeChangedListener() {
            @Override
            public void onTimeChanged(TimePicker timePicker, int hour, int minutes, int second) {
                text.setText("时间为:" + hour + minutes + second);
            }
        });
    }

    //每当datePicker里面的值发生改变的时候,系统都会自动的调用下面的方法
    //参数一:表示值发生变动的DatePicker

    //参数二~参数四:年、月、日
    @Override
    public void onValueChanged(DatePicker datePicker, int year, int month, int day) {
        text.setText(year + "年" + month + "月" + day + "日");
        //最简单,最不会出错的字符串和变量的拼接方法:
        //先把最终的结果写在字符串中
        //把其中有可能发生变化的值用变量替代
        //再把变量挪到外面去
    }
}

二、美化组件

1、美化组件分类

美化外形

  • 组件外形(方形,圆角,胶囊形,圆形)
  • 组件边框(颜色,粗细)
  • 背景颜色(有色号就行)
  • 背景渐变(线形或者辐射形)

美化状态

组件在不同状态时显示不同的样式。

暂时掌握三中状态:

  • 默认状态 (所有组件都有默认状态)
  • 按下状态 (组件按下不松时的状态)
  • 选中状态 (开关组件,多选按钮,单选按钮的开启状态)

2、graphic包中的shape标签:

graphic包中新建xml,根标签为:shape就可以自定义组件的形状。

根标签:shape

根标签包含一个属性:shape

可以取以下5个值:

  • rectangle:长方形
  • oval:椭圆

根标签包含五个子标签:

stroke:绘制边框

属性: 宽度,颜色

corners:圆角

属性:

  • radius半径
  • left_top_xleft_top_y 左上
  • right_top_xright_top_y 右上
  • left_bottom_xleft_bottom_y 左下
  • right_bottom_xright_bottom_y 右下
solid:背景填充

属性:

  • color 只能指定一个颜色
  • colors 可以指定多个颜色,渐变。
bounds:边框

可以单独设置上下左右的边框。

gradient:渐变

属性:

shader_type:类型 --- radial(辐射) linear(线性)

3、graphic包中的state-container标签:

graphic包中新建xml,根标签为:state-container就可以在不同状态下美化组件

  • 默认状态: component_state_empty
  • 按下不松的状态: component_state_pressed
  • 打开状态: component_state_checked

细节:

  • 1. component_state_empty必须要写在最下面。否则其他状态的设置不起作用。
  • 2. element中可以写指定的色号,也可以指定根标签为shapexml文件。
  • 3. element中可以指定固定的图片。

xml文件:

//按下
    <item ohos:state="component_state_pressed" ohos:element="#000000"/>
//打开状态
    <item ohos:state="component_state_checked" ohos:element="#FF0000"/>
//默认状态:要写在最下面
    <item ohos:state="component_state_empty" ohos:element="#21a8f6"/>
</state-container>

4、实际开发中的美化组件

情况一: 美工已经把图片给你做好

这种情况最简单,我们只要在state-container里面指定状态并关联图片即可。

<Button
    ohos:height="32vp"
    ohos:width="86vp"
    ohos:background_element="$graphic:press2"
    ohos:text_alignment="center"
    ohos:text_size="20fp"
    ohos:clickable="true"
    />


<item ohos:state="component_state_pressed" ohos:element="$media:registerpress"/>
<item ohos:state="component_state_empty" ohos:element="$media:register"/>

情况二: 美工没有把图片给你做好。

这种情况稍显复杂,你可以给美工提出需求。如果人家不鸟咱,咱就要自己写。

写法如下:

核心:针对于每一种状态都要写对应的xml文件。

针对于两种状态关联对应的xml文件
<item ohos:state="component_state_pressed" ohos:element="$media:registerpress"/>
<item ohos:state="component_state_empty" ohos:element="$media:register"/>
正常状态:
    <corners
        ohos:radius="15vp"
        />
    <solid
        ohos:colors="#21a8fd"
        />

按下不松时的状态:
    <corners
        ohos:radius="15vp"
        />

    <solid
        ohos:colors="#0177BE"
        />
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐