LVGL自定义滑动

请添加图片描述

触摸和编码器都可以操作


typedef struct
{
    lv_obj_t* obj;
    int16_t x;
    int16_t y;
    int16_t width;
    int16_t height;
}pos_and_size_t;

typedef struct
{
    lv_obj_t* obj;
    lv_coord_t height;
    lv_coord_t width;
    lv_coord_t width_pad;
    lv_coord_t height_pad;
    lv_coord_t child_widget;
    lv_coord_t child_height;
}widget_attr_t;

#define NUMBER_OF_MENUS    10

static pos_and_size_t ps[NUMBER_OF_MENUS+4];
static widget_attr_t widget =
{
    .height = 260,
    .height_pad = 10,
    .width = 360,
    .width_pad = 10,
};

void widget_refresh(void)
{
    for (int i = 0; i < sizeof(ps) / sizeof(ps[0]); i++)
    {
        lv_obj_set_size(ps[i].obj, ps[i].width, ps[i].height);
        lv_obj_set_pos(ps[i].obj, ps[i].x, ps[i].y);
    }
}

/**
 * @brief 根据x坐标,计算y坐标和宽度
*/
void widget_get_y_w(int x, int* y, int* w)
{
    float k1 = (2 * widget.height_pad + 3 * widget.child_height) * 1.0f / (2 * widget.width_pad + 3 * widget.child_widget);
    float b1 = widget.height_pad - k1 * widget.width_pad;
    float k2 = (3*widget.child_widget) * 1.0f / (2 * widget.width_pad + 3 * widget.child_widget);
    float b2 = widget.child_widget - k2 * widget.width_pad;

    float k3 = (2 * widget.height_pad + 3*widget.child_height) * -1.0f / (2 * widget.width_pad + 6 * widget.child_widget);
    float b3 = widget.height_pad - k3 * (5*widget.width_pad+9*widget.child_widget);
    float k4 = (3 * widget.child_widget) * -1.0f / (2 * widget.width_pad + 6 * widget.child_widget);
    float b4 = widget.child_widget - k4 * (5*widget.width_pad + 9*widget.child_widget);
    if (x < widget.width_pad)
    {
        *y = widget.height_pad;
        *w = widget.child_widget;
    }
    else if (x < 3 * widget.width_pad + 3 * widget.child_widget)
    {
        *y = k1 * x + b1;
        *w = k2 * x + b2;
    }
    else if (x < 5 * widget.width_pad + 9 * widget.child_widget)
    {
        *y = k3 * x + b3;
        *w = k4 * x + b4;
    }
    else
    {
        *y = widget.height_pad;
        *w = widget.child_widget;
    }
}


void widget_update(widget_attr_t* widget)
{
    int start_x = lv_obj_get_scroll_x(widget->obj);

    for (int i = 1; i < sizeof(ps) / sizeof(ps[0]); i++)
    {
        int x = ps[i - 1].x + ps[i - 1].width + widget->width_pad;
        int diff = (x - start_x);
        ps[i].x = x ;
        
        widget_get_y_w(diff, &ps[i].y, &ps[i].width);
        ps[i].height = ps[i].width;
    }

    int index = 1;
    for (int i = 1; i < sizeof(ps) / sizeof(ps[0]); i++)
    {
        if (ps[i].width > ps[index].width)
        {
            index = i;
        }
        lv_obj_clear_state(ps[i].obj, LV_STATE_FOCUS_KEY);
    }
    lv_obj_add_state(ps[index].obj, LV_STATE_FOCUS_KEY);

    widget_refresh();
}

/**
 * @brief 
*/
void widget_end(widget_attr_t* widget)
{
    static int start_x_old = 0;
    int start_x = lv_obj_get_scroll_x(widget->obj);

    if (abs(start_x_old - start_x) < 5)
    {
        return;
    }
    start_x_old = start_x;
    int index = 1;
    for (int i = 1; i < sizeof(ps) / sizeof(ps[0]); i++)
    {
        if (ps[i].width > ps[index].width)
        {
            index = i;
        }
        lv_obj_clear_state(ps[i].obj, LV_STATE_FOCUS_KEY);
    }

    lv_obj_scroll_to_x(widget->obj, (index-2)*(widget->width_pad + widget->child_widget), LV_ANIM_OFF);
    lv_group_focus_obj(ps[index].obj);
    lv_obj_add_state(ps[index].obj, LV_STATE_FOCUS_KEY);
}

lv_timer_t* s_timer = NULL;
static void timer_cb(lv_timer_t* t)
{
    lv_timer_pause(s_timer);
    widget_end(&widget);
}


static widget_cb(lv_event_t* e)
{
    lv_event_code_t code = lv_event_get_code(e);
    if (LV_EVENT_SCROLL == code)
    {
        lv_timer_pause(s_timer);
        widget_update(&widget);
    }
    else if(code == LV_EVENT_SCROLL_END)
    {
        //结束滑动时,如果没有控件在最中间位置,将最近的控件滑动到最中间
        lv_timer_reset(s_timer);
        lv_timer_resume(s_timer);
    }
    
}


static btn_cb(lv_event_t* e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t* obj = lv_event_get_target(e);
    if (LV_EVENT_FOCUSED == code)
    {
        //焦点移动时,滑动控件,始终保持最中间控件聚焦
        int index = lv_event_get_user_data(e);
        lv_obj_scroll_to_x(lv_obj_get_parent(obj), (index - 2) * (widget.width_pad + widget.child_widget), LV_ANIM_OFF);
    }
}
void widget_init(void)
{
    widget.child_widget = (widget.width - 6 * widget.width_pad) / 10;
    widget.child_height = (widget.height - 2 * widget.height_pad) / 8;

    widget.obj = lv_obj_create(lv_scr_act());
    lv_obj_set_size(widget.obj, widget.width, widget.height);
    //lv_obj_set_scrollbar_mode(widget.obj, LV_SCROLLBAR_MODE_OFF);
    lv_obj_set_style_bg_opa(widget.obj, LV_OPA_0, LV_STATE_DEFAULT);
    lv_obj_set_style_pad_all(widget.obj, 0, LV_STATE_DEFAULT);
    //lv_obj_set_scroll_snap_x(obj, LV_SCROLL_SNAP_CENTER);
    lv_obj_clear_flag(widget.obj, LV_OBJ_FLAG_SCROLL_ELASTIC);

    s_timer = lv_timer_create(timer_cb, 100, 0);
    lv_timer_pause(s_timer);

    //创建初始屏幕,显示5个控件,宽度 1, 2, 4, 2, 1,
    for (int i = 0; i < sizeof(ps) / sizeof(ps[0]); i++)
    {
        ps[i].obj = lv_btn_create(widget.obj);
        lv_obj_t* lab = lv_label_create(ps[i].obj);
        lv_label_set_text_fmt(lab, "%d", i);
        lv_obj_align(lab, LV_ALIGN_CENTER, 0, 0);
        lv_obj_set_scrollbar_mode(ps[i].obj, LV_SCROLLBAR_MODE_OFF);
        lv_obj_add_event_cb(ps[i].obj, btn_cb, LV_EVENT_ALL, i);
        ps[i].width = widget.child_widget;
        ps[i].height = widget.child_height;
    }

    ps[1].width = widget.child_widget*2;
    ps[1].height = widget.child_height*2;
    
    ps[2].width = widget.child_widget*4;
    ps[2].height = widget.child_height*4;
    
    ps[3].width = widget.child_widget*2;
    ps[3].height = widget.child_height*2;
    

    ps[0].x = widget.width_pad;
    ps[0].y = widget.height_pad;
    for (int i = 1; i < sizeof(ps) / sizeof(ps[0]); i++)
    {
        ps[i].y = widget.height_pad;
        ps[i].x = widget.width_pad + ps[i - 1].x + ps[i - 1].width;
    }
    ps[1].y = widget.height_pad*2 + widget.child_height;
    ps[2].y = widget.height_pad*3 + widget.child_height*3;
    ps[3].y = widget.height_pad*2 + widget.child_height;

    //隐藏开头两个
    lv_obj_add_flag(ps[0].obj, LV_OBJ_FLAG_HIDDEN);
    lv_obj_add_flag(ps[1].obj, LV_OBJ_FLAG_HIDDEN);

    //隐藏最后两个
    lv_obj_add_flag(lv_obj_get_child(ps[NUMBER_OF_MENUS + 2].obj, -1), LV_OBJ_FLAG_HIDDEN);
    lv_obj_add_flag(lv_obj_get_child(ps[NUMBER_OF_MENUS + 3].obj, -1), LV_OBJ_FLAG_HIDDEN);

    lv_obj_remove_style_all(ps[NUMBER_OF_MENUS + 2].obj);
    lv_obj_remove_style_all(ps[NUMBER_OF_MENUS + 3].obj);
    lv_obj_set_style_border_width(ps[NUMBER_OF_MENUS + 2].obj, 0, LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ps[NUMBER_OF_MENUS + 3].obj, 0, LV_STATE_DEFAULT);

    lv_obj_set_style_bg_opa(ps[NUMBER_OF_MENUS + 2].obj, LV_OPA_0, LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ps[NUMBER_OF_MENUS + 3].obj, LV_OPA_0, LV_STATE_DEFAULT);


    lv_obj_add_event_cb(widget.obj, widget_cb, LV_EVENT_ALL, NULL);
    widget_refresh();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/585249.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024王炸组合!基于Mamba的遥感图像处理引爆顶会!

对比传统方法&#xff0c;基于Mamba的遥感图像处理在计算效率和分析精度方面遥遥领先&#xff0c;Mamba遥感也成为了论文研究的新方向。 具体来说&#xff0c;在融合高分辨率的空间图像和低分辨率的光谱图像获取综合信息方面&#xff0c;Mamba可以提升性能&#xff0c;同时保持…

【Harmony3.1/4.0】笔记七-选项卡布局

概念 当页面信息较多时&#xff0c;为了让用户能够聚焦于当前显示的内容&#xff0c;需要对页面内容进行分类&#xff0c;提高页面空间利用率。Tabs组件可以在一个页面内快速实现视图内容的切换&#xff0c;一方面提升查找信息的效率&#xff0c;另一方面精简用户单次获取到的…

MySQL CRUD操作

前言&#x1f440;~ 上一章我们介绍了数据库的一些基础操作&#xff0c;关于如何去创建一个数据库&#xff0c;还有使用数据库&#xff0c;删 除数据库以及对表进行的一些基础操作&#xff0c;今天我们学习CRUD操作 俗称&#xff08;增删改查&#xff09; 如果各位对文章的内…

Objenesis 底层

Objenesis 简介 Objenesis 是一个 Java 库&#xff0c;用于在不调用构造方法的情况下创建对象。由于绕过了构造方法&#xff0c;所以无法调用构造方法中的初始化逻辑。相应的&#xff0c;Objenesis 无法创建抽象类、枚举、接口的实例对象。 起源 与其称之为起源&#xff0c;…

基于ST的STM32F407ZGT6嵌入式uCOS-III V3.08 操作系统工程实验

1.基于的开发板 2.原理图截图: 3.主控芯片框图与性能特点: High-performance foundation line, Arm Cortex-M4 core with DSP and FPU, 1 Mbyte of Flash memory, 168 MHz CPU, ART Accelerator, Ethernet, FSMC The STM32F405xx and STM32F407xx family is based on the high…

多家企业机密数据遭Lockbit3.0窃取,亚信安全发布《勒索家族和勒索事件监控报告》

本周态势快速感知 本周全球共监测到勒索事件87起&#xff0c;与上周相比勒索事件大幅下降。美国依旧为受勒索攻击最严重的国家&#xff0c;占比45%。 本周Cactus是影响最严重的勒索家族&#xff0c;Lockbit3.0和Bianlian恶意家族紧随其后&#xff0c;从整体上看Lockbit3.0依旧…

Meltdown 以及Linux KPTI技术简介

文章目录 前言一、Introduction二、 Background2.1 Out-of-order execution2.2 Address Spaces2.3 Cache Attacks 三、A Toy Example四、Building Blocks of the Attack4.1 Executing Transient Instructions4.2 Building a Covert Channel 五、Meltdown5.1 Attack Description…

深度学习之视觉特征提取器——LeNet

LeNet 引入 LeNet是是由深度学习巨头Yann LeCun在1998年提出&#xff0c;可以算作多层卷积网络在图像识别领域的首次成功应用。我们现在通常说的LeNet是指LeNet-5&#xff0c;最早的LeNet-1在1988年即开始研究&#xff0c;前后持续十年之久。但是&#xff0c;受限于当时计算机…

c++初阶——类和对象(下)

大家好&#xff0c;我是小锋&#xff0c;今天我们来学习我们类和对象的最后一个章节&#xff0c;我们本期的内容主要是类和对象的一些细节进行讲解 再谈构造函数 我们在初始化时有两种方式一种是函数体内初始化&#xff0c;一种是初始化列表 我们先来看看日期类的初始化 构造…

[机缘参悟-166] :周期论:万物的周期现象是这个世界有序性和稳定性保障;超越周期:在轮回中,把握周期节奏。

目录 前言&#xff1a;超越周期 一、周期是大自然和宇宙的规律&#xff0c;是天道 1.1 概述 1.2 万物的周期规律的现象 1.3 电磁波的周期 二、计算机世界中的周期性 三、佛家的生命轮回规律 四、人类社会发展的周期规律 五、经济活动的周期规律 5.1 概述 5.2 股市的…

Ieetcode——21.合并两个有序链表

21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 合并两个有序链表我们的思路是创建一个新链表&#xff0c;然后遍历已知的两个有序链表&#xff0c;并比较其节点的val值&#xff0c;将小的尾插到新链表中&#xff0c;然后继续遍历&#xff0c;直到将该两个链表…

C语言实验-函数与模块化程序设计

一&#xff1a; 编写函数fun&#xff0c;其功能是&#xff1a;输入一个正整数&#xff0c;将其每一位上为偶数的数取出重新构成一个新数并输出。主函数负责输入输出&#xff0c;如输入87653142&#xff0c;则输出8642。&#xff08;main函数->fun函数&#xff09; #define _…

【代码问题】【Pytorch】训练模型时Loss为NaN或INF

解决方法或者问题排查&#xff1a; 加归一化层&#xff1a; 我的问题是我新增的一个模块与原来的模块得到的张量相加&#xff0c;原张量是归一化后的&#xff0c;我的没有&#xff1a; class Module(nn.Module):def __init__(self,dim,):super().__init__()# 新增一个LayerNo…

节假日如何快速回应客户消息?

在宝贵的休闲时光或者特殊的节日期间&#xff0c;有时候由于工作、家庭等原因&#xff0c;我们很难及时回应客户的消息。那么如何在忙碌之时&#xff0c;如何确保与他人的交流畅通无阻呢&#xff1f;答案就是使用微信私域流量管理系统。 01 机器人自动回复设置 机器人自动回…

酷我音乐车机版+v6.0.1.0车机共存会员版【附带安装包下载地址】

简介 很多车机的酷我音乐app有限制&#xff0c;不能完全使用酷我音乐的所有功能。我这里分享一个可以使用全部功能的酷我音乐app&#xff0c;大家可以自行下载。 界面预览 软件下载地址【转存到自己的网盘后即可下载】 网盘地址&#xff1a;https://pan.xunlei.com/s/VNwgzNV…

Redis的事务机制能保证ACID属性吗?

目录 事务 ACID 属性 用户如何开启Redis的事务&#xff1f; 使用redis-cli客户端来展示 ​Go语言编码使用事务 Redis 的事务机制能保证哪些属性&#xff1f; 1. 原子性 语法错误 运行错误 执行EXEC时&#xff0c;Redis发生故障 Redis对事务原子性属性的保证情况 2. 一…

idm下载速度慢解决办法 idm批量下载怎么用 idm优化下载速度 Internet Download Manager解决下载速度慢的方法教程

IDM (Internet Download Manager)是一款兼容性大&#xff0c;支持多种语言的下载管理软件&#xff0c;它可以自动检测并下载网页上的内容&#xff0c;这正是这一优点&#xff0c;使得它受到了广大用户的喜爱。但是在下载的过程中&#xff0c;我们会遇到idm下载速度慢怎么回事&a…

深度学习系列66:试穿模型IDM-VTON上手

1. 模型概述 如图&#xff0c;总体流程为&#xff1a; 输入为&#xff1a;衣服的编码xg&#xff1b;人物noise的编码xt&#xff1b;人物身上衣物的mask和人体pose分割(densepose)&#xff1b;衣服部分经过两部分网络&#xff1a;1&#xff09;高级语义网络IP-Adapter&#xff…

假设检验随想

⭐️ 前言 你会吵架吗&#xff1f;你会用数学吵架吗&#xff0c;不会的话就过来看看吧&#xff0c;哈哈 西方人发明了现代意义上的概率论&#xff0c;于是就想把它推广到生产和生活中。借助一大堆的概率论中的概念&#xff0c;他们发明了假设检验&#xff0c;想利用有限的数据…

Cloudflare高级防御规则 看看我的网站如何用防御的

网站已趋于稳定&#xff0c;并且经过nginx调优。我想先分享一下Cloudflare的WAF规则&#xff0c;因为这是最有效的防御之一&#xff0c;可以抵御大量恶意攻击流量&#xff0c;我已经验证了数月。 对于海外独立站电商网站&#xff0c;Cloudflare的CDN服务是首选&#xff0c;它强…
最新文章