实现iOS弹出对话框中的进程视图设计

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在iOS开发中,添加进程视图到弹出对话框是一种提高用户体验的方法,尤其是当应用在执行后台任务时。这一功能涉及自定义UI设计、进度条控件的集成和更新逻辑。开发者可通过自定义UIAlertView或UIAlertController子类,并使用UIActivityIndicatorView或UIProgressView控件来展示任务进度。同时,标准的对话框元素如标题和消息也能通过UILabel来展示。该项目源码可能包含Objective-C文件,提供了自定义视图和进度显示的实现细节,是iOS开发者提升自定义对话框设计技能的优秀案例。 实现在弹出对话中添加进程视图效果

1. iOS UI设计原则

1.1 设计原则概述

在iOS应用开发中,良好的UI设计原则是打造高质量用户体验的基础。iOS的UI设计强调整洁、直观,并且注重用户的直接操作感受。设计时,需要考虑到易用性、可用性、一致性、反馈及时性等方面,以确保用户能够顺畅地与应用交互。在遵循平台指南的同时,还应结合应用的具体需求,设计出既美观又实用的用户界面。

1.2 基于人类工程学的设计

iOS的设计哲学还包括对人类工程学的深入理解。比如,视图应该足够大以便易于触摸,按钮和控件的位置需要考虑到用户的操作习惯。开发者在设计UI时应该对这些原则有深入的理解,这样才能够在视觉上吸引用户,同时保证操作的便利性和直观性。

1.3 视觉层次与布局

一个清晰的视觉层次对于用户体验至关重要。在iOS UI设计中,通过对比度、大小、颜色和布局来强调重要的元素,同时使用户界面保持整洁有序。开发者应该利用这些视觉线索来引导用户关注最核心的功能,同时确保布局的合理性和适应性,以适应不同设备的屏幕尺寸。

// 示例代码:Swift中使用布局约束创建视觉层次
view.addSubview(label)
view.addSubview(imageView)
// 约束定义
label.translatesAutoresizingMaskIntoConstraints = false
imageView.translatesAutoresizingMaskIntoConstraints = false
// 约束配置
NSLayoutConstraint.activate([
    label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 20),
    imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
    imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])

通过上述示例,可以看出在iOS开发中,合理利用AutoLayout来设置组件的位置,是构建良好视觉层次和布局的关键步骤。

2. 自定义对话框实现

2.1 自定义对话框的设计理念

2.1.1 对话框的功能和视觉层次

对话框是用户界面中的一种重要组件,其主要作用是与用户进行交云对话,显示重要信息,或者获取用户的输入。在设计对话框时,需要考虑其功能性和视觉层次。

对话框的功能主要包括:提示信息、请求输入、展示选项、进度显示等。在设计时,需要根据实际需求选择合适的功能。

视觉层次的设计对于用户体验非常重要。对话框应该有明显的边界和背景,以区别于主界面的其他内容。同时,对话框的主要操作按钮应该放在最显眼的位置,例如底部或者顶部,以引导用户进行下一步操作。

2.1.2 用户体验考量与界面布局

在设计对话框时,用户体验是必须要考虑的因素。对话框应该尽量简洁,只包含必要的信息和操作。过多的信息和选项会增加用户的认知负担,影响用户体验。

界面布局是对话框设计中的重要部分。一般来说,对话框的标题应该放在顶部,内容部分在标题下方,操作按钮则放在底部。这样的布局符合用户的阅读和操作习惯。

2.2 对话框的视图控制器创建

2.2.1 视图控制器的作用和类型选择

在iOS开发中,视图控制器(ViewController)是管理视图的对象,负责视图的显示、更新和转场。在创建对话框时,我们需要创建一个继承自UIViewController的自定义视图控制器。

对于对话框,我们可以选择使用UIModalPresentationFullScreen,这样可以保证对话框占据全屏,使用户只能操作对话框内的内容。这种方式可以提高用户的操作聚焦性,避免用户在操作对话框时被其他内容干扰。

2.2.2 视图控制器的实例化和配置

在创建了自定义视图控制器后,我们需要实例化并配置它。在实例化时,我们需要指定视图控制器的呈现样式,并将其呈现出来。

在配置视图控制器时,我们需要添加视图并进行布局。对于对话框,我们通常使用UIAlertView或者UIAlertController,它们都是视图控制器的一种,可以方便地进行配置和使用。

3. 进度条控件使用

进度条控件是应用程序中非常重要的用户界面元素,用于向用户展示某个任务的进度状态。它不仅可以提升用户体验,还能够增加用户对应用程序的信任度。在iOS开发中, UIActivityIndicatorView UIProgressView 是两个专门用于展示加载状态和进度信息的标准控件。

3.1 UIActivityIndicatorView的应用

UIActivityIndicatorView 是用于展示加载状态的控件,它通过一个旋转的动画来表示正在进行的操作。这一小节我们将详细分析活动指示器的属性和使用场景,以及如何定制动画效果。

3.1.1 活动指示器的属性和使用场景

活动指示器有如下几个属性可以被设置:

  • style :定义了活动指示器的外观样式,例如 .large .small
  • color :设置活动指示器的颜色。
  • hidesWhenStopped :当活动指示器停止旋转时,可以决定是否隐藏。

使用场景示例:

  • 在执行网络请求时,展示活动指示器来告诉用户“数据正在加载中”。
  • 在加载大量数据或者启动复杂计算时,给用户一个反馈表示有事情正在发生。

3.1.2 活动指示器的动画效果定制

默认情况下,活动指示器会有一个旋转动画。但有时候,我们可能需要一个不同的动画效果,或者对默认动画进行调整。例如,我们可以设置动画的速度、旋转方向等。下面是一个定制活动指示器动画效果的代码示例:

let activityIndicator = UIActivityIndicatorView(style: .large)
activityIndicator.color = UIColor.blue
activityIndicator.center = self.view.center

self.view.addSubview(activityIndicator)
activityIndicator.startAnimating()

// 定制动画效果,例如旋转速度
activityIndicator.transform = CGAffineTransform(scaleX: 2.0, y: 2.0)

// 自定义旋转动画方向
activityIndicator.transform = CGAffineTransform(rotationAngle: CGFloat.pi)

在这个例子中,我们首先创建了一个大尺寸的蓝色活动指示器,并将其添加到视图中心。然后通过修改 transform 属性来改变活动指示器的旋转速度和方向。

3.2 UIProgressView的应用

UIProgressView 是专门用于展示任务进度的控件,它通常用来显示文件下载、上传或其他耗时操作的完成百分比。

3.2.1 进度条控件的基本使用方法

使用 UIProgressView 的基本步骤如下:

  1. 创建一个 UIProgressView 实例。
  2. 设置 progress 属性来表示进度的完成度。
  3. 将进度条添加到视图中。

下面是一个基本使用 UIProgressView 的代码示例:

let progressView = UIProgressView(progressViewStyle: .default)
progressView.progress = 0.5 // 假设任务进度为50%
progressView.trackTintColor = UIColor.lightGray // 轨道颜色
progressView.progressTintColor = UIColor.blue // 进度条颜色

progressView.frame = CGRect(x: 20, y: 100, width: 280, height: 20)
self.view.addSubview(progressView)

在这个例子中,我们创建了一个默认样式的进度条,并设置了50%的进度,同时定义了进度条和轨道的颜色。

3.2.2 进度条控件的样式和自定义

UIProgressView 允许开发者自定义一些样式属性,例如进度条的颜色、轨道的样式等。同时,我们还可以通过自定义子类来实现更高级的自定义功能。

假设我们需要一个进度条,它的样式随着不同的进度阶段而改变,可以采取以下步骤:

  1. 创建一个 UIProgressView 的子类。
  2. 重写 draw(_:) 方法来自定义绘制进度条。
  3. 根据进度值 progress 来改变绘制内容。

下面是一个简单的示例代码,展示如何在 draw(_:) 方法中绘制一个自定义的进度条:

class CustomProgressView: UIProgressView {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        // 设置进度条的绘制样式
        let context = UIGraphicsGetCurrentContext()
        context?.setFillColor(UIColor.green.cgColor)
        context?.setStrokeColor(UIColor.clear.cgColor)
        // 根据当前进度绘制进度条
        let进度宽度 = rect.width * self.progress
        let进度区域 = CGRect(x: rect.minX, y: rect.minY, width: 进度宽度, height: rect.height)
        context?.addRect(进度区域)
        context?.drawPath(using: .fill)
    }
}

在这个例子中,我们通过改变填充颜色和绘制区域的大小来展示不同阶段的进度。

自定义进度条的样式和行为,不仅能够提升用户的视觉体验,还能够使进度显示更加符合应用的整体风格。开发者在设计和实现过程中应充分考虑到这一点,以满足不同用户的需求。

4. Objective-C代码实现

4.1 Objective-C基础语法回顾

4.1.1 类和对象的基本概念

Objective-C 是一种动态的面向对象编程语言,它扩展了 C 语言以支持类和对象。类是创建对象的模板,而对象是类的实例。在 Objective-C 中,每个对象都是 NSObject 的子类, NSObject 是所有类的根类,提供了对象模型的基础。

Objective-C 中使用 @interface 关键字来声明一个类的接口,定义它的公共属性和方法,而使用 @implementation 关键字来实现这些方法。类的私有部分可以在 @implementation 块的匿名分类中声明。

创建一个简单的类和对象的示例代码如下:

// Person.h
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
- (void)sayHello;
@end

// Person.m
@implementation Person
- (id)init {
    self = [super init];
    if (self) {
        _name = @"John";
    }
    return self;
}

- (void)sayHello {
    NSLog(@"Hello, my name is %@", _name);
}
@end

// main.m
#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        [person sayHello];
    }
    return 0;
}

上述代码定义了一个 Person 类,它有一个字符串类型的属性 name 和一个方法 sayHello 。然后在 main 函数中创建了 Person 类的一个实例并调用了其方法。

4.1.2 方法和消息传递机制

Objective-C 的方法调用机制基于“消息传递”。当你调用一个对象的方法时,实际上是在向该对象发送一条消息。该对象接收到消息后,根据方法名在类的方法列表中查找对应的实现并执行。

方法的定义格式如下:

- (returnType)methodName:(argumentType)argumentName {
    // 方法体
}

方法调用如下:

[receiver methodName:argument];

一个对象可以响应的消息数量没有限制,这使得 Objective-C 的对象能够具有很大的灵活性。消息传递不局限于已知的方法,这允许系统在运行时动态地添加方法(运行时方法调度)。

4.2 .m 和 .h 文件的结构分析

4.2.1 .m 文件中的方法实现

.m 文件包含了类的实现部分,也称为实现文件。在这里,定义了接口中声明的方法的具体行为。

实现文件的结构通常如下:

#import "Person.h"

@implementation Person

- (id)init {
    self = [super init];
    if (self) {
        // 初始化代码
    }
    return self;
}

- (void)sayHello {
    // 方法实现代码
}

@end

4.2.2 .h 文件中的接口定义

.h 文件,即头文件,定义了类的接口,它告诉编译器类是什么,包含哪些属性和方法。头文件是其他文件能够调用类方法的必要条件。

接口定义的结构如下:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, strong) NSString *name;

- (void)sayHello;

@end

接口定义了类的公共接口。属性和方法的声明使类的使用者能够知道如何与对象交互。头文件还经常包含对类使用者有用的宏定义、类型定义和常量。在编译时, @interface 会生成类的元数据,而 @implementation 会包含实际的方法实现。

代码块扩展性说明

在上述代码块中, Person 类通过 @interface 关键字声明了其接口,这包括一个属性和一个方法。然后通过 @implementation 关键字提供了这个类的实现。在 init 方法中,对象进行基本的初始化操作。 sayHello 方法则是一个简单的示例方法,它在运行时会输出一条消息。

这种结构允许开发者在不更改头文件的情况下,调整或扩展类的实现。如果需要向类添加新的行为,只需更新实现文件并重新编译。接口文件 Person.h 将保持不变,除非需要向类添加新的公共属性或方法。这样可以保证代码的封装性和模块化,同时提供了一种清晰且有效的方式来维护和升级代码。

5. 自定义UIAlertView或UIAlertController子类的创建

5.1 子类创建的目的和优势

5.1.1 重用性和扩展性的提升

在iOS开发中,使用UIAlertView或UIAlertController是非常常见的,它们用于显示警告信息或进行用户交互。然而,原生的警告框可能无法满足所有特定场景的需求。通过创建自定义的子类,开发者可以扩展原有类的功能,实现更丰富的交互和视觉效果,同时提高代码的重用性。自定义子类可以包含额外的按钮、自定义样式和动画等,使得警告框的使用更为灵活。

举个例子,假设需要一个带有额外操作项的警告框,可以创建一个继承自UIAlertController的子类,在其中添加自定义按钮和处理按钮点击事件的逻辑。创建子类的代码如下:

// MyCustomAlertController.h
#import <UIKit/UIKit.h>

@interface MyCustomAlertController : UIAlertController

- (instancetype)initWithCustomTitle:(NSString *)title customMessage:(NSString *)message;

@end

// MyCustomAlertController.m
#import "MyCustomAlertController.h"

@implementation MyCustomAlertController

- (instancetype)initWithCustomTitle:(NSString *)title customMessage:(NSString *)message {
    self = [super alertControllerWithTitle:title message:customMessage preferredStyle:UIAlertControllerStyleAlert];
    if (self) {
        // 添加自定义按钮
        [self addButtonWithTitle:@"Do Something" action:@selector(didTapCustomButton)];
    }
    return self;
}

- (void)addButtonWithTitle:(NSString *)title action:(SEL)action {
    UIAlertAction *button = [UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self performSelector:action];
    }];
    [self addAction:button];
}

- (void)didTapCustomButton {
    NSLog(@"User clicked the custom button!");
}

@end

这段代码定义了一个名为 MyCustomAlertController 的子类,它继承自 UIAlertController ,可以添加一个带有特定处理函数的自定义按钮。

5.1.2 自定义对话框的控制和灵活性

创建自定义的对话框子类不仅提供了更多的控制,还允许开发者根据应用的具体需求进行调整。例如,开发者可能希望对话框具有特定的动画效果、不同的样式,或是包含复杂的布局元素,如表单或列表。通过扩展对话框的子类,这些需求都可以得到满足。

在自定义子类中,开发者可以利用Objective-C的面向对象特性,如继承和多态,来实现这些功能。继承让子类可以复用父类的属性和方法,而多态则允许开发者通过接口定义新的行为,而不必改变现有的代码结构。

自定义子类还有一个优势是能够更好地保持代码的模块化,提高项目的可维护性。当UI组件的逻辑和样式都被封装在一个单独的类中时,其他开发者可以更容易地理解和使用这个组件。

5.2 子类的实现细节

5.2.1 子类中的属性和方法定义

在自定义子类的过程中,开发者需要决定要添加哪些属性和方法,以及它们如何与父类交互。一个常见的做法是添加新的方法来处理子类特有的行为,同时覆盖父类的方法来改变默认行为。

例如,在 MyCustomAlertController 中,除了覆盖初始化方法来添加自定义按钮外,还可以添加属性来保存与用户交互的数据,或者提供额外的方法来响应用户操作。

// MyCustomAlertController.h
@interface MyCustomAlertController : UIAlertController
@property (nonatomic, strong) NSString *customData; // 自定义数据属性
- (void)analyzeUserData; // 分析用户数据的方法
@end

在实现文件中,开发者可以添加相应的逻辑:

// MyCustomAlertController.m
@implementation MyCustomAlertController

- (void)analyzeUserData {
    // 根据自定义数据进行分析的逻辑
}

@end

5.2.2 与父类的继承和覆盖机制

子类通过继承获得了父类的特性,但也可以通过覆盖父类的方法来实现特殊的行为。例如,当用户点击自定义按钮时,可能需要在 MyCustomAlertController 中处理不同于父类的逻辑。

下面是一个覆盖父类方法的例子,其中 _ALERT UserController UIAlertController 的一个假设方法,用于处理用户点击默认按钮的事件:

// MyCustomAlertController.m
- (void)_alertUserController:(UIViewController *)controller
                         withAction:(UIAlertAction *)action {
    if ([action.title isEqualToString:@"Custom Button"]) {
        [self didTapCustomButton]; // 覆盖以处理自定义按钮逻辑
    } else {
        [super _alertUserController:controller withAction:action]; // 调用父类方法处理默认按钮
    }
}

在这个例子中,我们覆盖了 _alertUserController:withAction: 方法以改变点击自定义按钮时的行为。如果按钮是“Custom Button”,则调用 didTapCustomButton 方法,否则调用父类的同名方法。

通过这些细节的处理,自定义子类既保留了父类的功能,又增加了特定的功能和行为,这体现了面向对象编程的继承和多态的强大能力。

6. 进度更新逻辑的实现

进度更新是用户界面中不可或缺的部分,它为用户提供了后台任务执行状态的即时反馈。在移动应用中,特别是在涉及文件下载、视频播放、数据同步等操作时,一个良好的进度更新逻辑不仅能够提升用户体验,还能避免应用界面出现冻结或无响应的不良状态。

6.1 进度更新的触发机制

6.1.1 线程和异步操作的基础知识

在iOS开发中,理解线程和异步操作对实现良好的进度更新逻辑至关重要。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。

  • 主线程 (Main Thread) :负责运行用户界面相关的代码,如UI更新,事件响应等。
  • 后台线程 (Background Thread) :用于执行耗时操作,如网络请求,文件读写等,以避免阻塞主线程,影响用户体验。

异步操作则允许应用程序在后台线程执行耗时任务,同时保持主线程的响应性。iOS提供了多种机制来支持异步操作,包括Grand Central Dispatch (GCD), NSOperation, 循环引用(Blocks)等。

6.1.2 进度更新的触发条件和方法

  • 触发条件 :通常在异步任务执行的各个阶段来触发进度更新,比如开始时、加载中、出现错误或完成时。
  • 实现方法 :可以使用 NotificationCenter 进行通知发布,也可以使用 delegate 模式或 block 回调函数,将进度信息返回给主线程进行UI更新。
// 示例代码:使用NotificationCenter发布进度更新通知
NotificationCenter.default.post(name: NSNotification.Name("updateProgressNotification"), object: nil, userInfo: ["progress":进度值])
// 示例代码:使用Delegate模式回调进度更新
// 在子线程执行任务的类中定义
func updateProgress(_ progress: CGFloat) {
    delegate?.updateProgress(progress)
}

// 在主线程中接收进度更新的类中定义
func updateProgress(_ progress: CGFloat) {
    // 更新UI,例如更新进度条的值
    self.progressBar.progress = progress
}

6.2 进度数据的获取和处理

6.2.1 如何从后台任务获取进度数据

从后台任务获取进度数据,往往依赖于任务本身提供的进度信息。对于不同的任务,进度信息的获取方式可能不同。例如:

  • 网络请求 :可以利用 URLSession dataTask 方法在 URLSessionDelegate urlSession(_:dataTask:didReceive:totalBytesExpectedToReceive:) 方法中获取。
  • 文件下载 :根据已下载的字节数和总字节数进行计算。

6.2.2 进度数据显示的同步和更新策略

为了确保进度显示的准确性和用户体验,必须实现一个同步机制来同步进度数据到主线程。可以使用如下的方法:

  • 串行队列 :创建一个串行队列专门用于更新UI,确保每次只执行一个UI更新操作。
  • 锁机制 :如果多个后台线程可能同时更新进度信息,应该使用互斥锁来保证数据的一致性。
// 示例代码:使用串行队列来更新UI
let queue = DispatchQueue(label: "com.myapp.uiUpdateQueue")

func updateProgressOnQueue(_ progress: CGFloat) {
    queue.async {
        DispatchQueue.main.async {
            self.progressBar.progress = progress
        }
    }
}

通过以上各节对进度更新触发机制、数据获取和处理策略的介绍,我们不仅了解了进度更新逻辑的实现机制,还学习了如何在实际开发中应用这些理论。实践中,开发者需根据应用场景的不同,灵活选择最合适的进度更新策略。

7. UILabel的使用来展示title和message

7.1 UILabel的基本属性和应用

7.1.1 文本显示和样式定制

UILabel 是 iOS 开发中用于显示纯文本的基本组件。它的属性丰富,可以实现文本的多种显示和样式定制。开发者可以设置文本的字体(font)、颜色(textColor)、对齐方式(textAlignment)等基础属性,如下代码所示:

UILabel *label = [[UILabel alloc] init];
label.text = @"Hello, World!";
label.font = [UIFont boldSystemFontOfSize:16];
label.textColor = [UIColor redColor];
label.textAlignment = NSTextAlignmentCenter;

此外, UILabel 还支持富文本(NSAttributedString),允许开发者对文本的不同部分设置不同的样式。例如,对一段文本中的特定单词设置不同的颜色:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"Some text with a color change"];
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(10, 10)];
label.attributedText = attributedString;

7.1.2 标签与视图层次的布局和对齐

在设计界面时, UILabel 经常需要与其他界面元素(如按钮、图片等)协同布局。开发者可以使用 Auto Layout(自动布局)或 frame-based layout(基于frame的布局)来确定其位置。例如,使用 Auto Layout 将一个 UILabel 水平居中:

label.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(label);
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[label]-20-|" options:0 metrics:nil views:viewsDictionary]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[label]-20-|" options:0 metrics:nil views:viewsDictionary]];

7.2 动态更新文本内容

7.2.1 文本内容的数据绑定和动态更新

动态更新 UILabel 的文本内容是交互式应用中常见的需求。可以通过简单的属性设置来实现文本内容的动态更新。例如,根据用户的输入或数据变化来更新 UILabel 的显示:

- (IBAction)updateLabelContent:(id)sender {
    label.text = @"New content updated!";
}

当涉及到频繁更新(如进度提示、计时器等),则可以使用 NSTimer 定时器或 GCD 异步执行块来周期性地更新文本:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateLabelContent:) userInfo:nil repeats:YES];

7.2.2 多语言支持和国际化考量

对于需要支持多种语言的应用程序来说,国际化是一个重要考虑。 UILabel 支持本地化,可以为不同语言环境准备不同的字符串文件。例如,可以创建一个 Localizable.strings 文件,并为不同的语言设置相应的条目:

/* English */
"welcome_message" = "Welcome!";
/* 中文 */
"welcome_message" = "欢迎!";

在代码中引用本地化字符串:

label.text = NSLocalizedString(@"welcome_message", @"Welcome message");

NSLocalizedString 函数会根据用户设备的语言设置来返回相应的本地化字符串。这样,当用户更改设备语言时,应用程序能够自动适应并显示正确的文本内容。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在iOS开发中,添加进程视图到弹出对话框是一种提高用户体验的方法,尤其是当应用在执行后台任务时。这一功能涉及自定义UI设计、进度条控件的集成和更新逻辑。开发者可通过自定义UIAlertView或UIAlertController子类,并使用UIActivityIndicatorView或UIProgressView控件来展示任务进度。同时,标准的对话框元素如标题和消息也能通过UILabel来展示。该项目源码可能包含Objective-C文件,提供了自定义视图和进度显示的实现细节,是iOS开发者提升自定义对话框设计技能的优秀案例。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值