父对象滚动循环

拉到最左边滚到到最右

拉到最右边滚动到最左


#include "MyDemo/lv_mainstart.h"
#include "lvgl/lvgl.h"
#include <stdio.h>

static lv_coord_t scr_act_width, scr_act_height;    /* 活动屏幕宽度、高度 */
static lv_obj_t *parent_obj;                        /* 定义父对象 */
static lv_obj_t *child_obj_1;                         /* 定义子对象 */
static lv_obj_t *child_obj_2;                         /* 定义子对象 */
static lv_obj_t *child_obj_3;                         /* 定义子对象 */


// // 处理滚动事件,完成页面循环切换(无限切换)
// static void scroll_begin_event(lv_event_t * e)
// {
//     lv_obj_t * cont = lv_event_get_target(e);
//     lv_event_code_t code = lv_event_get_code(e);

//     lv_obj_t * tv = lv_obj_get_parent(cont);

//     if(lv_event_get_code(e) == LV_EVENT_SCROLL_END) //获得滚动结束事件
//     {
//         lv_tabview_t * tabview = (lv_tabview_t *)tv;

//         lv_coord_t s = lv_obj_get_scroll_x(cont);//获取滚动x轴

//         lv_point_t p;
//         lv_obj_get_scroll_end(cont, &p);

//         lv_coord_t w = lv_obj_get_content_width(cont);
//         lv_coord_t t;

//         if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL)  t = -(p.x - w / 2) / w;
//         else t = (p.x + w / 2) / w;

//         if(s < 0) t = tabview->tab_cnt - 1;
//         else if((t == (tabview->tab_cnt - 1)) && (s > p.x)) t = 0;

//         bool new_tab = false;
//         if(t != lv_tabview_get_tab_act(tv)) new_tab = true;
//         lv_tabview_set_act(tv, t, LV_ANIM_ON);
//     }
// }

/**
 * @brief  基础对象事件回调
 * @param  *e :事件相关参数的集合,它包含了该事件的所有数据
 * @return 无
 */
static void parent_obj_event_cb(lv_event_t *e)
{
    
    lv_obj_t * target = lv_event_get_target(e);     /* 获取事件触发源 */
    lv_event_code_t code = lv_event_get_code(e);    /* 获取事件触发源 */
    
    int x_scroll = lv_obj_get_scroll_x(target);     // 获取事件触发源水平滚动位置
    int y_scroll = lv_obj_get_scroll_y(target);     // 获取事件触发源垂直滚动位置
    
    lv_point_t p;
    lv_obj_get_scroll_end(target, &p);                // 获取事件触发源滚动结束x轴y轴位置

    // lv_coord_t width = lv_obj_get_content_width(target);//获取事件触发源总宽度 非显示宽度

    int scroll_L = 0;

    if(code == LV_EVENT_SCROLL_END)
    {
        // LV_LOG_USER("LV_EVENT_SCROLL_END");
        LV_LOG_USER("==================begin================");
        LV_LOG_USER("x_scroll: %d, y_scroll: %d", x_scroll, y_scroll);
        LV_LOG_USER("p.x: %d,p.y: %d", p.x, p.y);
        // LV_LOG_USER("width: %d", width);
        LV_LOG_USER("==================the=end==============");
        if (x_scroll > p.x + 100)//增加100冗余避免误判直接回到顶部
        {
            lv_obj_scroll_by_bounded(target,lv_obj_get_scroll_left(target), 0, LV_ANIM_ON);
            
        }
        if (x_scroll < 0 -100)//增加100冗余避免误判直接回到底部 
        {
            lv_obj_scroll_by_bounded(target,-lv_obj_get_scroll_right(target), 0, LV_ANIM_ON);
        }    
    }
}

void lv_mainstart(void)
{
    /* 动态获取屏幕大小 */
    scr_act_width = lv_obj_get_width(lv_scr_act());                             /* 获取活动屏幕的宽度 */
    scr_act_height = lv_obj_get_height(lv_scr_act());                           /* 获取活动屏幕的高度 */

    /* 父对象 */
    parent_obj = lv_obj_create(lv_scr_act());                                   /* 创建父对象 */
    lv_obj_set_size(parent_obj, scr_act_width * 2/3, scr_act_height * 2/3);     /* 设置父对象的大小 */
    lv_obj_align(parent_obj, LV_ALIGN_CENTER, 0, 0);                           /* 设置父对象的位置:顶部居中 */
    lv_obj_set_style_bg_color(parent_obj, lv_color_hex(0x99ccff), 0);           /* 设置父对象的背景色:浅蓝色 */
    lv_obj_add_event_cb(parent_obj, parent_obj_event_cb, LV_EVENT_ALL, NULL); /* 为父对象添加事件:长按触发 */

    // lv_obj_set_scroll_snap_x(parent_obj,LV_SCROLL_SNAP_CENTER);

    /* 子对象 */
    child_obj_1 = lv_obj_create(parent_obj);                                      /* 创建子对象 */
    lv_obj_set_size(child_obj_1, scr_act_width / 3, scr_act_height / 3);          /* 设置子对象的大小 */
    lv_obj_align(child_obj_1, LV_ALIGN_CENTER, -60, 0);                    /* 重新设置子对象的位置:右侧居中,再向X轴偏移100 */
    lv_obj_set_style_bg_color(child_obj_1, lv_color_hex(0x007f7f), 0);            /* 设置子对象的背景色:深蓝色 */
    // lv_obj_add_event_cb(child_obj_1, obj_event_cb, LV_EVENT_CLICKED, NULL);       /* 为子对象添加事件:按下释放后触发 */    

    /* 子对象 */
    child_obj_2 = lv_obj_create(parent_obj);                                      /* 创建子对象 */
    lv_obj_set_size(child_obj_2, scr_act_width / 3, scr_act_height / 3);          /* 设置子对象的大小 */
    lv_obj_align(child_obj_2, LV_ALIGN_CENTER, 120, 0);                    /* 重新设置子对象的位置:右侧居中,再向X轴偏移100 */
    lv_obj_set_style_bg_color(child_obj_2, lv_color_hex(0x7f007f), 0);            /* 设置子对象的背景色:深蓝色 */
    // lv_obj_add_event_cb(child_obj_2, obj_event_cb, LV_EVENT_CLICKED, NULL);       /* 为子对象添加事件:按下释放后触发 */    
    // lv_obj_add_flag(child_obj_2, LV_OBJ_FLAG_HIDDEN);                           /* 隐藏对象 */
    /* 子对象 */
    child_obj_3 = lv_obj_create(parent_obj);                                      /* 创建子对象 */
    lv_obj_set_size(child_obj_3, scr_act_width / 3, scr_act_height / 3);          /* 设置子对象的大小 */
    lv_obj_align(child_obj_3, LV_ALIGN_CENTER, 300, 0);                    /* 重新设置子对象的位置:右侧居中,再向X轴偏移100 */
    lv_obj_set_style_bg_color(child_obj_3, lv_color_hex(0x7f7f00), 0);            /* 设置子对象的背景色:深蓝色 */
    // lv_obj_add_event_cb(child_obj_3, obj_event_cb, LV_EVENT_CLICKED, NULL);       /* 为子对象添加事件:按下释放后触发 */    
    // lv_obj_add_flag(child_obj_3, LV_OBJ_FLAG_HIDDEN);                           /* 隐藏对象 */
}

### 实现 WPF 文本循环滚动动画 在 WPF 应用程序中,可以通过 `DoubleAnimation` 和 `Storyboard` 的组合来实现文本的循环滚动效果。具体来说,通过设置 `TextBlock` 或其他显示文本的控件的位置变化,可以模拟出文本滚动的效果。 #### 创建基本布局 首先定义 XAML 文件中的基础结构: ```xml <Window x:Class="ScrollingText.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="400"> <Grid> <!-- 定义用于展示滚动文本的 TextBlock --> <TextBlock Name="scrollingText" FontSize="24" HorizontalAlignment="Left"/> </Grid> </Window> ``` 这段代码设置了窗口的基本框架以及一个名为 `scrollingText` 的 `TextBlock` 控件,它将是实际执行滚动操作的对象[^2]。 #### 添加动画逻辑 接着,在后台 C# 代码里编写启动动画的方法: ```csharp using System; using System.Windows; using System.Windows.Media.Animation; namespace ScrollingText { public partial class MainWindow : Window { private string textToScroll = "这是一个测试字符串,用来演示WPF中文本的循环滚动效果"; public MainWindow() { InitializeComponent(); // 初始化并开始第一次动画 StartScrollingAnimation(); } void StartScrollingAnimation(){ scrollingText.Text = textToScroll; var widthOfText = MeasureStringWidth(scrollingText); Canvas.SetLeft(scrollingText, this.ActualWidth); DoubleAnimation animationX = new DoubleAnimation( from: this.ActualWidth, to: -widthOfText, duration: TimeSpan.FromSeconds((this.ActualWidth + widthOfText)/80d), fillBehavior: FillBehavior.Stop ); animationX.Completed += (sender, e) => { Dispatcher.Invoke(() => StartScrollingAnimation() ); }; Storyboard storyboard = new Storyboard(); Storyboard.SetTarget(animationX, scrollingText); Storyboard.SetTargetProperty(animationX, new PropertyPath("(Canvas.Left)")); storyboard.Children.Add(animationX); storyboard.Begin(this); } /// <summary> /// 测量指定 TextBlock 显示的文字宽度 /// </summary> static double MeasureStringWidth(TextBlock tb){ FormattedText ft = new FormattedText(tb.Text, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch), tb.FontSize, Brushes.Black); return ft.WidthIncludingTrailingWhitespace; } } } ``` 上述代码实现了如下功能: - 设置初始文本; - 计算所需移动的距离(即屏幕宽度加上文本本身的长度),以此决定动画持续时间; - 构建 `DoubleAnimation` 对象调整 `Canvas.Left` 属性使文本向左平移直至完全离开视窗范围; - 当一次完整的滚动完成后触发事件重新调用此方法继续下一轮滚动; 注意这里假设父容器为 `Canvas` 类型以便于管理绝对定位。如果使用的是其他类型的面板,则需相应修改位置属性名称和计算方式[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值