LVGL v8 可以实现真正的循环滚动,相关方法请自行百度,这里只是一种基于 v7.11.0 的实现方法

折腾了几天,还是把按键切换显示对象的形式换回了伪循环滚动,现将踩坑记录在此。

要想达到每个对象显示时居于屏幕中心、并且能循环滚动,就需要解决两个问题:

1. 实现一个将指定对象滚动到屏幕中心的函数

只用 lv_page_focus 不能实现 2 个以上对象居中显示的效果,但只有 2 个对象时却可以

  • 替代方案 1
    • 聚焦到第 2 个对象后删除第 1 个对象,但实测发现会导致动画丢失。
    • 如果将删除操作放在动画结束的回调函数中,则会出现更多奇怪的 bug
  • 替代方案 2
    • 在对象之间插入 1 条线作为聚焦对象
    • 实测发现对线聚焦后,线不会刚好在屏幕边沿出现,而是会在边沿靠上一点的位置,因此还是不行

2. 实现能循环滚动的函数

  • 替代方案 1
    • 循环删除和创建对象
    • 如前所述,会导致动画丢失
  • 替代方案 2
    • 用 tileview
    • tileview 无法仅用代码来选择聚焦哪个对象,必须要求屏幕是触屏,因此该方案无效

曲线解法:伪循环滚动

  • 使用 lv_page_focus,不同的是将卡片高度设置为屏幕高度、inner_pad 和 vertical_pad 都设置为 0
  • 优点
    • 聚焦到对应卡片时显示效果就是卡片刚好居中,并且不会丢失动画
    • 肉眼效果就是卡片在循环滚动
  • 缺点
    • 卡片之间的间隔没有了
    • 卡片实际没有滚动循环

下面是相关实现代码(不是完整代码):

//容器变量
lv_obj_t *cont_kitchen;//厨房节点容器
lv_obj_t *cont_livingRoom;//客厅节点容器
lv_obj_t *cont_hallway;//过道节点容器
lv_obj_t *cont_bedRoom;//卧室节点容器

//容器数组,用来循环切换焦点
static lv_obj_t *cards[CARD_NUM];
//卡片id
static int card_id = 0;

void SystemTab_Create(lv_obj_t* parent){
    /************配置页面样式********/
    lv_page_set_scrl_layout(parent,LV_LAYOUT_COLUMN_MID);
    lv_obj_set_style_local_pad_ver(parent,LV_PAGE_PART_SCROLLABLE,LV_STATE_DEFAULT,0);
    lv_obj_set_style_local_pad_inner(parent,LV_PAGE_PART_SCROLLABLE,LV_STATE_DEFAULT, 0);
    lv_obj_add_style(parent,LV_PAGE_PART_BG,&style_font_14);//14号中文字体
    lv_page_set_scrlbar_mode(parent,LV_SCRLBAR_MODE_OFF);//关闭滚动条

    /************创建各个节点对应容器********/
    cont_kitchen = cont_kitchen_create(parent);
    cont_livingRoom = cont_livingRoom_create(parent);
    cont_hallway = cont_hallway_create(parent);
    cont_bedRoom = cont_bedRoom_create(parent);

    //将各容器(卡片)保存到数组中,方便后续循环切换
    cards[0] = cont_kitchen;
    cards[1] = cont_livingRoom;
    cards[2] = cont_hallway;
    cards[3] = cont_bedRoom;
}

//每触摸一次按键就会调用该函数
void SwitchCard(void){
    card_id++;
    if(card_id >= CARD_NUM)
        card_id = 0;
    lv_page_focus(tab_SystemState,cards[card_id],LV_ANIM_ON);
}

void ReadButton(lv_task_t *task){
    if(button_touched[BUTTON_SWITCH_TAB] == true){
        SwitchTab();
        button_touched[BUTTON_SWITCH_TAB] = false;
    }
    if(button_touched[BUTTON_SCROLL_PAGE] == true){
        SwitchCard();
        button_touched[BUTTON_SCROLL_PAGE] = false;
    }
}

运行效果:

运行效果

最后修改:2023 年 10 月 18 日
如果觉得我的文章对你有用,请随意赞赏