Rust UI框架iced_style的使用,iced_style为Rust UI库iced提供可定制的主题和样式系统

Rust UI框架iced_style的使用,iced_style为Rust UI库iced提供可定制的主题和样式系统

iced_style是Rust UI库iced的样式系统,允许开发者自定义应用程序的主题和外观。以下是使用iced_style的完整示例:

use iced::{
    widget::{button, column, text},
    Application, Settings,
};
use iced_style::{button::StyleSheet, Color, Theme};

fn main() -> iced::Result {
    // 创建自定义主题
    let theme = Theme::custom(
        // 浅色主题
        iced_style::Theme::Light,
        // 自定义按钮样式
        CustomButtonStyle::new(),
    );

    // 运行应用程序
    Counter::run(Settings::with_flags(theme))
}

// 自定义按钮样式
#[derive(Debug, Clone, Copy)]
struct CustomButtonStyle {
    background: Color,
    text_color: Color,
    border_radius: f32,
}

impl CustomButtonStyle {
    fn new() -> Self {
        Self {
            background: Color::from_rgb(0.11, 0.42, 0.87),
            text_color: Color::WHITE,
            border_radius: 12.0,
        }
    }
}

impl StyleSheet for CustomButtonStyle {
    type Style = iced::Theme;

    fn active(&self, _style: &Self::Style) -> button::Appearance {
        button::Appearance {
            background: Some(self.background.into()),
            border_radius: self.border_radius,
            text_color: self.text_color,
            ..Default::default()
        }
    }

    fn hovered(&self, style: &Self::Style) -> button::Appearance {
        let mut appearance = self.active(style);
        appearance.background = appearance.background.map(|bg| bg.lighten(0.1));
        appearance
    }
}

// 示例应用
#[derive(Debug, Clone)]
struct Counter {
    count: i32,
    theme: Theme,
}

#[derive(Debug, Clone)]
enum Message {
    Increment,
    Decrement,
}

impl Application for Counter {
    type Message = Message;
    type Flags = Theme;
    type Theme = Theme;

    fn new(theme: Self::Flags) -> (Self, iced::Command<Self::Message>) {
        (
            Self {
                count: 0,
                theme,
            },
            iced::Command::none(),
        )
    }

    fn title(&self) -> String {
        String::from("iced_style示例")
    }

    fn update(&mut self, message: Self::Message) -> iced::Command<Self::Message> {
        match message {
            Message::Increment => self.count += 1,
            Message::Decrement => self.count -= 1,
        }
        iced::Command::none()
    }

    fn view(&self) -> iced::Element<Self::Message> {
        column![
            text(format!("计数: {}", self.count)).size(50),
            button("增加").on_press(Message::Increment),
            button("减少").on_press(Message::Decrement),
        ]
        .padding(20)
        .spacing(20)
        .into()
    }

    fn theme(&self) -> Self::Theme {
        self.theme.clone()
    }
}

安装

要在项目中使用iced_style,请运行以下Cargo命令:

cargo add iced_style

或者在Cargo.toml中添加:

iced_style = "0.12.1"

主要功能

  1. 提供预设主题(Light/Dark)
  2. 允许自定义各种控件的样式
  3. 支持响应式设计(hover/active状态)
  4. 可扩展性强,可以创建自己的StyleSheet实现

1 回复

Rust UI框架iced_style使用指南

iced_style是Rust UI库iced的样式系统,它提供了强大的主题定制能力,让开发者可以轻松创建美观且一致的UI界面。

基本概念

iced_style主要包含以下几个核心部分:

  • 主题(Theme): 定义应用程序的整体视觉风格
  • 样式(Style): 针对特定组件的视觉样式
  • 调色板(Palette): 定义颜色方案

安装

Cargo.toml中添加依赖:

[dependencies]
iced = { version = "0.10", features = ["widget"] }
iced_style = "0.10"

完整示例代码

下面是一个结合了上述所有功能的完整示例:

use iced::widget::{button, column, container, radio, text};
use iced::{Background, Color, Element, Length, Sandbox, Settings};
use iced_style::theme::{self, Theme};
use iced_style::button::{Appearance, StyleSheet as ButtonStyleSheet};
use iced_style::container::{Appearance as ContainerAppearance, StyleSheet as ContainerStyleSheet};

// 定义应用消息枚举
#[derive(Debug, Clone, Copy)]
enum Message {
    ThemeSelected(Theme),
    ButtonPressed,
}

// 主应用结构体
struct MyApp {
    current_theme: Theme,
    button_press_count: u32,
}

impl Sandbox for MyApp {
    type Message = Message;

    fn new() -> Self {
        Self {
            current_theme: Theme::Light,
            button_press_count: 0,
        }
    }

    fn title(&self) -> String {
        String::from("Iced Style 完整示例")
    }

    fn update(&mut self, message: Self::Message) {
        match message {
            Message::ThemeSelected(theme) => {
                self.current_theme = theme;
            }
            Message::ButtonPressed => {
                self.button_press_count += 1;
            }
        }
    }

    fn view(&self) -> iced::Element<Self::Message> {
        // 创建自定义按钮
        let custom_button = button("自定义按钮 (点击计数: {})".replace("{}", &self.button_press_count.to_string()))
            .on_press(Message::ButtonPressed)
            .style(theme::Button::Custom(Box::new(CustomButtonStyle)))
            .width(Length::Fill);
        
        // 创建自定义容器
        let custom_container = container(text("自定义容器"))
            .style(theme::Container::Custom(Box::new(CustomContainerStyle)))
            .width(Length::Fill)
            .height(Length::Units(100));
            
        // 组装UI
        column![
            text("主题选择器").size(24),
            radio("浅色主题", Theme::Light, Some(self.current_theme), Message::ThemeSelected),
            radio("深色主题", Theme::Dark, Some(self.current_theme), Message::ThemeSelected),
            radio("自定义主题", Theme::custom(theme::Palette {
                background: Color::from_rgb(0.9, 0.95, 1.0),
                text: Color::BLACK,
                primary: Color::from_rgb(0.3, 0.6, 0.8),
                success: Color::from_rgb(0.0, 0.7, 0.0),
                danger: Color::from_rgb(0.8, 0.2, 0.2),
            }), Some(self.current_theme), Message::ThemeSelected),
            
            text("按钮示例").size(24),
            button("默认样式按钮"),
            custom_button,
            
            text("容器示例").size(24),
            custom_container
        ]
        .padding(20)
        .spacing(10)
        .into()
    }

    fn theme(&self) -> Theme {
        self.current_theme
    }
}

// 自定义按钮样式
struct CustomButtonStyle;

impl ButtonStyleSheet for CustomButtonStyle {
    type Style = Theme;

    fn active(&self, _style: &Self::Style) -> Appearance {
        Appearance {
            background: Some(Color::from_rgb(0.2, 0.7, 0.2).into()),
            border_radius: 10.0,
            border_width: 2.0,
            border_color: Color::from_rgb(0.1, 0.5, 0.1),
            text_color: Color::WHITE,
            ..Default::default()
        }
    }

    fn hovered(&self, style: &Self::Style) -> Appearance {
        let active = self.active(style);
        Appearance {
            background: Some(Color::from_rgb(0.3, 0.8, 0.3).into()),
            ..active
        }
    }
}

// 自定义容器样式
struct CustomContainerStyle;

impl ContainerStyleSheet for CustomContainerStyle {
    type Style = Theme;

    fn appearance(&self, _style: &Self::Style) -> ContainerAppearance {
        ContainerAppearance {
            background: Some(Background::Color(Color::from_rgb(0.8, 0.8, 1.0))),
            border_radius: 15.0,
            border_width: 2.0,
            border_color: Color::from_rgb(0.6, 0.6, 0.8),
            text_color: Some(Color::from_rgb(0.2, 0.2, 0.4)),
        }
    }
}

fn main() -> iced::Result {
    MyApp::run(Settings::default())
}

代码说明

  1. 主题切换功能

    • 提供了三种主题选项:浅色、深色和自定义主题
    • 使用radio组件让用户选择主题
    • 选择后立即应用新主题
  2. 自定义按钮

    • 实现了自定义按钮样式
    • 包含点击计数功能
    • 定义了正常状态和悬停状态的不同样式
  3. 自定义容器

    • 创建了带有圆角和自定义背景的容器
    • 定义了容器的边框样式和文本颜色
  4. 最佳实践应用

    • 保持整个应用的样式一致性
    • 分层设计样式,从全局主题到组件特定样式
    • 考虑可访问性,确保足够的颜色对比度

这个完整示例演示了如何结合使用iced_style的各种功能来创建一个具有完整样式系统的Rust UI应用。

回到顶部