Android 实现滑动数字选择器

这篇具有很好参考价值的文章主要介绍了Android 实现滑动数字选择器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android 滑动数字选择器是一种用户界面控件,它允许用户从一系列数字中选择一个值。用户可以通过滑动手势或点击手势来选择数字。以下是一些关于 Android 滑动数字选择器的信息和链接:

  1. Android NumberPicker:这是 Android 框架提供的原生数字选择器控件。它可以通过 XML 或代码创建,并支持自定义样式和属性。官方文档链接:https://developer.android.com/reference/android/widget/NumberPicker

  2. Android WheelPicker:这是一个第三方的数字选择器库,它提供了多种样式和配置选项。它可以通过 Gradle 或手动导入方式添加到项目中。GitHub 链接:GitHub - AigeStudio/WheelPicker: Simple and fantastic wheel view in realistic effect for android.

  3. Android ScrollableNumberPicker:这是另一个第三方的数字选择器库,它支持水平和垂直滚动模式,并提供了多种自定义选项。它可以通过 Gradle 或手动导入方式添加到项目中。GitHub 链接:https://github.com/michaelbel/ScrollableNumberPicker

一、以下是一个简单的 Android NumberPicker 示例代码:

<NumberPicker
    android:id="@+id/numberPicker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:maxValue="10"
    android:minValue="1"
    android:value="5" />

 文章来源地址https://www.toymoban.com/news/detail-727831.html

NumberPicker numberPicker = findViewById(R.id.numberPicker);
numberPicker.setMinValue(1);
numberPicker.setMaxValue(10);
numberPicker.setValue(5);
numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
    @Override
    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
        // 处理数值变化事件
    }
});

二、以下是我个人写的一个滚动选择器

1.项目结构:

android 滚轮选择器,笔记,android,java,android studio

 2.先定义两个类

NumPicker
package com.example.myapplication;

import android.app.Activity;
import android.app.Dialog;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

/**
 * Author cjet
 * Date   2018-1-16 14:02
 */

public class NumPicker {

    private Activity mActivity;
    private TextView tvCancel;
    private Button tvComfirm;
    private TextView tvTitle;
    private NumPickView mNpv;
    private Dialog mDialog;
    private OnCancelClickListener mCancelListener;
    private onComfirmClickListener mComfirmListener;
    private int currentSelecedNum;

    NumPicker(Activity activity) {
        mActivity = activity;
        initDialog();

    }

    private void initDialog() {
        mDialog = new Dialog(mActivity, R.style.BottomSheetDialog);
        mDialog.setContentView(mActivity.getLayoutInflater().inflate(R.layout.picker_layout, null));
        Display dd = mActivity.getWindowManager().getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        dd.getMetrics(dm);
        WindowManager.LayoutParams attributes = mDialog.getWindow().getAttributes();
        mDialog.getWindow().setGravity(Gravity.BOTTOM);
        attributes.height = (int) (dm.heightPixels * 0.4);
        attributes.width = dm.widthPixels;
        mDialog.getWindow().setWindowAnimations(R.style.dialogWindowAnimation);

        //tvCancel = mDialog.findViewById(R.id.tvCancel);
        tvComfirm = mDialog.findViewById(R.id.tvConfirm);
        //tvTitle = mDialog.findViewById(R.id.tvTitle);
        mNpv = mDialog.findViewById(R.id.numPickView);
        currentSelecedNum = mNpv.getCurrentPostion();//当前选择数
        setListener();
    }

    private void setListener() {
        mNpv.setOnSelectNumListener(new NumPickView.OnSelectNumListener() {
            @Override
            public void onSelected(int num) {
                currentSelecedNum = num;
            }
        });

        tvComfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mComfirmListener != null) {
                    mComfirmListener.onClick(currentSelecedNum);
                }
            }
        });

//        tvCancel.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                if (mCancelListener != null) {
//                    mCancelListener.onClick();
//                }
//            }
//        });
    }

    public void show() {
        if (mDialog != null) {
            mDialog.show();
        }
    }

    public void dismiss() {
        if (mDialog != null) {
            mDialog.cancel();
        }
    }

    public void selecNum(int num) {
        mNpv.select(num);
    }

    public void setOnCancelListener(OnCancelClickListener listener) {
        this.mCancelListener = listener;
    }

    public void setOnComfirmListener(onComfirmClickListener listener) {
        this.mComfirmListener = listener;
    }

    public void setTitle(String title) {
        //tvTitle.setText(title);
    }

    public interface OnCancelClickListener {
        void onClick();
    }

    public interface onComfirmClickListener {
        void onClick(int num);
    }
}
NumPickView
package com.example.myapplication;

import static java.lang.Math.abs;
import static java.lang.Math.min;

import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;

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

/**
 * Author uidq1152
 * Date   2018-1-12 10:27
 */

public class NumPickView extends View {

    private static final String TAG = "NumPickView";
    private static final String DEF_TEXT_COLOR = "#FA6909";
    private static final String DEF_START_COLOR = "#ECECEC";
    /**
     * D0D1D2
     * 64666B
     * 4C4E53
     * 3A3D41
     */

    //高
    private int mHeight;
    //宽
    private int mWidth;
    //二分之一高
    private int middleHeight;
    //二分之一宽
    private int middleWidht;
    //单位高度
    private int mUnitHeight;
    //数据
    private List<String> mData = new ArrayList<>();
    //当前位置
    private int mCurrentPostion = 0;
    //偏移量
    private float pivot;
    //画笔
    private Paint mPaint;
    //字体的矩形
    private Rect mRect;
    //落点Y
    private float downY;
    //缩放扩大比例
    private float mScale;
    //滚轮状态
    private Status mStatus = Status.IDEL;
    //遮罩效果
    private LinearGradient mLg;
    //数值估值器
    private ValueAnimator mValueAnimator;
    //字体大小
    private int textSize;
    //字体大小差
    private int textStep;
    //显示个数
    private int mShowNum;
    //字体颜色
    private int mTextColor = Color.parseColor(DEF_TEXT_COLOR);
    //选择监听
    private OnSelectNumListener mListener;
    //颜色渐变计算器
    private ArgbEvaluator mArgvEvlauator;

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

    public NumPickView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public NumPickView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NumPickView);
        for (int i = 0; i < ta.getIndexCount(); i++) {
            int index = ta.getIndex(i);
            switch (index) {
                case R.styleable.NumPickView_totalNum:
                    int total = ta.getInteger(index, 24);
                    for (int j = 6; j < total; j++) {
                        if (j < 10) {
                            mData.add("0" + j);
                        } else {
                            mData.add(String.valueOf(j));
                        }
                    }
                    break;
                case R.styleable.NumPickView_showNum:
                    mShowNum = ta.getInteger(index, 6);
                    break;
                case R.styleable.NumPickView_textColor:
                    mTextColor = ta.getColor(index, mTextColor);
            }
        }
        ta.recycle();
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mRect = new Rect();
        mArgvEvlauator = new ArgbEvaluator();
        mValueAnimator = new ValueAnimator();
        mValueAnimator.setDuration(300);
        mValueAnimator.setInterpolator(new LinearInterpolator());
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                if (abs(pivot) > mUnitHeight) {
                    return;
                }
                pivot = value;
                mScale = min(1, abs(pivot / mUnitHeight));
                invalidate();
            }
        });
        mValueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {}

            @Override
            public void onAnimationEnd(Animator animation) {
                if (mStatus == Status.UP && pivot != 0) {
                    mCurrentPostion = clamp(mCurrentPostion + 1);
                } else if (mStatus == Status.DOWN && pivot != 0) {
                    mCurrentPostion = clamp(mCurrentPostion - 1);
                }
                invalidate();
                pivot = 0;
                mStatus = Status.IDEL;
                mScale = 0;
                if (mListener != null) {
                    mListener.onSelected(mCurrentPostion);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    //展示个数
    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mHeight = getMeasuredHeight();
        mWidth = getMeasuredWidth();
        middleHeight = mHeight / 2;
        middleWidht = mWidth / 2;
        mUnitHeight = (mHeight - getPaddingTop() + getPaddingBottom()) / mShowNum;
        textSize = mUnitHeight / 2;
        textStep = mUnitHeight / 9;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //画选中字体
        drawText(canvas, mData.get(mCurrentPostion), 0, 1);
        //画除中间外上下字体
        int num = mShowNum / 2;
        for (int i = 1; i <= num; i++) {
            drawText(canvas, mData.get(clamp(mCurrentPostion + i)), i, 1);
            drawText(canvas, mData.get(clamp(mCurrentPostion - i)), i, -1);
        }

    }

    /**
     * 选中当前数值
     *
     * @param num index
     */
    public void select(int num) {
        if (num < 0 || num >= mData.size()) {
            throw new IllegalArgumentException("The num must be in the range betwwen 0 and " + (mData.size() - 1));
        }
        mCurrentPostion = num;
        if (mListener != null) {
            mListener.onSelected(mCurrentPostion);
        }
        invalidate();
    }


    /**
     * @param canvas
     * @param text   要画的 String
     * @param level  选中为0级,每差一个 index 加一级
     * @param direct 以选中的为基准的方向,direct < 0 在上方,direct > 0 在下方
     */
    private void drawText(Canvas canvas, String text, int level, int direct) {
        mPaint.reset();
        mPaint.setShader(null);
        //字的位置渐变量
        float offset = direct * level * mUnitHeight;
        //字体的大小变化
        float step = (direct * mStatus.getValue() * mScale * textStep);

        if (level == 0) {
            //中间字体无论怎么样都是缩小的
            mPaint.setColor(mTextColor);
            mPaint.setTextSize(textSize - abs(step));
            mPaint.getTextBounds(text, 0, text.length(), mRect);
            canvas.drawText(text, middleWidht - mRect.width() / 2, mHeight / 2 + mRect.height() / 2 + pivot, mPaint);
        } else {
            //其他字体根据上下和滑动方向关系放大或缩小, 颜色渐变
            int color = (int) mArgvEvlauator.evaluate(1 - abs(mRect.height() / 2 + offset + pivot)/middleHeight
                    , Color.parseColor(DEF_START_COLOR)
                    , mTextColor);
            mPaint.setColor(color);
            mPaint.setTextSize(textSize - textStep * level + step);
            mPaint.getTextBounds(text, 0, text.length(), mRect);
            canvas.drawText(text, middleWidht - mRect.width() / 2, middleHeight + mRect.height() / 2 + offset + pivot, mPaint);
        }

    }


    /**
     * distanceY > 0: 向下
     * distanceY < 0: 向上
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = event.getY();
                mValueAnimator.cancel();
                break;
            case MotionEvent.ACTION_MOVE:
                pivot = event.getY() - downY;
                if (pivot > 0) {
                    //向下
                    mStatus = Status.DOWN;
                    if (abs(pivot) > mUnitHeight) {
                        mCurrentPostion = clamp(mCurrentPostion - 1);
                        downY = event.getY();
                        pivot = 0;
                    } else {
                        invalidate();
                    }
                } else {
                    //向上
                    mStatus = Status.UP;
                    if (abs(pivot) > mUnitHeight) {
                        mCurrentPostion = clamp(mCurrentPostion + 1);
                        downY = event.getY();
                        pivot = 0;
                    } else {
                        invalidate();
                    }
                }
                mScale = min(1, abs(pivot / mUnitHeight));
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:

                if (pivot == 0) {
                    //把点击事件统一为滑动事件处理,简化流程。
                    pivot = 0.00001f;
                }
                if (abs(pivot) > mUnitHeight / 2) {
                    //需要过渡
                    int rest = (int) abs(mUnitHeight / 2 - pivot);
                    if (mStatus == Status.UP) {
                        mValueAnimator.setFloatValues(pivot, -rest);
                    } else if (mStatus == Status.DOWN) {
                        //这里需要注意
                        mValueAnimator.setFloatValues(pivot, (int) pivot + rest + mUnitHeight / 2);
                    }
                } else {
                    //过渡失败,返回原数值,所以终点都是 0
                    if (mStatus == Status.UP) {
                        mValueAnimator.setFloatValues(pivot, 0);
                    } else if (mStatus == Status.DOWN) {
                        mValueAnimator.setFloatValues(pivot, 0);
                    }
                }
                if (mValueAnimator.getValues() == null || mValueAnimator.getValues().length == 0) {
                    return false;
                }
                mValueAnimator.start();
                break;
        }
        return true;
    }

    public int getCurrentPostion() {
        return mCurrentPostion;
    }

    /**
     * 保证 index 合法化
     *
     * @param p 下标
     * @return 合法后的下标
     */
    private int clamp(int p) {
        if (p > mData.size() - 1) {
            return p - mData.size();
        } else if (p < 0) {
            return mData.size() - abs(p);
        }
        return p;
    }

    /**
     * 设置滚轮监听
     *
     * @param listener 监听
     */
    public void setOnSelectNumListener(OnSelectNumListener listener) {
        this.mListener = listener;
    }

    /**
     * 滚轮状态
     */
    private enum Status {
        UP(1), DOWN(-1), IDEL(0);
        int value;

        Status(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    }

    /**
     * 监听接口
     */
    public interface OnSelectNumListener {
        void onSelected(int num);
    }
}

主布局文件activity_main

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

dialog中需要的布局文件,也就是数字选择器的布局picker_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="10dp"
                android:orientation="horizontal">
                <com.example.myapplication.NumPickView
                    android:id="@+id/numPickView"
                    android:layout_width="wrap_content"
                    android:layout_height="250dp"
                    app:textColor="#10b7ff"
                    app:showNum="6"
                    app:totalNum="49"/>
                <TextView
                    android:layout_width="15dp"
                    android:layout_height="wrap_content"
                    android:gravity="center_vertical"
                    android:layout_marginTop="110dp"
                    android:layout_marginLeft="-130dp"
                    android:textSize="20sp"
                    android:text="A"/>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="-30dp"
                android:paddingLeft="20dp"
                android:paddingRight="20dp"
                android:orientation="horizontal">
                <Button
                    android:id="@+id/tvConfirm"
                    android:layout_width="wrap_content"
                    android:layout_height="40dp"
                    android:layout_marginBottom="5dp"
                    android:text="确定"
                    android:textSize="18sp"
                    android:textColor="@color/white"
                    android:layout_weight="1"
                    android:gravity="center"/>
            </LinearLayout>
        </LinearLayout>
</LinearLayout>

剩下最后activity中的主代码了:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button dundong = this.findViewById(R.id.btn);
        final NumPicker np = new NumPicker(MainActivity.this);
        np.setOnCancelListener(new NumPicker.OnCancelClickListener() {
            @Override
            public void onClick() {
                np.dismiss();
            }
        });
        np.setOnComfirmListener(new NumPicker.onComfirmClickListener() {
            @Override
            public void onClick(int num) {
                np.dismiss();
                num = num + 6;
                Toast.makeText(MainActivity.this, "你选择了"+num, Toast.LENGTH_SHORT).show();
            }
        });
        dundong.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                np.show();
            }
        });
    }
}

运行效果

android 滚轮选择器,笔记,android,java,android studio

 

到了这里,关于Android 实现滑动数字选择器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android——禁止ViewPager的左右滑动功能实现

    Android——禁止ViewPager的左右滑动功能实现 在Android开发中,ViewPager是一种常用的滑动控件,用于实现页面的左右切换效果。然而,在某些场景中,我们可能需要禁止ViewPager的左右滑动功能,只允许通过其他方式进行页面切换。本文将介绍如何在Android中实现禁止ViewPager左右滑动

    2024年02月06日
    浏览(44)
  • js实现滚轮滑动到底部自动加载(完整版)

    这里我们用vue实现(原生js相似), 这里我们用一个div当作一个容器; css样式 给上面div添加一个高度 在methods中编写我们的滚动条方法 onScroll(){        // let innerHeight=document.querySelector(\\\"JL\\\").clientHeight //js中使用         //let scrollHeight=document.querySelector(\\\"JL\\\").scrollHeight       

    2024年02月12日
    浏览(37)
  • Android 实现单指滑动、双指缩放照片

    最近接到一个查看大图的需求,现在图片展示还不够大,要求还要能缩小能放大还能保存照片。直接开始Google实现方式。 根据查询到的结果分为两种,一个是使用手势监听来实现,第二种监听触摸事件来实现 手势监听-- ScaleGestureDetector Google提供的手势监听类 触摸事件–OnT

    2024年02月11日
    浏览(40)
  • android鼠标滚轮事件监听方法

    2024年02月08日
    浏览(33)
  • Android——使用ScrollView实现滚动效果,当内容超出屏幕范围时自动滑动显示

    Android——使用ScrollView实现滚动效果,当内容超出屏幕范围时自动滑动显示 ScrollView是Android中常用的布局容器,用于在屏幕空间有限的情况下实现内容的滑动显示。当内容超出屏幕范围时,用户可以通过滑动屏幕来查看更多内容,提供了更好的用户体验。 在Android中,使用Sc

    2024年01月16日
    浏览(45)
  • Android应用-Flutter实现丝滑的滑动删除、移动排序等-Dismissible控件详解

    Dismissible 是 Flutter 中用于实现可滑动删除或拖拽操作的一个有用的小部件。主要用于在用户对列表项或任何其他可滑动的元素执行删除或拖动操作时,提供一种简便的实现方式。 列表项删除: 允许用户在列表中通过滑动手势删除某个项。 左右滑动: 提供可自定义的背景,当

    2024年02月04日
    浏览(48)
  • Android 安卓开发语言kotlin与Java该如何选择

            如今在Android开发中,应用层开发语言主要是Java和Kotlin,Kotlin是后来加入的,主导的语言还是Java。kotlin的加入仿佛让会kotlin语言的开发者更屌一些,其实不然。         有人说kotlin的引入是解决开发者复杂的逻辑,并且对空指针控制的比较友好,但是我们在开

    2024年02月11日
    浏览(61)
  • Android 实现仿淘宝地址多级选择器

    先看下效果图  仿淘宝的选择完城市出来的选择省市区之类的,这个支持自定义层级,多少层都可以使用,接下来是代码: 接下来是布局: activity_main adapter_project pop_time_line popupwindow 我的时间线设计的有点问题,有点偏差对不准,欢迎各位大佬提点修改方法 接下来是drawable文

    2024年02月15日
    浏览(31)
  • Android相册选择图片、相机拍照上传功能实现(上)

    先上效果图 下面就来说一下相册选择图片和相机拍照的实现 相册选择图片很简单,只需要通过 Intent 设置拉起就可以了 Intent 拉起相册 /** 打开相册 @param type 打开类型区分码(type是我用来区分回调的) / private void openGallery(int type) { Intent gallery = new Intent(Intent.ACTION_PICK); galler

    2024年04月16日
    浏览(53)
  • 安卓android日期选择器对话框 DatePickerDialog,实现日期选择,滚动式选择日期

    基本想法是:点击一个文本框,然后弹出日期选择器对话框,选择日期按下确定键后,文本框显示所选择的日期。可以有多种显示的主题,完整代码会在最后给出。 一、设置XML文件 记得给TextView取一个id,这里我取的id是:date 二、获取文本框组件 三、设置文本框的点击事件

    2023年04月15日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包