android

Android UI开发

第一章

学习目标

一、Android开发环境搭建

HelloWorld程序的编写

二、Android程序结构

Android程序打包过程

三、通信技术

Android体系结构

(1)什么是Android?

Android本意指“机器人”,Google公司将Android的标识设计为一个绿色机器人、表示Android系统符合环保概念,是一个轻薄短小,功能强大的移动系统,是第一个真正为手机打造的开放性系统。

Android是一种基于Linux的开源的操作系统

主要使用于移动智能设备,如智能手机、平板电脑和智能电视等

Android操作系统最初由Andy Rubin开发,主要支持手机

目前Android系统由Google公司和84家硬件制造商、软件开发商及电信营运商组建的开放手机联盟领导及开发

1.1.1 通信技术

第一代通信技术(1G):是指最初的模拟、仅限语音的蜂窝电话标准。

第二代通信技术(2G):是指第2代移动通信技术,代表为GSM,以数字语音传输技术为核心。

第三代通信技术(3G):是指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。

第四代通信技术(4G):又称IMT-Advanced技术,它包括了TD-LTE 和 FDD-LTE。

1.1.2 Android起源

Android一词最早出现于法国作家利尔亚当在1886年发表的科幻小说《未来夏娃》中,将外表像人的机器起名为Android。

Android操作系统最初是由安迪·罗宾(Andy Rubin)开发出的,2005年被Google收购,并于2007年11月5日正式向外界展示了这款系统。

2003年10月鲁宾创建Android科技公司,并打造了Android手机操作系统,他也被誉为“Android之父”

2005年8月17日,Google收购了Android科技公司

2007年11月5日,在Google的领导下,成立开放手机联盟

2008年10月,第一部android智能手机T-Mobile G1 发布  
nexus

2010年2月份,Linux内核开发者Greg Kroah-Hartman将Android的驱动程序从Linux内核“状态树”(“staging tree”)上除去,从此,Android与Linux开发主流将分道扬镳

2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一

2013年的第四季度,Android平台手机的全球市场份额已经达到78.1%

1.1.5   Android 各个版本

1.5 Cupcake(纸杯蛋糕) --API 3

1.6 Donut(甜甜圈) --API 4

2.1 Éclair(闪电泡芙) --API 7

2.2 Froyo(冻酸奶) --API 8

2.3 Gingerbread(姜饼)
–API 9 10

3.0 Honeycomb(蜂巢)
–API 11

4.0 Icecream
SandWich(三明治) –API14 15

4.1 Jelly Bean (果冻豆 ) --API16

4.2 Jelly Bean (果冻豆 ) --API17

4.3 Jelly Bean (果冻豆 ) --API18

4.4 KitKat:(奇巧巧克力棒) --API 19

5.0 Lollipop  (棒棒糖)–API 21

5.1 Lollipop  (棒棒糖) --API 22

6.0 Marshmallow(棉花糖) –API 23

7.0 Nougat(牛轧糖) –API 24

为什么选择 Android 开发

开源性

开放性

JAVA语言

1.1.4 Dalvik虚拟机

Dalvik是Google公司自己设计用于Android平台的虚拟机,它可以简单的完成进程隔离和线程管理,并且可以提高内存的使用效率。

区别DVM与JVM(了解)

一、首要差别

Dalvik 基于寄存器,而 JVM 基于栈。

基于寄存器编译和运行都会更快些

二、字节码的区别

Dalvik执行.dex格式的字节码,是对.class文件进行压缩后产生的,文件变小

JVM执行.class格式的字节码

三、运行环境的区别

Dalvik 经过优化,允许在内存中同时运行多个Dalvik的实例,一个应用启动都运行一个单独的虚拟机,运行在一个单独的进程中

JVM只能运行一个实例, 也就是所有应用都运行在同一个JVM中

1.2.1 ADT Bundle开发工具集合

到“http://developer.android.com/sdk/index.html”网址,下载相应的版本的ADT Bundle。将ADT Bundle解压后,会看到eclipse目录、sdk目录和SDKManager.exe。

1.2.2  Android调试桥(ADB)

Android调试桥指的就是adb.exe工具(Android Debug Bridge简称ADB),存在于SDK的platform-tools目录中,允许开发人员与模拟器或者连接的Android设备进行通信。

ADB 常见命令

adb start-server:开启adb服务

adb device:列出所有设备

adb logcat:查看日志

adb kill-server:关闭adb服务

adb shell:挂载到Linux的空间

1.2.3  DDMS的使用

DDMS全称Dalvik Debug Monitor Service,它是Android开发环境中Dalvik虚拟机调试监控服务。DDMS作为IDE、emultor、真机之间的桥梁,将捕捉到终端的ID通过ADB建立调试桥,从而实现发送指令到测试终端的目的。

•    1.3.3 Android程序打包过程

•    Android程序开发完成后,如果要发布到互联网上供别人使用,就需要将自己的程序打包成正式的Android安装包文件(Android Package简称APK),其后缀名“.apk”。

•    使用run as也能生成一个apk安装包,但是使用run as生成的是测试的安装包,只供开发者自己测试使用。

1.4 本章小结

本章主要讲解了Android的基础知识,首先介绍了Android的起源以及体系结构,然后讲解Android开发环境的搭建,最后通过一个HelloWorld程序来讲解如何开发Android程序。本章的知识作为Android开发者的入门知识,要求初学者对Android开发有个简单的了解,方便学习后面的知识。

UI概述:在Android应用中,UI(User Interface)界面是人与手机之间数据传递、交互信息的重要媒介和对话接口。

Android程序开发最重要的一个环节就是界面处理,界面的美观度直接影响用户的第一印象,因此,开发一个整齐、美观的界面是至关重要的。

Android应用的界面是由View和ViewGroup对象构建而成的。View类是Android系统平台上用户界面表示的基本单元,View的一些子类被统称为Widgets(工具),它们提供了诸如文本输入框和按钮之类的UI对象的完整实现。

ViewGroup是View的一个扩展,它可以容纳多个View,通过ViewGroup类可以创建有联系的子View组成的复合控件。

理解UI事件:

当用户通过手指触摸UI时, 系统会自动创建对应的Event对象

Android中提供了多种方式拦截处理不同类型的事件

视图本身就可以处理发生在该视图上的事件.

使用UI事件:

Android提供了很多不同类型的事件监听器接口

View.OnClickListener:  onClick()

View.OnLongClickListener:
onLongClick()

View.OnTouchListener:
onTouch()

View.OnCreateContextMenuListener:
onCreateContextMenu()

View.OnFocusChangeListener:  onFocusChange()

View.OnKeyListener:  onKey()

TextView :  文本视图

<TextView

android:id=“@+id/tv_test1_message“     //指定id

android:layout_width=“match_parent“  //宽度

android:layout_height=“wrap_content“ //高度

android:text=“这是TextView的内容“     // 文本

android:textColor=“#ff0000“                    // 文本颜色

android:textSize=“20sp” />                       // 字体大小

关于颜色:

在Android中字体颜色或背景颜色使用RGB来表达

R : red 红色

G : green 绿色

B : blue 蓝色

每个色相用一个2位的十六进制的数来表达

颜色值的前面为带一个字符 : #

EditText :  文本输入框

<EditText

android:id="@+id/et_test1_number"

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:hint=“请输入手机号“       //默认提示文本

android:inputType=“phone”>    // 输入数据类型限定

ImageView : 图片视图 img

<ImageView

android:id="@+id/iv_test1_play"

android:layout_width=“70dp”

android:layout_height=“70dp”

android:background=“@drawable/ic_launcher“          //背景图片

android:src=“@android:drawable/ic_media_play”/> //前景图片

CheckBox : 多选框

<CheckBox

android:id="@+id/cb_test1_basket"

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“篮球”

android:checked=“true”/> //标识默认是否勾选

RadioGroup/RadioButton
单选框

<RadioGroup

android:id="@+id/rg_test1_sex"

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”

android:orientation=“horizontal” >

<RadioButton

android:id="@+id/rb_test1_male"

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“男”
/>

<RadioButton

android:id="@+id/rb_test1_female"

android:layout_width=“wrap_content”

android:layout_height="wrap_content“

android:checked=“true”

android:text=“女” />

常用UI组件:

OptionMenu:

OptionMenu在点击手机的menu键触发

Activity :
onCreateOptionsMenu(Menu menu)

显示OptionMenu的回调方法, 在此方法中向Menu中添加MenuItem

添加menuItem的两种方式:

纯编码方式:   menu.add(….)

加载menu文件的方式:

MenuInflater menuInflater = getMenuInflater();

menuInflater.inflate(R.menu.main_option,
menu);

Activity : onOptionsItemSelected(MenuItem
item)

当选择某个菜单项的回调方法

ContextMenu : 上下文菜单

View :
setOnCreateContextMenuListener(listener)

为某个视图添加创建ContextMenu的监听(需要长按触发)

Activity :
onCreateContextMenu(menu, view, menuInfo)

显示菜单的回调方法

Activity :
onContextItemSelected(MenuItem item)

当选择某个菜单项的回调方

Activity:.registerForContextMenu()将上下文菜单注册到某个组件上

Progressbar : 进度条

ProgressBar

void setProgress(int Progress) : 设置当前进度

int getProgress() : 得到当前进度

void
setMax(int max) : 设置最大进度

int getMax() : 设置或得到最大进度

View

void setVisibility(int visibility) : 设置视图的可见性

View. VISIBLE : 标识可见

View. INVISIBLE : 标识不可见, 但占屏幕空间

View.GONE : 标识不可见, 也不占屏幕空间

AlertDialog : 警告框

AlertDialog  :

show()
显示警告框

没有公开的构造方法, 只能通过其内部类Builder来创建

AlertDialog.Builder
:

create() : 创建AlertDialog对象

show() : 创建AlertDialog对象, 同时将其显示出来

setTitle(CharSequence title) : 设置标题

setMessage(CharSequence message) : 设置内容

setPositiveButton(String text,
OnClickListener listener) : 设置正面按钮

setNegativeButton(String text,
OnClickListener listener): 设置负面按钮

dismiss() : 移除dialog

setSingleChoiceItems(….)设置单选项列表

布局文件的创建:

在Android应用程序中,界面是通过布局文件设定的。

布局文件采用XML格式,每个应用程序默认包含一个主界面布局文件,该文件位于项目的“res/layout”目录中。

布局的类型:

在Eclipse中开发Android程序时,默认采用的就是相对布局。

相对布局通常有两种形式,一种是相对于容器而言的,一种是相对于控件而言的。

线性布局是Android中较为常用的布局方式,它使用标签表示。

线性布局有两种方式指定控件位置,一种是水平方向,一种是竖直方向。

表格布局就是让控件以表格的形式来排列组件的,只要将组件或信息放在单元格中,控件就可以整齐的排列。

在TableLayout中,行数由TableRow对象控制的,即布局中有多少TableRow对象,就有多少行。

网格布局是Android4.0新增的布局,它实现了控件的交错显示,能够避免因布局嵌套对设备性能的影响,更利于自由布局的开发。

网格布局用一组无限细的直线将绘图区域分成行、列和单元,并指定控件的显示区域和控件在该区域的显示方式。

帧布局为每个加入其中的控件创建一个空白区域(称为一帧,每个控件占据一帧)。

采用帧布局设计界面时,只能在屏幕左上角显示一个控件,如果添加多个控件,这些控件会按照顺序在屏幕的左上角重叠显示,且会透明显示之前控件的文本。

绝对布局需要通过指定x、y坐标来控制每一个控件的位置,放入该布局的组件需要通过android:layout_x和android:layout_y两个属性指定其准确的坐标值,并显示在屏幕上。

绝对布局多用于游戏开发中,由于多分辨率兼容麻烦,绝对布局在Android1.5后被Google弃用,因此应用开发一般情况下不推荐使用绝对布局。

样式和主题:

尽管Android系统提供了很多样式和主题,但有时这些效果并不能满足实际需求,此时还可以自定义样式或者主题。

自定义样式和主题的步骤如下:

1)在res/values 目录创建样式文件style.xml,添加  根节点。

2)在节点中添加一个

主题定义一个名称。

3)在

个属性名,并在元素内部设置这个属性的值。

国际化:

国际化是指软件开发时,应该具备支持多种语言和地区的功能,为不同国家和地区的用户,提供符合来访者阅读习惯的页面或数据。

由于国际化Internationalization这个单词的首字母“I”和尾字母“N”之间有18个字符,因此国际化被简称为I18N。

为了提供不同语言版本,开发者只需要在res目录下新建对应的values文件夹。

程序调试:

LogCat用于输出Android程序中的日志信息。它支持五种输出方式,级别由低到高分别是:

Verbose(V): 显示全部信息,黑色

Debug(D):    显示调试信息,蓝色

Info(I):          显示一般信息,绿色

Warming(W):显示警告信息,橙色

Error(E):       显示错误信息,红色

由于LogCat中输出的信息多而繁杂,找到所需要的Log信息会比较困难,因此可以使用过滤器,过滤掉不需要的信息,点击加号 ,弹出LogCat信息过滤框。

Toast会显示一个小消息告诉用户一些必要信息,该消息在短时间内自动消失,不会干扰用户操作。

Toast组件有两个方法makeText()和show(),其中makeText()方法用于设置需要显示的字符串,show()方法显示消息框。

Toast toast =
Toast.makeText(Context,Text,Time);

toast.show();

简写形式如下:

Toast.makeText(context,“这是弹出消息!”,0).sho

第二章

Activity的启动模式有四种,分别是standard、singleTop、singleTask和singleInstance。

在AndroidManifest.xml中,可以通过标签的android:launchMode属性设置启动模式。

standard标准模式

standard是Activity默认的启动模式,在不指定Activity启动模式的情况下,所有Activity使用的都是standard模式。

在standard模式下,每当启动一个新的Activity,它就会进入任务栈,并处于栈顶的位置,对于使用standard模式的Activity,每次启动都会创建一个新的实例。

singleTask模式

当Activity的启动模式为singleTask时,每次启动该Activity时,系统首先会检查栈中是否存在该Activity的实例,如果发现已经存在则直接使用该实例,并将当前Activity之上的所有Activity出栈,如果没有发现则创建一个新的实例。

Intent中文翻译为“意图”,它是Android程序中各个组件进行交互的一种重要方式,它不仅可以指定当前组件要执行的动作,还可以在不同组件之间进行数据传递。

Intent一般用于启动Activity、启动服务、发送广播等,承担了Android应用程序三大核心组件相互间的通信功能。

Intent启动Activity的方法有:

startActivity(Intent
intent)

startActivityForResult(Intent
intent,int code)

显式意图

即在通过Intent启动Activity时,需明确指定激活组件的名称。如果需要在本应用中启动其他的Activity时,可以使用显式意图来启动Activity。

Intent intent =
new Intent(this, Activity02.class);

startActivity(intent);

显式意图还可以根据目标组件的包名、全路径名来指定开启组intent.setClassName(“cn.itcast.xxx”,“cn.itcast.xxx.xxxx”);

startActivity(intent);

隐式意图

使用隐式意图开启Activity的示例代码如下所示:

Intent intent =
new Intent();

// 设置动作和清单文件一样

intent.setAction(“cn.itscast.xxx”);

startActivity(intent);

Intent不仅可以用来开启Activity,也可以在Activity之间传递数据。在数据传递时,可以使用putExtra()方法将数据存储在Intent中。

String data = “Hello Activity02”

Intent intent =
new Intent(this,Activity02.class);

intent.putExtra(“extra_data”,data);

startActivity(intent);

将数据从Activity02中取出

Intent intent =
getIntent();

String data = =
intent.getStringExtra(“extra_data”);

putExtra()不仅可以传递基本类型数据,还可以传递Bundle对象。

Bundle bundle =
new Bundle();

bundle.putString(“name”,
“Linda”);

Intent intent =
new Intent(this,Activity02.class);

intent.putExtra(bundle);

startActivity(intent);

将数据从Activity02中取出

Intent intent =
getIntent();

Bundle bundle =
intent.getExtras();

String stuName =
bundle.getString(“name”);

在使用新浪微博APP时,能发现在微博发布页面进入图库选择图片后,会回到微博发布页面并带回了图片选择页面的图片信息。这个功能的实现利用了Activity回传数据。

Andorid提供了一个startActivityForResult()方法,来实现回传数据。startActivityForResult()方法接收两个参数,第一个参数是Intent,第二个参数用于判断数据的来源。

Android中的数据存储方式有五种,分别是文件存储、SharedPreferences、

SQLite数据库、ContentProvider以及网络存储。

第三章

文件存储是Android中最基本的一种数据存储方式,它与Java中的文件存

储类似,都是通过I/O流的形式把数据原封不动的存储到文档中。

序列化是将对象状态转换为可保持或传输的过程。在序列化对象时,需要使用XmlSerialize序列化器,它可以将IO流中传输的对象变得像基本类型数据一样,实现数据传递的功能。

序列化后的对象以XML形式保存,因此,先来看一下person.xml文件。

SharedPreferences是Android平台上一个轻量级的存储类,用于存储一些应用程序的配置参数,例如用户名、密码、自定义参数的设置等。

SharedPreferences中存储的数据是以key/value键值对的形式保存在XML文件中,该文件位于“data/data//shared_prefs”文件夹中。

存储数据

SharedPreferences
sp  = 
getSharedPreferences(“data”,MODE_PRIVATE);

Editor editor =
sp.edit();

editor.putString(“name”,
“传智播客”);

editor.putInt(“age”,
8);

editor.commit();

取出数据

SharedPreferences
sp  = 
context.getSharedPreferences();

String   data  

sp.getString(“name”,"");

编辑数据

SharedPreferences
sp = context.getSharedPreferences ();

Editor editor  = 
sp.edit();

editor.remove(“name”);

editor.clear();

editor.commit();

SP存储专门用来存储一些单一的小数据

存储数据的类型:  boolean,
float, int, long, String

数据保存的路径: 
/data/data/packageName/shared_prefs/yyy.xml

可以设置数据只能是当前应用读取, 而别的应用不可以

应用卸载时会删除此数据

SharedPreferences:
对应sp文件的接口

context. getSharedPreferences (String name,
int mode): 得到SP对象

name: 文件名(不带.xml)

mode: 生成的文件模式(是否是私有的,即其它应用是否可以访问)

Editor sp.edit() :
得到Editor对象

Xxx
sp.getXxx(name,defaultValue): 根据name得到对应的数据

Editor : 能更新sp文件的接口

Editor putXxx(String name, Xxx  value) : 保存一个键值对, 没有真正保存到文件中

Editor
remove(name)

commit(): 提交,
数据真正保存到文件中了

大多数人使用电脑第一件事基本上都是登录QQ,为了方便,大家通常会使用记住密码功能,直接点击登录按钮即可完成登录功能。

在Android手机中,同样可以实现这个功能,接下来通过一个“QQ登录”的案例来演示如何使用SharedPreferences存储数据。

第六章

内容提供者(ContentProvider)是Android系统四大组件之一,用于保存和检索数据,是Android系统中不同应用程序之间共享数据的接口。

ContentProvider是不同应用程序之间进行数据交换的标准API,以Uri形式对外提供数据,允许其他应用操作本应用数据。其他应用则使用ContentResolver,并根据ContentProvider提供的Uri操作指定数据。

定义一个类继承android.content包下的ContentProvider类(抽象类)。子类需要重写它的onCreate()、delete()、getType()、insert()、query()、update()这几个抽象方法。

ContentProvider是四大组件之一,必须要在清单文件中注册

ContentProvider的几个抽象方法,这几个抽象方法中有一个参数Uri,它代表了数据的操作方法。Uri是由scheme、authorites、path三部分组成。

(scheme:“content://”是一个标准的前缀,表明这个数据被内容提供者所  控制,它不会被修改;

authorities:“cn.itcast.db.personprovider”是在清单文件中指定的android:authorities属性值,该值必须唯一,它表示了当前的内容提供者;

path:“/person”代表资源(或者数据),当访问者需要操作不同数据时,这个部分是动态改变的

Uri.parse(String str)方法是将字符串转化成Uri对象的。为了解析Uri对象,Android系统提供了一个辅助工具类UriMatcher用于匹配Uri。

在Android系统中,ContentResolver充当着桥梁的角色。应用程序通过ContentProvider暴露自己的数据,通过ContentResolver对应用程序暴露的数据进行操作。

从图可以看出,使用ContentObserver观察A应用的数据时,首先要在A应用的ContentProvider中调用ContentResolver的notifyChange()方法。调用了这个方法之后当数据发生变化时,它就会向“消息中心”发送数据变化的消息。然后C应用观察到“消息中心”有数据变化时,就会触发ContentObserver的onChange()方法。

第7章广播接收者

首先明白定义,什么是广播接收者:实际生活中,电台用于发送广播,收音机用于接收广播。

Android系统中,内置了很多系统级别的广播,例如手机开机完成后会发送一条广播,电池电量不足时会发送一条广播等。

Android系统中提供了广播接收者BroadcastReceiver,广播接收者的作用就是接收来自系统或其他应用程序的广播,并作出回应。

广播(Broadcast)是一种运用在应用程序之间传递消息的机制。

广播接收者(BroadcastReceiver)是用来过滤、接收并响应广播的一类组件。

广播接收者可以监听系统中的广播消息,在不同组件之间进行通信。

之后,具体理解广播与广播接收器:

广播事件处理属于系统级的事件处理(一般事件处理是属于View级的事件处理)

一个应用可以在发生特定事件时发送Broadcast, 系统中任何应用只要注册了对应的Receiver就会接收到此Broadcast

一个应用如果对某个广播感兴趣, 就可以注册对应的Receiver来接收广播

广播事件机制是应用程序(进程间)之间通信的一种手段

广播机制最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的,通过这种形式来达到接、收双方的完全解耦

广播事件处理过程即针对某一广播做出响应的过程

广播接收者,在工作前必须要完成创建于注册,注册广播有两种方式,常驻型广播与非常驻型广播。

1、注册常驻型广播

常驻型广播是当应用程序关闭后,如果接收到其他应用程序发出的广播,那么该程序会自动重新启动。常驻型广播在清单文件中注册。

2、注册非常驻型广播

非常驻型广播依赖于注册广播的组件的生命周期,例如,在Activity中注册广播接收者,当Activity销毁后广播也随之被移除。这种广播事件在代码中注册。

MyBroadCastReceiver receiver = new MyBroadCastReceiver();

String action = “android.provider.Telephony.SMS_RECEIVED”;

IntentFilter intentFilter = new IntentFilter(action);

registerReceiver(receiver, intentFilter);

此外,我们还要懂得区别静态注册与动态注册

最大区别在于:静态注册的应用情景是需要监听的时间为应用的整个生命过程中

动态注册的应用场景只服务于某个Activity/Service

广播接收者的一个典型案例是IP拨号器:

Android系统中自带了很多广播,如果需要监听某个广播只需创建对应的广播接收者即可。

当这些系统级别的广播事件不能满足实际需求时,我们还可以自定义广播。

接下来就涉及到广播的类型

广播分为有序广播和无序广播

1、无序广播

无序广播是一种完全异步执行的广播,在广播发出去后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息。

当发送的是无序广播时,广播接收器之间是没有先后顺序的。

2、有序广播

有序广播则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够接收到这条消息。

当发送有序广播时,广播接收器是有先后顺序的,并且可以被拦截。

常用的广播接收者:案例——杀毒软件

在Windows电脑中,有些软件一开机就会自动启动,同样在Android系统下也可以实现这种功能,例如杀毒程序,手机一开机便会自动启动,这种功能就是通过广播接收者监听开机启动的广播事件实现的。

案例——短信拦截器

在日常生活中,大家经常会被一些广告短信骚扰,为了避免这些垃圾短信频繁的发送到手机上,我们通常会将其拦截。接下来分步骤讲解如何使用广播接收者实现短信拦截器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值