Android自定义View实现流式布局

【Android】掌握自定义LayoutManager(二) 实现流式布局 private int mVerticalOffset;//竖直偏移量 每次换行时,要根据这个offset判断 private int mFirstVisiPos;//屏幕可见的第一个View的Position private int mLastVisiPos;//屏幕可见的最后一个View的Position @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { i 阅读详情

实现效果如图

这里写图片描述

大概流程图

这里写图片描述

实现分析

1.在FlowLayout的构造里面获取自定义属性,让其支持横向间距和纵向间距

  public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
        horizontal_space = typedArray.getDimension(R.styleable.FlowLayout_width_space, 0);
        vertical_space = typedArray.getDimension(R.styleable.FlowLayout_height_space, 0);
        typedArray.recycle();
    }

2.在OnMeasure()里面进行测量

  @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mLines.clear();
        mCurrentLine = null;

        //获取总的宽度
        int width = MeasureSpec.getSize(widthMeasureSpec);
        //计算最大的宽度
        mMaxWidth = width - getPaddingRight() - getPaddingLeft();

        //测量孩子
        int childCount = this.getChildCount();

        for (int i = 0; i < childCount; i++) {

            View childView = getChildAt(i);

            measureChild(childView, widthMeasureSpec, heightMeasureSpec);

            //测量完成之后将孩子添加 到管理行进行管理
            if (mCurrentLine == null) {

                //第一次添加孩子的时候
                mCurrentLine = new Line(mMaxWidth,horizontal_space);

                //添加孩子
                mCurrentLine.addView(childView);
                //.添加行
                mLines.add(mCurrentLine);
            }else{

                //先判断行里是否可以继续添加孩子
                if(mCurrentLine.canAddView(childView)){

                    mCurrentLine.addView(childView);

                }else{
                    //换到下一行

                    mCurrentLine=new Line(mMaxWidth ,horizontal_space);
                    mCurrentLine.addView(childView);
                    mLines.add(mCurrentLine);
                }
            }
        }


        //完成了测量孩子,那么就来测量自己
        //计算自己只需要测量自己的高度,宽度肯定回被填充
        int height = getPaddingTop() + getPaddingBottom();
        for(int i=0;i<mLines.size();i++){
            //所有的行高
            height+=mLines.get(i).height;
        }

        //所有竖直方向的间距
        height+=(mLines.size()-1)*vertical_space;

        //测量

        setMeasuredDimension(width,height);
    }

3.在OnLayout()里面遍历获取所有的行,让行去指定孩子的位置,指定行的高度。

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {


        //这里只负责具体 高度位置,具体 的 宽度和子孩子的高度让具体 的行去管理
        l=getPaddingLeft();
        t=getPaddingTop();

        for(int j=0 ;j<mLines.size(); j++){

            //获取 行
            Line line = mLines.get(j);

            line.onLayout(t,l);

            //更新高度
            t+=line.height;
            if(j!=mLines.size()-1){

                //不是最后一条 添加间距

                t+=vertical_space;

            }


        }

    }

4.在内部类里面对孩子进行管理,包括添加子view,子view的位置摆放

/**
     * 内部类,行管理器,管理每一行的孩子
     */
    public static class Line {

        private float horizontalSpace;
        private int   maxWidth;
        //定义一个行的集合来装子View
        List<View> views = new ArrayList<>();
        private int usedWidth;
        private int height;

        public Line(int maxWidth, float horizontalSpace) {

            this.maxWidth = maxWidth;
            this.horizontalSpace = horizontalSpace;
        }

        public void addView(View view) {

            int childWidth = view.getMeasuredWidth();
            int childHeight = view.getMeasuredHeight();

            //更新行里面 的宽度与高度
            if (views.size() == 0) {
                //集合里面没有孩子的时候
                if (childWidth > maxWidth) {

                    usedWidth = maxWidth;
                    height = childHeight;

                } else {

                    usedWidth = childWidth;
                    height = childHeight;

                }

            } else {

                usedWidth += childWidth + horizontalSpace;
                height = childHeight > height ? childHeight : height;

            }

            //添加孩子到集合
            views.add(view);
        }


        public boolean canAddView(View view) {
            //集合里面添加孩子
            if (views.size() == 0) {
                return true;
            }

            //最后一个孩子的宽度大于剩余的宽度返回false
            if (view.getMeasuredWidth() > (maxWidth - usedWidth - horizontalSpace)) {

                return false;
            }


            return true;
        }


        /**
         * 指定孩子的显示位子
         */

        public void onLayout(int t, int l) {

            //平分剩余的空间
            int avg = (maxWidth - usedWidth) / views.size();

            //循环指定孩子的位子

            for (View view : views) {

                //获取宽高
                int measuredWidth = view.getMeasuredWidth();
                int measuredHeight = view.getMeasuredHeight();

                //重新测量
                view.measure(MeasureSpec.makeMeasureSpec(measuredWidth + avg, MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY));


                //重新获取宽高
                measuredWidth = view.getMeasuredWidth();

                //指定左上右下
                int top = t;
                int left = l;
                int right = measuredWidth + left;
                int bottom = measuredHeight + top;

                view.layout(left, top, right, bottom);

                //跟新数据
                l += measuredWidth + horizontalSpace;

            }


        }

    }

下面是完整代码

package com.zyh.jsondemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * @创建者 Administrator
 * @创建时间 2016/10/16 10:32
 * @描述 ${TODO}
 */
public class FlowLayout extends ViewGroup {


    /**
     * 储存行的集合
     */
    private List<Line> mLines = new ArrayList<>();

    // 当前行的指针
    private Line mCurrentLine;


    //水平方向的间距
    private float horizontal_space;
    //垂直方向的间距
    private float vertical_space;
    private int   mMaxWidth;

    public FlowLayout(Context context) {
        this(context, null);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
        horizontal_space = typedArray.getDimension(R.styleable.FlowLayout_width_space, 0);
        vertical_space = typedArray.getDimension(R.styleable.FlowLayout_height_space, 0);
        typedArray.recycle();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mLines.clear();
        mCurrentLine = null;

        //获取总的宽度
        int width = MeasureSpec.getSize(widthMeasureSpec);
        //计算最大的宽度
        mMaxWidth = width - getPaddingRight() - getPaddingLeft();

        //测量孩子
        int childCount = this.getChildCount();

        for (int i = 0; i < childCount; i++) {

            View childView = getChildAt(i);

            measureChild(childView, widthMeasureSpec, heightMeasureSpec);

            //测量完成之后将孩子添加 到管理行进行管理

            if (mCurrentLine == null) {

                //第一次添加孩子的时候
                mCurrentLine = new Line(mMaxWidth, horizontal_space);

                //添加孩子
                mCurrentLine.addView(childView);
                //.添加行
                mLines.add(mCurrentLine);
            } else {

                //先判断行里是否可以继续添加孩子
                if (mCurrentLine.canAddView(childView)) {

                    mCurrentLine.addView(childView);

                } else {
                    //换到下一行

                    mCurrentLine = new Line(mMaxWidth, horizontal_space);
                    mCurrentLine.addView(childView);
                    mLines.add(mCurrentLine);
                }
            }
        }


        //完成了测量孩子,那么就来测量自己
        //计算自己只需要测量自己的高度,宽度肯定回被填充
        int height = getPaddingTop() + getPaddingBottom();
        for (int i = 0; i < mLines.size(); i++) {
            //所有的行高
            height += mLines.get(i).height;
        }

        //所有竖直方向的间距
        height += (mLines.size() - 1) * vertical_space;

        //测量

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {


        //这里只负责具体 高度位置,具体 的 宽度和子孩子的高度让具体 的行去管理
        l = getPaddingLeft();
        t = getPaddingTop();

        for (int j = 0; j < mLines.size(); j++) {

            //获取 行
            Line line = mLines.get(j);

            line.onLayout(t, l);

            //更新高度
            t += line.height;
            if (j != mLines.size() - 1) {

                //不是最后一条 添加间距

                t += vertical_space;

            }


        }

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }


    /**
     * 内部类,行管理器,管理每一行的孩子
     */
    public static class Line {

        private float horizontalSpace;
        private int   maxWidth;
        //定义一个行的集合来装子View
        List<View> views = new ArrayList<>();
        private int usedWidth;
        private int height;

        public Line(int maxWidth, float horizontalSpace) {

            this.maxWidth = maxWidth;
            this.horizontalSpace = horizontalSpace;
        }

        public void addView(View view) {

            int childWidth = view.getMeasuredWidth();
            int childHeight = view.getMeasuredHeight();

            //更新行里面 的宽度与高度
            if (views.size() == 0) {
                //集合里面没有孩子的时候
                if (childWidth > maxWidth) {

                    usedWidth = maxWidth;
                    height = childHeight;

                } else {

                    usedWidth = childWidth;
                    height = childHeight;

                }

            } else {

                usedWidth += childWidth + horizontalSpace;
                height = childHeight > height ? childHeight : height;

            }

            //添加孩子到集合
            views.add(view);
        }


        public boolean canAddView(View view) {
            //集合里面添加孩子
            if (views.size() == 0) {
                return true;
            }

            //最后一个孩子的宽度大于剩余的宽度返回false
            if (view.getMeasuredWidth() > (maxWidth - usedWidth - horizontalSpace)) {

                return false;
            }


            return true;
        }


        /**
         * 指定孩子的显示位子
         */

        public void onLayout(int t, int l) {

            //平分剩余的空间
            int avg = (maxWidth - usedWidth) / views.size();

            //循环指定孩子的位子

            for (View view : views) {

                //获取宽高
                int measuredWidth = view.getMeasuredWidth();
                int measuredHeight = view.getMeasuredHeight();

                //重新测量
                view.measure(MeasureSpec.makeMeasureSpec(measuredWidth + avg, MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY));


                //重新获取宽高
                measuredWidth = view.getMeasuredWidth();

                //指定左上右下
                int top = t;
                int left = l;
                int right = measuredWidth + left;
                int bottom = measuredHeight + top;

                view.layout(left, top, right, bottom);

                //跟新数据
                l += measuredWidth + horizontalSpace;

            }


        }

    }


}

2.自定义属性

<resources>
    <declare-styleable name="FlowLayout">
        <attr name="width_space" format="dimension"></attr>
        <attr name="height_space" format="dimension"></attr>

    </declare-styleable>

</resources>

3.xml文件

   <com.zyh.jsondemo.FlowLayout
        android:id="@+id/fl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:width_space="5dp"
        app:height_space="5dp"
        />

4.MainActivity代码

public class MainActivity2 extends Activity{

    private FlowLayout mFl;

    /**
     * 显示的文字
     */
    private String[] mDatas = new String[]{"QQ",
            "视频",
            "放开那三国",
            "电子书",
            "酒店",
            "单机",
            "小说",
            "斗地主",
            "优酷",
            "网游",
            "WIFI万能钥匙",
            "播放器",
            "捕鱼达人2",
            "机票",
            "游戏",
            "熊出没之熊大快跑",
            "美图秀秀",
            "浏览器",
            "单机游戏",
            "我的世界",
            "电影电视",
            "QQ空间",
            "旅游",
            "免费游戏",
            "2048",
            "刀塔传奇",
            "壁纸",
            "节奏大师",
            "锁屏",
            "装机必备",
            "天天动听",
            "备份",
            "网盘",
            "海淘网",
            "大众点评",
            "爱奇艺视频",
            "腾讯手机管家",
            "百度地图",
            "猎豹清理大师",
            "谷歌地图",
            "hao123上网导航",
            "京东",
            "有你",
            "万年历-农历黄历",
            "支付宝钱包"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);



        setContentView(R.layout.activity_main2);


        initView();
        initData();


    }

    private void initView() {

        mFl = (FlowLayout) findViewById(R.id.fl);

    }

    private void initData() {
        Random random = new Random();

        for(String name:mDatas){


            final TextView view = new TextView(this);
            view.setText(name);
            view.setTextColor(Color.WHITE);
            view.setPadding(8, 8, 8, 8);
            view.setGravity(Gravity.CENTER);
            view.setTextSize(20);
            // 设置点击事件
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(MainActivity2.this, view.getText().toString(), Toast.LENGTH_SHORT).show();
                }
            });

            // 设置彩色背景
            GradientDrawable normalDrawable = new GradientDrawable();
            normalDrawable.setShape(GradientDrawable.RECTANGLE);
            int a = 255;
            int r = 50 + random.nextInt(150);
            int g = 50 + random.nextInt(150);
            int b = 50 + random.nextInt(150);
            normalDrawable.setColor(Color.argb(a, r, g, b));

            // 设置按下的灰色背景
            GradientDrawable pressedDrawable = new GradientDrawable();
            pressedDrawable.setShape(GradientDrawable.RECTANGLE);
            pressedDrawable.setColor(Color.GRAY);

            // 背景选择器
            StateListDrawable stateDrawable = new StateListDrawable();
            stateDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
            stateDrawable.addState(new int[]{}, normalDrawable);

            // 设置背景选择器到TextView上
            view.setBackground(stateDrawable);

            mFl.addView(view);
        }

    }
}
Android自定义View之实现流式布局 流式布局 把子控件从左到右摆放,如果一行放不下,自动放到下一行 自定义布局流程 1. 自定义属性:声明,设置,解析获取自定义值 在attr.xml中声明 3. 测量:在onMeasure 方法测量自身的宽高和child的宽高 4. 布局:在onLayout方法里面根据自己的规则来确定children的位置 5. 绘制:onDraw 6. 处理layoutParams 7. 触摸反馈:滑动事件 ... 阅读详情

相关推荐

Android自定义View实现动画流式布局及点击添加功能

动画显示流式布局点击动画添加 上一篇已经发表了流式布局点击添加功能这里就不用了,需要的可以去上一篇博客查看 步入正题 在build。gradle中配置以下: //Gson依赖 implementation ‘com.google.code.gson:gson:2.8.5’ //volley请求框架 implementation ‘com.android.volley:volley:1.1.1’ 首...

Mr_Songdada的博客 722

安卓快速实现流式布局(RecyclerView+ FlexboxLayout)

安卓快速实现流式布局(RecyclerView+ FlexboxLayout)

Jason_HD的博客 1601

自定义ViewGroup实现流式布局(支持ViewGroup Padding, 子View margin,每行高度可以不一样)

http://blog.youkuaiyun.com/zxt0601/article/details/50533658 博客资源

安卓自定义流式布局——真正像潺潺流水一样

通过重写RelativeLayout,设置其中的每个子View的相对关系来实现的流式布局,全局只有一层父view,也就是说布局结构只有两层。 主要功能: 1.设置行间距 2.设置子View之间的间距 3.设置水平是否均匀平铺 4.设置垂直方向对齐方式——顶部对齐,居中对齐,底部对齐。 5.支持子View删除时的布局重绘。 效果图如下:

xx23x的博客 1077

android 自定义view流式布局

android 自定义view流式布局,

自定义实现流式布局

该资源包含了一个自定义ViewGroup实现的流式布局,需要的可以下载

Android自定ViewGroup实现流式布局

转载请标明出处:http://blog.youkuaiyun.com/yansong_post ,本文出自【李岩松的博客】 1.概述 本篇给大家带来一个实例,FlowLayout,什么是FlowLayout,我们常在App 的搜索界面看到热门搜索词,就是FlowLayout,我们要实现的就是图中的效果,就是根据容器的宽,往容器里面添加元素,如果剩余的控件不足时候,自行添加到下一行,FlowLayo

yansong 405

Android中自定义View之流式布局

Android中自定义View之流式布局的Demo,代码中关键步骤并有注释原理解说,轻松掌握自定义View的onMeasure和onLayout的实现

android 自定义view实现流式布局

页面效果实现 import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /** * @description:自定义流式布局 * @date: 2019/9/11 11:14 * @author:..

72的博客 278

自定义流式布局,侧边栏

自定义流式布局,自定义属性,滑动侧边栏,覆盖式滑动侧边栏。

Open3D (C++) 使用点云创建数字高程模型DEM

Open3D (C++) 使用点云创建数字高程模型DEM

点云侠的博客 1392

android 自定义View之继承ViewGroup实现流式布局

主要实现效果如下:接下来讲述如何实现:通过自定义ViewGroup实现:1:onMeasure:测量view的宽高--     在重写的onMeasure方法中,会传入2个参数,他们分别代表“宽的测量规格”,“高的测量规格”,如下所示(spec:规格)protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {测量规...

Cdaimadada的博客 982

华为OD机试真题 新系统2026-04-01 Java&Go 实现【勇攀数字高峰】

请你在给定的数字地形图中寻找登山路径,数字代表当前位置的海拔高度,要求从最低海拔出发,不断攀登,最终到达最高山峰。你需要寻找所有满足条件的登山路径。地图已经保证最低海拔和最高山峰都只有一个。

MISAYAONE的博客 621

android自定义View实现流式布局

//先来一张效果图   //自定义的控件 import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widge...

72的博客 672

内存泄漏系列专题分析之二十一:高通相机CamX内存泄漏&内存占用分析--GPU内存拆解

通过上述debug方式,可以看到patch补丁可以顺利debug各种ION内存分布,可以通过它分析ION内存占用问题。同时我们还可以分析GPU内存泄漏问题,同样的方式可以看到所有的GPU内存分布,如果某个GPU内存持续增长,就极有可能内存泄漏,然后更具堆栈信息去分析代码,并解决GPU内存泄漏问题。!!

454

TurboQuant: Online Vector Quantization with Near-optimal Distortion Rate

这篇被 ICLR 2026 接收的论文提出了一种名为TurboQuant的全新在线向量量化(Vector Quantization, VQ)算法。该研究的核心目标是解决大语言模型(LLM)在长上下文推理时面临的 KV Cache 显存消耗瓶颈,以及大规模向量数据库在近似最近邻检索中的存储与延迟问题。有别于现有技术,TurboQuant 是一种无需任何校准数据、无需训练的在线算法(Data-oblivious)。

c_cpp_csharp的专栏 118

Android中自定义view实现流式布局

实现效果: 一.布局文件 &lt;comp.bwei.flowlayout.FlowLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp"&gt; &lt;TextView and...

jzw_8899174的博客 410

微信小程序 - 实现Java微信支付退款功能以及退款流程,微信小程序前端+java后端完整示例源码,微信小程序退款功能详解,小程序订单申请退款和退款回调方法、查询退款等(新版微信支付,详细示例代码)

微信小程序开发-微信支付退款功能以及退款回调方法,微信支付退款API详解,微信小程序支付V3(支付、退款)Java实现微信小程序开发 小程序支付开发-小程序退款功能,微信小程序小程序和公众号 退款功能教程(含申请退款和退款回调,退款回调地址在商户后台配置或者代码自定义)最新版微信小程序支付,退款问题,小程序支付和退款功能详解,小程序申请退款,小程序处理退款,微信小程序支付与退款java,微信小程序退款及回调,JAVA实现微信小程序支付退款功能,退款api调用报错,如何解决退款申请无响应,如何用实现小程序订单

🏆 前端领域优质创作者 4159

Android 自定义View修炼-Android中常见的热门标签的流式布局的实现

一、概述:在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧(源码下载在下面最后给出哈) 类似的自定义布局。下面我们就来详细介绍流式布局的应用特点以及用的的技术点: 1.流式布局的特点以及应用场景 特点:当上面一行的空间不够容纳新的TextView时候, 才开辟下一行的空间 ...

weixin_30553837的博客 94

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合ollama无限token实现7*24小时工作(附配置)

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合 ollama 无限token实现7*24小时工作,以及部署安装需要的 skills 完成复杂的工作任务(附完整可以运行的配置文件)。 很多人已经会配置安装 openclaw 了 ,但是 安装完成之后真正让电脑自动运行起来的很好,完成出色工作的更少,最常见的就是聊聊天,或者执行一些简单的命令,理解要让电脑自动化工作,openclaw、skills、大模型这三样。

代码讲故事 2963

【k8s故障处理篇】calico-kube-controllers状态为“ImagePullBackOff”解决办法

【k8s故障处理篇】calico-kube-controllers状态为“ImagePullBackOff”解决办法

jks212454的博客 2308

【流式布局】Android自定义View--简单实现

蛮简单的,核心代码总共不到100行就可以实现,想要实现其他功能也可以在此基础上拓展

qq_46205625的博客 553

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Android 自定义View实现流式布局——彩色背景

效果图: 概述 1.流式布局原理: 在布局内,随意摆放任意个view,每行所摆放的view个数,根据实施计算出来的宽度,一旦当前要摆放的view宽度和之前摆放的所有view宽度加在一起,超过了布局的宽度,那么就把该view换行摆放 2.应用场景: 一般,像这种流式布局会应用在一些热门标签,热门推荐之类的应用上 3.测量模式: 谈到FlowLayout流式布局,不得不提及他的测量模...

baipenggui_bo 1149

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Android中的自定义View(二)之 流式布局实现

我们在上一篇文章《Android中的自定义View(一)》中介绍过自定义View的几种方式,并通过示例一演示了“直接继承View”的自定义View的使用情况。今天接着来介绍自定义View里稍为复杂的“直接继承ViewGroup”的使用情况。一般地,直接继承ViewGroup的自定义View需要我们自己去处理ViewGroup的measure和layout这两个过程,并同时处理子元素的measure...

子云心的博客 731

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

上一篇: Android中WebView的使用
下一篇: Android Apk瘦身
Hello_word1024
博客等级 码龄11年 5粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值