Android自定义控件系列——Paint类全解析

Paint

常量

常量名作用
ANTI_ALIAS_FLAG抗锯齿标志
DITHER_FLAG防抖动标志
EMBEDDED_BITMAP_TEXT_FLAG绘制标记,在绘制文本时使用位图字体。禁用此标志将阻止文本绘制操作在字体中使用嵌入式位图冲击,从而导致具有可缩放轮廓和位图冲突的字体仅绘制可缩放轮廓,并且仅使用位图冲击的字体无法绘制
FAKE_BOLD_TEXT_FLAG绘制标志,其对绘制文本应用合成加粗效果
FILTER_BITMAP_FLAG绘制标志,可在缩放位图上实现双线性采样
HINTING_OFF字体hinter选项禁用字体提示
HINTING_ON字体hinter选项启用字体提示
LINEAR_TEXT_FLAG绘制标志,使文本能够平滑线性缩放
STRIKE_THRU_TEXT_FLAG绘制标志,将穿透装饰应用于绘制文本
SUBPIXEL_TEXT_FLAG启用该标志会导致以子像素精度计算字形进步,与LINEAR_TEXT_FLAG一起使用,以防止文本在平滑缩放转换期间抖动
UNDERLINE_TEXT_FLAG绘制标记,其将下划线装饰应用于绘制文本

通用API

Alpha

//设置、获取透明度。透明度取值:0~255
void setAlpha(int a);
int getAlpha();

Color

ColorFilter		//对RGB(A)进行过滤
	PorterDuffColorFilter
	ColorMatrixColorFilter
	LightingColorFilter
void setColor(int color);
void setARGB(int a, int r, int g, int b);
int getColor();
//设置或清除paint的颜色过滤器
ColorFilter setColorFilter(ColorFilter filter);
//获取颜色过滤器(可能为null)
ColorFilter getColorFilter();

1、ColorMatrixColorFilter

​ 通过颜色矩阵(ColorMatrix)对图像中的像素色值(不包含Alpha)进行改变。由于图片的每个像素是以RGBA的形式加载到内存中的,所以改变图片的颜色需要Android ColorMatrix颜色矩阵类支持,而颜色矩阵是一个以一维数组存储在代码中的5x4矩阵(每一行代表RGBA中一个)。但是我们图像中每个像素的展示效果却取决于存储在一个5x1颜色分量矩阵中。所以为了修改我们图像每个像素点的效果,我们只需修改ColorMatrix的颜色矩阵值,然后与分量矩阵做运算即可。

//上图中两矩阵乘积
R' = a*R + b*G + c*B + d*A + e; 
G' = f*R + g*G + h*B + i*A + j; 
B' = k*R + l*G + m*B + n*A + o; 
A' = p*R + q*G + r*B + s*A + t; 
//通过传入ColorMatrix矩阵进行使用
public ColorMatrixColorFilter(ColorMatrix matrix)
//通过传入一个自定义的矩阵,上面讲到了,这个矩阵实质是一维数组
public ColorMatrixColorFilter(float[] array)

案例

//传入不同的参数就能得到各种过滤处理的图片,譬如老照片、QQ在线离线头像图标颜色变换
mColorMatrix = new ColorMatrix(new float[] {  
	red, 0, 0, 0, 0,  
	0, green, 0, 0, 0,  
	0, 0, blue, 0, 0,  
	0, 0, 0, alpha, 0,  
});  
mPaint.setColorFilter(new ColorMatrixColorFilter(mColorMatrix));  

2、LightingColorFilter

public LightingColorFilter(int mul, int add);
//mul:(colorMultiply)色彩倍增,16进制的色彩值0xAARRGGBB
//add:(colorAdd)色彩添加,16进制的色彩值0xAARRGGBB

案例

//应用在Bitmap上之后会过滤掉图片里的红色,加强图片里的绿色。计算方式就是(mul * 原色值 + add)% 255
//该过滤器是不处理Alpha,只对图片里的RGB有效,A无效
mPaint.setColorFilter(new LightingColorFilter(0xFF00FFFF, 0x0000FF00));

3、PorterDuffColorFilter

public PorterDuffColorFilter(int color, PorterDuff.Mode mode);
//color:16进制的颜色值
//mode:PorterDuff.Mode的混合模式

Flags

//设置、获取标志
void setFlags(int flags);
int getFlags();

Hinting

//返回paint的模式。 返回HINTING_OFF或HINTING_ON
void setHinting(int mode);
int getHinting();

MaskFilter

MaskFilter
	BlurMaskFilter		//模糊遮罩滤镜
	EmbossMaskFilter	//浮雕遮罩滤镜
//设置或清除maskfilter对象
MaskFilter setMaskFilter(MaskFilter maskfilter)
//获取paint的maskfilter对象
MaskFilter getMaskFilter();

1、BlurMaskFilter

BlurMaskFilter(float radius, Blur style);
//radius:阴影范围
//style:模糊类型

BlurMaskFilter.Blur取值

在这里插入图片描述

枚举含义
NORMAL整个图像被模糊掉
SOLID在图像的Alpha边界外产生一层与Paint颜色一致的阴影效果而不影响图像本身
OUTER在图像的Alpha边界外产生一层阴影且会将原图像变为透明效果
INNER在图像内部边沿产生模糊效果

案例

在这里插入图片描述在这里插入图片描述

//对应图一
//必须关闭硬件加速才有效果
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//具备alpha通道的颜色
paint.setColor(Color.RED);
paint.setMaskFilter(new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL));
canvas.drawRect(rect, paint);
//对应图二
//图片提取Bitmap的Alpha通道做法
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
//提取Alpha通道
Bitmap bitmapAlpha = bitmap.extractAlpha();
paint.setColor(Color.RED);
paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.SOLID));
//绘制模糊背景
canvas.drawBitmap(bitmapAlpha, 300, 500, paint);
//绘制原图
canvas.drawBitmap(bitmap, 300, 500, paint);

2、EmbossMaskFilter

public EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius);
//direction:长度为3的数组标量[x,y,z],用来指定光源的方向
//ambient:周边背景光,取值为0到1之间
//specular:镜面反射系数
//blurRadius:模糊半径

案例

在这里插入图片描述

paint.setMaskFilter(new EmbossMaskFilter(new float[]{20, 20, 20}, 0.4f, 10, 15));
canvas.drawRect(rect5, paint);

StrokeWidth

//设置或获取线宽
void setStrokeWidth(float width);
float getStrokeWidth();

Style

//设置或获取填充模式
void setStyle(Paint.Style style);
Paint.Style getStyle();

StrokeMiter

//设置或获取画笔笔触斜接值,该值必须>=0。在Stroke或StrokeAndFill风格时有效
void setStrokeMiter(float miter)
float getStrokeMiter()

Xfermode

//设置或清除传输模式对象。 传输模式定义了源像素(由绘图命令生成)如何与之合成目标像素(渲染目标的内容)
Xfermode setXfermode(Xfermode xfermode);
Xfermode getXfermode();
Xfermode
	AvoidXfermode		(已过时)
	PixelXorXfermode	(已过时)
	PorterDuffXfermode

AvoidXfermode

public AvoidXfermode(int opColor, int tolerance, Mode mode);
//opColor:要匹配的目标颜色
//tolerance: 容差值,0代表最小容差,也就是我们目标相素值和opcolor颜色一样的点才匹配成功,255代表最大容差,mode 有两个可取枚举值,如下:
	Avoid模式:只在目标像素值和opcolor匹配成功的地方进行绘制
    Target模式:只在目标像素值和opcolor匹配没成功的地方进行绘制
//案例:保持正方形背景不变,改变五角星的颜色
//1、创建AvoidXfermode对象,并指定要替换的颜色(红色)
AvoidXfermode mAvoidXfermode = new AvoidXfermode(Color.RED, 10, Mode.TARGET);
Bitmap mBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.red_star)).getBitmap();
//2、创建Paint并指定新颜色(黑色)
Paint mAvoidPaint = new Paint();
mAvoidPaint.setColor(Color.BLACK);	
//3、绘制图片
canvas.drawBitmap(mBitmap, mLeft, mTop, mAvoidPaint);
//4、设置图层混合模式  
mAvoidPaint.setXfermode(mAvoidXfermode);  
//5、绘制色块进行混合(让mBitmap中在mAvoidDestRect区域接近为红色的像素点变为黑色),得到最终效果  
canvas.drawRect(mAvoidDestRect, mAvoidPaint);

PixelXorXfermode

​ 对重叠的像素进行opPixColor ^ srcPixColor ^ dstPixColor,变成简单的异或颜色显示

PixelXorXfermode(int opColor);
//opColor:目标颜色

PorterDuffXfermode

在这里插入图片描述

//关闭硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mSrcPaint mSrcPaint = new Paint();
mSrcPaint.setColor(Color.BLUE);
Paint mDstPaint = new Paint();
mDstPaint.setColor(Color.YELLOW);
//只有两个bitmap,mode才能生效。两个bitmap大小尽量一样,背景色为透明色
//如果两个bitmap位置不完全一样,生成的图像可能误以为是错误的
mSrcBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
mSrcCanvas = new Canvas(mSrcBitmap);
mDstBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
mDstCanvas = new Canvas(mDstBitmap);

//画第一个bitmap
mDstCanvas.drawRect(20, 20, 80, 80, mDstPaint);
canvas.drawBitmap(mDstBitmap, 0, 0, mDstPaint);
//设置PorterDuffXfermode.此设置最好设置在两个bitmap中间
mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
//画第二个bitmap
mSrcCanvas.drawCircle(25, 25, 25, mSrcPaint);
canvas.drawBitmap(mSrcBitmap, 0, 0, mSrcPaint);

AntiAlias

//是否打开抗锯齿,默认不打开
void setAntiAlias(boolean aa);
final boolean isAntiAlias();

Dither

//设置或获取图像抖动处理。处理后的图片颜色更加平滑和饱满,图像更清晰
void setDither(boolean dither);
final boolean isDither();

FilterBitmap

//设置或获取是否激活位图过滤器
void setFilterBitmap(boolean filter);
final boolean isFilterBitmap();

reset

//重置
void reset();

set(Paint src)

//利用其他paint来设置本paint
void set(Paint src);

Shader

Shader	//可以单独或者组合使用
	BitmapShader	//位图图像渲染
	LinearGradient	//线性渲染
	RadialGradient	//环形渲染
	SweepGradient	//扫描渐变渲染/梯度渲染
	ComposeShader	//组合渲染
Shader.TileMode{CLAMP,REPEAT,MIRROR}
	CLAMP 	//拉伸最后一个像素铺满
    REPEAT	//类似电脑壁纸,横向纵向不足的重复放置
    MIRROR	//横向纵向不足处不断翻转镜像平铺	
   	//两个矩阵变换方法
    boolean getLoaclMatrix(Matrix localM);
    void setLocalMatrix(Matrix localM);

BitmapShader

public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY);
//bitmap:被渲染的图片
//tileX、tileY:位图在XY方向的TileMode模式
Paint mPaint = new Paint();
BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.icon1);
Bitmap bitmap = drawable.getBitmap();

BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
/*如下四行Matrix可以不设置,这里是为了处理不等宽高图片渲染后铺不满问题
Matrix matrix = new Matrix();
float scale = Math.max(bitmap.getWidth(), bitmap.getHeight())*1.0f / Math.min(bitmap.getWidth(), bitmap.getHeight());
matrix.setScale(scale, scale);
shader.setLocalMatrix(matrix);*/

mPaint.setShader(shader);
canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, bitmap.getHeight()/2, mPaint); //需要啥图形就怎么画

/*如上两行还可以这么实现
ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
shapeDrawable.getPaint().setShader(shader);
shapeDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getWidth());
shapeDrawable.draw(canvas);  */

LinearGradient

public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile);
//x0,y0,x1,y1:渐变起始点与结束点坐标
//colors:数组为颜色的int数组
//positions:数组为相对位置的颜色数组,null则颜色沿渐变线均匀分布
//tile:渲染器平铺模式Shader.TileMode

RadialGradient

public RadialGradient(float x, float y, float radius, int[] colors, float[] positions,Shader.TileMode tile);
//x,y:圆心坐标
//radius:圆半径
//colors:数组为颜色的int数组
//positions:数组为相对位置的颜色数组,null则颜色沿渐变线均匀分布
//tile:渲染器平铺模式Shader.TileMode

SweepGradient

public SweepGradient(float cx, float cy, int color0, int color1);
public SweepGradient(float cx, float cy, int[] colors, float[] positions);
//cx,cy:渲染中心坐标
//color0,color1:起始,结束渲染颜色
//colors:围绕中心渲染的颜色数组,最少要有两种颜色
//positions:数组为相对位置的颜色数组,null则颜色沿渐变线均匀分布

ComposeShader

public ComposeShader(Shader shaderA,Shader shaderB, Xfermode mode);
public ComposeShader(Shader shaderA,Shader shaderB, PorterDuff.Mode mode);
//shaderA,shaderB:两种渲染器
//mode:两种渲染器组合的模式,使用Xfermode或PorterDuff.Mode对象
//设置辐射渐变模式
Shader setShader(Shader shader);
Shader getShader();

ShaderLayer

//在主层下面绘制一个阴影层,具有指定的偏移和颜色以及模糊半径
//应用:绘制一个圆,在圆周给一个阴影扩散效果
void setShadowLayer(float radius, float dx, float dy, int shadowColor)//清除阴影扩散效果
void clearShadowLayer();

StrokeCap

在这里插入图片描述

//当画笔样式为STROKE或FILL_OR_STROKE时,设置或返回paint的Cap,控制开始和结束时的线条与路径样式。默认值是BUTT
void setStrokeCap(Paint.Cap cap);
Paint.Cap getStrokeCap();

StrokeJoin

在这里插入图片描述

//当画笔样式为STROKE或FILL_OR_STROKE时,获取与设置画笔画线等连接处的轮廓样式。默认为MITER
//三种样式:Join.MITER  Join.ROUND, Join.BEVEL
Paint.Join  getStrokeJoin();
void setStrokeJoin(Paint.Join join);

getFillPath

//将任何/全部效果(patheffect,抚摸)应用于src,将结果返回到dst
//将src的属性复制到dst里面。dst在几何视角上与src有一样的展示
boolean getFillPath(Path src, Path dst);

PathEffect

PathEffect
	DashPathEffect
	PathDashPathEffect
	SumPathEffect
	CornerPathEffect
	DiscretePathEffect
	ComposePathEffect
//设置或清除patheffect对象
PathEffect  setPathEffect(PathEffect effect);
//获取paint的patheffect对象
PathEffect  getPathEffect();

效果图

在这里插入图片描述

//不设置效果,默认转角处带有毛刺
paint.setPathEffect(null);

//用平滑的圆角代替尖角
public CornerPathEffect(float radius);	
//radius:转角处的圆滑程度

//创建一个虚线的轮廓(短横线或者小圆点)
public DashPathEffect(float intervals[], float phase);	
//intervals[]:参数定义为实线长度,虚线长度,实线长度,虚线长度。可看做一个周期
//phase:偏移值,动态改变其值会让路径产生动画的效果,就像进度条往前走一样

//添加了随机性,类似生锈铁丝的效果
public DiscretePathEffect(float segmentLength, float deviation);
//segmentLength:指定突出杂点的密度,值越小杂点越密集
//deviation:指定杂点突出的大小,值越大突出的距离越大

// 和DashPathEffect类似,只不过可以自定义路径虚线的样式
public PathDashPathEffect(Path shape, float advance, float phase,Style style);
//shape:自定义的路径样式,这里定义为方形
//advance:每个shape间的距离
//phase:偏移值,动态改变其值会让路径产生动画的效果,就像进度条往前走一样
//style:设置连接处的样式,取值如下
//      ROTATE 		线段连接处的shape进行适当角度旋转连接
//      MORPH 		线段连接处的shape以拉伸或者压缩形变连接
//      TRANSLATE 	线段连接处的shape平行平移连接

//组合两种路径效果,先将路径变成innerpe的效果,再去复合outerpe的路径效果
public ComposePathEffect(PathEffect outerpe, PathEffect innerpe);
//outerpe,innerpe:两种PathEffect效果

//组合两种路径效果,把两种路径效果加起来再作用于路径
public SumPathEffect(PathEffect first, PathEffect second);
//first,second:两种PathEffect效果

关于text的API

ascent

float ascent();

descent

float dscent();

breakText

//测量文本,如果测量的宽度超过maxWidth,则提早停止
int breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth);
int breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth);
int breakText(CharSequence text, int start, int end, boolean measureForwards, 
float maxWidth, float[] measuredWidth);
//measureForwards:true则从首个字符开始测量,否则从最后一个字符开始测量
//maxWidth:可接受的最大长度
//count:绘制字符总数
//measureWidth:绘制的字符的实际宽度

案例

//打印结果:width = 2 str = 2 realWidth = 21.0
paint.setTextSize(20);
String str = "ab";
float[] floatArr= new float[1];
int width = paint.breakText(str, true, 50, floatArr);
Log.d(TAG, "width = " + width + " str = " + str.length() + " realWidth = " + floatArr[0]);

FontFeatureSettings

//返回字体设置
void setFontFeatureSettings(String settings);
String getFontFeatureSettings();

FontMetrics

在这里插入图片描述
​ canvas的drawText绘制文字传入的y其实是上图的base线,绘制文字坐标是以base基线为参考的
​ FontMetrics中的top是base到最高字符的最大值(即ascent的最大值),ascent是base到最高字符的推荐值
​ descent是base到最低字符的推荐值,bottom是base到最低字符的最大值(即decent的最大值)
​ leading是文本行之间推荐的额外高度,单行文字一般为0
​ 获取文字的高就是mPaint.ascent() + mPaint.descent(),获取文字的宽就是mPaint.measureText(text)

//返回metrics对象
Paint.FontMetrics getFontMetrics();
Paint.FontMetricsInt getFontMetricsInt();
//返回字体的推荐行间距,给出paint的字体,文字大小等的设置
//FontMetrics与FontMetricsInt都有top、ascent、descent、bottom、leading这几个属性
float getFontMetrics(Paint.FontMetrics metrics);	//返回float类型
int getFontMetricsInt(Paint.FontMetricsInt fmi);	//返回int类型

getFontSpacing

//根据当前的字体和文字大小返回推荐行间距
float getFontSpacing();

getFontVariationSettings

//返回字体变体设置。 api26以上
boolean setFontVariationSettings(String fontVariationSettings);
String getFontVariationSettings();

LetterSpacing

//文字间距
void setLetterSpacing(float letterSpacing);
//返回文字间距
float getLetterSpacing();

OffsetForAdvance

//获取位置最接近指定水平位置的字符串中的字符偏移量
int getOffsetForAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance);
int getOffsetForAdvance(char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance);

RunAdvance

//在文本运行中测量光标位置
float getRunAdvance(char[] text, int start, int end, int contextStart,int contextEnd, boolean isRtl, int offset);
float getRunAdvance(CharSequence text, int start, int end,int contextStart, int contextEnd, boolean isRtl, int offset);

TextAlign

//返回字体对齐方式
void setTextAlign(Paint.Align align);
Paint.Align getTextAlign()

TextBounds

//获取文本的宽高,通过bounds的Rect拿到整型
void getTextBounds(char[] text, int index, int count, Rect bounds);
void getTextBounds(String text, int start, int end, Rect bounds)

TextLocale

//获取当前文本的区域
Locale getTextLocale();
//设置文本的区域,比如中文,英文,一般传入Local.getDefault();
void setTextLocale(Locale locale);
//api 24以上
LocaleList getTextLocales();
//api 24以上
void setTextLocales(LocaleList locales);

TextPath

//返回指定文本的路径(轮廓)
void getTextPath(char[] text, int index, int count, float x, float y, Path path);
void getTextPath(String text, int start, int end, float x, float y, Path path);

案例

paint.getTextPath("abcd", 0, "abcd".length(), centerX, centerY, path);
path.close();
paint.setStrokeWidth(2);
canvas.drawPath(path, paint);

TextScaleX

//返回在水平方向的比例 默认为1
void setTextScaleX(float scaleX);
float getTextScaleX();

TextSize

//设置或获取Text的字体大小
void setTextSize(float textSize);
float getTextSize();

TextSkewX

//获取水平偏移
void setTextSkewX(float skewX);
float getTextSkewX();

TextWidths

//精确计算文字宽度
int getTextWidths(char[] text, int index, int count, float[] widths);
int getTextWidths(String text, float[] widths);
int getTextWidths(String text, int start, int end, float[] widths);
int getTextWidths(CharSequence text, int start, int end, float[] widths);

案例

//numWidth = 4 charWidth =10.0
//numWidth = 4 charWidth =11.0
//numWidth = 4 charWidth =11.0
//numWidth = 4 charWidth =11.0
String str = "abcd";
float[] floatArr = new float[str.length()];
int numWidth = paint.getTextWidths(str, 0,str.length(),  floatArr);
canvas.drawPaint(paint);
for (float charWidth: floatArr){
    Log.d(TAG, "numWidth = " + numWidth  + " charWidth =" + charWidth);
}

Typeface

//获取与设置字体类型
//四种模式:BOLD(加粗)、BOLD_ITALIC(加粗并倾斜)、ITALIC(倾斜)、NORMAL(正常)
Typeface setTypeface(Typeface typeface);
Typeface getTypeface();

hasGlyph

//判断Paint设置的Typeface是否支持该字符串
boolean hasGlyph(String string);

measureText

//粗略获取文本的宽度
float measureText(char[] text, int index, int count);
float measureText(CharSequence text, int start, int end);
float measureText(String text, int start, int end);
float measureText(String text);

FakeBoldText

//获取与设置文本是否仿粗体,小字体设置效果非常差
void setFakeBoldText(boolean fakeBoldText);
//获取与设置文本是否仿粗体
final boolean isFakeBoldText();

ElegantTextHeight

void setElegantTextHeight(boolean elegant);
boolean isElegantTextHeight();

LinearText

//setFlags()的帮助器,设置或清除LINEAR_TEXT_FLAG位
void setLinearText(boolean linearText);
//getFlags()的帮助器,如果设置了LINEAR_TEXT_FLAG位,则返回true
//获取与设置是否打开线性文本标识。默认Android中文本绘制需要使用一个Bitmap作为单个字符缓存,因此会使用一定的空间,为了不使用该空间则设为true即可
final boolean isLinearText();

trikeThruText

//设置是否有删除线
void setStrikeThruText(boolean strikeThruText);
//删除线
final boolean isStrikeThruText();

SubpixelText

//能优化LCD屏幕显示效果
void setSubpixelText(boolean subpixelText);
final boolean isSubpixelText();

UnderlineText

//下划线
void setUnderlineText(boolean underlineText);
final boolean isUnderlineText();
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值