Android View - 滑动

Android View 实现View滑动的六种方法 一 View的滑动简介 View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理。其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后的触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标。 实现View滑动有很多种方法,这篇文章主要讲解六种滑动的方法,分别是:layout()、offsetLeftAndRight()与offsetTopAndBottom()、LayoutParams、动画、sc 阅读详情

View的滑动主要有3种:
(1)调用scrollTo/scrollBy方法: 滑动的是View内容,操作比较简单。
(2)动画: 滑动的View位置,其实改变的是View的translationX或者translationY。(参考我的博文 Android View - 位置参数)
(3)改变布局参数: 通过设置LayoutParams,使View改变位置,只要加上延时,不断得改变位置参数,就可以达到滑动效果。

scrollTo/scrollBy滑动

为了View的滑动,Android在View内实现了2个方法:scrollTo和scrollBy。
代码如下:

public void scrollTo(int x, int y) {  
    if (mScrollX != x || mScrollY != y) {  
        int oldX = mScrollX;  
        int oldY = mScrollY;  
        mScrollX = x;  
        mScrollY = y;  
        invalidateParentCaches();  
        onScrollChanged(mScrollX, mScrollY, oldX, oldY);  
        if (!awakenScrollBars()) {  
            postInvalidateOnAnimation();  
        }  
    }  
}  
public void scrollBy(int x, int y) {  
    scrollTo(mScrollX + x, mScrollY + y);  
}

其实scrollBy方法调用了scrollTo方法。scrollTo改变了mScrollX和mScrollY,然后重绘,调用onScrollChanged通知View(子类可以重写,监听滑动)。
我们说过,调用scrollTo移动的View的内容,比如我们调用某个View的scrollTo(100, 100),那么View的内容发生如下变化:

你会发现内容向x轴和y轴负方向都移动了100,为什么是负方向呢?因为调用scrollTo移动的是View的内容,你可以看做是View边界移动了100,所以View内容相对于View就移动了-100了。

其实调用scrollTo方法会瞬间完成View的内容移动,这个用户体验显然是不好的。Android还提供了一个Scroller类,配合View的滑动,实现在规定时间内,移动指定距离。

我们从源码分析Scroller类。先从构造函数看起:

public Scroller(Context context) {  
    this(context, null);  
}   
public Scroller(Context context, Interpolator interpolator) {  
    mFinished = true;  
    mInterpolator = interpolator;  
    float ppi = context.getResources().getDisplayMetrics().density * 160.0f;  
    mDeceleration = SensorManager.GRAVITY_EARTH   // g (m/s^2)  
                  * 39.37f                        // inch/meter  
                  * ppi                           // pixels per inch  
                  * ViewConfiguration.getScrollFriction();  
}  

我们使用Scroller时,可以定义插值器。插值器可以指定View滑动的变化速度,可以先快后慢,也可以先慢后快,也可以匀速。

还要介绍Scroller类的2个方法:

startScroll

public void startScroll(int startX, int startY, int dx, int dy, int duration) {  
    mMode = SCROLL_MODE;  
    // 设置没有完成滑动
    mFinished = false; 
    // 滑动的时间
    mDuration = duration;
    // 滑动的开始时间  
    mStartTime = AnimationUtils.currentAnimationTimeMillis();
    // 开始滑动的坐标  
    mStartX = startX;  
    mStartY = startY;
    // 结束滑动的坐标  
    mFinalX = startX + dx;  
    mFinalY = startY + dy;
    // 滑动的距离  
    mDeltaX = dx;  
    mDeltaY = dy;  
    // 计算指定移动距离应该分几次完成,如20秒内完成,则每次移动为1/20
    mDurationReciprocal = 1.0f / (float) mDuration;  
    // This controls the viscous fluid effect (how much of it)  
    mViscousFluidScale = 8.0f;  
    // must be set to 1.0 (used in viscousFluid())  
    mViscousFluidNormalize = 1.0f;  
    mViscousFluidNormalize = 1.0f / viscousFluid(1.0f);  
}  

可以看出,startScroll方法只是设置了滑动的基本信息,并没有滑动呢。所以如果我们只是调用startScroll,View的滑动并不会开始哦。

computeScrollOffset

public boolean computeScrollOffset() {  
    // 如果结束了,就返回false
    if (mFinished) {  
        return false;  
    }  
    // 计算已经滑动的时间
    int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);  
    // 如果已经移动的时间小于指定移动的时间
    if (timePassed < mDuration) {  
        switch (mMode) {  
        case SCROLL_MODE:  
            // 计算当前时间应该滑动的距离
            float x = (float)timePassed * mDurationReciprocal;  
            if (mInterpolator == null)  
                x = viscousFluid(x);   
            else  
                x = mInterpolator.getInterpolation(x); 
            // 如x=10/20,那么10秒钟应该移动 mDeltaX * 10/20 的距离
            mCurrX = mStartX + Math.round(x * mDeltaX);  
            mCurrY = mStartY + Math.round(x * mDeltaY);  
            break;  
        case FLING_MODE:  
            float timePassedSeconds = timePassed / 1000.0f;  
            float distance = (mVelocity * timePassedSeconds)  
                    - (mDeceleration * timePassedSeconds * timePassedSeconds / 2.0f);  
            mCurrX = mStartX + Math.round(distance * mCoeffX);  
            // Pin to mMinX <= mCurrX <= mMaxX  
            mCurrX = Math.min(mCurrX, mMaxX);  
            mCurrX = Math.max(mCurrX, mMinX);  
            mCurrY = mStartY + Math.round(distance * mCoeffY);  
            // Pin to mMinY <= mCurrY <= mMaxY  
            mCurrY = Math.min(mCurrY, mMaxY);  
            mCurrY = Math.max(mCurrY, mMinY);  
            break;  
        }  
    }  
    // 如果到时间了,就设置当前位置为滑动最终位置,并设置结束标志
    else {  
        mCurrX = mFinalX;  
        mCurrY = mFinalY;  
        mFinished = true;  
    }  
    return true;  
}  

computeScrollOffset方法主要设置当前时间的位置,供View使用。

接下来我们看看View怎么使用Scroller,从View的绘制draw方法开始,只给出重要代码:

public void draw(Canvas canvas) {   
    ... 
    final int viewFlags = mViewFlags;  
    boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;  
    boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;  
    if (!verticalEdges && !horizontalEdges) {    
        if (!dirtyOpaque) onDraw(canvas);   
        dispatchDraw(canvas);  
        onDrawScrollBars(canvas);  
        return;  
    }  
    ...  
}

在draw方法会调用dispatchDraw方法,dispatchDraw会传入子View调用drawChild方法:

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {  
    ...  
    if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) &&  
            (child.mPrivateFlags & DRAW_ANIMATION) == 0) {  
        return more;  
    }  
    child.computeScroll();  
    final int sx = child.mScrollX;  
    final int sy = child.mScrollY;  
    boolean scalingRequired = false;  
    Bitmap cache = null;  
    ...
}  

此时每个View的computeScroll会被调用:

public void computeScroll() {  
}  

而computeScroll却是一个空方法,供子类重写。

所以我们可以在这个方法调用Scroller的computeScrollOffset方法,让Scroller帮我们计算当前滑动的位置,并判断滑动是否完成,然后我们获取Scroller帮我们计算的位置,调用View的scrollTo方法滑动View一部分。

整个流程下来,是这样的:

代码实现:

import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.Scroller;

public class MyViewGroup extends FrameLayout {
    private Scroller scroller;
    public MyViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        scroller = new Scroller(context);
        // 延时看的清楚一点
        postDelayed(new Runnable() {
            @Override
            public void run() {
                scroller.startScroll(0, 0, 100, 100, 2000);
                invalidate();
            }
        }, 1000);
    }
    public MyViewGroup(Context context) {
        super(context);
    }
    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            invalidate();
        }
    }
}

例子实现的效果果然是蓝色块向上和向左移动了100。

动画滑动

采用动画也可以实现View的滑动,主要操作translationX和translationY属性。简单介绍一下动画。
动画分两种:传统动画和属性动画。

传统动画分为帧动画(Frame Animation)和补间动画(Tweened Animation)。
帧动画是最容易实现的一种动画,这种动画更多的依赖于完善的UI资源,他的原理就是将一张张单独的图片连贯的进行播放,从而在视觉上产生一种动画的效果;有点类似于某些软件制作gif动画的方式。

补间动画又可以分为四种形式,分别是 alpha(淡入淡出),translate(位移),scale(缩放大小),rotate(旋转)。
补间动画的实现,一般会采用xml 文件的形式;代码会更容易书写和阅读,同时也更容易复用。

使用传统补间动画做View的滑动,滑动的是View的影像,并非真正改变View的位置。滑动结束瞬间,View便回到初始状态。如果设置了fillAfter属性为true,View会保留到动画后的状态,但是位置依然没有改变。如果你给这个View设置点击事件,此时点击这个View,会发现这个View不会响应点击事件,因为点击事件的范围还保留在原始状态的位置范围。所以给View设置了事件的,不适合使用传统动画。

属性动画是Android3.0之后才有的,不过有兼容包(nineoldandroids)。属性动画容易操作,代码简单,不会出现传统动画上面的负面影响,所以属性动画肯定是不二之选。

改变布局滑动

改变布局滑动,其实就是设置View的LayoutParams,设置View的padding或者margin来改变View的位置,达到View滑动的效果。和scrollTo/scrollBy不同的是,改变布局,其实是改变View的位置,而scrollTo/scrollBy改变的是View的内容,不过也是瞬间完成,体验效果不过,通常配合动画使用或者利用延时机制使用。

滑动冲突

分2中情况分析滑动冲突
(1)外部滑动和内部滑动不一致。
(2)外部滑动和内部滑动一致。

如果不懂View事件分发和拦截的,请参考Android View - 事件分发,拦截,处理机制,因为处理滑动冲突,需要理解View事件分发和拦截。

滑动不一致
这种情况比较容易解决,只要外部重写onInterceptTouchEvent拦截事件时,判断滑动方向,如果符合自己的滑动方向的,就拦截下来。如果不符合,则不拦截,交给内部View处理滑动。

滑动一致
这种情况稍微复杂,因为滑动方向一样。解决这种冲突的方案,一般是外部不拦截,先把事件交给内部,内部判断符合自己的条件,重写onTouchEvent处理事件,并返回true,事件到此结束。如果不符合自己的条件,重写onTouchEvent不处理事件,并返回false,交给外部处理。

处理滑动冲突还是比较复杂的,需要我们不断积累经验,才能处理好,慢慢体会吧。

Android——View的事件体系(一)View的滑动 主要介绍内容: View的基础知识 View的位置参数 MotionEvent 和 TouchSlope VelocityTracker、GestureDetector 和 Scroller View的滑动 使用scrollTo/scrollBy 使用动画 改变布局参数 各种滑动方式的对比 弹性滑动 使用Scroller 通过动画 使用延时策略 View的事件分发机制 点击事件的传递规则 事 阅读详情

相关推荐

Android View体系(二)实现View滑动的六种方法

View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理。其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后的触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标。

Android进阶三部曲 - 刘望舒 2万+

recycleview去掉自带的滑动效果

xml中实现(添加最后一个属性即可)   &lt;android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never"/&gt;   更多好内容戳下面...

wuqingsen1的博客 6941

Android 自定义View:实现View的滑动效果

讲解了View的触摸事件,已经实现View滑动的7种方式

MR_D_j的专栏 8285

View 移动

Android开发中,View一直是Android开发人员的一块心病,一方面想要进阶,一方面又害怕进阶,可以说Android的View是进阶路上的最大绊脚石,因为它涉及的东西太多了,比如本次我们此次要写的View移动,另外还包括View的触摸事件的传递,创建自定义View,这些都是极其重要且不得不面对的难题。但是无论如何,现在不克服的困难将来就会被困难克服。 Let's begin!

renjianhhong的博客 318

Android自定义view-打造酷炫的字体滑动高亮控件

前言: 相信很多时候开发会遇到类似于音乐歌词同步,播放到哪句歌词的哪个词时会逐渐高亮,这样的描述还是不够准确,iPhone的滑动解锁的那种效果,相信很多人都会熟悉吧。今天,我们的首要任务就是开发一个类似于这种效果的安卓控件,以便在以后的项目中直接使用,看起来高大上有木有。其实也不用害怕,需要我们分析和撰写的内容并不多,废话不多说,开始我们今天的教程吧。 正文: 在开始讲解之前,需要准

SmartIceberg的博客 2404

Android View的滑动效果

View的滑动效果可分为两类: 1.View本身的位置不变,View内部的内容滑动; 2. View的位置发生变化,View作为一个整体滑动; ##.View内部内容的滑动 1.通过以下View的以下两个API方法可实现滑动: scrollTo(int x, int y);//滑动到坐标值x、y的位置,初始时x=0,y=0。 //从右向左滑动x增大,从下向上滑动y增大。反之减小。 s...

u013914309的博客 1169

android listview添加数据到顶部 动画,【Android 一般进阶】ListView滑动到顶部smoothScrollToPosition...

ListView一般用来展示数据,当不停的往下翻页,数据会不停的加载,数据也就会越来越多,listview也就越来越长。当用户想回到顶部的时候,难道还需要用户自己往上翻页吗?那也太落后了吧。一般会做一个按钮,跳转至顶部,有两种方式实现:1.使用setSelection(0),不过这样的跳转是没有动画的,瞬间到达顶部;2.使用smoothScrollToPosition(0),这样的跳转是有动画,有...

weixin_36259939的博客 656

避坑指南:Dify+Docker+Ollama离线部署实战与疑难解析

本文详细解析了在国产化系统(如银河麒麟V10)内网环境中,如何从零开始离线部署Dify、Docker与Ollama的全栈AI应用开发平台。文章重点拆解了Docker安装中的“没有Release文件”和“GPG密钥错误”等典型报错解决方案,并提供了Ollama离线模型导入与Dify连接配置的完整实战指南,旨在帮助开发者高效完成本地部署,避开常见陷阱。

dd012的博客 465

【Android 一般进阶】ListView滑动到顶部smoothScrollToPosition

ListView一般用来展示数据,当不停的往下翻页,数据会不停的加载,数据也就会越来越多,listview也就越来越长。当用户想回到顶部的时候,难道还需要用户自己往上翻页吗?那也太落后了吧。 一般会做一个按钮,跳转至顶部,有两种方式实现: 1.使用setSelection(0),不过这样的跳转是没有动画的,瞬间到达顶部; 2.使用smoothScrollToPosition(0),这样的跳转

ben0612的专栏 8620

Python 使用Pygame库实现足球游戏:创建一个球员和一个足球,并使玩家能够控制球员的移动。游戏将包括碰撞检测、简单的物理模拟,以及基本的用户输入处理

本文将介绍如何使用Python和Pygame库创建一个简单的足球游戏。我们将搭建一个基本的游戏环境,创建一个球员和一个足球,并使玩家能够控制球员的移动。游戏将包括碰撞检测、简单的物理模拟,以及基本的用户输入处理。这个简单的足球游戏展示了Pygame的一些基本功能。虽然这是一个简单的游戏,但它包含了创建游戏循环、用户输入处理、物理模拟、碰撞检测等重要概念。

程序熊的博客 743

逆向分析PerimeterX px3:从混淆JS到生成有效令牌的完整实战

在Web安全与数据采集领域,反自动化防护是保障服务稳定和数据安全的关键技术。其核心原理是通过收集浏览器环境指纹和用户行为特征,动态生成加密令牌来区分真人用户与自动化脚本。这项技术的工程价值在于平衡安全性与用户体验,广泛应用于电商、金融、社交等需要防止恶意爬虫和自动化攻击的场景。本文聚焦于业界广泛部署的PerimeterX px3防护方案,通过JavaScript逆向工程,深入剖析其令牌生成机制。我们将探讨如何运用动态调试、反混淆工具和算法还原等关键技术,突破px3的防护壁垒,为自动化测试和数据采集提供稳定可

diankui6178的博客 533

Android RecyclerView 滑动到指定item(position)并加动画

其实Android RecyclerView组件已经自带了移动方法: RecyclerView.scrollToPosition(position) //没有动画效果 但是这个方法没有动画效果,很生硬,直接就滑动过去了,下面来看一个有滑动动画效果的: val smoothScroller= object : androidx.recyclerview.widget.LinearSmoothScro...

新猿的博客 5458

shader多图叠加变换

shader Shader "Paint3D/AddTexture" { Properties { _MainTex ("Main Texture", 2D) = "white" {} _MainColor("Main Color", Color)=(1,1,1,1) _AddTex0 ("Texture0", 2D) = "white" {} _AddTex1 ("Texture1", 2D) = "white" {} .

李长江的博客 909

【Android】View 的滑动

View 的滑动是 Android 实现自定义控件的基础,同时在开发中我们也难免会遇到 View 的滑动处理。其实不管是哪种滑动方式,其基本思想都是类似的:当点击事件传到 View 时,系统记下触摸点的坐标,手指移动时系统记下移动后触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标。

Creativity + Efficiency = Success 1878

紫光同创PDS软件操作指南:如何为FPGA新增自定义Flash型号

本文详细介绍了在紫光同创PDS软件中为FPGA新增自定义Flash型号的完整操作指南。针对官方支持列表之外的SPI Flash芯片,文章从理解FPGA配置逻辑入手,逐步讲解如何通过扫描Flash ID、在Flash Operator中精准填写参数、转换.sbit文件,最终完成固化的全过程,并分享了高级技巧与常见问题排查方法,帮助工程师摆脱对预设型号的依赖,实现灵活选型。

weixin_29204749的博客 327

ThingsBoard-阿里云短信规则节点

由于Thingsboard平台国内只支持短信服务,那我们运维人员去及时接收邮箱肯定是没有短信来的方便的,在这基础上,需要自己从规则链入手,自定义一个支持阿里云短信服务的规则节点。

weixin_67440240的博客 2094

【Android】View滑动的实现

我们在computeScroll()内部调用 scrollTo实现滑动,之后调用postInvalidate()再次重绘,又会调用computeScroll()方法,如此反复,直到滑动结束。由上我们发现,scrollBy实际是通过调用scrollTo实现的,scrollTo是基于所传递参数的绝对滑动,而scrollBy是基于当前位置的相对滑动。Scroller是弹性滑动对象,用于实现View的弹性滑动,即有过渡效果的滑动,需要和View的computeScroll方法配合使用。

2401_87463988的博客 853

MySQL——cost成本计算之MySQL如何选择使用索引(trace)

文章目录前言trace工具分析执行计划 前言 在之前博客中,根据测试案例,发现同样的sql语句,因为传入的条件值的不同,导致MySQL有时候选择使用索引,有时候又不适用索引。 如下所示sql的执行计划: EXPLAIN SELECT * FROM employees WHERE name > 'aaa'; EXPLAIN SELECT * FROM employees WHERE name > 'zzzz'; 在MySQL中,为什么会出现上述这种玄乎的现象呢? 本篇博客重点说明原因。 在说

专注写bug 679

【Android】View的解析—滑动篇

Android系统当中有两种坐标系,分别为Android坐标与View坐标在Android当中我们将左上角的顶点作为Android坐标系的原点,向右为X轴正方向,向下为Y轴正方向,在方法和方法获得的也是Android坐标系的坐标View获取自身的宽和高View自身就有和方法,方法本质是什么: View自身的坐标通过如下方法可以获得View到其父控件ViewGroup的距离: getTop():获取View自身顶边到其父布局顶边的距离getLeft():获取View自身左边到其父布局左边的距离getRight

2301_79828182的博客 1499

【LLM评估篇】Ceval | GAIA | MMLU benchmarks

- 一些大模型的评估模型: - 多轮:MTBench - 关注评估:agent bench - 长文本评估:longbench,longeval - 工具调用评估:toolbench - 安全评估:cvalue,safetyprompt等 本文还介绍了其他主流的大模型评估指标等及其使用

发现问题,并解决问题,批判性思维 6947

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

【Android】View—基础知识,滑动,弹性滑动

在 Android 中,View是用户界面(UI)中的基本组件,用于绘制图形和处理用户交互。所有的 UI 组件(如按钮、文本框、图片等)都是View的子类。可以说,View是构建 Android 应用界面的基础。View是一种界面层的控件的一种抽象,它代表了一个控件。除了View还有ViewGroup,里面包含了许多个控件,即一组View。在Android设计中,ViewGroup也继承了View,也就意味着View本身可以是单个控件也可以是由多个控件组成的一组控件。

2301_79977698的博客 1395

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

安卓开发之View滑动与滑动冲突

在View工作流程中自定义View的一些注意事项里面,我们提到过要避免View的滑动冲突,那么这次就来看下View的滑动与滑动冲突。安卓中我们常见的下拉刷新等操作的基础就是滑动,有些时候由于Android手机屏幕比较小,为了给用户呈现更多的内容,也会需要使用滑动来隐藏或显示一些内容。 View 滑动 View的滑动本质上来说是移动 View,也就是改变其当前所处的位置。它的原理与动画效果的实现非常相似,都是通过不断地改变坐标来实现这一效果。 所以要实现View的滑动,就必须监听用户触摸的事件,并根据事件传入

iris的博客 607

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Android:View的滑动

使用动画去实现滑动的效果,主要操作View的translationX和translationY属性,既可以采用传统的View动画,也可以采用属性动画(采用属性动画,需要采用开源库nineoldandroid)注意:View动画时对View的影像做操作,并不能真正改变View的位置参数(包括宽/高);改变布局参数即改变LayoutParams,如想要把一个Button向右平移100px,我们可以将这个Button的LayoutParams里的。参数的值增加100px。

qq_53092981的博客 644

android群英传 自定义滑动view,Android 自定义滑动的view

安卓开发中经常会涉及到一些滑动的view 只需要使用scroller 就可以实现代码如下 以ImageView 为列 其他的 view 代码都是一样的public classScrollerImageViewextendsSinaImageView {privateScrollermScroller;publicScrollerImageView(Context context) {this(co...

weixin_42504230的博客 164

android view滑动动画,Android实现View滑动的6种方式

本文实例为大家分享了Android实现View滑动的具体方法,供大家参考,具体内容如下1.View的滑动简介View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理。其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后的触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标。实现View滑...

weixin_29503627的博客 885
上一篇: Android View - 事件分发,拦截,处理机制
下一篇: Android View - RemoteViews
JohanMan
博客等级 码龄10年 72粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值