计算7日签到

计算7日签到

1.横向平分屏幕 计算每段距离大小

private void calcucateCirclePoints(List<String> viewData) {
        if (null != viewData) {
            //横向平分屏幕  计算每段距离大小
            int intervalSize = viewData.size() + 1;
            int onePiece = (viewWidth - signInBallRadio * 2 * viewData.size()) / intervalSize;


            for (int i = 0; i < viewData.size(); i++) {
                //每个六边形的 位置
                Point circlePoint = new Point((i + 1) * onePiece + ((i + 1) * 2 - 1) * signInBallRadio, circleY);
                //矩形的位置
                Point descPoint = new Point((int) ((i + 1) * onePiece + ((i + 1) * 2 - 1) * signInBallRadio -
                        signInTextPaint.measureText(viewData.get(i)) / 2), descY);
                //签到的矩形
                RectF rectF = new RectF(0, viewHeight * SECTION_SCALE - signInBallRadio - signInRectHeight, circlePoint.x - signInBallRadio + 3, viewHeight * SECTION_SCALE - signInBallRadio);
                //签到时候矩形的路径
                Path selectPath = new Path();//选择矩形
                selectPath.moveTo(i == 0 ? 0 : i * onePiece + (2 * i - 1) * signInBallRadio, circlePoint.y);
                if (i == viewData.size() - 1) {
                    selectPath.lineTo(viewWidth, circlePoint.y);
                } else {
                    selectPath.lineTo(circlePoint.x - signInBallRadio, circlePoint.y);
                }

                //没用到
                Path signInPath = new Path();
                signInPath.moveTo(circlePoint.x - signInBallRadio / 2, circlePoint.y);
                signInPath.lineTo(circlePoint.x, circlePoint.y + signInBallRadio / 2);
                signInPath.lineTo(circlePoint.x + signInBallRadio / 2, circlePoint.y - signInBallRadio + signInBallRadio / 2);

                //大的六边形 路径
                Path signInDoublePath = new Path();
                signInDoublePath.moveTo((float) (circlePoint.x - signInBallRadio * 1.75 + 10), circlePoint.y);
                signInDoublePath.lineTo((float) (circlePoint.x - signInBallRadio * 1.75 / 4), (float) (circlePoint.y + 1.65 * signInBallRadio / 2 - 5));
                signInDoublePath.lineTo((float) (circlePoint.x + signInBallRadio * 1.75 / 2 + 5), (float) (circlePoint.y - 1.65 * signInBallRadio / 3 - 5));
                signInDoublePath.lineTo((float) (circlePoint.x - signInBallRadio * 1.75 / 4), (float) (circlePoint.y + 1.65 * signInBallRadio / 4 * 3));
//                signInDoublePath.lineTo(circlePoint.x + signInBallRadio , circlePoint.y - signInBallRadio + signInBallRadio);
                signInDoublePath.close();

                //小得六边形
                Path sexanglePath = new Path();
                sexanglePath.moveTo(circlePoint.x - signInBallRadio, circlePoint.y);
                sexanglePath.lineTo(circlePoint.x - signInBallRadio / 2, circlePoint.y - 4 * signInBallRadio / 4);
                sexanglePath.lineTo(circlePoint.x + signInBallRadio / 2, circlePoint.y - 4 * signInBallRadio / 4);
                sexanglePath.lineTo(circlePoint.x + signInBallRadio, circlePoint.y);
                sexanglePath.lineTo(circlePoint.x + signInBallRadio / 2, circlePoint.y + 4 * signInBallRadio / 4);
                sexanglePath.lineTo(circlePoint.x - signInBallRadio / 2, circlePoint.y + 4 * signInBallRadio / 4);
                sexanglePath.close();

                // 大的六边形  做动画
                Path sexangleDoublePath = new Path();
                sexangleDoublePath.moveTo((float) (circlePoint.x - signInBallRadio * 1.75), circlePoint.y);
                sexangleDoublePath.lineTo(circlePoint.x - signInBallRadio, (float) (circlePoint.y - (1.65 * signInBallRadio)));
                sexangleDoublePath.lineTo(circlePoint.x + signInBallRadio, (float) (circlePoint.y - 1.65 * signInBallRadio));
                sexangleDoublePath.lineTo((float) (circlePoint.x + signInBallRadio * 1.75), circlePoint.y);
                sexangleDoublePath.lineTo(circlePoint.x + signInBallRadio, (float) (circlePoint.y + 1.65 * signInBallRadio));
                sexangleDoublePath.lineTo(circlePoint.x - signInBallRadio, (float) (circlePoint.y + 1.65 * signInBallRadio));
                sexangleDoublePath.close();

                circlePoints.add(circlePoint);
                descPoints.add(descPoint);
                signInPbRectFs.add(rectF);
                signInPaths.add(signInPath);
                signInDoublePaths.add(signInDoublePath);
                sexangleDoublePaths.add(sexangleDoublePath);
                sexanglePaths.add(sexanglePath);
                selectLinePath.add(selectPath);
            }

            //设置礼物图标
            int new_W_H = circlePoints.get(viewData.size() - 1).y - signInBallRadio * 2;

            desBitmap = new Rect(circlePoints.get(viewData.size() - 1).x - new_W_H / 2,
                    circlePoints.get(viewData.size() - 1).y - signInBallRadio * 2 - new_W_H,
                    circlePoints.get(viewData.size() - 1).x + new_W_H / 2,
                    circlePoints.get(viewData.size() - 1).y - signInBallRadio * 2);
        }
    }

2.测量

  /**
     * 测量
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int newHeight;
        //如果不是精准模式   就使用默认的高度      具体用法请百度 MeasureSpec.getMode()
        if (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) {
            newHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEF_HEIGHT, getResources().getDisplayMetrics());
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }
    //初始化一个画笔工具
 private Paint createPaint(int paintColor, int textSize, Paint.Style style, int linWidth) {
        Paint p = new Paint();
        p.setColor(paintColor);
        p.setAntiAlias(true);
        p.setStrokeWidth(linWidth);
        p.setDither(true);
        p.setTextSize(textSize);
        p.setStyle(style);
        p.setStrokeCap(Paint.Cap.ROUND);
        p.setStrokeJoin(Paint.Join.ROUND);
        return p;
    }

3.动态linerlayout

package com.example.horizontalscrollview.ui.adapter;

import android.content.Context;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import com.example.horizontalscrollview.ui.adapter.DynamivAdapter;

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

/**
 * 自定义viewGroup 适配adapter
 *
 */

public class GridViewGroup extends ViewGroup implements DynamivAdapter.OnDataChangeListen {
    public DynamivAdapter dynamivAdapter;
    public List<DynamivAdapter.ViewHolder> viewHolders = new ArrayList<>();

    public GridViewGroup(Context context) {
        super(context);
    }

    public GridViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public GridViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public GridViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获得ViewGroup 宽高和测量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
//        measureChildren(widthMeasureSpec,heightMeasureSpec);

        int cw=0;
        int ch=0;
        int count = getChildCount();
        for (int i=0;i<count;i++){
            View view = getChildAt(i);
            cw = view.getMeasuredWidth();
            ch = view.getMeasuredHeight();
            Log.d("测试","---m"+cw+"----"+ch);
            cw+=cw+cw;
            ch+=ch;
        }
        Log.d("测试","---mm"+cw+"----"+ch);

//
//        //计算所有的childview的宽高
        setMeasuredDimension(cw, sizeHeight);
    }

    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        int count = getChildCount();
        Log.d("测试",count+"---");
        int cw = 0;
        int ch =0;

        int cl= 0;
        int ct = 0;
        int cr=0;
        int cb=0;

        for (int j=0;j<count;j++){
            View view = getChildAt(j);
            cw = view.getMeasuredWidth();
            ch = view.getMeasuredHeight();
            Log.d("测试","cw"+cw);
            if (j==0){
                cl=0;
            }else {
                cl=(cl+cw);
            }
            cr=cl+cw;
            cb=ch;
            Log.d("测试",count+"---"+cl+"===="+ct+"--"+cr+"==="+cb);

            view.layout(cl,ct,cr,cb);
        }
    }

    public void setAdapter(DynamivAdapter dynamivAdapter){
        Log.d("测试","-------");
        this.dynamivAdapter = dynamivAdapter;
        this.dynamivAdapter.setOnDataChangeListen(this);
        changerAdapter();
    }

    private void changerAdapter() {
        Log.d("测试","-------");
        int srcCount = dynamivAdapter.getItemCount();
        int destCount = this.getChildCount();
        int maxCount = Math.max(srcCount,destCount);
        Log.d("测试","-------"+destCount+"======"+srcCount);
        for (int i=0;i<maxCount;i++){
            Log.d("测试","-------++"+destCount+"======"+srcCount);
            DynamivAdapter.ViewHolder viewHolder;
            if (i < destCount){
                viewHolder = viewHolders.get(i);
            }else {
                viewHolder = dynamivAdapter.onCreateViewHolder(this);
                if (viewHolder.itemView.getParent() != null){
                    ((ViewGroup)viewHolder.itemView.getParent()).removeAllViews();
                }
                addView(viewHolder.itemView);
                viewHolders.add(i,viewHolder);
            }
            Log.d("测试","-------vh");
            if (viewHolder != null){
                if (i<srcCount){
                    dynamivAdapter.onBindViewHolder(viewHolder,i);
                    viewHolder.itemView.setVisibility(VISIBLE);
                }else {
                    viewHolder.itemView.setVisibility(GONE);
                }
            }
        }
        requestLayout();
    }

    @Override
    public void onChange() {
        changerAdapter();
    }
}

适配

package com.example.horizontalscrollview.ui.adapter;

import androidx.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

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

public abstract class DynamivAdapter <T,VH extends DynamivAdapter.ViewHolder> {
    private final List<T> dataSouse = new ArrayList<>();
    private OnDataChangeListen onDataChangeListen;


    public void setOnDataChangeListen(OnDataChangeListen onDataChangeListen) {
        this.onDataChangeListen = onDataChangeListen;
    }

    public void  notifyDataChangeListen(){
        if (onDataChangeListen != null){
            onDataChangeListen.onChange();
        }
    }

    public void sublist(List<T> newItems){
        Log.d("测试","-------"+newItems.size());
        dataSouse.clear();
        dataSouse.addAll(newItems);
        notifyDataChangeListen();
    }

    protected int getItemCount(){ return dataSouse.size();}

    protected T getItem(int position){ return dataSouse.get(position);}

    public abstract VH onCreateViewHolder(@NonNull ViewGroup parent);

    public abstract void onBindViewHolder(@NonNull VH vh,int position);

    public interface OnDataChangeListen{
        void onChange();
    }
    public class ViewHolder{
        public View itemView;

        public ViewHolder(View itemView) {
            this.itemView = itemView;
        }
    }
}

使用adapter

package com.example.horizontalscrollview.ui.adapter;

import androidx.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.horizontalscrollview.R;
import com.example.horizontalscrollview.ui.model.Bean;

public class PageDynamicAdapter extends DynamivAdapter<Bean, PageDynamicAdapter.BaseViewHolder>{
    private TextView tvName,tvAge;
    private PageDynamicAdapter adapter;

    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent) {
        return new BaseViewHolder(View.inflate(parent.getContext(),R.layout.item_layout,parent));
    }

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder baseViewHolder, int position) {
        Bean bean = getItem(position);
        Log.d("测试","+---------");
        tvName.setText(bean.name);
        tvAge.setText(bean.age);

    }

    public class BaseViewHolder extends DynamivAdapter.ViewHolder{

        public BaseViewHolder(View itemView) {
            super(itemView);
            tvName = itemView.findViewById(R.id.tv_name);
            tvAge = itemView.findViewById(R.id.tv_age);

        }
    }
}


List<Bean> beans= new ArrayList<>();
        Bean bean = new Bean();
        bean.age=12;
        bean.name="哈哈";
        Bean bean1 = new Bean();
        bean1.age=12;
        bean1.name="哈哈";
        beans.add(bean);
        beans.add(bean1);
        pageDynamicAdapter = new PageDynamicAdapter();
        pageDynamicAdapter.setOnDataChangeListen(this);
        gridViewGroup.setAdapter(pageDynamicAdapter);
        pageDynamicAdapter.sublist(beans);

 int maxWidth = 0;
        int maxHeight = 0;
        int childCount = getChildCount();
        //计算宽度即可
        for (int i = 0; i < childCount; i++) {
            View view = getChildAt(i);
            if (view != null && view.getVisibility() != GONE) {
                measureChild(view, widthMeasureSpec, heightMeasureSpec);
                MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
                maxWidth += view.getMeasuredWidth() + params.leftMargin + params.rightMargin;
                maxHeight = Math.max(maxHeight, view.getMeasuredHeight() + params.topMargin + params.bottomMargin);
            }
        }
        int resultWidth = maxWidth + getPaddingLeft() + getPaddingRight() + spacing * (childCount - 1);
        int resultHeight = maxHeight + getPaddingTop() + getPaddingBottom();
        setMeasuredDimension(resolveSize(resultWidth,widthMeasureSpec), resolveSize(resultHeight,heightMeasureSpec));
int left = getPaddingLeft();
        int top = getPaddingTop();
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
            if (view.getVisibility() == View.GONE) {
                continue;
            }
            int lc = left + lp.leftMargin;
            int tc = top + lp.topMargin;
            int rc = lc + view.getMeasuredWidth();
            int bc = tc + view.getMeasuredHeight();

            view.layout(lc, tc, rc, bc);

            left += view.getMeasuredWidth() + lp.leftMargin
                    + lp.rightMargin + spacing;
        }

测试代码

public class DynamicVerticalLayout extends ViewGroup implements DynamicAdapter.OnDataChangedListener {

    private DynamicAdapter repeatAdapter;
    private List<DynamicAdapter.ViewHolder> holderList = new ArrayList<>();
    private int spacing = 0;

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

    public DynamicVerticalLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public DynamicVerticalLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DynamicVerticalLayout);
        if (array != null) {
            spacing = array.getDimensionPixelSize(R.styleable.DynamicVerticalLayout_android_spacing, 0);
            array.recycle();
        }
    }


    public void setAdapter(DynamicAdapter adapter) {
        this.repeatAdapter = adapter;
        this.repeatAdapter.setOnDataChangedListener(this);
        changeAdapter();
    }

    private void changeAdapter() {
        int srcCount = repeatAdapter.getItemCount();
        int destCount = this.getChildCount();
        int maxCount = Math.max(srcCount, destCount);
        for (int i = 0; i < maxCount; i++) {
            DynamicAdapter.ViewHolder viewHolder;
            if (i < destCount) {
                viewHolder = holderList.get(i);
            } else {
                viewHolder = repeatAdapter.onCreateViewHolder(this);
                addView(viewHolder.itemView);
                holderList.add(i, viewHolder);
            }

            if (viewHolder != null) {
                if (i < srcCount) {
                    repeatAdapter.onBindViewHolder(viewHolder, i);
                    viewHolder.itemView.setVisibility(VISIBLE);
                } else {
                    viewHolder.itemView.setVisibility(GONE);
                }
            }
        }
        requestLayout();
    }


    @Override
    public void onChanged() {
        changeAdapter();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int maxWidth = 0;
        int maxHeight = 0;
        int childCount = getChildCount();
        //计算宽度即可
        for (int i = 0; i < childCount; i++) {
            View view = getChildAt(i);
            if (view != null && view.getVisibility() != GONE) {
                MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
                measureChild(view, widthMeasureSpec, heightMeasureSpec);
                maxHeight += view.getMeasuredHeight() + params.topMargin + params.bottomMargin;
                maxWidth = Math.max(maxWidth, view.getMeasuredWidth() + params.leftMargin + params.rightMargin);
            }
        }
        int resultHeight = maxHeight + getPaddingTop() + getPaddingBottom() + spacing * (childCount - 1);
        int resultWidth = maxWidth + getPaddingLeft() + getPaddingRight();
        if (widthMode == MeasureSpec.AT_MOST) {
            if (resultWidth > widthSize) {
                resultWidth = widthSize;
            }
        }
        setMeasuredDimension(resolveSize(resultWidth, widthMeasureSpec), resolveSize(resultHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = getPaddingLeft();
        int top = getPaddingTop();
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
            if (view.getVisibility() == View.GONE) {
                continue;
            }
            int lc = left + lp.leftMargin;
            int tc = top + lp.topMargin;
            int rc = lc + view.getMeasuredWidth();
            int bc = tc + view.getMeasuredHeight();

            view.layout(lc, tc, rc, bc);

            top += view.getMeasuredHeight() + lp.topMargin
                    + lp.bottomMargin + spacing;
        }
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(MarginLayoutParams.MATCH_PARENT, MarginLayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected boolean checkLayoutParams(LayoutParams p) {
        return p instanceof MarginLayoutParams;
    }
}
public abstract class DynamicAdapter<T, VH extends DynamicAdapter.ViewHolder> {

    private final List<T> mDataSource = new ArrayList<>();

    private OnDataChangedListener mOnDataChangedListener;

    interface OnDataChangedListener {
        void onChanged();
    }
    private Path path;

    public void setPath(Path path) {
        this.path = path;
    }

    public Path getPath() {
        return path;
    }


    void setOnDataChangedListener(OnDataChangedListener listener) {
        mOnDataChangedListener = listener;
    }

    private void notifyDataSetChanged() {
        if (mOnDataChangedListener != null) {
            mOnDataChangedListener.onChanged();
        }
    }
    public void submitList(List<T> newItems) {
        mDataSource.clear();
        mDataSource.addAll(newItems);
        notifyDataSetChanged();
    }

    protected int getItemCount() {
        return mDataSource.size();
    }

    protected T getItem(int position) {
        return mDataSource.isEmpty() ? null : mDataSource.get(position);
    }

    public abstract VH onCreateViewHolder(@NonNull ViewGroup parent);

    public abstract void onBindViewHolder(@NonNull VH vh, int position);


    public static class ViewHolder {
        public View itemView;

        public ViewHolder(View itemView) {
            this.itemView = itemView;
        }
    }
}

测试数据

public class FindInsuranceAdapter extends DynamicAdapter<HealthSecurity, FindInsuranceAdapter.ViewHolder>{
    public OnItemOperateListener onItemOperateListener;

    public void setOnItemOperateListener(OnItemOperateListener onItemOperateListener) {
        this.onItemOperateListener = onItemOperateListener;
    }

    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_find_insurance, viewGroup, false);
        return new ViewHolder(view, new SoftReference<>(this));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
        HealthSecurity healthSecurity = getItem(position);
            viewHolder.tvTitle.setText(healthSecurity.title);
            viewHolder.ivInsuranceCover.setRoundImageUri(healthSecurity.imgUrl,R.drawable.ic_default, ScreenUtil.getPixDimension(R.dimen.w16));
            viewHolder.tvContent.setText(healthSecurity.description);
            if (!TextUtils.isEmpty(healthSecurity.labels)){
                viewHolder.tvLabel.setVisibility(View.VISIBLE);
                viewHolder.tvLabel.setText(healthSecurity.labels);
            }else {
                viewHolder.tvLabel.setVisibility(View.GONE);
            }
            viewHolder.relFindInsurance.setOnClickListener(v -> {
                onItemOperateListener.onItemClick(healthSecurity);
            });
    }

    public static class ViewHolder extends DynamicAdapter.ViewHolder implements OnPagerViewVisibleListener {
        RemoteImageView ivInsuranceCover;
        TextView tvTitle;
        TextView tvContent;
        TextView tvLabel;
        RelativeLayout relFindInsurance;
        private final FindInsuranceAdapter adapter;

        public ViewHolder(@NonNull View itemView, SoftReference<FindInsuranceAdapter> softReference) {
            super(itemView);
            ivInsuranceCover = itemView.findViewById(R.id.iv_insurance_cover);
            tvTitle = itemView.findViewById(R.id.tv_insurance_title);
            tvContent = itemView.findViewById(R.id.tv_insurance_content);
            tvLabel = itemView.findViewById(R.id.tv_insurance_label);
            relFindInsurance = itemView.findViewById(R.id.rel_find_insurance);
            adapter = softReference.get();
            ViewAnalysis.with((PagerVisibleOwner) itemView.getContext()).listener(this).analyse(itemView);
        }
        @Override
        public void onPagerViewVisibleChanged(boolean visible) {
//            AnalysisPacket.obtain(AnalysisEventConstants.CHENGZHANGZHUSHOU_LIEBIAO_S)
//                    .addPath(adapter.getPath())
//                    .post();
        }
    }

    public interface OnItemOperateListener {
        void onItemClick(HealthSecurity healthSecurity);

        void onItemShow(HealthSecurity healthSecurity);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值