uni-app UI 设计

章节简介

UI 设计是 uni-app 应用开发的重要组成部分,它直接影响用户对应用的第一印象和使用体验。本章节将详细介绍 uni-app UI 设计的核心知识点,包括设计原则、色彩搭配、布局设计等,并通过实际案例演示如何设计一个美观、易用的 uni-app 应用界面。

核心知识点

1. 设计原则

1.1 核心设计原则

  • 简洁性:保持界面简洁明了,减少视觉干扰
  • 一致性:界面元素和交互方式保持一致
  • 层次感:通过视觉层次引导用户注意力
  • 可读性:确保文本内容清晰可读
  • 可访问性:确保所有用户都能使用应用
  • 响应式:适配不同设备尺寸和屏幕方向

1.2 uni-app 特有设计原则

  • 多端适配:考虑不同平台的设计规范和用户习惯
  • 性能考量:避免过度设计影响应用性能
  • 触摸友好:优化触摸界面的交互元素大小和间距
  • 平台特性:充分利用各平台的设计特性和优势

2. 色彩搭配

2.1 色彩基础理论

  • 色彩三要素:色相、饱和度、明度
  • 色彩心理学:不同色彩传递的情感和意义
  • 色彩和谐:如何创建和谐的色彩组合
  • 色彩对比:通过对比突出重要信息

2.2 实用色彩搭配方案

  • 单色方案:基于单一色相的不同明度和饱和度变化
  • 互补色方案:使用色轮上相对的颜色
  • 类比色方案:使用色轮上相邻的颜色
  • 三元色方案:使用色轮上均匀分布的三种颜色
  • 中性色方案:以黑白灰为主,辅以少量强调色

2.3 uni-app 色彩配置

  • 主题色定义:在应用中定义统一的主题色
  • 色彩变量:使用 CSS 变量或预处理器变量管理色彩
  • 平台适配:根据不同平台调整色彩表现
  • 深色模式:设计支持深色模式的色彩方案

3. 布局设计

3.1 布局基础

  • 网格系统:使用网格系统创建整齐的布局
  • 间距规范:定义统一的间距标准
  • 对齐方式:确保元素对齐一致
  • 比例关系:使用黄金比例等美学原则

3.2 常见布局模式

  • 单栏布局:适合内容单一的页面
  • 双栏布局:适合需要同时展示多种信息的页面
  • 卡片布局:适合展示列表数据
  • 标签页布局:适合分类展示内容
  • 抽屉式布局:适合展示次要功能或导航

3.3 uni-app 布局技巧

  • Flex 布局:使用 Flexbox 实现灵活的布局
  • Grid 布局:使用 Grid 实现复杂的网格布局
  • 定位技巧:合理使用绝对定位和相对定位
  • 响应式布局:适配不同设备尺寸

4. 排版设计

4.1 字体选择

  • 系统字体:使用各平台的系统默认字体
  • 自定义字体:如需特殊字体,注意性能影响
  • 字体特性:考虑字体的可读性和美观性

4.2 排版规范

  • 字体大小层级:建立清晰的字体大小层级
  • 字重搭配:合理使用不同字重强调信息
  • 行高设置:确保文本行高适中,提高可读性
  • 字间距:适当调整字间距和词间距

5. 图标设计

5.1 图标类型

  • 线性图标:简洁现代,适合大多数应用
  • 填充图标:视觉冲击力强,适合强调操作
  • 面性图标:风格多样,适合品牌化设计
  • 拟物化图标:模拟现实物体,适合特定风格应用

5.2 图标使用规范

  • 风格统一:确保所有图标风格一致
  • 尺寸规范:使用标准尺寸的图标
  • 色彩规范:图标色彩与整体设计协调
  • 表意明确:图标含义清晰易懂

实用案例分析

案例:设计电商应用首页

1. 设计目标

  • 创建美观现代的电商应用首页
  • 确保良好的用户体验和导航流程
  • 突出商品信息和促销活动
  • 适配不同设备尺寸

2. 色彩方案

  • 主色调:#FF6B6B(红色)- 代表活力和促销
  • 辅助色:#4ECDC4(青色)- 代表信任和科技感
  • 中性色:#F7FFF7(白色)、#E0E0E0(浅灰)、#2F2F2F(深灰)
  • 强调色:#FFD166(黄色)- 用于突出重要按钮和信息

3. 布局设计

  • 顶部导航栏:搜索框、消息通知、购物车入口
  • 轮播图:展示促销活动和热门商品
  • 分类导航:图标+文字的分类入口
  • 推荐商品:卡片式布局,展示商品图片、名称和价格
  • 热门活动:专题活动入口
  • 底部标签栏:首页、分类、购物车、个人中心

4. 排版设计

  • 标题:18px,粗体
  • 副标题:16px,中等字重
  • 正文:14px,常规字重
  • 辅助文字:12px,常规字重
  • 价格:16px,粗体,红色

5. 图标设计

  • 使用线性图标,风格统一
  • 主要功能图标尺寸:24px
  • 辅助图标尺寸:16px
  • 色彩:主要功能图标使用主色调,辅助图标使用中性色

代码示例

1. 色彩变量定义

styles/variables.css

/* 色彩变量定义 */
:root {
  /* 主色调 */
  --primary-color: #FF6B6B;
  --primary-light: #FF8787;
  --primary-dark: #E05252;
  
  /* 辅助色 */
  --secondary-color: #4ECDC4;
  --secondary-light: #7EDDD7;
  --secondary-dark: #3AAFA9;
  
  /* 中性色 */
  --white: #F7FFF7;
  --light-gray: #E0E0E0;
  --gray: #9E9E9E;
  --dark-gray: #424242;
  --black: #2F2F2F;
  
  /* 强调色 */
  --accent-color: #FFD166;
  
  /* 功能色 */
  --success-color: #28A745;
  --warning-color: #FFC107;
  --error-color: #DC3545;
  --info-color: #17A2B8;
  
  /* 背景色 */
  --bg-primary: #FFFFFF;
  --bg-secondary: #F5F5F5;
  --bg-tertiary: #EEEEEE;
}

2. 首页布局实现

pages/index/index.vue

<template>
  <view class="index">
    <!-- 顶部导航栏 -->
    <view class="header">
      <view class="search-bar">
        <text class="search-icon">🔍</text>
        <text class="search-placeholder">搜索商品</text>
      </view>
      <view class="header-actions">
        <view class="action-item">
          <text class="action-icon">🔔</text>
          <text class="badge">3</text>
        </view>
        <view class="action-item">
          <text class="action-icon">🛒</text>
          <text class="badge">5</text>
        </view>
      </view>
    </view>
    
    <!-- 轮播图 -->
    <swiper class="banner" indicator-dots autoplay interval="3000">
      <swiper-item>
        <image src="https://example.com/banner1.jpg" mode="aspectFill"></image>
      </swiper-item>
      <swiper-item>
        <image src="https://example.com/banner2.jpg" mode="aspectFill"></image>
      </swiper-item>
      <swiper-item>
        <image src="https://example.com/banner3.jpg" mode="aspectFill"></image>
      </swiper-item>
    </swiper>
    
    <!-- 分类导航 -->
    <view class="category-nav">
      <view class="category-item" v-for="(category, index) in categories" :key="index">
        <view class="category-icon" :style="{ backgroundColor: category.color }">{{ category.icon }}</view>
        <text class="category-name">{{ category.name }}</text>
      </view>
    </view>
    
    <!-- 推荐商品 -->
    <view class="recommend-section">
      <view class="section-header">
        <text class="section-title">推荐商品</text>
        <text class="section-more">查看更多 →</text>
      </view>
      <view class="goods-list">
        <view class="goods-card" v-for="(goods, index) in recommendGoods" :key="index">
          <image class="goods-image" :src="goods.image" mode="aspectFill"></image>
          <view class="goods-info">
            <text class="goods-title">{{ goods.title }}</text>
            <view class="goods-price-row">
              <text class="goods-price">¥{{ goods.price }}</text>
              <text class="goods-original-price">¥{{ goods.originalPrice }}</text>
            </view>
            <text class="goods-sales">已售 {{ goods.sales }} 件</text>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 热门活动 -->
    <view class="activity-section">
      <view class="section-header">
        <text class="section-title">热门活动</text>
        <text class="section-more">查看更多 →</text>
      </view>
      <view class="activity-list">
        <view class="activity-card" v-for="(activity, index) in activities" :key="index">
          <image class="activity-image" :src="activity.image" mode="aspectFill"></image>
          <text class="activity-title">{{ activity.title }}</text>
        </view>
      </view>
    </view>
    
    <!-- 底部标签栏 -->
    <view class="tab-bar">
      <view class="tab-item active">
        <text class="tab-icon">🏠</text>
        <text class="tab-text">首页</text>
      </view>
      <view class="tab-item">
        <text class="tab-icon">🔍</text>
        <text class="tab-text">分类</text>
      </view>
      <view class="tab-item">
        <text class="tab-icon">🛒</text>
        <text class="tab-text">购物车</text>
      </view>
      <view class="tab-item">
        <text class="tab-icon">👤</text>
        <text class="tab-text">我的</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      categories: [
        { icon: "👕", name: "服装", color: "#FF6B6B" },
        { icon: "👟", name: "鞋靴", color: "#4ECDC4" },
        { icon: "📱", name: "数码", color: "#FFD166" },
        { icon: "🏠", name: "家居", color: "#6A0572" },
        { icon: "🍎", name: "食品", color: "#1A535C" }
      ],
      recommendGoods: [
        {
          image: "https://example.com/goods1.jpg",
          title: "时尚休闲T恤 舒适透气",
          price: "99",
          originalPrice: "199",
          sales: "1280"
        },
        {
          image: "https://example.com/goods2.jpg",
          title: "轻便运动鞋 减震防滑",
          price: "299",
          originalPrice: "499",
          sales: "856"
        },
        {
          image: "https://example.com/goods3.jpg",
          title: "智能手机 6GB+128GB",
          price: "2999",
          originalPrice: "3999",
          sales: "342"
        },
        {
          image: "https://example.com/goods4.jpg",
          title: "北欧风格沙发 舒适耐用",
          price: "1999",
          originalPrice: "2999",
          sales: "156"
        }
      ],
      activities: [
        {
          image: "https://example.com/activity1.jpg",
          title: "限时特惠"
        },
        {
          image: "https://example.com/activity2.jpg",
          title: "新品上市"
        },
        {
          image: "https://example.com/activity3.jpg",
          title: "会员专享"
        }
      ]
    };
  }
};
</script>

<style scoped>
/* 导入色彩变量 */
@import "../../styles/variables.css";

.index {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background-color: var(--bg-secondary);
}

/* 顶部导航栏 */
.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background-color: var(--bg-primary);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.search-bar {
  flex: 1;
  display: flex;
  align-items: center;
  background-color: var(--bg-tertiary);
  border-radius: 20px;
  padding: 8px 16px;
  margin-right: 12px;
}

.search-icon {
  margin-right: 8px;
  color: var(--gray);
}

.search-placeholder {
  color: var(--gray);
  font-size: 14px;
}

.header-actions {
  display: flex;
  align-items: center;
}

.action-item {
  position: relative;
  margin-left: 20px;
}

.action-icon {
  font-size: 20px;
  color: var(--dark-gray);
}

.badge {
  position: absolute;
  top: -8px;
  right: -8px;
  background-color: var(--primary-color);
  color: white;
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 10px;
  min-width: 16px;
  text-align: center;
}

/* 轮播图 */
.banner {
  width: 100%;
  height: 180px;
}

.banner image {
  width: 100%;
  height: 100%;
}

/* 分类导航 */
.category-nav {
  display: flex;
  flex-wrap: wrap;
  padding: 20px 16px;
  background-color: var(--bg-primary);
  margin-bottom: 12px;
}

.category-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 20%;
  margin-bottom: 16px;
}

.category-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin-bottom: 8px;
}

.category-name {
  font-size: 12px;
  color: var(--dark-gray);
}

/* 推荐商品 */
.recommend-section {
  background-color: var(--bg-primary);
  padding: 16px;
  margin-bottom: 12px;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.section-title {
  font-size: 18px;
  font-weight: bold;
  color: var(--dark-gray);
}

.section-more {
  font-size: 14px;
  color: var(--gray);
}

.goods-list {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -8px;
}

.goods-card {
  width: 50%;
  padding: 0 8px;
  margin-bottom: 16px;
}

.goods-image {
  width: 100%;
  height: 160px;
  border-radius: 8px;
  margin-bottom: 8px;
}

.goods-info {
  padding: 0 4px;
}

.goods-title {
  font-size: 14px;
  color: var(--dark-gray);
  margin-bottom: 8px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.goods-price-row {
  display: flex;
  align-items: center;
  margin-bottom: 4px;
}

.goods-price {
  font-size: 16px;
  font-weight: bold;
  color: var(--primary-color);
  margin-right: 8px;
}

.goods-original-price {
  font-size: 12px;
  color: var(--gray);
  text-decoration: line-through;
}

.goods-sales {
  font-size: 12px;
  color: var(--gray);
}

/* 热门活动 */
.activity-section {
  background-color: var(--bg-primary);
  padding: 16px;
  margin-bottom: 60px;
}

.activity-list {
  display: flex;
  overflow-x: auto;
  padding-bottom: 8px;
}

.activity-card {
  flex: 0 0 120px;
  margin-right: 12px;
}

.activity-image {
  width: 100%;
  height: 80px;
  border-radius: 8px;
  margin-bottom: 8px;
}

.activity-title {
  font-size: 12px;
  color: var(--dark-gray);
}

/* 底部标签栏 */
.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-around;
  align-items: center;
  height: 50px;
  background-color: var(--bg-primary);
  box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.1);
}

.tab-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px 0;
}

.tab-item.active .tab-icon,
.tab-item.active .tab-text {
  color: var(--primary-color);
}

.tab-icon {
  font-size: 20px;
  margin-bottom: 2px;
  color: var(--gray);
}

.tab-text {
  font-size: 12px;
  color: var(--gray);
}
</style>
« 上一篇 uni-app 原型设计 下一篇 » uni-app 用户体验优化